mirror of
https://git.alemi.dev/dashboard.git
synced 2024-11-22 07:24:52 +01:00
feat: floating windows to edit stuff
allow editing models via floating windows. Also added weird buttons to create new models. Still need to do relations!
This commit is contained in:
parent
3fcf059095
commit
76772465a3
9 changed files with 265 additions and 121 deletions
|
@ -13,7 +13,7 @@ pub struct Model {
|
|||
pub id: i64,
|
||||
pub name: String,
|
||||
pub source_id: i64,
|
||||
pub query_x: Option<String>,
|
||||
pub query_x: String,
|
||||
pub query_y: String,
|
||||
pub panel_id: i64,
|
||||
pub color: i32,
|
||||
|
@ -29,14 +29,8 @@ impl ActiveModelBehavior for ActiveModel {}
|
|||
impl Model {
|
||||
pub fn extract(&self, value: &serde_json::Value) -> Result<PlotPoint, FetchError> {
|
||||
let x: f64;
|
||||
let fallback_query = "".into();
|
||||
let q_x = self.query_x.as_ref().unwrap_or(&fallback_query);
|
||||
// TODO because of bad design, empty queries are
|
||||
// empty strings in my db. Rather than converting
|
||||
// them right away, I'm putting this jank fix:
|
||||
// checking len
|
||||
if q_x.len() > 0 {
|
||||
x = jql::walker(value, q_x.as_str())?
|
||||
if self.query_x.len() > 0 {
|
||||
x = jql::walker(value, self.query_x.as_str())?
|
||||
.as_f64()
|
||||
.ok_or(FetchError::JQLError("X query is null".to_string()))?; // TODO what if it's given to us as a string?
|
||||
} else {
|
||||
|
@ -55,7 +49,7 @@ impl Default for Model {
|
|||
id: 0,
|
||||
name: "".into(),
|
||||
source_id: 0,
|
||||
query_x: None,
|
||||
query_x: "".into(),
|
||||
query_y: "".into(),
|
||||
panel_id: 0,
|
||||
color: 0,
|
||||
|
|
|
@ -36,8 +36,7 @@ pub fn _metric_display_ui(ui: &mut Ui, metric: &entities::metrics::Model, _width
|
|||
pub fn metric_edit_ui(ui: &mut Ui, metric: &entities::metrics::Model, panels: Option<&Vec<entities::panels::Model>>, width: f32) {
|
||||
let text_width = width - 195.0;
|
||||
let mut name = metric.name.clone();
|
||||
let def_str = "".into();
|
||||
let mut query_x = metric.query_x.as_ref().unwrap_or(&def_str).clone();
|
||||
let mut query_x = metric.query_x.clone();
|
||||
let mut query_y = metric.query_y.clone();
|
||||
let mut panel_id = 0;
|
||||
ui.horizontal(|ui| {
|
||||
|
|
|
@ -9,7 +9,7 @@ use eframe::egui::{CentralPanel, Context, SidePanel, TopBottomPanel, Window};
|
|||
use tokio::sync::watch;
|
||||
use tracing::error;
|
||||
|
||||
use crate::{data::entities, worker::visualizer::AppStateView};
|
||||
use crate::{data::entities, worker::{visualizer::AppStateView, BackgroundAction}};
|
||||
use panel::main_content;
|
||||
use scaffold::{
|
||||
// confirmation_popup_delete_metric, confirmation_popup_delete_source, footer,
|
||||
|
@ -17,7 +17,7 @@ use scaffold::{
|
|||
};
|
||||
use source::source_panel;
|
||||
|
||||
use self::scaffold::footer;
|
||||
use self::scaffold::{footer, popup_edit_ui, EditingModel};
|
||||
|
||||
pub struct App {
|
||||
view: AppStateView,
|
||||
|
@ -29,11 +29,12 @@ pub struct App {
|
|||
width_tx: watch::Sender<i64>,
|
||||
logger_view: watch::Receiver<Vec<String>>,
|
||||
|
||||
buffer_panel: entities::panels::Model,
|
||||
// buffer_panel: entities::panels::Model,
|
||||
buffer_source: entities::sources::Model,
|
||||
buffer_metric: entities::metrics::Model,
|
||||
// buffer_metric: entities::metrics::Model,
|
||||
|
||||
edit: bool,
|
||||
editing: Vec<EditingModel>,
|
||||
sidebar: bool,
|
||||
padding: bool,
|
||||
// windows: Vec<Window<'open>>,
|
||||
|
@ -51,11 +52,10 @@ impl App {
|
|||
let panels = view.panels.borrow().clone();
|
||||
Self {
|
||||
db_path, interval, panels, width_tx, view, logger_view,
|
||||
buffer_panel: entities::panels::Model::default(),
|
||||
buffer_source: entities::sources::Model::default(),
|
||||
buffer_metric: entities::metrics::Model::default(),
|
||||
last_redraw: 0,
|
||||
edit: false,
|
||||
editing: vec![],
|
||||
sidebar: true,
|
||||
padding: false,
|
||||
// windows: vec![],
|
||||
|
@ -75,6 +75,12 @@ impl App {
|
|||
error!(target: "app", "Could not request flush: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn op(&self, op: BackgroundAction) {
|
||||
if let Err(e) = self.view.op.blocking_send(op) {
|
||||
error!(target: "app", "Could not send operation: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for App {
|
||||
|
@ -87,20 +93,9 @@ impl eframe::App for App {
|
|||
footer(ctx, ui, self.logger_view.clone(), self.db_path.clone(), self.view.points.borrow().len());
|
||||
});
|
||||
|
||||
let _w = Window::new("a");
|
||||
|
||||
// if let Some(index) = self.deleting_metric {
|
||||
// Window::new(format!("Delete Metric #{}?", index))
|
||||
// .show(ctx, |ui| confirmation_popup_delete_metric(self, ui, index));
|
||||
// }
|
||||
// if let Some(index) = self.deleting_source {
|
||||
// Window::new(format!("Delete Source #{}?", index))
|
||||
// .show(ctx, |ui| confirmation_popup_delete_source(self, ui, index));
|
||||
// }
|
||||
|
||||
// for window in self.windows {
|
||||
|
||||
// }
|
||||
for m in self.editing.iter_mut() {
|
||||
Window::new(m.id_repr()).show(ctx, |ui| popup_edit_ui(ui, m));
|
||||
}
|
||||
|
||||
if self.sidebar {
|
||||
SidePanel::left("sources-bar")
|
||||
|
@ -113,7 +108,7 @@ impl eframe::App for App {
|
|||
main_content(self, ctx, ui);
|
||||
});
|
||||
|
||||
if let Some(viewsize) = self.panels.iter().map(|p| p.view_size).max() {
|
||||
if let Some(viewsize) = self.panels.iter().map(|p| p.view_size + p.view_offset).max() {
|
||||
if let Err(e) = self.width_tx.send(viewsize as i64) {
|
||||
error!(target: "app", "Could not update fetch size : {:?}", e);
|
||||
}
|
||||
|
@ -123,5 +118,13 @@ impl eframe::App for App {
|
|||
ctx.request_repaint();
|
||||
self.last_redraw = Utc::now().timestamp();
|
||||
}
|
||||
|
||||
for m in self.editing.iter() {
|
||||
if m.should_fetch() {
|
||||
self.op(m.to_msg());
|
||||
}
|
||||
}
|
||||
|
||||
self.editing.retain(|v| v.modifying());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ pub fn main_content(app: &mut App, ctx: &Context, ui: &mut Ui) {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn panel_edit_inline_ui(_ui: &mut Ui, _panel: &entities::panels::Model) {
|
||||
pub fn _panel_edit_inline_ui(_ui: &mut Ui, _panel: &entities::panels::Model) {
|
||||
// TextEdit::singleline(&mut panel.name)
|
||||
// .hint_text("name")
|
||||
// .desired_width(100.0)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use eframe::{Frame, egui::{collapsing_header::CollapsingState, Context, Ui, Layout, ScrollArea, global_dark_light_mode_switch}, emath::Align};
|
||||
use eframe::{Frame, egui::{collapsing_header::CollapsingState, Context, Ui, Layout, ScrollArea, global_dark_light_mode_switch, TextEdit, Checkbox, Slider}, emath::Align};
|
||||
use sea_orm::{Set, Unchanged, ActiveValue::NotSet};
|
||||
use tokio::sync::watch;
|
||||
|
||||
use crate::gui::App;
|
||||
|
||||
use super::panel::panel_edit_inline_ui;
|
||||
use crate::{gui::App, data::entities, util::unpack_color, worker::BackgroundAction};
|
||||
|
||||
// TODO make this not super specific!
|
||||
pub fn _confirmation_popup_delete_metric(_app: &mut App, ui: &mut Ui, _metric_index: usize) {
|
||||
|
@ -58,6 +57,166 @@ pub fn _confirmation_popup_delete_source(_app: &mut App, ui: &mut Ui, _source_in
|
|||
});
|
||||
}
|
||||
|
||||
pub struct EditingModel {
|
||||
pub id: i64,
|
||||
m: EditingModelType,
|
||||
new: bool,
|
||||
valid: bool,
|
||||
ready: bool,
|
||||
}
|
||||
|
||||
impl EditingModel {
|
||||
pub fn id_repr(&self) -> String {
|
||||
let prefix = match self.m {
|
||||
EditingModelType::EditingPanel { panel: _ } => "panel",
|
||||
EditingModelType::EditingSource { source: _ } => "source",
|
||||
EditingModelType::EditingMetric { metric: _ } => "metric",
|
||||
};
|
||||
format!("edit_{}_{}", prefix, self.id)
|
||||
}
|
||||
|
||||
pub fn should_fetch(&self) -> bool {
|
||||
return self.ready && self.valid;
|
||||
}
|
||||
|
||||
pub fn modifying(&self) -> bool {
|
||||
return !self.ready;
|
||||
}
|
||||
|
||||
pub fn to_msg(&self) -> BackgroundAction {
|
||||
match &self.m {
|
||||
EditingModelType::EditingPanel { panel } =>
|
||||
BackgroundAction::UpdatePanel {
|
||||
panel: entities::panels::ActiveModel {
|
||||
id: if self.new { NotSet } else { Unchanged(panel.id) },
|
||||
name: Set(panel.name.clone()),
|
||||
view_scroll: Set(panel.view_scroll),
|
||||
view_size: Set(panel.view_size),
|
||||
timeserie: Set(panel.timeserie),
|
||||
height: Set(panel.height),
|
||||
limit_view: Set(panel.limit_view),
|
||||
position: Set(panel.position),
|
||||
reduce_view: Set(panel.reduce_view),
|
||||
view_chunks: Set(panel.view_chunks),
|
||||
shift_view: Set(panel.shift_view),
|
||||
view_offset: Set(panel.view_offset),
|
||||
average_view: Set(panel.average_view),
|
||||
}
|
||||
},
|
||||
EditingModelType::EditingSource { source } =>
|
||||
BackgroundAction::UpdateSource {
|
||||
source: entities::sources::ActiveModel {
|
||||
id: if self.new { NotSet } else { Unchanged(source.id) },
|
||||
name: Set(source.name.clone()),
|
||||
enabled: Set(source.enabled),
|
||||
url: Set(source.url.clone()),
|
||||
interval: Set(source.interval),
|
||||
last_update: Set(source.last_update),
|
||||
position: Set(source.position),
|
||||
}
|
||||
},
|
||||
EditingModelType::EditingMetric { metric } =>
|
||||
BackgroundAction::UpdateMetric {
|
||||
metric: entities::metrics::ActiveModel {
|
||||
id: if self.new { NotSet} else { Unchanged(metric.id) },
|
||||
name: Set(metric.name.clone()),
|
||||
source_id: Set(metric.source_id),
|
||||
color: Set(metric.color),
|
||||
panel_id: Set(metric.panel_id),
|
||||
query_x: Set(metric.query_x.clone()),
|
||||
query_y: Set(metric.query_y.clone()),
|
||||
position: Set(metric.position),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<entities::sources::Model> for EditingModel {
|
||||
fn from(s: entities::sources::Model) -> Self {
|
||||
EditingModel {
|
||||
new: if s.id == 0 { true } else { false },
|
||||
id: s.id, m: EditingModelType::EditingSource { source: s }, valid: false, ready: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<entities::metrics::Model> for EditingModel {
|
||||
fn from(m: entities::metrics::Model) -> Self {
|
||||
EditingModel {
|
||||
new: if m.id == 0 { true } else { false },
|
||||
id: m.id, m: EditingModelType::EditingMetric { metric: m }, valid: false, ready: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<entities::panels::Model> for EditingModel {
|
||||
fn from(p: entities::panels::Model) -> Self {
|
||||
EditingModel {
|
||||
new: if p.id == 0 { true } else { false },
|
||||
id: p.id, m: EditingModelType::EditingPanel { panel: p }, valid: false, ready: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum EditingModelType {
|
||||
EditingPanel { panel : entities::panels::Model },
|
||||
EditingSource { source: entities::sources::Model },
|
||||
EditingMetric { metric: entities::metrics::Model },
|
||||
}
|
||||
|
||||
pub fn popup_edit_ui(ui: &mut Ui, model: &mut EditingModel) {
|
||||
match &mut model.m {
|
||||
EditingModelType::EditingPanel { panel } => {
|
||||
ui.heading(format!("Edit panel #{}", panel.id));
|
||||
TextEdit::singleline(&mut panel.name)
|
||||
.hint_text("name")
|
||||
.show(ui);
|
||||
},
|
||||
EditingModelType::EditingSource { source } => {
|
||||
ui.heading(format!("Edit source #{}", source.id));
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(Checkbox::new(&mut source.enabled, ""));
|
||||
TextEdit::singleline(&mut source.name)
|
||||
.hint_text("name")
|
||||
.show(ui);
|
||||
});
|
||||
TextEdit::singleline(&mut source.url)
|
||||
.hint_text("url")
|
||||
.show(ui);
|
||||
ui.add(Slider::new(&mut source.interval, 1..=3600).text("interval"));
|
||||
},
|
||||
EditingModelType::EditingMetric { metric } => {
|
||||
ui.heading(format!("Edit metric #{}", metric.id));
|
||||
ui.horizontal(|ui| {
|
||||
ui.color_edit_button_srgba(&mut unpack_color(metric.color));
|
||||
TextEdit::singleline(&mut metric.name)
|
||||
.hint_text("name")
|
||||
.show(ui);
|
||||
});
|
||||
TextEdit::singleline(&mut metric.query_x)
|
||||
.hint_text("x")
|
||||
.show(ui);
|
||||
TextEdit::singleline(&mut metric.query_y)
|
||||
.hint_text("y")
|
||||
.show(ui);
|
||||
},
|
||||
}
|
||||
ui.separator();
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button(" save ").clicked() {
|
||||
model.valid = true;
|
||||
model.ready = true;
|
||||
}
|
||||
ui.with_layout(Layout::top_down(Align::RIGHT), |ui| {
|
||||
if ui.button(" close ").clicked() {
|
||||
model.valid = false;
|
||||
model.ready = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn header(app: &mut App, ui: &mut Ui, frame: &mut Frame) {
|
||||
ui.horizontal(|ui| {
|
||||
global_dark_light_mode_switch(ui);
|
||||
|
@ -77,17 +236,29 @@ pub fn header(app: &mut App, ui: &mut Ui, frame: &mut Frame) {
|
|||
app.refresh_data();
|
||||
}
|
||||
ui.separator();
|
||||
ui.checkbox(&mut app.edit, "edit");
|
||||
if app.edit {
|
||||
ui.label("+ panel");
|
||||
panel_edit_inline_ui(ui, &mut app.buffer_panel);
|
||||
if ui.button("add").clicked() {
|
||||
// if let Err(e) = app.data.add_panel(&app.input_panel) {
|
||||
// error!(target: "ui", "Failed to add panel: {:?}", e);
|
||||
// };
|
||||
if ui.button("new panel").clicked() {
|
||||
app.editing.push(entities::panels::Model::default().into());
|
||||
}
|
||||
ui.separator();
|
||||
if ui.button("new source").clicked() {
|
||||
app.editing.push(entities::sources::Model::default().into());
|
||||
}
|
||||
ui.separator();
|
||||
if ui.button("new metric").clicked() {
|
||||
app.editing.push(entities::metrics::Model::default().into());
|
||||
}
|
||||
// ui.separator();
|
||||
// ui.checkbox(&mut app.edit, "edit");
|
||||
// if app.edit {
|
||||
// ui.label("+ panel");
|
||||
// panel_edit_inline_ui(ui, &mut app.buffer_panel);
|
||||
// if ui.button("add").clicked() {
|
||||
// // if let Err(e) = app.data.add_panel(&app.input_panel) {
|
||||
// // error!(target: "ui", "Failed to add panel: {:?}", e);
|
||||
// // };
|
||||
// }
|
||||
// ui.separator();
|
||||
// }
|
||||
ui.with_layout(Layout::top_down(Align::RIGHT), |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.small_button("×").clicked() {
|
||||
|
|
|
@ -3,16 +3,14 @@ use eframe::{
|
|||
emath::Align,
|
||||
};
|
||||
use rfd::FileDialog;
|
||||
use tracing::error;
|
||||
|
||||
use crate::util::deserialize_values;
|
||||
use crate::gui::App;
|
||||
use crate::data::entities;
|
||||
|
||||
use super::metric::metric_edit_ui;
|
||||
|
||||
pub fn source_panel(app: &mut App, ui: &mut Ui) {
|
||||
let mut source_to_put_metric_on : Option<i64> = None;
|
||||
let source_to_put_metric_on : Option<i64> = None;
|
||||
let mut to_swap: Option<usize> = None;
|
||||
let _to_insert: Vec<entities::metrics::Model> = Vec::new();
|
||||
// let mut to_delete: Option<usize> = None;
|
||||
|
@ -48,8 +46,8 @@ pub fn source_panel(app: &mut App, ui: &mut Ui) {
|
|||
ui.horizontal(|ui| {
|
||||
source_edit_ui(ui, source, remaining_width - 34.0);
|
||||
if ui.small_button("×").clicked() {
|
||||
// app.deleting_metric = None;
|
||||
// app.deleting_source = Some(i);
|
||||
// TODO don't add duplicates
|
||||
app.editing.push(source.clone().into());
|
||||
}
|
||||
});
|
||||
let metrics = app
|
||||
|
@ -83,65 +81,12 @@ pub fn source_panel(app: &mut App, ui: &mut Ui) {
|
|||
}
|
||||
}
|
||||
if ui.small_button("×").clicked() {
|
||||
// app.deleting_source = None;
|
||||
// app.deleting_metric = Some(j);
|
||||
// TODO don't add duplicates
|
||||
app.editing.push(metric.clone().into());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
ui.horizontal(|ui| {
|
||||
metric_edit_ui(
|
||||
ui,
|
||||
&mut app.buffer_metric,
|
||||
None,
|
||||
remaining_width - 53.0,
|
||||
);
|
||||
ui.add_space(2.0);
|
||||
if ui.small_button(" + ").clicked() {
|
||||
source_to_put_metric_on = Some(source.id);
|
||||
}
|
||||
ui.add_space(1.0); // DAMN!
|
||||
if ui.small_button("o").clicked() {
|
||||
let path = FileDialog::new()
|
||||
.add_filter("csv", &["csv"])
|
||||
.pick_file();
|
||||
if let Some(path) = path {
|
||||
match deserialize_values(path) {
|
||||
Ok((_name, _query_x, _query_y, _data)) => {
|
||||
// let mut store = app
|
||||
// .data
|
||||
// .storage
|
||||
// .lock()
|
||||
// .expect("Storage Mutex poisoned");
|
||||
// match store.new_metric(
|
||||
// name.as_str(),
|
||||
// source.id,
|
||||
// query_x.as_str(),
|
||||
// query_y.as_str(),
|
||||
// -1,
|
||||
// Color32::TRANSPARENT,
|
||||
// metrics.len() as i32,
|
||||
// ) {
|
||||
// Ok(verified_metric) => {
|
||||
// store.put_values(verified_metric.id, &data).unwrap ();
|
||||
// *verified_metric.data.write().expect("Values RwLock poisoned") = data;
|
||||
// to_insert.push(verified_metric);
|
||||
// }
|
||||
// Err(e) => {
|
||||
// error!(target: "ui", "could not save metric into archive : {:?}", e);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
Err(e) => {
|
||||
error!(target: "ui", "Could not deserialize metric from file : {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ui.small_button("×").clicked() {
|
||||
app.buffer_metric = entities::metrics::Model::default();
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -175,9 +175,9 @@ fn main() {
|
|||
native_options,
|
||||
Box::new(
|
||||
move |cc| {
|
||||
ctx_tx.send(Some(cc.egui_ctx.clone())).unwrap_or_else(|_| {
|
||||
if let Err(_e) = ctx_tx.send(Some(cc.egui_ctx.clone())) {
|
||||
error!(target: "launcher", "Could not share reference to egui context (won't be able to periodically refresh window)");
|
||||
});
|
||||
};
|
||||
Box::new(
|
||||
App::new(
|
||||
cc,
|
||||
|
|
|
@ -13,9 +13,8 @@ const _PREFIXES: &'static [&'static str] = &["", "k", "M", "G", "T"];
|
|||
pub fn _serialize_values(values: &Vec<PlotPoint>, metric: &entities::metrics::Model, path: PathBuf) -> Result<(), Box<dyn Error>> {
|
||||
let mut wtr = csv::Writer::from_writer(std::fs::File::create(path)?);
|
||||
// DAMN! VVVVV
|
||||
let def_q_x = "".into();
|
||||
let name = metric.name.as_str();
|
||||
let q_x = metric.query_x.as_ref().unwrap_or(&def_q_x).as_str();
|
||||
let q_x = metric.query_x.as_str();
|
||||
let q_y = metric.query_y.as_str();
|
||||
wtr.write_record(&[name, q_x, q_y])?;
|
||||
// DAMN! AAAAA
|
||||
|
@ -26,7 +25,7 @@ pub fn _serialize_values(values: &Vec<PlotPoint>, metric: &entities::metrics::Mo
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn deserialize_values(path: PathBuf) -> Result<(String, String, String, Vec<PlotPoint>), Box<dyn Error>> {
|
||||
pub fn _deserialize_values(path: PathBuf) -> Result<(String, String, String, Vec<PlotPoint>), Box<dyn Error>> {
|
||||
let mut values = Vec::new();
|
||||
|
||||
let mut rdr = csv::Reader::from_reader(std::fs::File::open(path)?);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use chrono::Utc;
|
||||
use sea_orm::{TransactionTrait, DatabaseConnection, EntityTrait, Condition, ColumnTrait, QueryFilter, Set, QueryOrder, Order};
|
||||
use sea_orm::{TransactionTrait, DatabaseConnection, EntityTrait, Condition, ColumnTrait, QueryFilter, Set, QueryOrder, Order, ActiveModelTrait, ActiveValue::NotSet};
|
||||
use tokio::sync::{watch, mpsc};
|
||||
use tracing::{info, error};
|
||||
use std::collections::VecDeque;
|
||||
|
@ -17,7 +17,7 @@ pub struct AppStateView {
|
|||
}
|
||||
|
||||
impl AppStateView {
|
||||
pub async fn _request_flush(&self) -> bool {
|
||||
pub async fn request_flush(&self) -> bool {
|
||||
match self.flush.send(()).await {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
|
@ -109,17 +109,23 @@ impl AppState {
|
|||
|
||||
pub async fn fetch(&mut self, db: &DatabaseConnection) -> Result<(), sea_orm::DbErr> {
|
||||
// TODO parallelize all this stuff
|
||||
self.panels = entities::panels::Entity::find().all(db).await?;
|
||||
self.panels = entities::panels::Entity::find()
|
||||
.order_by(entities::panels::Column::Position, Order::Asc)
|
||||
.all(db).await?;
|
||||
if let Err(e) = self.tx.panels.send(self.panels.clone()) {
|
||||
error!(target: "worker", "Could not send panels update: {:?}", e);
|
||||
}
|
||||
|
||||
self.sources = entities::sources::Entity::find().all(db).await?;
|
||||
self.sources = entities::sources::Entity::find()
|
||||
.order_by(entities::sources::Column::Position, Order::Asc)
|
||||
.all(db).await?;
|
||||
if let Err(e) = self.tx.sources.send(self.sources.clone()) {
|
||||
error!(target: "worker", "Could not send sources update: {:?}", e);
|
||||
}
|
||||
|
||||
self.metrics = entities::metrics::Entity::find().all(db).await?;
|
||||
self.metrics = entities::metrics::Entity::find()
|
||||
.order_by(entities::metrics::Column::Position, Order::Asc)
|
||||
.all(db).await?;
|
||||
if let Err(e) = self.tx.metrics.send(self.metrics.clone()) {
|
||||
error!(target: "worker", "Could not send metrics update: {:?}", e);
|
||||
}
|
||||
|
@ -178,6 +184,30 @@ impl AppState {
|
|||
self.panels = panels;
|
||||
}
|
||||
},
|
||||
BackgroundAction::UpdatePanel { panel } => {
|
||||
let op = if panel.id == NotSet { panel.insert(&db) } else { panel.update(&db) };
|
||||
if let Err(e) = op.await {
|
||||
error!(target: "worker", "Could not update panel: {:?}", e);
|
||||
} else {
|
||||
self.view.request_flush().await;
|
||||
}
|
||||
},
|
||||
BackgroundAction::UpdateSource { source } => {
|
||||
let op = if source.id == NotSet { source.insert(&db) } else { source.update(&db) };
|
||||
if let Err(e) = op.await {
|
||||
error!(target: "worker", "Could not update source: {:?}", e);
|
||||
} else {
|
||||
self.view.request_flush().await;
|
||||
}
|
||||
},
|
||||
BackgroundAction::UpdateMetric { metric } => {
|
||||
let op = if metric.id == NotSet { metric.insert(&db) } else { metric.update(&db) };
|
||||
if let Err(e) = op.await {
|
||||
error!(target: "worker", "Could not update metric: {:?}", e);
|
||||
} else {
|
||||
self.view.request_flush().await;
|
||||
}
|
||||
},
|
||||
// _ => todo!(),
|
||||
}
|
||||
},
|
||||
|
@ -300,7 +330,10 @@ impl AppState {
|
|||
#[derive(Debug)]
|
||||
pub enum BackgroundAction {
|
||||
UpdateAllPanels { panels: Vec<entities::panels::Model> },
|
||||
// UpdatePanel { panel : entities::panels::ActiveModel },
|
||||
// UpdateSource { source: entities::sources::ActiveModel },
|
||||
// UpdateMetric { metric: entities::metrics::ActiveModel },
|
||||
UpdatePanel { panel : entities::panels::ActiveModel },
|
||||
UpdateSource { source: entities::sources::ActiveModel },
|
||||
UpdateMetric { metric: entities::metrics::ActiveModel },
|
||||
// InsertPanel { panel : entities::panels::ActiveModel },
|
||||
// InsertSource { source: entities::sources::ActiveModel },
|
||||
// InsertMetric { metric: entities::metrics::ActiveModel },
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue