implement pagination totals info

This commit is contained in:
yggverse 2025-08-05 19:21:08 +03:00
parent 3b95561c08
commit a4ce8e29d5
5 changed files with 38 additions and 20 deletions

View file

@ -18,3 +18,4 @@ chrono = { version = "0.4.41", features = ["serde"] }
url = { version = "2.5", features = ["serde"] } url = { version = "2.5", features = ["serde"] }
urlencoding = "2.1" urlencoding = "2.1"
rocket_dyn_templates = { version = "0.2", features = ["tera"] } rocket_dyn_templates = { version = "0.2", features = ["tera"] }
plurify = "0.2"

View file

@ -36,6 +36,7 @@ fn index(
storage: &State<Storage>, storage: &State<Storage>,
meta: &State<Meta>, meta: &State<Meta>,
) -> Result<Template, Custom<String>> { ) -> Result<Template, Custom<String>> {
use plurify::Plurify;
#[derive(Serialize)] #[derive(Serialize)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
struct Row { struct Row {
@ -45,13 +46,21 @@ fn index(
size: String, size: String,
torrent: Torrent, torrent: Torrent,
} }
let rows = storage let (total, torrents) = storage
.torrents( .torrents(
Some((Sort::Modified, Order::Asc)), Some((Sort::Modified, Order::Asc)),
page.map(|p| if p > 0 { p - 1 } else { p } * storage.default_limit), page.map(|p| if p > 0 { p - 1 } else { p } * storage.default_limit),
Some(storage.default_limit), Some(storage.default_limit),
) )
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))? .map_err(|e| Custom(Status::InternalServerError, e.to_string()))?;
Ok(Template::render(
"index",
context! {
meta: meta.inner(),
back: page.map(|p| uri!(index(if p > 2 { Some(p - 1) } else { None }))),
next: if page.unwrap_or(1) * storage.default_limit >= total { None }
else { Some(uri!(index(Some(page.map_or(2, |p| p + 1))))) },
rows: torrents
.into_iter() .into_iter()
.map(|torrent| Row { .map(|torrent| Row {
created: torrent created: torrent
@ -62,15 +71,13 @@ fn index(
size: format::bytes(torrent.size), size: format::bytes(torrent.size),
torrent, torrent,
}) })
.collect::<Vec<Row>>(); .collect::<Vec<Row>>(),
Ok(Template::render( pagination_totals: format!(
"index", "Page {} / {} ({total} {} total)",
context! { page.unwrap_or(1),
meta: meta.inner(), (total as f64 / storage.default_limit as f64).ceil(),
back: page.map(|p| uri!(index(if p > 2 { Some(p - 1) } else { None }))), total.plurify(&["torrent", "torrents", "torrents"])
next: if rows.len() < storage.default_limit { None } )
else { Some(uri!(index(Some(page.map_or(2, |p| p + 1))))) },
rows
}, },
)) ))
} }
@ -85,6 +92,7 @@ fn rss(feed: &State<Feed>, storage: &State<Storage>) -> Result<RawXml<String>, C
Some(storage.default_limit), Some(storage.default_limit),
) )
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))? .map_err(|e| Custom(Status::InternalServerError, e.to_string()))?
.1
{ {
feed.push(&mut b, torrent) feed.push(&mut b, torrent)
} }

View file

@ -76,9 +76,10 @@ impl Storage {
sort_order: Option<(Sort, Order)>, sort_order: Option<(Sort, Order)>,
start: Option<usize>, start: Option<usize>,
limit: Option<usize>, limit: Option<usize>,
) -> Result<Vec<Torrent>, String> { ) -> Result<(usize, Vec<Torrent>), String> {
let f = self.files(sort_order)?; let f = self.files(sort_order)?;
let l = limit.unwrap_or(f.len()); let t = f.len();
let l = limit.unwrap_or(t);
let mut b = Vec::with_capacity(l); let mut b = Vec::with_capacity(l);
for file in f.into_iter().skip(start.unwrap_or_default()).take(l) { for file in f.into_iter().skip(start.unwrap_or_default()).take(l) {
if file if file
@ -163,7 +164,7 @@ impl Storage {
.into(), .into(),
}) })
} }
Ok(b) Ok((t, b))
} }
// Helpers // Helpers

View file

@ -27,4 +27,5 @@
{% endif %} {% endif %}
{% if next %}<a href="{{ next }}">Next</a>{% endif %} {% if next %}<a href="{{ next }}">Next</a>{% endif %}
{% if back %}<a href="{{ back }}">Back</a>{% endif %} {% if back %}<a href="{{ back }}">Back</a>{% endif %}
<span>{{ pagination_totals }}</span>
{% endblock content %} {% endblock content %}

View file

@ -107,12 +107,12 @@
padding: 24px; padding: 24px;
} }
/* description */ /* item row description */
main > div > p { main > div > p {
margin: 8px 0; margin: 8px 0;
} }
/* meta, controls */ /* item row meta, controls */
main > div > div { main > div > div {
border-top: 1px #4f536a solid; border-top: 1px #4f536a solid;
margin-top: 16px; margin-top: 16px;
@ -148,6 +148,13 @@
float: right; float: right;
vertical-align: middle; vertical-align: middle;
} }
/* pagination info */
main > span {
display: inline-block;
float: right;
padding: 8px;
}
</style> </style>
</head> </head>
<body> <body>