Skip to content

Commit 678a8dc

Browse files
committed
Pagination for user table, ts list and random style fixes
1 parent 80630cf commit 678a8dc

File tree

11 files changed

+223
-126
lines changed

11 files changed

+223
-126
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
@@ -306,6 +306,27 @@ pub async fn logs(
306306
.await
307307
}
308308

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

@@ -58,6 +59,13 @@ struct DisplayLogRow {
5859
raw_sample: Value,
5960
}
6061

62+
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
63+
#[serde(rename_all = "snake_case")]
64+
pub enum DisplayLogRowSort {
65+
#[default]
66+
CreatedAt,
67+
}
68+
6169
#[derive(Template)]
6270
#[template(path = "management/time_source_details.html.j2")]
6371
struct TimeSourceInfoTemplate {
@@ -68,6 +76,7 @@ struct TimeSourceInfoTemplate {
6876
monitors: Vec<String>,
6977
cur_monitor: Option<MonitorId>,
7078
cur_protocol: IpVersion,
79+
pagination: PaginationInfo<DisplayLogRowSort>,
7180
}
7281

7382
#[derive(Deserialize)]
@@ -123,6 +132,7 @@ pub async fn time_source_info(
123132
app: AppContext,
124133
State(state): State<AppState>,
125134
Query(log_choice): Query<LogSelection>,
135+
pagination: Pagination<DisplayLogRowSort>,
126136
) -> Result<impl IntoResponse, AppError> {
127137
let ts = time_source::details(&state.db, time_source_id).await?;
128138
let scores = time_source::scores(&state.db, time_source_id).await?;
@@ -136,10 +146,27 @@ pub async fn time_source_info(
136146
}
137147
}
138148
let monitors: Vec<String> = scoremap.iter().map(|v| v.0.clone()).collect();
139-
let logs = if let Some(cur_monitor) = cur_monitor {
140-
time_source::logs(&state.db, time_source_id, cur_monitor, cur_protocol, 0, 200).await?
149+
150+
let (pagination, logs) = if let Some(cur_monitor) = cur_monitor {
151+
let total_items =
152+
time_source::log_count(&state.db, time_source_id, cur_monitor, cur_protocol).await?
153+
as u64;
154+
let pagination = pagination.set_total(total_items);
155+
(
156+
pagination.clone(),
157+
time_source::logs(
158+
&state.db,
159+
time_source_id,
160+
cur_monitor,
161+
cur_protocol,
162+
pagination.offset(),
163+
pagination.limit(),
164+
)
165+
.await?,
166+
)
141167
} else {
142-
vec![]
168+
let pagination = pagination.set_total(0);
169+
(pagination, vec![])
143170
};
144171

145172
Ok(HtmlTemplate(TimeSourceInfoTemplate {
@@ -185,6 +212,7 @@ pub async fn time_source_info(
185212
monitors,
186213
cur_monitor,
187214
cur_protocol,
215+
pagination,
188216
}))
189217
}
190218

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)