Keep form save behind in-flight uploads, make retries idempotent via X-Upload-Id, cap remaining JSON bodies, and surface pending pivot type errors instead of zeroing them.
Co-authored-by: Cursor <cursoragent@cursor.com>
- RelationManager renders create/link/delete/unlink in declared order with
one primary, opens the child modal (update or view form) or the pivot
modal on row click, and deletes selected children behind a busy confirm
- RelationChildModal creates and edits children with its own session key
(X-Child-Session-Key) so uploads and dates work inside it
- RelationPivotModal edits link details; the picker links one record with
its pivot values when the relation has a pivot form
- deferrable managers render on the create screen with owner id 0, the
form's X-Session-Key and the pending note, and mark the form dirty
- the registry resolves RelationManager lazily (child forms close an
import cycle); DataTable gains openable rows and a trailing cell
- relation lang keys in en and pl; rebuilt boardwalk dist
- sessionKey.ts: one 32-byte base64url key per form mount, sent only in headers
- api/files.ts: FileRoutes over the record and child file routes, XHR upload with progress, 401 refresh and retry
- FileuploadField and FileCaptionModal per UI-SPEC section 3: dropzone, image grid, rows, per-item states, client pre-checks, reorder, protected previews
- FormView provides FORM_SESSION, counts pending changes as dirty and sends X-Session-Key on create and update
- fileupload lang keys in en and pl, admin-spa docs note, deferred smoke test, rebuilt dist
- pluginAssets loads controller scripts and stylesheets from {base}/assets/ only, once per URL
- WidgetField mounts the custom element with attributes only and posts summer-action through the typed client
- Only declared fill keys returned by the server are patched; the form turns dirty and nothing saves
- widget is a registered valueless type rendered on create and update, labelled as a group
- backend::lang.extension strings in en and pl; embedded dist rebuilt
- useSidebar: collapsed below 1100px (matchMedia) or by the admin's choice,
persisted as a boolean under summer-admin.sidebar; the viewport never
overwrites the stored choice
- SectionPanel collapse and rail expand buttons; SectionFlyout (role menu)
opens on hover, focus, Enter or ArrowDown on a rail item, closes on Esc or
about 200 ms after leaving and returns focus to the rail item
- Breadcrumbs with plugin, controller and record crumbs; UserMenu (Reka
DropdownMenu) with initials, name, role and Wyloguj
- useAuth.logout POSTs /auth/logout, clears user, navigation and settings
and routes to login even when the call fails
- applyColorScheme toggles .dark from prefers-color-scheme (no toggle, A6)
- newest toast first, 200 ms fade and scale for dialogs and toasts
- one relation-manager type constant in the registry
- shell smoke tests; tests default to a desktop, light matchMedia
- relation-manager registered in the field registry; renders only on an
existing record, never on create, and is never part of the save body
- RelationManager: relation schema label and comment, debounced search,
selectable linked list (DataTable relation variant), toolbar buttons in
declared order, confirmed unlink with plural messages and toasts
- RelationPickerModal: Reka Dialog (aria-modal, focus trap, Esc) over the
candidates endpoint five per page, selection kept across pages, Dodaj (N)
POSTs link, focus returns to the opener
- admin OpenAPI documents search, sort, dir, page and per_page on the linked
and candidate relation routes so the SPA sends them typed
- neutral acme.demo.widgets members fixtures and relation smoke tests
- FormTabs groups fields by tab (untabbed fields in the default tab) as a
segmented tablist; a tab holding invalid fields after a 422 shows a
count badge and the form switches to the first invalid field
- switch, checkbox and relation join the renderer registry: toggle cards
(role=switch, 20px checkbox) keep a numeric value numeric; relation
fields are read-only labels from meta.labels, a searchable single
select over fields/{field}/options with emptyOption first, or ordered
removable chips with an appending search (300 ms debounce, 20 per
page, more on scroll or the more action)
- FormView gets the back button, record title and update subtitle, a
sticky footer (Usuń with deleteConfirm then DELETE, Anuluj, Zapisz i
zamknij to the mapped redirectClose, Zapisz), and asks before leaving a
dirty form on any route change plus a beforeunload guard
- Settings: the rail pins Ustawienia to the bottom when /settings is
non-empty; /settings lists pages by category; /settings/:code renders
the settings schema through FormGrid and the registry, PUTs the values
and maps a 422 like the record form
- New backend::lang keys (form.more_options, tab_default, discard,
settings.back); form and settings smoke tests; boardwalk/dist rebuilt
- 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