Alingment
This commit is contained in:
parent
2819df185e
commit
3a87c7a011
9 changed files with 325 additions and 78 deletions
|
|
@ -1,9 +1,12 @@
|
|||
use std::cmp::min;
|
||||
|
||||
use crate::i18n::t;
|
||||
use crate::ui::dashboard::model::DashboardViewState;
|
||||
use crate::ui::dashboard::model::{DashboardViewState, GroupViewState};
|
||||
use crate::ui::dashboard::{MonitorStatus, MonitorViewState};
|
||||
use ratatui::layout::Layout;
|
||||
use ratatui::{
|
||||
Frame,
|
||||
layout::{Constraint, Rect},
|
||||
layout::{Alignment, Constraint, Direction, Rect},
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span},
|
||||
widgets::{Block, Borders, Row, Table},
|
||||
|
|
@ -13,42 +16,110 @@ const STATUS_LINE_LENGTH: usize = 100;
|
|||
const MAX_NAME_LENGTH: usize = 30;
|
||||
|
||||
pub fn render_monitor_list(frame: &mut Frame, area: Rect, state: &DashboardViewState) {
|
||||
let block = Block::default()
|
||||
.title(t("monitors"))
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default().fg(Color::Blue));
|
||||
let group_areas = layout_groups(area, state.groups.len());
|
||||
|
||||
let header = vec![
|
||||
for (i, group) in state.groups.iter().enumerate() {
|
||||
if i < group_areas.len() {
|
||||
render_group(frame, group_areas[i], group, i == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn layout_groups(area: Rect, group_count: usize) -> Vec<Rect> {
|
||||
if group_count == 0 {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let height_per_group = (area.height as usize / group_count).max(3);
|
||||
let mut current_y = area.y;
|
||||
let mut areas = Vec::new();
|
||||
|
||||
for _ in 0..group_count {
|
||||
if current_y + height_per_group as u16 > area.y + area.height {
|
||||
break;
|
||||
}
|
||||
|
||||
areas.push(Rect {
|
||||
x: area.x,
|
||||
y: current_y,
|
||||
width: area.width,
|
||||
height: height_per_group as u16,
|
||||
});
|
||||
|
||||
current_y += height_per_group as u16;
|
||||
}
|
||||
areas
|
||||
}
|
||||
|
||||
fn render_group(frame: &mut Frame, area: Rect, group: &GroupViewState, is_first: bool) {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.margin(0)
|
||||
.constraints([Constraint::Length(1), Constraint::Min(1)])
|
||||
.split(area);
|
||||
|
||||
let group_title = Line::from(vec![
|
||||
Span::styled(format!("{} ", group.name), title_style()),
|
||||
Span::styled(
|
||||
format!("({})", group.monitors.len()),
|
||||
Style::default().fg(Color::Gray),
|
||||
),
|
||||
]);
|
||||
|
||||
let title_block = Block::default()
|
||||
.borders(if is_first {
|
||||
Borders::TOP | Borders::LEFT | Borders::RIGHT
|
||||
} else {
|
||||
Borders::ALL
|
||||
})
|
||||
.border_style(Style::default().fg(Color::Blue))
|
||||
.title(group_title)
|
||||
.title_alignment(Alignment::Left);
|
||||
|
||||
frame.render_widget(title_block, chunks[0]);
|
||||
|
||||
if !group.monitors.is_empty() {
|
||||
render_monitor_table(frame, chunks[1], &group.monitors);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_monitor_table(frame: &mut Frame, area: Rect, monitors: &Vec<MonitorViewState>) {
|
||||
let max_items = area.height as usize;
|
||||
let items_to_show = min(monitors.len(), max_items);
|
||||
|
||||
let header_cells = vec![
|
||||
"".to_string(),
|
||||
t("monitor"),
|
||||
t("Response"),
|
||||
t("uptime"),
|
||||
t("history"),
|
||||
];
|
||||
let constraints = vec![
|
||||
|
||||
let header = Row::new(header_cells).style(title_style()).height(1);
|
||||
|
||||
let rows: Vec<Row> = monitors
|
||||
.iter()
|
||||
.take(items_to_show)
|
||||
.map(|monitor| create_monitor_item(monitor))
|
||||
.collect();
|
||||
|
||||
let widths = vec![
|
||||
Constraint::Length(3),
|
||||
Constraint::Length(MAX_NAME_LENGTH as u16),
|
||||
Constraint::Length(10),
|
||||
Constraint::Length(10),
|
||||
Constraint::Length(STATUS_LINE_LENGTH as u16 + 8),
|
||||
Constraint::Length(STATUS_LINE_LENGTH as u16),
|
||||
];
|
||||
|
||||
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
|
||||
.iter()
|
||||
.take(visible_items)
|
||||
.map(|m| create_monitor_item(m))
|
||||
.collect();
|
||||
|
||||
let table = Table::new(rows, constraints)
|
||||
.header(Row::new(header))
|
||||
.block(block)
|
||||
let table = Table::new(rows, widths)
|
||||
.header(header)
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::LEFT | Borders::RIGHT | Borders::BOTTOM)
|
||||
.border_style(Style::default().fg(Color::Blue)),
|
||||
)
|
||||
.column_spacing(1)
|
||||
.highlight_symbol(">> ")
|
||||
.row_highlight_style(Style::default().add_modifier(Modifier::REVERSED));
|
||||
.style(Style::default());
|
||||
|
||||
frame.render_widget(table, area);
|
||||
}
|
||||
|
|
@ -126,3 +197,9 @@ fn create_status_line_spans(status_history: &[MonitorStatus]) -> Line<'_> {
|
|||
}
|
||||
Line::from(spans)
|
||||
}
|
||||
|
||||
fn title_style() -> Style {
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue