feat(labs): let a person order the lab categories (#1349)

The labs list layout gains categoryOrder, a bounded allow-list of
category keys (200 entries, 64 characters each, deduplicated, malformed
values dropped on read). GET /api/labs/overview reads the caller's own
layout and answers categories already in that order, so every client
renders them as given. Listed categories come first; keys the data does
not have are ignored; a category the order does not name follows in
the default order (catalog panels, then the person's own by label, then
other). Other left at the end of the order stays last, behind any
category added later; moved anywhere else, it stays there.

Settings > Arrangement > Labs shows a category order card while
categories are on. It lists the overview's categories under their
localised labels, sends the whole order after every move, moves the
cached overview at once and refetches it. The card says how the default
order works. The OpenAPI document carries the new field.
This commit is contained in:
Marc-André Bombeck committed 2026-11-10 18:57:48 +01:00
1 parent 157809c24f
commit 928ade5109
28 files changed
+660 -34

No files matched your search

+21 -2
View File
@@ -34362,6 +34362,13 @@ components:
- expanded
- flagged
- collapsed
categoryOrder:
maxItems: 200
type: array
items:
type: string
minLength: 1
maxLength: 64
required:
- version
- list
@@ -75520,6 +75527,15 @@ components:
- collapsed
description: 'Which labs categories start open: every one (`expanded`), only those whose `status` is `above` or `below`
(`flagged`), or none (`collapsed`). Default "expanded". The other lists ignore it.'
categoryOrder:
type: array
items:
type: string
description: The person's order of the labs categories, as `categories[].key` values of `GET /api/labs/overview`. The
server applies it there, so a client renders `categories` as given and never sorts them itself. Keys missing
from the live data are ignored; a category missing from the list follows the listed ones in the default
order, and "other" left at the end of the list stays last. Default empty (the default order). The other
lists ignore it.
saved:
type: boolean
description: True when the server holds a choice for this list; false means every field is a default.
@@ -75529,6 +75545,7 @@ components:
- sortDir
- groupBy
- groupsOpen
- categoryOrder
- saved
additionalProperties: false
ModuleListLayoutSavedEnvelope:
@@ -77121,8 +77138,10 @@ components:
type: array
items:
$ref: "#/components/schemas/LabOverviewCategory"
description: "The list's categories in display order: catalog panels in catalog order, then the person's own panels by
label, then `other`."
description: "The list's categories in display order, already arranged for the caller: the default order is catalog
panels in catalog order, then the person's own panels by label, then `other`, and the caller's
`categoryOrder` (`PUT /api/settings/module-list-layout`, labs list) is applied over it. Render them in this
order."
grouped:
type: boolean
description: "Whether grouping adds anything: true when there are two categories or more and at least one is not