Skip to content

Commit cb6c1e4

Browse files
committed
Pagination for user table, ts list and random style fixes
1 parent a7dad52 commit cb6c1e4

File tree

11 files changed

+229
-132
lines changed

11 files changed

+229
-132
lines changed

nts-pool-management/assets/components.css

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ a.btn {
3838
}
3939

4040
.btn-alt:hover {
41-
color: color-mix(in lab, var(--primary), var(--black) 30%);
41+
color: color-mix(in lab, var(--primary), var(--black) 30%) !important;
4242
}
4343

4444
.btn-link,
@@ -53,7 +53,7 @@ a.btn {
5353

5454
.btn-sm {
5555
max-width: fit-content;
56-
padding: var(--space-xs) var(--space-sm);
56+
padding: 0 var(--space-sm);
5757
}
5858

5959
highlight-actions {
@@ -95,43 +95,16 @@ input[type="password"].error {
9595
background-color: var(--white);
9696
}
9797

98-
nav.pagination {
99-
margin: var(--space-md) 0;
100-
a.btn, button {
101-
color: var(--secondary);
102-
background-color: inherit;
103-
padding: 0 var(--space-sm);
104-
border: inherit;
105-
}
106-
107-
[aria-disabled] {
108-
color: var(--grey);
109-
}
110-
111-
[aria-disabled]:hover {
112-
color: var(--grey);
113-
cursor: inherit;
114-
}
115-
116-
[aria-current="page"] {
117-
text-decoration: underline;
118-
}
119-
120-
a.btn:hover, button:hover {
121-
border: inherit;
122-
color: var(--primary);
123-
}
124-
}
125-
12698
#accept-terms + span {
12799
font-weight: normal;
128100
}
129101

130102
h1 {
131-
font-size: 2.25rem;
103+
font-size: 2.25rem;
132104
}
133105

134106
h2 {
107+
margin-top: var(--space-md);
135108
margin-bottom: var(--space-sm);
136109
}
137110

@@ -140,6 +113,7 @@ h3 {
140113
}
141114

142115
section > p {
116+
font-size: 18px;
143117
margin-bottom: var(--space-sm);
144118
}
145119

@@ -163,7 +137,7 @@ code-block {
163137
display: block;
164138
width: 100%;
165139
margin: var(--space-sm) 0;
166-
padding: var(--space-xs) var(--space-xs);
140+
padding: var(--space-sm) var(--space-md);
167141
}
168142

169143
.key {
@@ -243,12 +217,12 @@ details.confirmation-btn > div {
243217

244218
@keyframes animateDown {
245219
0% {
246-
opacity: 0;
247-
transform: translatey(-15px);
220+
opacity: 0;
221+
transform: translatey(-15px);
248222
}
249223
100% {
250-
opacity: 1;
251-
transform: translatey(0);
224+
opacity: 1;
225+
transform: translatey(0);
252226
}
253227
}
254228

@@ -291,6 +265,7 @@ dialog .dialog-actions {
291265

292266
details.toast > summary,
293267
aside {
268+
font-weight: bold;
294269
padding: var(--space-sm) var(--space-md);
295270
border-width: var(--border-width);
296271
border-style: solid;
@@ -316,19 +291,19 @@ table {
316291

317292
th,
318293
td {
319-
width: 100%;
320294
white-space: nowrap;
321295
padding: var(--space-sm);
322296
}
323-
297+
324298
tbody {
325-
tr:nth-child(odd) {
326-
background-color: var(--white);
299+
tr {
300+
border-bottom: 1px solid var(--grey);
327301
}
328302
}
329303

330-
.actions {
331-
text-align: right;
304+
305+
td.actions {
306+
float: right;
332307
display: flex;
333308
gap: var(--space-xs);
334309
white-space: nowrap;
@@ -337,16 +312,20 @@ table {
337312

338313
table.birowed {
339314
tbody {
340-
tr:nth-child(4n + 1),
315+
tr:nth-child(4n + 2),
341316
tr:nth-child(4n + 4) {
342-
background-color: var(--white);
317+
border: none;
343318
}
344319

345-
tr:nth-child(4n + 2),
320+
tr:nth-child(4n + 1),
346321
tr:nth-child(4n + 3) {
347-
background-color: transparent;
348322
}
349323
}
324+
325+
details {
326+
cursor: pointer;
327+
user-select: none;
328+
}
350329
}
351330

352331
table.autowidth {
@@ -358,6 +337,43 @@ table.autowidth {
358337
}
359338
}
360339

340+
.table-controls {
341+
display: flex;
342+
gap: var(--space-md);
343+
margin-top: var(--space-sm);
344+
justify-content: space-between;
345+
padding: 0 var(--space-sm);
346+
347+
.pagination {
348+
a.btn, button {
349+
color: var(--secondary);
350+
background-color: inherit;
351+
padding: 0 var(--space-sm);
352+
border: inherit;
353+
}
354+
}
355+
356+
[aria-disabled] {
357+
color: var(--grey);
358+
}
359+
360+
[aria-disabled]:hover {
361+
color: var(--grey);
362+
cursor: inherit;
363+
}
364+
365+
[aria-current="page"] {
366+
text-decoration: underline;
367+
}
368+
}
369+
370+
.table-filter {
371+
margin: var(--space-sm) 0;
372+
display: flex;
373+
gap: var(--space-sm);
374+
align-items: baseline;
375+
}
376+
361377
.multivalue-box {
362378
display: flex;
363379
width: fit-content;

nts-pool-management/assets/variables.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
--success: #74ce42;
1616
--info: #99b6d5;
1717
--link: #0a57f0;
18+
--text-color-body: #333;
1819

1920
--muted: var(--grey);
2021

nts-pool-management/src/models/time_source.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,27 @@ pub async fn logs(
308308
.await
309309
}
310310

311+
pub async fn log_count(
312+
conn: impl DbConnLike<'_>,
313+
time_source_id: TimeSourceId,
314+
monitor_id: MonitorId,
315+
protocol: IpVersion,
316+
) -> Result<i64, sqlx::Error> {
317+
Ok(sqlx::query!(
318+
r#"
319+
SELECT COUNT(*) as "count!"
320+
FROM monitor_samples
321+
WHERE time_source_id = $1 AND protocol = $2 AND monitor_id = $3
322+
"#,
323+
time_source_id as _,
324+
protocol as _,
325+
monitor_id as _,
326+
)
327+
.fetch_one(conn)
328+
.await?
329+
.count)
330+
}
331+
311332
pub async fn source_name(
312333
conn: impl DbConnLike<'_>,
313334
owner: UserId,

nts-pool-management/src/pagination/info.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct PaginationInfo<S> {
1212
pub has_prev: bool,
1313
pub has_next: bool,
1414
pub total_pages: u32,
15+
pub total_items: u64,
1516
/// Pre-computed markup-friendly page links (numbers and ellipses).
1617
pub links: Vec<PageLink>,
1718

@@ -33,6 +34,10 @@ where
3334
((self.page - 1) as i64) * self.per_page as i64
3435
}
3536

37+
pub fn total_items(&self) -> u64 {
38+
self.total_items
39+
}
40+
3641
/// Generate a URL query string for the given page and per-page values.
3742
pub fn url(&self, page: u32, per_page: u32) -> String {
3843
Pagination {
@@ -112,6 +117,7 @@ where
112117
has_prev,
113118
has_next,
114119
total_pages,
120+
total_items,
115121
links: build_links(page, total_pages),
116122
sort: pagination.sort,
117123
order: pagination.order,

nts-pool-management/src/pagination/pagination.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fn is_default_page(page: &u32) -> bool {
5858

5959
/// Default page size when unspecified.
6060
const fn default_per_page() -> u32 {
61-
500
61+
100
6262
}
6363

6464
fn is_default_per_page(per_page: &u32) -> bool {

nts-pool-management/src/routes/management.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use axum::{
88
};
99
use chrono::{DateTime, Utc};
1010
use nts_pool_shared::IpVersion;
11-
use serde::Deserialize;
11+
use serde::{Deserialize, Serialize};
1212
use serde_json::Value;
1313

1414
use crate::{
@@ -21,6 +21,7 @@ use crate::{
2121
monitor::MonitorId,
2222
time_source::{self, NewTimeSourceForm, TimeSource, TimeSourceId, UpdateTimeSourceForm},
2323
},
24+
pagination::{Pagination, PaginationInfo},
2425
templates::{HtmlTemplate, filters},
2526
};
2627

@@ -60,6 +61,13 @@ struct DisplayLogRow {
6061
raw_sample: Value,
6162
}
6263

64+
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
65+
#[serde(rename_all = "snake_case")]
66+
pub enum DisplayLogRowSort {
67+
#[default]
68+
CreatedAt,
69+
}
70+
6371
#[derive(Template)]
6472
#[template(path = "management/time_source_details.html.j2")]
6573
struct TimeSourceInfoTemplate {
@@ -70,6 +78,7 @@ struct TimeSourceInfoTemplate {
7078
monitors: Vec<String>,
7179
cur_monitor: Option<MonitorId>,
7280
cur_protocol: IpVersion,
81+
pagination: PaginationInfo<DisplayLogRowSort>,
7382
}
7483

7584
#[derive(Deserialize)]
@@ -125,6 +134,7 @@ pub async fn time_source_info(
125134
app: AppContext,
126135
State(state): State<AppState>,
127136
Query(log_choice): Query<LogSelection>,
137+
pagination: Pagination<DisplayLogRowSort>,
128138
) -> Result<impl IntoResponse, AppError> {
129139
#[derive(Default)]
130140
struct Scores {
@@ -152,10 +162,27 @@ pub async fn time_source_info(
152162
}
153163
}
154164
let monitors: Vec<String> = scoremap.iter().map(|v| v.0.clone()).collect();
155-
let logs = if let Some(cur_monitor) = cur_monitor {
156-
time_source::logs(&state.db, time_source_id, cur_monitor, cur_protocol, 0, 200).await?
165+
166+
let (pagination, logs) = if let Some(cur_monitor) = cur_monitor {
167+
let total_items =
168+
time_source::log_count(&state.db, time_source_id, cur_monitor, cur_protocol).await?
169+
as u64;
170+
let pagination = pagination.set_total(total_items);
171+
(
172+
pagination.clone(),
173+
time_source::logs(
174+
&state.db,
175+
time_source_id,
176+
cur_monitor,
177+
cur_protocol,
178+
pagination.offset(),
179+
pagination.limit(),
180+
)
181+
.await?,
182+
)
157183
} else {
158-
vec![]
184+
let pagination = pagination.set_total(0);
185+
(pagination, vec![])
159186
};
160187

161188
Ok(HtmlTemplate(TimeSourceInfoTemplate {
@@ -203,6 +230,7 @@ pub async fn time_source_info(
203230
monitors,
204231
cur_monitor,
205232
cur_protocol,
233+
pagination,
206234
}))
207235
}
208236

nts-pool-management/templates/admin/monitor_key.html.j2

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
Monitor key created succesfully. <strong>The key will only be showed once.</strong>
88
</aside>
99
<section>
10+
<h2>{{ name }}</h2>
1011
<dl>
11-
<dd>Monitor name:</dd>
12-
<dt>{{ name }}</dt>
1312
<dd>Key:</dd>
1413
<dt><code class="key">{{ key }}</code></dt>
1514
</dl>

0 commit comments

Comments
 (0)