mirror of
https://git.alemi.dev/dashboard.git
synced 2024-11-22 07:24:52 +01:00
feat: show file size in footer (update every s)
also made jq_rs use bundled jqlib because rust-analyzer won't work otherwise
This commit is contained in:
parent
c72e8801f9
commit
203cff23f9
5 changed files with 46 additions and 28 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "dashboard"
|
name = "dashboard"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -16,7 +16,7 @@ eframe = { version = "0.18", features = ["persistence"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
rusqlite = { version = "0.27" }
|
rusqlite = { version = "0.27" }
|
||||||
jq-rs = "0.4"
|
jq-rs = { version = "0.4", features = ["bundled"] }
|
||||||
ureq = { version = "2", features = ["json"] }
|
ureq = { version = "2", features = ["json"] }
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
|
|
|
@ -37,35 +37,39 @@ impl From::<rusqlite::Error> for FetchError {
|
||||||
|
|
||||||
pub struct ApplicationState {
|
pub struct ApplicationState {
|
||||||
pub run: bool,
|
pub run: bool,
|
||||||
|
pub file_path: PathBuf,
|
||||||
|
pub file_size: RwLock<u64>,
|
||||||
pub panels: RwLock<Vec<Panel>>,
|
pub panels: RwLock<Vec<Panel>>,
|
||||||
pub storage: Mutex<SQLiteDataStore>,
|
pub storage: Mutex<SQLiteDataStore>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplicationState {
|
impl ApplicationState {
|
||||||
pub fn new(path:PathBuf) -> Self {
|
pub fn new(path:PathBuf) -> Self {
|
||||||
let storage = SQLiteDataStore::new(path).unwrap();
|
let storage = SQLiteDataStore::new(path.clone()).unwrap();
|
||||||
|
|
||||||
let panels = storage.load_panels().unwrap();
|
let panels = storage.load_panels().unwrap();
|
||||||
|
|
||||||
return ApplicationState{
|
return ApplicationState{
|
||||||
run: true,
|
run: true,
|
||||||
|
file_size: RwLock::new(std::fs::metadata(path.clone()).unwrap().len()),
|
||||||
|
file_path: path,
|
||||||
panels: RwLock::new(panels),
|
panels: RwLock::new(panels),
|
||||||
storage: Mutex::new(storage),
|
storage: Mutex::new(storage),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_panel(&self, name:&str) -> Result<(), FetchError> {
|
pub fn add_panel(&self, name:&str) -> Result<(), FetchError> {
|
||||||
let panel = self.storage.lock().unwrap().new_panel(name, 100, 200, 280)?; // TODO make values customizable and useful
|
let panel = self.storage.lock().expect("Storage Mutex poisoned").new_panel(name, 100, 200, 280)?; // TODO make values customizable and useful
|
||||||
self.panels.write().unwrap().push(panel);
|
self.panels.write().expect("Panels RwLock poisoned").push(panel);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_source(&self, panel_id:i32, name:&str, url:&str, query_x:&str, query_y:&str) -> Result<(), FetchError> {
|
pub fn add_source(&self, panel_id:i32, name:&str, url:&str, query_x:&str, query_y:&str) -> Result<(), FetchError> {
|
||||||
let source = self.storage.lock().unwrap().new_source(panel_id, name, url, query_x, query_y)?;
|
let source = self.storage.lock().expect("Storage Mutex poisoned").new_source(panel_id, name, url, query_x, query_y)?;
|
||||||
let panels = self.panels.read().unwrap();
|
let panels = self.panels.read().expect("Panels RwLock poisoned");
|
||||||
for panel in &*panels {
|
for panel in &*panels {
|
||||||
if panel.id == panel_id {
|
if panel.id == panel_id {
|
||||||
panel.sources.write().unwrap().push(source);
|
panel.sources.write().expect("Sources RwLock poisoned").push(source);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,26 +108,19 @@ pub struct Source {
|
||||||
|
|
||||||
impl Source {
|
impl Source {
|
||||||
pub fn valid(&self) -> bool {
|
pub fn valid(&self) -> bool {
|
||||||
let last_fetch = self.last_fetch.read().unwrap();
|
let last_fetch = self.last_fetch.read().expect("LastFetch RwLock poisoned");
|
||||||
return (Utc::now() - *last_fetch).num_seconds() < self.interval as i64;
|
return (Utc::now() - *last_fetch).num_seconds() < self.interval as i64;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn values(&self) -> Values {
|
pub fn values(&self) -> Values {
|
||||||
Values::from_values(self.data.read().unwrap().clone())
|
Values::from_values(self.data.read().expect("Values RwLock poisoned").clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn values_filter(&self, min_x:f64) -> Values {
|
pub fn values_filter(&self, min_x:f64) -> Values {
|
||||||
let mut values = self.data.read().unwrap().clone();
|
let mut values = self.data.read().expect("Values RwLock poisoned").clone();
|
||||||
values.retain(|x| x.x > min_x);
|
values.retain(|x| x.x > min_x);
|
||||||
Values::from_values(values)
|
Values::from_values(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not really useful since different data has different fetch rates
|
|
||||||
// pub fn values_limit(&self, size:usize) -> Values {
|
|
||||||
// let values = self.data.read().unwrap().clone();
|
|
||||||
// let min = if values.len() < size { 0 } else { values.len() - size };
|
|
||||||
// Values::from_values(values[min..values.len()].to_vec())
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch(url:&str, query_x:&str, query_y:&str) -> Result<Value, FetchError> {
|
pub fn fetch(url:&str, query_x:&str, query_y:&str) -> Result<Value, FetchError> {
|
||||||
|
|
|
@ -3,20 +3,13 @@ pub mod worker;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
use chrono::Utc;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use eframe::egui::{plot::{Line, Plot}};
|
use eframe::egui::{plot::{Line, Plot}};
|
||||||
|
|
||||||
use self::data::ApplicationState;
|
use self::data::ApplicationState;
|
||||||
use self::worker::native_save;
|
use self::worker::native_save;
|
||||||
|
use self::util::{human_size, timestamp_to_str};
|
||||||
fn timestamp_to_str(t:i64) -> String {
|
|
||||||
format!(
|
|
||||||
"{}",
|
|
||||||
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(t, 0), Utc)
|
|
||||||
.format("%Y/%m/%d %H:%M:%S")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct InputBuffer {
|
struct InputBuffer {
|
||||||
panel_name: String,
|
panel_name: String,
|
||||||
|
@ -112,7 +105,9 @@ impl eframe::App for App {
|
||||||
});
|
});
|
||||||
egui::TopBottomPanel::bottom("footer").show(ctx, |ui| {
|
egui::TopBottomPanel::bottom("footer").show(ctx, |ui| {
|
||||||
ui.horizontal(|ui|{
|
ui.horizontal(|ui|{
|
||||||
ui.label(self.data.file.to_str().unwrap());
|
ui.label(self.data.file_path.to_str().unwrap());
|
||||||
|
ui.separator();
|
||||||
|
ui.label(human_size(*self.data.file_size.read().unwrap()));
|
||||||
ui.with_layout(egui::Layout::top_down(egui::Align::RIGHT), |ui| {
|
ui.with_layout(egui::Layout::top_down(egui::Align::RIGHT), |ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label(format!("v{}-{}", env!("CARGO_PKG_VERSION"), git_version::git_version!()));
|
ui.label(format!("v{}-{}", env!("CARGO_PKG_VERSION"), git_version::git_version!()));
|
||||||
|
|
23
src/app/util.rs
Normal file
23
src/app/util.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// if you're handling more than terabytes of data, it's the future and you ought to update this code!
|
||||||
|
use chrono::{DateTime, Utc, NaiveDateTime};
|
||||||
|
|
||||||
|
const PREFIXES: &'static [&'static str] = &["", "k", "M", "G", "T"];
|
||||||
|
|
||||||
|
pub fn human_size(size:u64) -> String {
|
||||||
|
let mut buf : f64 = size as f64;
|
||||||
|
let mut prefix : usize = 0;
|
||||||
|
while buf > 1024.0 && prefix < PREFIXES.len() -1 {
|
||||||
|
buf /= 1024.0;
|
||||||
|
prefix += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return format!("{:.3} {}B", buf, PREFIXES[prefix]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn timestamp_to_str(t:i64) -> String {
|
||||||
|
format!(
|
||||||
|
"{}",
|
||||||
|
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(t, 0), Utc)
|
||||||
|
.format("%Y/%m/%d %H:%M:%S")
|
||||||
|
)
|
||||||
|
}
|
|
@ -79,6 +79,9 @@ impl BackgroundWorker for NativeBackgroundWorker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut fsize = state.file_size.write().expect("File Size RwLock poisoned");
|
||||||
|
*fsize = std::fs::metadata(state.file_path.clone()).unwrap().len();
|
||||||
|
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue