1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::collections::BTreeMap;
use std::time::Duration;
use fedimint_core::PeerId;
use fedimint_server_core::dashboard_ui::{ConnectionType, P2PConnectionStatus};
use maud::{Markup, html};
pub fn render(
consensus_ord_latency: Option<Duration>,
p2p_connection_status: &BTreeMap<PeerId, Option<P2PConnectionStatus>>,
) -> Markup {
html! {
div class="card h-100" id="consensus-latency" {
div class="card-header dashboard-header" { "System Latency" }
div class="card-body" {
@if let Some(duration) = consensus_ord_latency {
div class=(format!("alert {}", if duration.as_millis() < 1000 {
"alert-success"
} else if duration.as_millis() < 2000 {
"alert-warning"
} else {
"alert-danger"
})) {
"Consensus Latency: " strong {
(format!("{} ms", duration.as_millis()))
}
}
}
@if p2p_connection_status.is_empty() {
p { "No peer connections available." }
} @else {
table class="table table-striped" {
thead {
tr {
th { "ID" }
th { "Status" }
th { "Connection Type" }
th { "Round Trip" }
}
}
tbody {
@for (peer_id, status) in p2p_connection_status {
tr {
td { (peer_id.to_string()) }
td {
@match status {
Some(_) => {
span class="badge bg-success" { "Connected" }
}
None => {
span class="badge bg-danger" { "Disconnected" }
}
}
}
td {
@match status.as_ref().and_then(|s| s.conn_type) {
Some(ConnectionType::Direct) => {
span class="badge bg-success" { "Direct" }
}
Some(ConnectionType::Relay) => {
span class="badge bg-warning" { "Relay" }
}
Some(ConnectionType::Mixed) => {
span class="badge bg-info" { "Mixed" }
}
None => {
span class="text-muted" { "N/A" }
}
}
}
td {
@match status.as_ref().and_then(|s| s.rtt) {
Some(duration) => {
(format!("{} ms", duration.as_millis()))
}
None => {
span class="text-muted" { "N/A" }
}
}
}
}
}
}
}
}
}
}
}
}