mirror of
https://git.alemi.dev/dashboard.git
synced 2024-11-22 07:24:52 +01:00
feat: improved top panel, allow to reconnect during session
This commit is contained in:
parent
a6bc0da6fa
commit
c59c4b0009
4 changed files with 113 additions and 89 deletions
|
@ -6,7 +6,7 @@ mod scaffold;
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use eframe::egui::{CentralPanel, Context, SidePanel, TopBottomPanel, Window};
|
use eframe::egui::{CentralPanel, Context, SidePanel, TopBottomPanel, Window};
|
||||||
use tokio::sync::watch;
|
use tokio::sync::{watch, mpsc};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::{data::entities, worker::{visualizer::AppStateView, BackgroundAction}};
|
use crate::{data::entities, worker::{visualizer::AppStateView, BackgroundAction}};
|
||||||
|
@ -21,7 +21,8 @@ use self::scaffold::{footer, EditingModel, popup_edit_ui};
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
view: AppStateView,
|
view: AppStateView,
|
||||||
db_path: String,
|
db_uri: String,
|
||||||
|
db_uri_tx: mpsc::Sender<String>,
|
||||||
interval: i64,
|
interval: i64,
|
||||||
last_redraw: i64,
|
last_redraw: i64,
|
||||||
|
|
||||||
|
@ -31,19 +32,19 @@ pub struct App {
|
||||||
|
|
||||||
// buffer_panel: entities::panels::Model,
|
// buffer_panel: entities::panels::Model,
|
||||||
buffer_source: entities::sources::Model,
|
buffer_source: entities::sources::Model,
|
||||||
// buffer_metric: entities::metrics::Model,
|
buffer_metric: entities::metrics::Model,
|
||||||
|
|
||||||
edit: bool,
|
edit: bool,
|
||||||
editing: Vec<EditingModel>,
|
editing: Vec<EditingModel>,
|
||||||
sidebar: bool,
|
sidebar: bool,
|
||||||
padding: bool,
|
_padding: bool,
|
||||||
// windows: Vec<Window<'open>>,
|
// windows: Vec<Window<'open>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
_cc: &eframe::CreationContext,
|
_cc: &eframe::CreationContext,
|
||||||
db_path: String,
|
db_uri_tx: mpsc::Sender<String>,
|
||||||
interval: i64,
|
interval: i64,
|
||||||
view: AppStateView,
|
view: AppStateView,
|
||||||
width_tx: watch::Sender<i64>,
|
width_tx: watch::Sender<i64>,
|
||||||
|
@ -51,13 +52,15 @@ impl App {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let panels = view.panels.borrow().clone();
|
let panels = view.panels.borrow().clone();
|
||||||
Self {
|
Self {
|
||||||
db_path, interval, panels, width_tx, view, logger_view,
|
db_uri_tx, interval, panels, width_tx, view, logger_view,
|
||||||
|
db_uri: "".into(),
|
||||||
buffer_source: entities::sources::Model::default(),
|
buffer_source: entities::sources::Model::default(),
|
||||||
|
buffer_metric: entities::metrics::Model::default(),
|
||||||
last_redraw: 0,
|
last_redraw: 0,
|
||||||
edit: false,
|
edit: false,
|
||||||
editing: vec![],
|
editing: vec![],
|
||||||
sidebar: true,
|
sidebar: true,
|
||||||
padding: false,
|
_padding: false,
|
||||||
// windows: vec![],
|
// windows: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +93,7 @@ impl eframe::App for App {
|
||||||
});
|
});
|
||||||
|
|
||||||
TopBottomPanel::bottom("footer").show(ctx, |ui| {
|
TopBottomPanel::bottom("footer").show(ctx, |ui| {
|
||||||
footer(ctx, ui, self.logger_view.clone(), self.db_path.clone(), self.view.points.borrow().len());
|
footer(ctx, ui, self.logger_view.clone(), self.db_uri.clone(), self.view.points.borrow().len());
|
||||||
});
|
});
|
||||||
|
|
||||||
for m in self.editing.iter_mut() {
|
for m in self.editing.iter_mut() {
|
||||||
|
@ -101,7 +104,7 @@ impl eframe::App for App {
|
||||||
|
|
||||||
if self.sidebar {
|
if self.sidebar {
|
||||||
SidePanel::left("sources-bar")
|
SidePanel::left("sources-bar")
|
||||||
.width_range(if self.edit { 400.0..=1000.0 } else { 280.0..=680.0 })
|
.width_range(280.0..=800.0)
|
||||||
.default_width(if self.edit { 450.0 } else { 330.0 })
|
.default_width(if self.edit { 450.0 } else { 330.0 })
|
||||||
.show(ctx, |ui| source_panel(self, ui));
|
.show(ctx, |ui| source_panel(self, ui));
|
||||||
}
|
}
|
||||||
|
@ -110,7 +113,13 @@ impl eframe::App for App {
|
||||||
main_content(self, ctx, ui);
|
main_content(self, ctx, ui);
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(viewsize) = self.panels.iter().map(|p| p.view_size + p.view_offset).max() {
|
if let Some(viewsize) =
|
||||||
|
self.panels
|
||||||
|
.iter()
|
||||||
|
.chain(self.view.panels.borrow().iter())
|
||||||
|
.map(|p| p.view_size + p.view_offset)
|
||||||
|
.max()
|
||||||
|
{
|
||||||
if let Err(e) = self.width_tx.send(viewsize as i64) {
|
if let Err(e) = self.width_tx.send(viewsize as i64) {
|
||||||
error!(target: "app", "Could not update fetch size : {:?}", e);
|
error!(target: "app", "Could not update fetch size : {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,39 +11,33 @@ use crate::data::entities;
|
||||||
use super::scaffold::EditingModel;
|
use super::scaffold::EditingModel;
|
||||||
|
|
||||||
pub fn main_content(app: &mut App, ctx: &Context, ui: &mut Ui) {
|
pub fn main_content(app: &mut App, ctx: &Context, ui: &mut Ui) {
|
||||||
let mut _to_swap: Option<usize> = None;
|
let metrics = app.view.metrics.borrow();
|
||||||
let mut _to_delete: Option<usize> = None;
|
|
||||||
ScrollArea::vertical().show(ui, |ui| {
|
ScrollArea::vertical().show(ui, |ui| {
|
||||||
let panels = &mut app.panels;
|
ui.separator();
|
||||||
let _panels_count = panels.len();
|
if app.edit {
|
||||||
let metrics = app.view.metrics.borrow();
|
for mut panel in app.panels.iter_mut() {
|
||||||
for (index, panel) in panels.iter_mut().enumerate() {
|
CollapsingState::load_with_default_open(
|
||||||
if index > 0 {
|
ctx,
|
||||||
ui.separator(); // only show this if there is at least one panel
|
ui.make_persistent_id(format!("panel-{}-compressable", panel.id)),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.show_header(ui, |ui| {
|
||||||
|
panel_title_ui_edit(ui, &mut panel, &mut app.editing, &app.view.metrics.borrow(), &app.view.panel_metric.borrow());
|
||||||
|
})
|
||||||
|
.body(|ui| panel_body_ui(ui, panel, &metrics, &app.view.points.borrow(), &app.view.panel_metric.borrow()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for panel in app.view.panels.borrow().iter() {
|
||||||
|
CollapsingState::load_with_default_open(
|
||||||
|
ctx,
|
||||||
|
ui.make_persistent_id(format!("panel-{}-compressable", panel.id)),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.show_header(ui, |ui| {
|
||||||
|
panel_title_ui(ui, &panel);
|
||||||
|
})
|
||||||
|
.body(|ui| panel_body_ui(ui, panel, &metrics, &app.view.points.borrow(), &app.view.panel_metric.borrow()));
|
||||||
}
|
}
|
||||||
CollapsingState::load_with_default_open(
|
|
||||||
ctx,
|
|
||||||
ui.make_persistent_id(format!("panel-{}-compressable", panel.id)),
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.show_header(ui, |ui| {
|
|
||||||
// if ui.small_button(" + ").clicked() {
|
|
||||||
// if index > 0 {
|
|
||||||
// to_swap = Some(index); // TODO kinda jank but is there a better way?
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if ui.small_button(" − ").clicked() {
|
|
||||||
// if index < panels_count - 1 {
|
|
||||||
// to_swap = Some(index + 1); // TODO kinda jank but is there a better way?
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if ui.small_button(" × ").clicked() {
|
|
||||||
// to_delete = Some(index); // TODO kinda jank but is there a better way?
|
|
||||||
// }
|
|
||||||
// ui.separator();
|
|
||||||
panel_title_ui(ui, panel, &mut app.editing, &app.view.metrics.borrow(), &app.view.panel_metric.borrow());
|
|
||||||
})
|
|
||||||
.body(|ui| panel_body_ui(ui, panel, &metrics, &app.view.points.borrow(), &app.view.panel_metric.borrow()));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -56,6 +50,46 @@ pub fn _panel_edit_inline_ui(_ui: &mut Ui, _panel: &entities::panels::Model) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn panel_title_ui(
|
pub fn panel_title_ui(
|
||||||
|
ui: &mut Ui,
|
||||||
|
panel: &entities::panels::Model,
|
||||||
|
) { // TODO make edit UI in separate func
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.heading(panel.name.as_str());
|
||||||
|
ui.with_layout(Layout::right_to_left(eframe::emath::Align::Min), |ui| {
|
||||||
|
ui.horizontal(|_ui| {
|
||||||
|
// TODO just show these, with no editing
|
||||||
|
// ui.toggle_value(&mut panel.view_scroll, "🔒");
|
||||||
|
// ui.separator();
|
||||||
|
// ui.add(
|
||||||
|
// DragValue::new(&mut panel.view_size)
|
||||||
|
// .speed(10)
|
||||||
|
// .suffix(" min")
|
||||||
|
// .clamp_range(0..=2147483647i32),
|
||||||
|
// );
|
||||||
|
// ui.separator();
|
||||||
|
// ui.add(
|
||||||
|
// DragValue::new(&mut panel.view_offset)
|
||||||
|
// .speed(10)
|
||||||
|
// .suffix(" min")
|
||||||
|
// .clamp_range(0..=2147483647i32),
|
||||||
|
// );
|
||||||
|
// ui.separator();
|
||||||
|
// if panel.reduce_view {
|
||||||
|
// ui.add(
|
||||||
|
// DragValue::new(&mut panel.view_chunks)
|
||||||
|
// .speed(1)
|
||||||
|
// .prefix("x")
|
||||||
|
// .clamp_range(1..=1000), // TODO allow to average larger spans maybe?
|
||||||
|
// );
|
||||||
|
// ui.toggle_value(&mut panel.average_view, "avg");
|
||||||
|
// }
|
||||||
|
// ui.toggle_value(&mut panel.reduce_view, "reduce");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn panel_title_ui_edit(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
panel: &mut entities::panels::Model,
|
panel: &mut entities::panels::Model,
|
||||||
editing: &mut Vec<EditingModel>,
|
editing: &mut Vec<EditingModel>,
|
||||||
|
|
|
@ -72,7 +72,7 @@ impl EditingModel {
|
||||||
EditingModelType::EditingSource { source: _ } => "source",
|
EditingModelType::EditingSource { source: _ } => "source",
|
||||||
EditingModelType::EditingMetric { metric: _ } => "metric",
|
EditingModelType::EditingMetric { metric: _ } => "metric",
|
||||||
};
|
};
|
||||||
format!("edit_{}_{}", prefix, self.id)
|
format!("edit {} #{}", prefix, self.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn should_fetch(&self) -> bool {
|
pub fn should_fetch(&self) -> bool {
|
||||||
|
@ -200,7 +200,6 @@ pub fn popup_edit_ui(
|
||||||
) {
|
) {
|
||||||
match &mut model.m {
|
match &mut model.m {
|
||||||
EditingModelType::EditingPanel { panel, opts } => {
|
EditingModelType::EditingPanel { panel, opts } => {
|
||||||
ui.heading(format!("Edit panel #{}", panel.id));
|
|
||||||
TextEdit::singleline(&mut panel.name)
|
TextEdit::singleline(&mut panel.name)
|
||||||
.hint_text("name")
|
.hint_text("name")
|
||||||
.show(ui);
|
.show(ui);
|
||||||
|
@ -216,7 +215,6 @@ pub fn popup_edit_ui(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
EditingModelType::EditingSource { source } => {
|
EditingModelType::EditingSource { source } => {
|
||||||
ui.heading(format!("Edit source #{}", source.id));
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add(Checkbox::new(&mut source.enabled, ""));
|
ui.add(Checkbox::new(&mut source.enabled, ""));
|
||||||
TextEdit::singleline(&mut source.name)
|
TextEdit::singleline(&mut source.name)
|
||||||
|
@ -233,7 +231,6 @@ pub fn popup_edit_ui(
|
||||||
ui.add(Slider::new(&mut source.interval, 1..=3600).text("interval"));
|
ui.add(Slider::new(&mut source.interval, 1..=3600).text("interval"));
|
||||||
},
|
},
|
||||||
EditingModelType::EditingMetric { metric } => {
|
EditingModelType::EditingMetric { metric } => {
|
||||||
ui.heading(format!("Edit metric #{}", metric.id));
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let mut color_buf = unpack_color(metric.color);
|
let mut color_buf = unpack_color(metric.color);
|
||||||
ui.color_edit_button_srgba(&mut color_buf);
|
ui.color_edit_button_srgba(&mut color_buf);
|
||||||
|
@ -284,29 +281,30 @@ pub fn header(app: &mut App, ui: &mut Ui, frame: &mut Frame) {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
ui.checkbox(&mut app.sidebar, "sources");
|
ui.checkbox(&mut app.sidebar, "sources");
|
||||||
ui.separator();
|
ui.separator();
|
||||||
if ui.button("reset").clicked() {
|
|
||||||
app.panels = app.view.panels.borrow().clone();
|
|
||||||
}
|
|
||||||
ui.separator();
|
|
||||||
if ui.button("save").clicked() {
|
|
||||||
app.save_all_panels();
|
|
||||||
}
|
|
||||||
ui.separator();
|
|
||||||
if ui.button("refresh").clicked() {
|
if ui.button("refresh").clicked() {
|
||||||
app.refresh_data();
|
app.refresh_data();
|
||||||
}
|
}
|
||||||
ui.separator();
|
TextEdit::singleline(&mut app.db_uri)
|
||||||
if ui.button("new panel").clicked() {
|
.hint_text("db uri")
|
||||||
app.editing.push(entities::panels::Model::default().into());
|
.show(ui);
|
||||||
|
if ui.button("connect").clicked() {
|
||||||
|
app.db_uri_tx.blocking_send(app.db_uri.clone()).unwrap(); // TODO!!!
|
||||||
|
app.refresh_data();
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
if ui.button("new source").clicked() {
|
ui.checkbox(&mut app.edit, "edit");
|
||||||
app.editing.push(entities::sources::Model::default().into());
|
if app.edit {
|
||||||
|
if ui.button("reset").clicked() {
|
||||||
|
app.panels = app.view.panels.borrow().clone();
|
||||||
|
}
|
||||||
|
if ui.button("save").clicked() {
|
||||||
|
app.save_all_panels();
|
||||||
|
}
|
||||||
|
if ui.button("+").clicked() {
|
||||||
|
app.editing.push(entities::panels::Model::default().into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
if ui.button("new metric").clicked() {
|
|
||||||
app.editing.push(entities::metrics::Model::default().into());
|
|
||||||
}
|
|
||||||
// ui.separator();
|
// ui.separator();
|
||||||
// ui.checkbox(&mut app.edit, "edit");
|
// ui.checkbox(&mut app.edit, "edit");
|
||||||
// if app.edit {
|
// if app.edit {
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use eframe::{
|
use eframe::egui::{ScrollArea, Ui, DragValue, TextEdit, Checkbox};
|
||||||
egui::{Layout, ScrollArea, Ui, DragValue, TextEdit, Checkbox, Button},
|
|
||||||
emath::Align,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::gui::App;
|
use crate::gui::App;
|
||||||
use crate::data::entities;
|
use crate::data::entities;
|
||||||
|
@ -77,7 +74,9 @@ pub fn source_panel(app: &mut App, ui: &mut Ui) {
|
||||||
ui.horizontal(|ui| { // 1 more for uncategorized sources
|
ui.horizontal(|ui| { // 1 more for uncategorized sources
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
ui.add_enabled(false, Button::new("#").small());
|
if ui.small_button("+").clicked() {
|
||||||
|
app.editing.push(entities::sources::Model::default().into());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
ui.vertical(|ui| { // actual sources list container
|
ui.vertical(|ui| { // actual sources list container
|
||||||
ui.group(|ui| {
|
ui.group(|ui| {
|
||||||
|
@ -110,33 +109,17 @@ pub fn source_panel(app: &mut App, ui: &mut Ui) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Add an empty metric to insert new ones
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
metric_edit_ui(ui, &mut app.buffer_metric);
|
||||||
|
if ui.small_button("+").clicked() {
|
||||||
|
app.editing.push(entities::metrics::Model::default().into());
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if app.edit {
|
|
||||||
ui.separator();
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.heading("new source");
|
|
||||||
ui.with_layout(Layout::top_down(Align::RIGHT), |ui| {
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
if ui.button("add").clicked() {
|
|
||||||
// if let Err(e) = app.data.add_source(&app.input_source) {
|
|
||||||
// error!(target: "ui", "Error adding source : {:?}", e);
|
|
||||||
// } else {
|
|
||||||
// app.input_source.id += 1;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
ui.toggle_value(&mut app.padding, "#");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
source_edit_ui(ui, &mut app.buffer_source);
|
|
||||||
ui.add_space(5.0);
|
|
||||||
if app.padding {
|
|
||||||
ui.add_space(300.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
//if let Some(i) = to_delete {
|
//if let Some(i) = to_delete {
|
||||||
// // TODO can this be done in background? idk
|
// // TODO can this be done in background? idk
|
||||||
|
|
Loading…
Reference in a new issue