Skip to content

Commit 847e8bc

Browse files
committed
controllers/helpers/pagination: Generate prev_page for seek-based pagination
1 parent 193a57d commit 847e8bc

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

src/controllers/helpers/pagination.rs

+29
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,35 @@ impl<T> Paginated<T> {
277277
Ok(Some(opts))
278278
}
279279

280+
pub(crate) fn prev_seek_params<S, F>(&self, f: F) -> AppResult<Option<IndexMap<String, String>>>
281+
where
282+
F: Fn(&T) -> S,
283+
S: Serialize,
284+
{
285+
// When the data size is smaller than the page size, we would expect the prev page to be
286+
// unavailable during backward pagination but available during forward pagination.
287+
if self.options.is_explicit()
288+
|| self.records_and_total.is_empty()
289+
|| (self.records_and_total.len() < self.options.per_page as usize
290+
&& self.options.is_backward())
291+
{
292+
return Ok(None);
293+
}
294+
295+
// We also like to return None for prev page when it's the first forward pagination.
296+
let mut opts = IndexMap::new();
297+
match self.options.page {
298+
Page::Unspecified => return Ok(None),
299+
Page::Seek(ref raw) if raw.is_empty() => return Ok(None),
300+
Page::Seek(_) | Page::SeekBackward(_) => {
301+
let seek = f(&self.records_and_total.first().unwrap().record);
302+
opts.insert("seek".into(), format!("-{}", encode_seek(seek)?));
303+
}
304+
Page::Numeric(_) => unreachable!(),
305+
};
306+
Ok(Some(opts))
307+
}
308+
280309
pub(crate) fn iter(&self) -> impl Iterator<Item = &T> {
281310
self.records_and_total.iter().map(|row| &row.record)
282311
}

src/controllers/krate/search.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ pub async fn list_crates(
245245
data.total(),
246246
data.next_seek_params(|last| seek.to_payload(last))?
247247
.map(|p| req.query_with_params(p)),
248-
None,
248+
data.prev_seek_params(|first| seek.to_payload(first))?
249+
.map(|p| req.query_with_params(p)),
249250
data.into_iter().collect::<Vec<_>>(),
250251
)
251252
} else {

src/tests/routes/crates/list.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,9 @@ async fn seek_based_pagination() -> anyhow::Result<()> {
10771077
assert_eq!(resp.meta.total, 0);
10781078
}
10791079

1080-
assert_eq!(resp.meta.prev_page, None);
1080+
if calls == 1 {
1081+
assert_eq!(resp.meta.prev_page, None);
1082+
}
10811083
}
10821084

10831085
assert_eq!(calls, 4);

0 commit comments

Comments
 (0)