Commit Graph

87 Commits

Author SHA1 Message Date
logaritmisk 04ed0c50e2 feat(web): indigo brand token + status tokens + Badge success/warning variants (#49)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:08:08 +02:00
logaritmisk 303c986d40 chore(web): raise bundle budget 180→250 KB gz (#47)
Generous ceiling so the budget stops blocking per-feature work (this is the third
raise in three frontend milestones) while still catching gross regressions. A
vendor-split / bundle audit can revisit always-loaded weight later.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:35:35 +02:00
logaritmisk fcad638549 feat(web): per-mutation success/error toast metadata (#47)
Declare meta on all 18 mutation hooks: meta.successMessage (toast.* key)
on every discrete user action, meta.suppressErrorToast where the consuming
component already renders the error inline. Corrected useUpdateFieldDefinition
to suppress (FieldForm renders update.isError as form.rejected inline).

Add an RTL+MSW integration test wiring the real MutationCache via
makeQueryClient() + ToastRegion: success toast, catch-all error toast, and
suppressed-no-toast. Tidy the toast Close aria-label to t("common.close")
with en/sv parity.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:55:54 +02:00
logaritmisk 604d4f6005 feat(web): Base UI toast region + global mutation feedback wiring (#47)
Add a module-scope Base UI toast manager bridged to the QueryClient so
every mutation can give consistent feedback. A MutationCache (extracted
into a makeQueryClient() factory for test reuse) emits a catch-all,
type-aware error toast (unless meta.suppressErrorToast) and an opt-in
success toast (meta.successMessage), reading mutation.meta + i18n.t
outside React. meta is type-checked via a react-query Register
augmentation. ToastRegion is mounted app-wide in main.tsx. Adds a toast
i18n namespace (en/sv parity) and a validated story.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:46:26 +02:00
logaritmisk 03d5b59b48 feat(web): readable, grouped object detail (labels, placeholders, actions toolbar) (#45)
Refactor object-detail.tsx to resolve term/authority ids to labels via
FlexibleFieldValue, group flexible fields by def.group in definition order
(ungrouped → trailing "Other"), always show core fields with "—" placeholders,
and move Edit (button-styled Link) + Delete into a right-aligned toolbar.

Move formatDate into lib/format-date.ts so the component module no longer
co-exports a non-component (clears the react-refresh/only-export-components
warning); both flexible-field-value.tsx and object-detail.tsx import it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:44:35 +02:00
logaritmisk 2e38af565a feat(web): FlexibleFieldValue — resolve term/authority/localized field values (#45)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:32:17 +02:00
logaritmisk 6a62cf64bf chore(web): drop dead objects.selectPrompt i18n key (#44)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 00:13:32 +02:00
logaritmisk c052ddc5af test(web): widen findBy timeout for the lazy/portaled narrow-drawer detail test (#44)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 00:03:46 +02:00
logaritmisk e7b0f65686 chore(web): raise bundle budget 165→180 KB gz (#44)
The collapsed-sidebar tooltips use Base UI's Tooltip, which pulls floating-ui
into the always-loaded shell chunk. Kept the richer tooltip over native title;
the index is a feature-rich admin SPA bundle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:58:03 +02:00
logaritmisk b8f70212a1 feat(web): responsive object detail (pane/drawer) at canonical /objects/:id (#44, #58)
Wide (>=1024px): right-hand pane beside the table with a close control.
Narrow: Base UI Drawer sliding from the right (lazy-loaded so its code splits
out of the main chunk). Both preserve the table's query string on close.

Remove the index SelectPrompt route (the table is the landing view) and delete
the now-unused SelectPrompt. Make table rows keyboard-activatable
(role=link, tabIndex, Enter).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:53:10 +02:00
logaritmisk 184e4ea2a5 feat(web): collapsible icon sidebar (persisted, auto-collapse on narrow) (#44, #58)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:44:40 +02:00
logaritmisk 04c33cb1aa feat(web): useMediaQuery hook + Base UI tooltip wrapper (#44)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:40:19 +02:00
logaritmisk 49f694d1fb feat(web): full-width sortable/filterable objects table with URL state (#44)
Replace the narrow ObjectList with a full-width ObjectsTable whose state
(sort/order/q/visibility/limit/offset) lives entirely in the URL via
useSearchParams. Sortable headers toggle sort+dir with aria-sort, a
debounced quick-filter and visibility chips mirror the search-panel
pattern, and a pagination footer offers prev/next + page-size select.
Rows deep-link to /objects/:id preserving the query string.

useObjectsPage now takes an ObjectListParams object (sort/order/
visibility/q) with keepPreviousData. ObjectsPage renders the table as
the full-width landing view, surfacing the nested <Outlet/> detail as a
simple right-side panel only when a :id child route is active (Phase 3
makes this responsive). object-list.tsx and its test are removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:34:13 +02:00
logaritmisk 98c00d3732 chore(web): regenerate API types (object list params + timestamps) (#44)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:24:42 +02:00
logaritmisk 4267aae4e5 chore(web): raise bundle budget 150→165 KB gz (#27)
The index chunk is a feature-rich admin SPA bundle (Base UI + TanStack Query +
react-hook-form + i18n); 150 KB was set early and now trips on most features.
The combobox itself lands in the lazy object-form chunk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 10:59:12 +02:00
logaritmisk c84b84b153 feat(web): use searchable combobox for term/authority fields on the object form (#27) 2026-06-06 10:41:28 +02:00
logaritmisk 0188e730e8 feat(web): searchable combobox (Base UI) for term/authority options (#27) 2026-06-06 10:37:01 +02:00
logaritmisk c9120848f5 feat(web): edit/delete authorities in place (#30) 2026-06-05 20:35:26 +02:00
logaritmisk 83ca506702 feat(web): rename vocabularies + edit/delete terms in place (#30) 2026-06-05 20:32:35 +02:00
logaritmisk 65ca79f2bd feat(web): edit/delete field definitions on /fields (in-place edit pane) (#36) 2026-06-05 20:24:57 +02:00
logaritmisk 194f18c8ed feat(web): reusable DeleteConfirmDialog with in-use handling + stories 2026-06-05 20:12:23 +02:00
logaritmisk 282e6430d4 feat(web): mutation hooks + InUseError + i18n for reference-data edit/delete 2026-06-05 20:06:23 +02:00
logaritmisk 78c950d2ee chore(web): regenerate API types for reference-data edit/delete
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 20:04:03 +02:00
logaritmisk b2d026f217 feat(web): set up Storybook (preview + MSW + stories for real components) 2026-06-05 16:55:40 +02:00
logaritmisk e6fc3eaf2c build(web): pin pnpm via packageManager + align CI to pnpm 11 (#26)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:50:40 +02:00
logaritmisk b4d71b0f80 fix(web): VisibilityBadge typed to the union (#38); normalize localized_text to default language on save (#41)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:46:48 +02:00
logaritmisk 0a29127f7e fix(web): name the field in the edit banner on create->fields-error redirect (#28)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:43:35 +02:00
logaritmisk 0c9db7bcdb feat(web): highlight the offending field on a set_fields 422 (#28)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:39:49 +02:00
logaritmisk d6dc1c9b57 feat(api): field-level set_fields 422 body (#28); enum-type SearchHitView.visibility (#38)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:32:48 +02:00
logaritmisk 9d0475e8ec feat(web): single-language content authoring (LabelEditor + localized_text at default lang)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:05:20 +02:00
logaritmisk 04e9c95c52 refactor(web): split config hook/context (.ts) from provider (.tsx) to clear react-refresh lint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:01:33 +02:00
logaritmisk de11292203 feat(web): config provider — fetch /api/config, default UI language from instance
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 14:58:01 +02:00
logaritmisk 2460a1368d feat: DEFAULT_LANGUAGE/DEFAULT_TIMEZONE config + public GET /api/config 2026-06-05 14:52:09 +02:00
logaritmisk 0ee3b970cb refactor(web): drop redundant fields/visibility casts now the client is typed (#24 #29)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 20:20:13 +02:00
logaritmisk 5a72f85989 feat(api): enum-typed visibility/data_type/kind + open-map fields in OpenAPI (#24 #29)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 20:14:30 +02:00
logaritmisk 914527edc6 fix(web): place aria-selected on the role=tab element (#32) + assert it
Per WAI-ARIA, aria-selected must be on the same element carrying role="tab".
The previous impl placed it on an inner <span> via the render-prop, making it
invisible to assistive technology. Move both role="tab" and aria-selected to
the NavLink, compute currentKind once from useParams, drop the render-prop.
Add a Vitest assertion that the selected tab has aria-selected="true" and an
unselected tab has aria-selected="false".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:32:18 +02:00
logaritmisk ff513e1712 fix(web): search 503 vs error (#34); terms/authorities list error states (#31); authority-tab a11y + dead keys (#32); authority-kind test (#37) 2026-06-04 17:28:01 +02:00
logaritmisk fd1c22191b polish(web): fields form resets error, shared labelText, drop dead nav.soon, a11y required marker, Other group last
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 14:29:25 +02:00
logaritmisk 37c80121ed feat(web): /fields two-pane screen (grouped list + create form) + nav (no stubs left)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 14:22:57 +02:00
logaritmisk 6ad1304efd feat(web): useCreateFieldDefinition mutation + MSW handler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 14:16:55 +02:00
logaritmisk b508273a52 feat(api): POST /api/admin/field-definitions (create field definition)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 14:09:08 +02:00
logaritmisk 4dd00362b8 polish(web): search pill aria-pressed, keepPreviousData, plural result count, URL-hydration test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 12:47:38 +02:00
logaritmisk 358d793e44 feat(web): /search two-pane screen (debounced query, visibility filter, load more) + nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 12:40:46 +02:00
logaritmisk ee65b27595 feat(web): Highlight (XSS-safe) + SearchResultRow components 2026-06-04 12:34:27 +02:00
logaritmisk de830999d4 test(web): embed highlight sentinels in search fixture snippet 2026-06-04 12:32:23 +02:00
logaritmisk 18ed9bd947 feat(web): useSearch infinite query + useDebouncedValue + MSW search handler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 12:29:11 +02:00
logaritmisk a87501b902 feat(api): GET /api/admin/search endpoint + regenerated client types
Expose full-text search over catalogue objects via a new admin endpoint
backed by the Meilisearch SearchClient. Validates visibility filter values,
short-circuits on empty queries, clamps pagination, and returns 503 when
search is not configured. Registered in OpenAPI; schema.d.ts regenerated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 11:48:32 +02:00
logaritmisk 352d899fa5 fix(web): authorities unknown-kind redirect, extract labelText util, EN-required test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 09:39:15 +02:00
logaritmisk 38673e52ba feat(web): authorities kind-tabbed screen (list/create) + nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 09:32:57 +02:00
logaritmisk 02e4f34a1b fix(web): vocab form-level error states, newVocabulary heading, id guard, EN-required test 2026-06-04 09:29:51 +02:00