Close to the ui final version
This commit is contained in:
parent
d614ec4d18
commit
b130c4550d
9 changed files with 46 additions and 69 deletions
|
|
@ -2,4 +2,3 @@ pub mod data;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
|
||||||
pub use data::unify_data;
|
pub use data::unify_data;
|
||||||
pub use models::{UnifiedData, UnifiedMonitorData};
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,2 @@
|
||||||
pub mod heartbeat;
|
pub mod heartbeat;
|
||||||
pub mod status_page;
|
pub mod status_page;
|
||||||
|
|
||||||
pub use heartbeat::HeartbeatResponse;
|
|
||||||
pub use status_page::StatusPageResponse;
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub use model::StatusPageResponse;
|
|
||||||
pub use parser::parse_response;
|
pub use parser::parse_response;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use ratatui::{
|
||||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||||
style::{Color, Modifier, Style},
|
style::{Color, Modifier, Style},
|
||||||
text::{Line, Span, Text},
|
text::{Line, Span, Text},
|
||||||
widgets::{Block, Borders, TableState, Padding, Paragraph},
|
widgets::{Block, Borders, Padding, Paragraph},
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -32,7 +32,6 @@ pub struct App {
|
||||||
update_interval: Duration,
|
update_interval: Duration,
|
||||||
endpoints: UptimeKumaEndpoints,
|
endpoints: UptimeKumaEndpoints,
|
||||||
client: UptimeKumaClient,
|
client: UptimeKumaClient,
|
||||||
list_state: TableState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -102,21 +101,7 @@ impl App {
|
||||||
frame.render_widget(no_data, area);
|
frame.render_widget(no_data, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_selection(&mut self, direction: isize) {
|
|
||||||
if self.state.monitors.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let current = self.list_state.selected().unwrap_or(0);
|
|
||||||
let new_index = (current as isize + direction) as usize;
|
|
||||||
let new_index = new_index.clamp(0, self.state.monitors.len() - 1);
|
|
||||||
|
|
||||||
self.list_state.select(Some(new_index));
|
|
||||||
self.state.selected_index = new_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render(&mut self) {
|
fn render(&mut self) {
|
||||||
let mut list_state = self.list_state.clone();
|
|
||||||
let _ = self.terminal.draw(|frame| {
|
let _ = self.terminal.draw(|frame| {
|
||||||
let area = frame.area();
|
let area = frame.area();
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
|
|
@ -134,7 +119,7 @@ impl App {
|
||||||
} else if self.state.monitors.is_empty() {
|
} else if self.state.monitors.is_empty() {
|
||||||
Self::render_no_data(frame, chunks[1]);
|
Self::render_no_data(frame, chunks[1]);
|
||||||
} else {
|
} else {
|
||||||
render_monitor_list(frame, chunks[1], &self.state, &mut list_state);
|
render_monitor_list(frame, chunks[1], &self.state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -148,8 +133,6 @@ impl App {
|
||||||
|
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Char('q') | KeyCode::Esc => self.should_quit = true,
|
KeyCode::Char('q') | KeyCode::Esc => self.should_quit = true,
|
||||||
KeyCode::Up => self.move_selection(-1),
|
|
||||||
KeyCode::Down => self.move_selection(1),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,8 +168,6 @@ impl App {
|
||||||
terminal.hide_cursor()?;
|
terminal.hide_cursor()?;
|
||||||
|
|
||||||
let state = DashboardViewState::new();
|
let state = DashboardViewState::new();
|
||||||
let mut list_state = TableState::default();
|
|
||||||
list_state.select(Some(0));
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state,
|
state,
|
||||||
|
|
@ -196,7 +177,6 @@ impl App {
|
||||||
update_interval: Duration::from_secs(30),
|
update_interval: Duration::from_secs(30),
|
||||||
endpoints,
|
endpoints,
|
||||||
client: UptimeKumaClient::new(),
|
client: UptimeKumaClient::new(),
|
||||||
list_state: list_state,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,16 @@ use crate::ui::dashboard::model::DashboardViewState;
|
||||||
use crate::ui::dashboard::{MonitorStatus, MonitorViewState};
|
use crate::ui::dashboard::{MonitorStatus, MonitorViewState};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
Frame,
|
Frame,
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Rect},
|
||||||
style::{Color, Modifier, Style},
|
style::{Color, Modifier, Style},
|
||||||
text::{Line, Span},
|
text::{Line, Span},
|
||||||
widgets::{Block, Borders, List, ListItem, Row, Table, TableState},
|
widgets::{Block, Borders, Row, Table},
|
||||||
};
|
};
|
||||||
|
|
||||||
const STATUS_LINE_LENGTH: usize = 100;
|
const STATUS_LINE_LENGTH: usize = 100;
|
||||||
const MAX_NAME_LENGTH: usize = 30;
|
const MAX_NAME_LENGTH: usize = 30;
|
||||||
|
|
||||||
pub fn render_monitor_list(
|
pub fn render_monitor_list(frame: &mut Frame, area: Rect, state: &DashboardViewState) {
|
||||||
frame: &mut Frame,
|
|
||||||
area: Rect,
|
|
||||||
state: &DashboardViewState,
|
|
||||||
list_state: &mut TableState,
|
|
||||||
) {
|
|
||||||
let block = Block::default()
|
let block = Block::default()
|
||||||
.title(t("monitors"))
|
.title(t("monitors"))
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
|
|
@ -45,8 +40,7 @@ pub fn render_monitor_list(
|
||||||
.monitors
|
.monitors
|
||||||
.iter()
|
.iter()
|
||||||
.take(visible_items)
|
.take(visible_items)
|
||||||
.enumerate()
|
.map(|m| create_monitor_item(m))
|
||||||
.map(|(i, m)| create_monitor_item(m, list_state.selected() == Some(i)))
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let table = Table::new(rows, constraints)
|
let table = Table::new(rows, constraints)
|
||||||
|
|
@ -56,7 +50,7 @@ pub fn render_monitor_list(
|
||||||
.highlight_symbol(">> ")
|
.highlight_symbol(">> ")
|
||||||
.row_highlight_style(Style::default().add_modifier(Modifier::REVERSED));
|
.row_highlight_style(Style::default().add_modifier(Modifier::REVERSED));
|
||||||
|
|
||||||
frame.render_stateful_widget(table, area, list_state);
|
frame.render_widget(table, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_status_char(status: &MonitorStatus) -> char {
|
pub fn get_status_char(status: &MonitorStatus) -> char {
|
||||||
|
|
@ -83,7 +77,7 @@ pub fn get_status_emoji(status: &MonitorStatus) -> &str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_monitor_item(monitor: &MonitorViewState, item_selected: bool) -> Row<'_> {
|
fn create_monitor_item(monitor: &MonitorViewState) -> Row<'_> {
|
||||||
let status_icon = get_status_emoji(&monitor.status);
|
let status_icon = get_status_emoji(&monitor.status);
|
||||||
let status_color = get_status_color(&monitor.status);
|
let status_color = get_status_color(&monitor.status);
|
||||||
|
|
||||||
|
|
@ -95,35 +89,55 @@ fn create_monitor_item(monitor: &MonitorViewState, item_selected: bool) -> Row<'
|
||||||
|
|
||||||
let response_text = format!("{:>7}ms", monitor.response_time);
|
let response_text = format!("{:>7}ms", monitor.response_time);
|
||||||
let uptime_text = format!("{:>7}%", monitor.uptime_24h);
|
let uptime_text = format!("{:>7}%", monitor.uptime_24h);
|
||||||
let status_line = create_status_line_text(&monitor.status_history);
|
|
||||||
|
|
||||||
let style = if item_selected {
|
let status_line_spans = create_status_line_spans(&monitor.status_history);
|
||||||
Style::default().add_modifier(Modifier::REVERSED)
|
|
||||||
} else {
|
|
||||||
Style::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
format!("{} ", status_icon),
|
get_formated_line(format!("{} ", status_icon), status_color, Modifier::empty()),
|
||||||
display_name,
|
get_formated_line(display_name, Color::White, Modifier::empty()),
|
||||||
response_text,
|
get_formated_line(response_text, Color::Cyan, Modifier::empty()),
|
||||||
uptime_text,
|
get_formated_line(uptime_text, Color::Magenta, Modifier::empty()),
|
||||||
format!("(1h) {} ({})", status_line, t("now")),
|
status_line_spans,
|
||||||
])
|
])
|
||||||
.style(style)
|
.style(Style::default())
|
||||||
.height(1)
|
.height(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_status_line_text(status_history: &[MonitorStatus]) -> String {
|
fn get_formated_line(text: String, color: Color, modifier: Modifier) -> Line<'static> {
|
||||||
let mut line = String::new();
|
Line::from(vec![Span::styled(
|
||||||
|
text,
|
||||||
|
Style::default().fg(color).add_modifier(modifier),
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_status_line_spans(status_history: &[MonitorStatus]) -> Line<'_> {
|
||||||
|
let mut spans = Vec::new();
|
||||||
let recent_status: Vec<_> = status_history
|
let recent_status: Vec<_> = status_history
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.take(STATUS_LINE_LENGTH)
|
.take(STATUS_LINE_LENGTH)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
spans.push(Span::styled(
|
||||||
|
"(1h)",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Gray)
|
||||||
|
.add_modifier(Modifier::ITALIC),
|
||||||
|
));
|
||||||
|
spans.push(Span::raw(" "));
|
||||||
|
|
||||||
for status in recent_status.iter().rev() {
|
for status in recent_status.iter().rev() {
|
||||||
line.push(get_status_char(status));
|
let c = get_status_char(status);
|
||||||
|
let color = get_status_color(status);
|
||||||
|
|
||||||
|
spans.push(Span::styled(c.to_string(), Style::default().fg(color)));
|
||||||
}
|
}
|
||||||
line
|
spans.push(Span::raw(" "));
|
||||||
|
spans.push(Span::styled(
|
||||||
|
t("now"),
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Gray)
|
||||||
|
.add_modifier(Modifier::ITALIC),
|
||||||
|
));
|
||||||
|
Line::from(spans)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub use model::{DashboardViewState, MonitorStatus, MonitorViewState};
|
pub use model::{MonitorStatus, MonitorViewState};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::core::models::{UnifiedData, UnifiedMonitorData};
|
use crate::core::models::UnifiedData;
|
||||||
use crate::data::heartbeat::model::HeartbeatEntry;
|
use crate::data::heartbeat::model::HeartbeatEntry;
|
||||||
use crate::i18n::t;
|
use crate::i18n::t;
|
||||||
|
|
||||||
|
|
@ -96,10 +96,6 @@ impl DashboardViewState {
|
||||||
error_message: None,
|
error_message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_selected_monitor(&self) -> Option<&MonitorViewState> {
|
|
||||||
self.monitors.get(self.selected_index)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_status_history(heartbeats: &[HeartbeatEntry]) -> Vec<MonitorStatus> {
|
fn get_status_history(heartbeats: &[HeartbeatEntry]) -> Vec<MonitorStatus> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum AppEvent {
|
|
||||||
KeyPress(char),
|
|
||||||
RefreshData,
|
|
||||||
Quit,
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod dashboard;
|
pub mod dashboard;
|
||||||
pub mod events;
|
|
||||||
|
|
||||||
pub use app::App;
|
pub use app::App;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue