Split the model admin into a list and a page per model
/admin/models rendered a full edit form for every model. With eight that
was merely long; with a hundred it was unusable, which is the report.
The list is now compact rows only -- avatar, name, badges, position,
reorder buttons, Edit link -- with search across id and display name,
filter tabs (All / Enabled / Disabled / Pinned / Restricted, each with a
count), a connection filter, and pagination at 40. Filters are links, so
a filtered view is a real URL you can keep. Editing moved to
/admin/models/{id}/edit, one model per page, with Previous/Next links so
a freshly imported connection can be tidied without returning to the
list each time.
Measured with 128 models: the list is 73 KB showing 40 rows over 4
pages, and a detail page is 17 KB. The old page would have rendered all
128 forms into one response.
Reordering needed rethinking at that size too. Up/down is fine for
nudging a model one place but hopeless for moving it sixty, so the
detail page has a position field you type into; the value is clamped and
a non-numeric one is ignored rather than throwing. The move buttons take
a `back` field so they return to whatever filtered, paginated view they
were pressed on instead of dumping you at page 1.
Also adds a select-all checkbox for the bulk bar, scoped to a container
selector rather than the page so a future list can carry more than one.
212 tests, ruff clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,7 @@ lembas info # paths + counts, useful when confused
|
||||
lembas secret-key # generate LEMBAS_SECRET_KEY
|
||||
lembas create-admin # create or promote an admin
|
||||
|
||||
pytest # 197 tests, ~7s
|
||||
pytest # 212 tests, ~8s
|
||||
ruff check . # lint (line length 100)
|
||||
python scripts/build_artwork.py # regenerate all SVG artwork
|
||||
python scripts/fetch_vendor.py # verify vendored JS against the lockfile
|
||||
@@ -197,6 +197,12 @@ it; `POST /api/chats/start` writes the chat together with its first message.
|
||||
That is why an opened-and-abandoned chat never appears in the sidebar. Tests
|
||||
that just need a chat use the `make_chat` fixture rather than the HTTP flow.
|
||||
|
||||
**Admin lists are list-plus-detail, never a form per row.** `/admin/models`
|
||||
renders compact rows with search, filter tabs and pagination; the full form
|
||||
lives at `/admin/models/{id}/edit`. A connection can advertise a hundred models,
|
||||
and a page that renders a form for each is unusable. Any future admin list
|
||||
(tools, agents) should follow the same shape.
|
||||
|
||||
**Route order matters for static path segments.** FastAPI matches in
|
||||
registration order, so `/admin/models/bulk` must be registered *before*
|
||||
`/admin/models/{model_id}` or "bulk" is parsed as a model id and 404s. This has
|
||||
|
||||
Reference in New Issue
Block a user