feat(media): pagination

This commit is contained in:
Florian Sylvain committed 2026-10-13 19:54:59 +02:00
1 parent 04dc151ed7
commit 63c1e7076e
65 files changed
+2960 -365

No files matched your search

+11 -7
View File
@@ -20,8 +20,12 @@ Feature: Media page, part 1: browse and manage
And useMedia is a composable over useApi. It exposes the list state (items, counts, loading,
error), the request functions for list, usage, rename and delete, and the copy helper, and
it maps ApiError and NetworkError to the states below
And MediaPage calls GET /v1/media/ with the query built from the URL, always with limit=100,
and every request carries the jwt cookie through useApi
And MediaPage calls GET /v1/media/ with the query built from the URL, always with an explicit
page and size (page=1&size=25 by default, or the stored size), and every request carries
the jwt cookie through useApi
And this slice is amended by features/media_pagination_api.feature and
features/media_pagination_screen.feature: limit=100 and next_cursor are gone, the body is
{ items, total, page, size, counts }, and the list is paginated
And search, tab, sort and view live in the URL query string so the view can be linked and
survives a reload: ?q= (search text), ?filter= ("unused" or "duplicates"; absent means
All), ?sort= ("oldest", "name" or "largest"; absent means Newest), ?view= ("list"; absent
@@ -90,10 +94,10 @@ Feature: Media page, part 1: browse and manage
| 10 | bathroom-tiles.png | 860 KB | 1800 × 1200 | PNG | 0 | Marta Alves | 4 Aug 2026 | alpha |
| 11 | lime-plaster.jpg | 2.1 MB | 3200 × 2133 | JPEG | 2 | Inès Duarte | 19 Jul 2026 | |
| 12 | floorboards.jpg | 2.4 MB | 3600 × 2400 | JPEG | 4 | Inès Duarte | 14 Jun 2026 | duplicate |
with counts { all: 12, unused: 2, duplicates: 2 }, and next_cursor null
with counts { all: 12, unused: 2, duplicates: 2 }, total 12, page 1, size 25
Scenario: Default, many images
Given GET /v1/media/?filter=all&sort=newest&limit=100 resolves 200 with the 12-image fixture
Given GET /v1/media/?filter=all&sort=newest&page=1&size=25 resolves 200 with the 12-image fixture
When the user navigates to /media
Then the breadcrumb reads "Media" (mobile title "Media")
And the tabs read "All 12", "Unused 2", "Duplicates 2", with "All" selected, and the
@@ -144,7 +148,7 @@ Feature: Media page, part 1: browse and manage
Scenario Outline: The query string is the source of truth for search, tab, sort and view
Given GET /v1/media/ is mocked
When the user opens /media<url>
Then GET /v1/media/ is sent with "<request>" and limit=100
Then GET /v1/media/ is sent with "<request>" and page=1&size=25
And the control shows "<control>"
Examples:
@@ -161,7 +165,7 @@ Feature: Media page, part 1: browse and manage
Scenario: Changing a control writes the query string and reloads the list
Given the Default state has loaded
When the user types "wall" in the search field
Then after a 120 ms debounce the URL gains ?q=wall and GET /v1/media/?q=wall&filter=all&sort=newest&limit=100 is sent
Then after a 120 ms debounce the URL gains ?q=wall and GET /v1/media/?q=wall&filter=all&sort=newest&page=1&size=25 is sent
When the user selects the "Unused" tab
Then the URL reads ?q=wall&filter=unused and the list is requested again
When the user picks "Largest" in the sort menu
@@ -187,7 +191,7 @@ Feature: Media page, part 1: browse and manage
Scenario: No results, search and filter
Given the Default state has loaded
When the user selects "Unused" and types "wall" and GET /v1/media/?q=wall&filter=unused&sort=newest&limit=100 resolves 200 with zero items
When the user selects "Unused" and types "wall" and GET /v1/media/?q=wall&filter=unused&sort=newest&page=1&size=25 resolves 200 with zero items
Then a panel replaces the images with the search icon, title `No images match "wall"`, text "Nothing matches in Unused. Check the spelling, or clear the filters." and an outline "Clear filters" button
When the user activates "Clear filters"
Then the search field is emptied, the tab returns to "All", ?q and ?filter leave the URL, and the Default cards reappear