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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! Formatting and layout helpers for the unified monitor dashboard.
//!
//! Why: pure functions that format data and compute layouts can be tested
//! without a terminal backend; keeping them here makes assertions in the test
//! suite straightforward.
//! What: uptime/count formatting, thousands grouping, string truncation,
//! help text, panel layout constraints, and the status-badge mapping.
//! Test: `test_uptime_format`, `test_format_count`, `test_truncate`,
//! `test_help_text_lists_bindings`, `test_layout_wide`, `test_layout_narrow`,
//! `test_status_badge`.
use ;
use Color;
use ;
/// Format a daemon uptime in seconds as a compact `Xh Ym` string.
///
/// Why: the search panel shows uptime; raw seconds are hard to read.
/// What: returns `"{hours}h {minutes}m"`, e.g. `7440` → `"2h 4m"`. Sub-minute
/// uptimes show `"0h 0m"`.
/// Test: `test_uptime_format`.
/// Format a count with thousands separators and a `k` suffix above 10,000.
///
/// Why: large chunk and vector counts (19,400) are easier to scan abbreviated
/// (`19.4k`); small counts stay exact.
/// What: counts below 10,000 are grouped with commas (`1,200`); counts at or
/// above 10,000 are shown as `{n}k` with one decimal (`19.4k`).
/// Test: `test_format_count`.
/// Placeholder rendered in place of a count that is not known.
///
/// Why (issue #4682): an unknown count printed as `0` reads as a measurement.
/// An em dash reads as "no value", which is what it is.
/// What: the single string every count renderer uses for the unknown case.
/// Test: `test_format_opt_count`.
pub const UNKNOWN_COUNT: &str = "—";
/// Format an optional count, rendering [`UNKNOWN_COUNT`] when it is unknown.
///
/// Why (issue #4682): `GET /api/v1/palaces` returns `0` for every count of a
/// palace whose handle is not resident (`cached: false`) — the zeros mean
/// *unknown*, not *empty*. Printing them verbatim made the /ui dashboard
/// contradict itself (`0 drawers` above a "Drawers (1)" list). Funnelling every
/// count through one formatter that takes an `Option` is the guard: a caller
/// holding an `Option<u64>` cannot accidentally print `0` for "not loaded".
/// What: `Some(n)` formats exactly as [`format_count`]; `None` returns
/// [`UNKNOWN_COUNT`].
/// Test: `test_format_opt_count`.
/// Insert commas every three digits into a number.
///
/// Why: shared by [`format_count`] for the exact-count branch.
/// What: returns the decimal string of `n` with `,` group separators.
/// Test: covered via `test_format_count`.
/// Compute the layout constraints for the two daemon panels.
///
/// Why: the wide/narrow decision is the dashboard's single responsive rule;
/// isolating it as a pure function makes it directly unit-testable.
/// What: returns `(Direction, [Constraint; 2])` — `Horizontal` with two equal
/// halves when `width >= WIDE_LAYOUT_MIN_COLS`, otherwise `Vertical` with two
/// equal halves so the panels stack.
/// Test: `test_layout_wide`, `test_layout_narrow`.
/// The body text for the help overlay, one binding per line.
///
/// Why: kept separate so a test can assert every binding is documented.
/// What: returns the multi-line help string.
/// Test: `test_help_text_lists_bindings`.
/// The status badge `(glyph, label, colour)` for a panel.
///
/// Why: every panel header shows a coloured liveness badge; centralising the
/// mapping keeps the two panel renderers consistent and testable.
/// What: `● ONLINE` (green), `◌ CONNECTING` (yellow), `○ OFFLINE` (red).
/// Test: `test_status_badge`.
/// Truncate a string to `max` characters, appending an ellipsis when cut.
///
/// Why: index ids and palace names can be long; the fixed-width table columns
/// need bounded labels.
/// What: returns `s` unchanged when short enough, else its first `max - 1`
/// characters plus `…`.
/// Test: `test_truncate`.