Moving from Line to Table
This commit is contained in:
parent
ce32ab53f0
commit
d614ec4d18
4 changed files with 78 additions and 112 deletions
|
|
@ -3,6 +3,7 @@ missing_api_key = ❌ API key not provided. Use --api-key or environment variabl
|
||||||
success = ✅ Metrics received successfully!
|
success = ✅ Metrics received successfully!
|
||||||
metrics_preview = 📋 First 200 characters of metrics:
|
metrics_preview = 📋 First 200 characters of metrics:
|
||||||
Response = Response
|
Response = Response
|
||||||
|
response = response
|
||||||
invalid-json-status-page = ❌ Error parssing status page JSON
|
invalid-json-status-page = ❌ Error parssing status page JSON
|
||||||
invalid-json-heartbeat = ❌ Error parssing heartbeat JSON
|
invalid-json-heartbeat = ❌ Error parssing heartbeat JSON
|
||||||
invalid-uptime-key-format = Invalid format for uptime key. Expected format "monitorID_period". Received key: {key}
|
invalid-uptime-key-format = Invalid format for uptime key. Expected format "monitorID_period". Received key: {key}
|
||||||
|
|
@ -20,3 +21,5 @@ never = Never
|
||||||
auto-update-failed = Automatic update failed
|
auto-update-failed = Automatic update failed
|
||||||
update-fail = Failed to update data
|
update-fail = Failed to update data
|
||||||
now = Now
|
now = Now
|
||||||
|
uptime = Uptime
|
||||||
|
history = History
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ metrics_preview = 📋 Primeiras 200 caracteres das métricas:
|
||||||
missing_api_key = ❌ API key não fornecida. Use --api-key ou a variável de ambiente UPTIME_API_KEY
|
missing_api_key = ❌ API key não fornecida. Use --api-key ou a variável de ambiente UPTIME_API_KEY
|
||||||
missing_url = ❌ URL não fornecida. Use --url ou a variável de ambiente UPTIME_URL
|
missing_url = ❌ URL não fornecida. Use --url ou a variável de ambiente UPTIME_URL
|
||||||
Response = Resposta
|
Response = Resposta
|
||||||
|
response = resposta
|
||||||
invalid-json-status-page = ❌ Falha ao parsear JSON do status page
|
invalid-json-status-page = ❌ Falha ao parsear JSON do status page
|
||||||
invalid-json-heartbeat = ❌ Falha ao parsear JSON do heartbeat
|
invalid-json-heartbeat = ❌ Falha ao parsear JSON do heartbeat
|
||||||
invalid-uptime-key-format = Formato inválido na chave de uptime. Chave esperada no formato "monitorID_periodo". Chave recebida: {key}
|
invalid-uptime-key-format = Formato inválido na chave de uptime. Chave esperada no formato "monitorID_periodo". Chave recebida: {key}
|
||||||
|
|
@ -10,6 +11,7 @@ invalid-monitor-id = ID de monitor inválido: {id}
|
||||||
invalid-period-hours = Período em horas inválido: {hours}
|
invalid-period-hours = Período em horas inválido: {hours}
|
||||||
loading = Carregando...
|
loading = Carregando...
|
||||||
monitors = Monitors
|
monitors = Monitors
|
||||||
|
monitor = Monitor
|
||||||
unknown = Desconhecido
|
unknown = Desconhecido
|
||||||
services = Serviços
|
services = Serviços
|
||||||
monitor-not-found = Nenhum monitor encontrado
|
monitor-not-found = Nenhum monitor encontrado
|
||||||
|
|
@ -20,3 +22,4 @@ never = Nunca
|
||||||
auto-update-failed = Falha na atualização automática
|
auto-update-failed = Falha na atualização automática
|
||||||
update-fail = Falha ao atualizar dados
|
update-fail = Falha ao atualizar dados
|
||||||
now = Agora
|
now = Agora
|
||||||
|
history = Historico
|
||||||
|
|
|
||||||
|
|
@ -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, ListState, Padding, Paragraph},
|
widgets::{Block, Borders, TableState, Padding, Paragraph},
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -32,7 +32,7 @@ pub struct App {
|
||||||
update_interval: Duration,
|
update_interval: Duration,
|
||||||
endpoints: UptimeKumaEndpoints,
|
endpoints: UptimeKumaEndpoints,
|
||||||
client: UptimeKumaClient,
|
client: UptimeKumaClient,
|
||||||
list_state: ListState,
|
list_state: TableState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -185,7 +185,7 @@ impl App {
|
||||||
terminal.hide_cursor()?;
|
terminal.hide_cursor()?;
|
||||||
|
|
||||||
let state = DashboardViewState::new();
|
let state = DashboardViewState::new();
|
||||||
let mut list_state = ListState::default();
|
let mut list_state = TableState::default();
|
||||||
list_state.select(Some(0));
|
list_state.select(Some(0));
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
|
||||||
|
|
@ -6,61 +6,57 @@ use ratatui::{
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
style::{Color, Modifier, Style},
|
style::{Color, Modifier, Style},
|
||||||
text::{Line, Span},
|
text::{Line, Span},
|
||||||
widgets::{Block, Borders, List, ListItem, ListState},
|
widgets::{Block, Borders, List, ListItem, Row, Table, TableState},
|
||||||
};
|
};
|
||||||
|
|
||||||
const STATUS_LINE_LENGTH: usize = 20;
|
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,
|
frame: &mut Frame,
|
||||||
area: Rect,
|
area: Rect,
|
||||||
state: &DashboardViewState,
|
state: &DashboardViewState,
|
||||||
list_state: &mut ListState,
|
list_state: &mut TableState,
|
||||||
) {
|
) {
|
||||||
let block = Block::default()
|
let block = Block::default()
|
||||||
.title(t("monitors"))
|
.title(t("monitors"))
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.style(Style::default().fg(Color::Blue));
|
.style(Style::default().fg(Color::Blue));
|
||||||
|
|
||||||
let items: Vec<ListItem> = state
|
let header = vec![
|
||||||
|
"".to_string(),
|
||||||
|
t("monitor"),
|
||||||
|
t("Response"),
|
||||||
|
t("uptime"),
|
||||||
|
t("history"),
|
||||||
|
];
|
||||||
|
let constraints = vec![
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(MAX_NAME_LENGTH as u16),
|
||||||
|
Constraint::Length(10),
|
||||||
|
Constraint::Length(10),
|
||||||
|
Constraint::Length(STATUS_LINE_LENGTH as u16 + 16),
|
||||||
|
];
|
||||||
|
|
||||||
|
let available_height = area.height.saturating_sub(2);
|
||||||
|
let visible_items = state.monitors.len().min(available_height as usize);
|
||||||
|
|
||||||
|
let rows: Vec<Row> = state
|
||||||
.monitors
|
.monitors
|
||||||
.iter()
|
.iter()
|
||||||
.map(|monitor| create_monitor_item(monitor))
|
.take(visible_items)
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, m)| create_monitor_item(m, list_state.selected() == Some(i)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let list = List::new(items)
|
let table = Table::new(rows, constraints)
|
||||||
|
.header(Row::new(header))
|
||||||
.block(block)
|
.block(block)
|
||||||
.highlight_style(Style::default().add_modifier(Modifier::REVERSED))
|
.column_spacing(1)
|
||||||
.highlight_symbol(">> ");
|
.highlight_symbol(">> ")
|
||||||
|
.row_highlight_style(Style::default().add_modifier(Modifier::REVERSED));
|
||||||
|
|
||||||
frame.render_stateful_widget(list, area, list_state);
|
frame.render_stateful_widget(table, area, list_state);
|
||||||
}
|
|
||||||
|
|
||||||
fn create_status_line_spans(status_history: &[MonitorStatus]) -> Vec<Span<'static>> {
|
|
||||||
let mut spans = Vec::new();
|
|
||||||
let recent_status: Vec<_> = status_history
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.take(STATUS_LINE_LENGTH)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for status in recent_status.iter().rev() {
|
|
||||||
let c = get_status_char(status);
|
|
||||||
let color = get_status_color(status);
|
|
||||||
|
|
||||||
spans.push(Span::styled(c.to_string(), Style::default().fg(color)));
|
|
||||||
}
|
|
||||||
|
|
||||||
spans.push(Span::raw(" "));
|
|
||||||
spans.push(Span::styled(
|
|
||||||
t("now"),
|
|
||||||
Style::default()
|
|
||||||
.fg(Color::Gray)
|
|
||||||
.add_modifier(Modifier::ITALIC),
|
|
||||||
));
|
|
||||||
|
|
||||||
spans
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_status_char(status: &MonitorStatus) -> char {
|
pub fn get_status_char(status: &MonitorStatus) -> char {
|
||||||
|
|
@ -87,83 +83,47 @@ pub fn get_status_emoji(status: &MonitorStatus) -> &str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_monitor_item(monitor: &MonitorViewState) -> ListItem {
|
fn create_monitor_item(monitor: &MonitorViewState, item_selected: bool) -> 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);
|
||||||
let status_line = create_status_line_spans(&monitor.status_history);
|
|
||||||
|
|
||||||
let item_layout = Layout::default()
|
let display_name: String = if monitor.name.len() > MAX_NAME_LENGTH {
|
||||||
.direction(Direction::Horizontal)
|
format!("{:.width$}...", &monitor.name, width = MAX_NAME_LENGTH - 3)
|
||||||
.constraints([
|
} else {
|
||||||
Constraint::Length(3),
|
monitor.name.clone()
|
||||||
Constraint::Length(MAX_NAME_LENGTH as u16),
|
};
|
||||||
Constraint::Length(10),
|
|
||||||
Constraint::Length(10),
|
|
||||||
Constraint::Length(STATUS_LINE_LENGTH as u16),
|
|
||||||
])
|
|
||||||
.split(Rect {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 1000,
|
|
||||||
height: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
let status_span = Span::styled(
|
let response_text = format!("{:>7}ms", monitor.response_time);
|
||||||
|
let uptime_text = format!("{:>7}%", monitor.uptime_24h);
|
||||||
|
let status_line = create_status_line_text(&monitor.status_history);
|
||||||
|
|
||||||
|
let style = if item_selected {
|
||||||
|
Style::default().add_modifier(Modifier::REVERSED)
|
||||||
|
} else {
|
||||||
|
Style::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
Row::new(vec![
|
||||||
format!("{} ", status_icon),
|
format!("{} ", status_icon),
|
||||||
Style::default()
|
display_name,
|
||||||
.fg(status_color)
|
response_text,
|
||||||
.add_modifier(Modifier::BOLD),
|
uptime_text,
|
||||||
);
|
format!("(1h) {} ({})", status_line, t("now")),
|
||||||
|
])
|
||||||
let mut name_text = monitor.name.clone();
|
.style(style)
|
||||||
if name_text.len() > MAX_NAME_LENGTH {
|
.height(1)
|
||||||
name_text = format!("{}...", &name_text[..MAX_NAME_LENGTH - 3]);
|
}
|
||||||
}
|
|
||||||
|
fn create_status_line_text(status_history: &[MonitorStatus]) -> String {
|
||||||
let name_span = Span::styled(
|
let mut line = String::new();
|
||||||
name_text,
|
let recent_status: Vec<_> = status_history
|
||||||
Style::default()
|
.iter()
|
||||||
.fg(Color::White)
|
.rev()
|
||||||
.add_modifier(Modifier::BOLD),
|
.take(STATUS_LINE_LENGTH)
|
||||||
);
|
.collect();
|
||||||
|
|
||||||
let response_span = Span::styled(
|
for status in recent_status.iter().rev() {
|
||||||
format!("{:>7}ms", monitor.response_time),
|
line.push(get_status_char(status));
|
||||||
Style::default().fg(Color::Cyan),
|
}
|
||||||
);
|
line
|
||||||
|
|
||||||
let uptime_span = Span::styled(
|
|
||||||
format!("{:>7}%", monitor.uptime_24h),
|
|
||||||
Style::default().fg(Color::Magenta),
|
|
||||||
);
|
|
||||||
|
|
||||||
let status_spans = create_status_line_spans(&monitor.status_history);
|
|
||||||
let status_line_start_period = Span::styled(
|
|
||||||
"(1h)",
|
|
||||||
Style::default()
|
|
||||||
.fg(Color::Gray)
|
|
||||||
.add_modifier(Modifier::ITALIC),
|
|
||||||
);
|
|
||||||
let status_line_end_period = Span::styled(
|
|
||||||
t("now"),
|
|
||||||
Style::default()
|
|
||||||
.fg(Color::Gray)
|
|
||||||
.add_modifier(Modifier::ITALIC),
|
|
||||||
);
|
|
||||||
let mut lines = Vec::new();
|
|
||||||
let main_line = Line::from(vec![
|
|
||||||
status_span,
|
|
||||||
name_span,
|
|
||||||
Span::raw(" | "),
|
|
||||||
response_span,
|
|
||||||
Span::raw(" | "),
|
|
||||||
uptime_span,
|
|
||||||
Span::raw(" | "),
|
|
||||||
status_line_start_period,
|
|
||||||
]);
|
|
||||||
lines.push(main_line);
|
|
||||||
|
|
||||||
let status_line = Line::from(status_spans);
|
|
||||||
lines.push(status_line);
|
|
||||||
ListItem::new(lines)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue