Commit Graph

10 Commits

Author SHA1 Message Date
cd25af0878 fix(admin): scope remembered list state to the signed-in admin and recover from bad restored queries
- Store list queries under summer-admin.list:<admin id>:<controller>; me()
  and setCurrentUser set the owner, which removes other admins' keys and
  the unscoped keys of older builds; nothing is read or written without one
- clearUser removes every stored query, so logout, session expiry and an
  unrecoverable 401 (expireSession, now used by main.ts) all clear them
- A list request built from a restored query that fails for any reason
  (422, 500, network) forgets the query and loads the plain list once
- A failing URL query keeps the error and offers a reset button
  (backend::lang.list.reset_list, en and pl)
- Document remembered list state in docs/backend/lists-and-filters.md
- Rebuild modules/boardwalk/dist
2026-10-09 23:53:19 +02:00
9cac45c389 fix(admin): keep list state in the URL and browser storage
- listState.ts stores each list's query (search, sort, dir, page, per_page,
  filter[name]) under summer-admin.list:<controller>; an empty query is
  never stored, malformed stored values are dropped like a hand-edited URL
- ListView restores the stored query into the URL before its first list
  request when entered without list params; a URL with list params wins
- a 422 forgets the stored query; an out-of-range page clamps to last_page
- logout clears every stored list query
- check-phase10.sh allows browser storage in useSidebar.ts and listState.ts
- list smoke tests start from a clean list state
- rebuilt modules/boardwalk/dist
2026-10-09 21:04:00 +02:00
Jakub Zych
61d5fc72ad feat(12.1-01): list row states from one controller call per page
- pact.ListRowStates with the fixed RowState set deleted, negative, disabled
- list response meta.row_states keyed by row id; unknown values dropped
- list messages rowStateDeleted, rowStateNegative, rowStateDisabled
- update writes through the scope the load used, so a soft-deleted record
  a controller includes stays soft-deleted
- DataTable row state badges and text styles
- roster fixture, smoke tests, OpenAPI, TS types, dist, READMEs, docs
2026-10-04 23:45:44 +02:00
Jakub Zych
a879d6388c feat(12.1-01): declared bulk actions on admin lists
- pact.HasAdminBulkActions with AdminBulkAction, its input and result
- config_list.yaml bulkActions, compiled fail-loud, needs showCheckboxes
- POST .../{controller}/bulk/{action}: ids resolved and locked through the
  list scope in one transaction; partial selection is 409
- list schema offers declared actions per principal, with confirm text
- admin SPA bulk actions menu with confirm, busy state and failure toasts
- acme.roster fixture, tracer test, OpenAPI, TS types, dist, READMEs, docs
2026-10-04 23:28:30 +02:00
Jakub Zych
a5e7dac10f feat(10.1-02): run registered toolbar actions and scope plugin CSS per controller
- ListToolbar renders server-filtered actions after delete as outline buttons, busy during their POST
- ListView posts {} to toolbar/{action}, toasts, reloads the list and refetches the header partial
- Lists load controller assets too, so other controllers' stylesheet links are disabled on every open
- Vite dev server proxies {prefix}/assets to summer serve; dist rebuilt
2026-09-29 02:13:26 +02:00
Jakub Zych
9df9fae930 feat(10.1-02): render header and form partials through an allowlisted node renderer
- partialNodes rebuilds the server node tree with h() under the server's tag, attribute and URL lists
- PartialHost owns the skeleton, empty and failure states and keeps nodes visible on refetch
- type: partial is a valueless group-labelled field rendered on create and update
- ListView shows headerPartial above the list card and refetches it after bulk delete
- summer-partial and summer-stats style kit in main.css, documented in the cabana README; dist rebuilt
2026-09-29 02:10:18 +02:00
Jakub Zych
1c2a66df45 test(10-05): bring every SPA module, composable and component under Vitest
- 41 unit and component suites under admin/tests/{app,state,shell,list,form,relation,views,ui}
  covering states and a11y roles; every src module is imported by a test
- typed fixture helper assigns each JSON fixture to its generated OpenAPI type
- fix: iconFor ignores inherited object members such as "constructor"
- fix: field controls import ./control instead of the registry (import cycle
  left a renderer unregistered depending on module load order)
- fix: dropdown shows the placeholder for an unknown stored value next to an emptyOption
- fix: list announces a failed schema load even when the rows arrive after it
- tailwind no longer scans admin/tests; boardwalk/dist rebuilt
2026-09-27 17:53:57 +02:00
Jakub Zych
8b5f85603f feat(10-03): search, sort, filter, page and bulk-delete any list
- List state (search, sort, dir, page, per_page, filter[<name>]) lives in
  the URL query through parseListQuery/toListQuery; every change is a
  router replace and clears the selection; search is debounced 300 ms and
  resets the page
- DataTable renders the schema columns with a tri-state page checkbox,
  asc/desc/none sorting with aria-sort, selected rows, a sticky header,
  eight skeleton rows while loading and an empty slot
- CellValue renders text (muted dash when empty, arrays comma-joined),
  datetime as YYYY-MM-DD HH:mm and switch as the Tak/Nie pills
- The heading shows the plural recordCount and the create button;
  delete sits in the toolbar, disabled without a selection, and confirms
  with the plural deleteConfirm in a Reka alert dialog before POSTing
  bulk-delete; a 409 shows a danger toast
- FilterBar renders switch (JSON of the option value), daterange
  (from..to) and scope filters (choices from filters/{scope}/options)
- Pagination shows the range, the per-page select over perPageOptions
  (hidden with one choice) and a pager with ellipsis
- The tracer smoke test skips the new checkbox column; new backend::lang
  list keys; boardwalk/dist rebuilt
2026-09-27 16:51:00 +02:00
Jakub Zych
126ca5b8ed feat(10-03): open, edit and save a record with toast and 422 feedback
- The SPA loads the backend::lang bundle before /auth/me, sets the
  document language from meta.locale and renders plural messages with
  Intl.PluralRules; interpolate mirrors phrasebook for :name/:Name/:NAME
- Create and record routes; mapWinterUrl maps recordUrl and redirects
  onto the controller's list, create and record routes only
- List rows open their record; FormView loads the form schema and the
  record, shows context-allowed fields in the span grid, saves values
  keyed by field name and toasts the resolved saved message
- A 422 puts each message under its field (aria-invalid,
  aria-describedby), shows the plural banner, focuses the first invalid
  field in schema order and clears a field's error on change
- The D-05 registry maps text, textarea, number and dropdown; any other
  type renders the unsupported-field box with the type in DM Mono
- The admin OpenAPI document declares the write request bodies
  (AdminRecord, AdminIDsRequest) and the list filter query as a
  deepObject, so the typed client can send them
- New backend::lang form.load_failed key; boardwalk/dist rebuilt
2026-09-27 16:43:47 +02:00
Jakub Zych
5f9353841b feat(10-01): serve the embedded admin SPA at backend.uri with cookie login
- backend.uri prefix (default /backend) mounts the admin API at {prefix}/api/v1
  and the embedded SPA shell at {prefix} with an api/ JSON 404 fallback
- cookie transport: an X-Requested-With login sets the HttpOnly summer_admin
  cookie and returns no token; the backend guard reads the cookie after Bearer
- CSRF wrapper refuses cookie-only POST/PUT/DELETE without X-Requested-With
- boardwalk package embeds boardwalk/dist, rewrites index.html once per prefix
  and sets cache and security headers
- framework admin OpenAPI pipeline (swag, swagger2openapi, openapi-typescript)
  with prefix-relative paths and typed envelopes for the tracer routes
- admin/ Vite SPA: login, plugin rail, section panel and read-only list
  through the openapi-fetch client typed by the generated schema
2026-09-27 15:21:48 +02:00