feat(media): pagination
This commit is contained in:
1 parent
04dc151ed7
commit
63c1e7076e
65 files changed
+2960
-365
No files matched your search
@@ -205,7 +205,7 @@ class Component extends DCLogic {
|
||||
withM({ ...L({ modal: del(false, 'Couldn\'t delete the article, so it\'s still there. Try again in a moment.') }), name: 'Delete: failed', trigger: '500, a partial failure where the article is kept. The error shows inside the dialog.' }),
|
||||
withM({ ...L({ list: { counts: [5, 4, 1], rows: rows().filter((r, i) => i !== 3) }, toasts: [T('success', 'circle-check', 'Article deleted', '"Winter checklist for timber windows" and its images are gone.')] }), name: 'Deleted', trigger: '204: the row is removed and focus moves to the next row. This is also where a delete from the editor ends up.' })
|
||||
] },
|
||||
{ label: 'Articles: pagination', title: 'Articles: pagination', route: '/articles?page=2&size=50', api: 'GET /v1/article/?page=&size=&q=&status= (proposed: needs backend page, size, total in the response)', note: 'Page and page size live in the URL as page and size. Defaults (page 1, size 25) are omitted. Allowed sizes 5, 25, 50, 100. Search, tab or sort changes reset to page 1. Rows equal the page size; the frames draw at most 10 rows. The paginator hides when everything fits on one page; the summary stays. Mobile shows Previous, "Page N of M" and Next. Keyboard: Tab reaches page size, first, previous, each page, next, last; Enter or Space activates; the current page has aria-current="page"; ArrowDown opens the page-size list, Enter selects, Esc closes.', states: [
|
||||
{ label: 'Articles: pagination', title: 'Articles: pagination', route: '/articles?page=2&size=50', api: 'GET /v1/article/?page=&size=&q=&status= (page, size; total in the X-Total-Count header; invalid values are normalised in the URL, never shown as an error)', note: 'Page and page size live in the URL as page and size. Defaults (page 1, size 25) are omitted. Allowed sizes 5, 25, 50, 100. Search, tab or sort changes reset to page 1. Rows equal the page size; the frames draw at most 10 rows. The paginator hides when everything fits on one page; the summary stays. Mobile shows Previous, "Page N of M" and Next. Keyboard: Tab reaches page size, first, previous, each page, next, last; Enter or Space activates; the current page has aria-current="page"; ArrowDown opens the page-size list, Enter selects, Esc closes.', states: [
|
||||
withM({ ...PG({ page: 1 }), name: 'First page', trigger: '/articles. Previous and First are disabled. Summary "Showing 1–25 of 312".' }),
|
||||
withM({ ...PG({ page: 7 }), name: 'Middle page', trigger: '/articles?page=7. Current page uses --rc-sand and --rc-on-sand; ellipses mark skipped ranges.' }),
|
||||
withM({ ...PG({ page: 13 }), name: 'Last page', trigger: '/articles?page=13. Next and Last are disabled. Summary "Showing 301–312 of 312".' }),
|
||||
@@ -269,7 +269,16 @@ class Component extends DCLogic {
|
||||
E({ notfound: true }, { name: 'Not found (404)', trigger: 'Unknown id, or the article was deleted elsewhere.' })
|
||||
] },
|
||||
{ label: 'Media', title: 'Media', route: '/media', api: 'GET /v1/media/ · POST /v1/media/ · PATCH /v1/media/{id} · DELETE /v1/media/{id} · POST /v1/media/merge · GET /v1/media/{id}/usage', note: 'New route for verified users, in the sidebar between Articles and Users with the images icon. Images belong to the library, not to an article: one image can be used in many articles, and deleting an article never deletes images. Uploads from this page are not cropped or resized, and the file is stored as chosen. "Used in" is read from article bodies each time the list loads. Duplicates are images with identical content, whatever their filenames. Alt text is not stored on the image; it is set when inserting into an article. Search, filter, sort and view are stored in the query string. Keyboard: grid items are buttons in one tab stop each; Enter opens the detail panel, Space toggles selection, and Escape closes the panel or clears the selection. Selection changes are announced ("north-wall.jpg selected, 1 selected").', states: [
|
||||
Mp({ name: 'Grid, many images', trigger: 'Default view. 12 images, newest first. Each item is a button labelled like "north-wall.jpg, 3.9 MB, used in 2 articles". Badges: "Unused" (warm), "Duplicate" (info), "Used in N" (outline). The Duplicates tab carries a count of groups only while duplicates exist.' }),
|
||||
Mp({ name: 'Grid, many images', trigger: 'Default view. 12 images, newest first. Each item is a button labelled like "north-wall.jpg, 3.9 MB, used in 2 articles". Badges: "Unused" (warm), "Duplicate" (info), "Used in N" (outline). The Duplicates tab carries a count of groups only while duplicates exist. Below the grid: "Showing 1–12 of 12" and the page-size select (same paginator as Articles).' }),
|
||||
Mp({ pg: { page: 1, total: 312 }, name: 'Pagination: first page', trigger: '/media. Previous and First are disabled. Summary "Showing 1–25 of 312". The paginator sits under the grid or list and uses the Articles controls: 5, 25, 50 or 100 per page, default 25; page and size live in the URL as page and size (/media?page=7&size=50); search, tab, sort, view and size changes reset to page 1. API: GET /v1/media/?page=&size=&q=&filter= with the total in X-Total-Count.' }),
|
||||
Mp({ pg: { page: 7, total: 312 }, name: 'Pagination: middle page', trigger: '/media?page=7. Current page uses --rc-sand and --rc-on-sand; ellipses mark skipped ranges.' }),
|
||||
Mp({ pg: { page: 13, total: 312 }, name: 'Pagination: last page', trigger: '/media?page=13. Next and Last are disabled. Summary "Showing 301–312 of 312".' }),
|
||||
Mp({ view: 'list', pg: { page: 2, total: 312 }, name: 'Pagination: list view', trigger: 'Same paginator under the table. On mobile: Previous, "Page 2 of 13", Next, with the 44 px targets.' }),
|
||||
Mp({ loading: true, pg: { page: 6, total: 312, loading: 7 }, name: 'Pagination: loading next page', trigger: 'Next was pressed. Skeleton cards keep the grid height, controls are disabled, summary reads "Loading page 7…".' }),
|
||||
Mp({ pg: { page: 6, total: 312, err: 'Couldn\'t load page 7. Showing page 6.' }, name: 'Pagination: error loading a page', trigger: '500 or network failure on page change. Previous images stay; Retry sits in the notice.' }),
|
||||
Mp({ pg: { page: 13, total: 312, note: 'That page doesn\'t exist. Showing the last page.' }, name: 'Pagination: page out of range', trigger: '/media?page=99 is replaced with ?page=13 and this notice is shown.' }),
|
||||
Mp({ pg: { page: 1, total: 312, sizeOpen: true }, name: 'Pagination: page size menu', trigger: 'The select opens upward. 5, 25, 50 or 100; the chosen size is saved as size and the page resets to 1.' }),
|
||||
Mp({ pg: { page: 7, total: 312, focus: 'next' }, name: 'Pagination: focus-visible', trigger: 'Keyboard focus on Next: 2 px --ui-primary outline, 2 px offset. Same ring on every paginator control.' }),
|
||||
Mp({ ids: [1, 4, 8], name: 'Grid, few images', trigger: 'Three images. Cards keep their size instead of stretching. Checkerboard shows behind the SVG.' }),
|
||||
Mp({ view: 'list', name: 'List view', trigger: 'The list icon in the toggle. A table from md up (Filename, Dimensions, Size, Type, Used in, Uploaded by, Uploaded) and a card list below md. The "Used in" count opens the article list in the detail panel.' }),
|
||||
Mp({ loading: true, name: 'Loading', trigger: 'The first load, a retry, or a change of search or filter. Skeleton cards appear after 150 ms.' }),
|
||||
|
||||
Reference in new issue
Block a user