1use crate::output::MultiFormatDisplay;
4use comfy_table::{presets::UTF8_FULL, Cell, Color, ContentArrangement, Table};
5use serde::Serialize;
6
7#[derive(Debug, Serialize)]
8pub struct NodeInfo {
9 pub id: String,
10 pub role: String,
11 pub state: String,
12 pub address: String,
13 pub agents: usize,
14 pub uptime: String,
15 pub version: String,
16}
17
18#[derive(Debug, Serialize)]
19pub struct NodeList {
20 pub nodes: Vec<NodeInfo>,
21 pub total: usize,
22}
23
24impl MultiFormatDisplay for NodeList {
25 fn to_table(&self) -> Table {
26 let mut table = Table::new();
27 table
28 .load_preset(UTF8_FULL)
29 .set_content_arrangement(ContentArrangement::Dynamic)
30 .set_header(vec![
31 Cell::new("ID").fg(Color::Cyan),
32 Cell::new("ROLE").fg(Color::Cyan),
33 Cell::new("STATE").fg(Color::Cyan),
34 Cell::new("ADDRESS").fg(Color::Cyan),
35 Cell::new("AGENTS").fg(Color::Cyan),
36 Cell::new("UPTIME").fg(Color::Cyan),
37 ]);
38
39 for node in &self.nodes {
40 let state_color = match node.state.as_str() {
41 "Running" => Color::Green,
42 "Stopped" => Color::Red,
43 _ => Color::Yellow,
44 };
45
46 table.add_row(vec![
47 Cell::new(&node.id[..8]),
48 Cell::new(&node.role),
49 Cell::new(&node.state).fg(state_color),
50 Cell::new(&node.address),
51 Cell::new(node.agents.to_string()),
52 Cell::new(&node.uptime),
53 ]);
54 }
55
56 table
57 }
58
59 fn to_quiet(&self) -> String {
60 self.nodes
61 .iter()
62 .map(|n| n.id.clone())
63 .collect::<Vec<_>>()
64 .join("\n")
65 }
66}
67
68#[derive(Debug, Serialize)]
69pub struct MeshStatus {
70 pub state: String,
71 pub local_node: String,
72 pub connected_peers: usize,
73 pub total_agents: usize,
74 pub gossip_round: u64,
75 pub dht_entries: usize,
76}
77
78impl MultiFormatDisplay for MeshStatus {
79 fn to_table(&self) -> Table {
80 let mut table = Table::new();
81 table
82 .load_preset(UTF8_FULL)
83 .set_content_arrangement(ContentArrangement::Dynamic);
84
85 let state_color = match self.state.as_str() {
86 "Healthy" => Color::Green,
87 "Degraded" => Color::Yellow,
88 "Critical" => Color::Red,
89 _ => Color::White,
90 };
91
92 table.add_row(vec![
93 Cell::new("Status").fg(Color::Cyan),
94 Cell::new(&self.state).fg(state_color),
95 ]);
96 table.add_row(vec![
97 Cell::new("Local Node").fg(Color::Cyan),
98 Cell::new(&self.local_node),
99 ]);
100 table.add_row(vec![
101 Cell::new("Connected Peers").fg(Color::Cyan),
102 Cell::new(self.connected_peers.to_string()),
103 ]);
104 table.add_row(vec![
105 Cell::new("Total Agents").fg(Color::Cyan),
106 Cell::new(self.total_agents.to_string()),
107 ]);
108 table.add_row(vec![
109 Cell::new("Gossip Round").fg(Color::Cyan),
110 Cell::new(self.gossip_round.to_string()),
111 ]);
112 table.add_row(vec![
113 Cell::new("DHT Entries").fg(Color::Cyan),
114 Cell::new(self.dht_entries.to_string()),
115 ]);
116
117 table
118 }
119
120 fn to_quiet(&self) -> String {
121 self.state.clone()
122 }
123}