Repository navigation
fix(manifest): open a related object's detail page and refetch on a page-size pick - #1390
Conversation
…age-size pick On a manifest `type:"detail"` page the Related widget's rows looked like links and went nowhere: `CnRelatedObjectsWidget` emitted `select-object` and nothing above it listened. `CnDetailWidgetHost` now forwards it as `select-object`, `CnDetailPage` re-emits it as `related-object-click`, and `CnPageRenderer` opens the first detail page bound to the object's register and schema. `@self` names those by id while a manifest may name them by slug, so a miss on the literal pair describes both through the OpenRegister API once (cached) and matches again; no page or no route warns like a dead row click. `CnIndexPage` only emitted `page-size-changed` on a page-size pick, and a manifest page has no host listening, so the select changed and the table did not. In self-fetch mode the list now refetches page 1 at the new size before the event fires. Docs, generated partials and changelog updated; specs cover both paths. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ry path, and a failed lookup is retried Review of #1390: the first commit wired the click only through the three CnDetailWidgetHost mounts of CnDetailPage, so two documented paths stayed dead (f1): a Related tab inside a Tabs widget (CnTabsWidget nests a host of its own and forwarded only geo-saved/open-integration) and a v2 widget-grid page, where CnWidgetGrid mounts the related widget directly. CnTabsWidget, CnWidgetGrid and the host's registry-rendered mounts now re-emit `select-object`; CnPageRenderer listens on its body and sidebar grids. A failed register/schema describe was cached as null for good, pinning the click to nowhere after one 503 (f2): the cache entry is dropped on failure and the next click retries. The docstring said every miss warns; the no-id and no-router misses are silent and the docstring now says so (f4). The cache lives for the bundle's lifetime, not the page's — docs reworded (f6). Specs now drive the template wiring instead of calling methods (f3): the widget's event through the host, a registry widget nesting a host, the Tabs widget, the page, the grid, and the renderer on both the page and the grid path; plus the retry and the silent no-router miss. Class sweep: every `<component :is>` mount that can render a related widget (host ×2, grid ×2, Tabs ×1) carries the listener. `git grep "page lifetime"` finds no other copy. Checks after the last edit: jest on the nine touched suites (109 + 60 tests green), eslint 0 errors, check:docs and check:jsdoc green, generated partials regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Quality Report — ConductionNL/nextcloud-vue @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ⏭️ | ||||
| phpcs | ⏭️ | ||||
| phpmd | ⏭️ | ||||
| psalm | ⏭️ | ||||
| phpstan | ⏭️ | ||||
| phpmetrics | ⏭️ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| test | ✅ | ||||
| check-build | ✅ | ||||
| check-public-safe | ✅ | ||||
| check-docs | ✅ | ||||
| check-jsdoc | ✅ | ||||
| check-integration-parity | ✅ | ||||
| check-peers | ✅ | ||||
| check-docs-fresh | ✅ | ||||
| check-a11y | ✅ | ||||
| check-smoke | ✅ | ||||
| check-vue3-compile | ✅ | ||||
| composer | ✅ | ✅ | |||
| npm | ✅ | ✅ 643/643 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ⏭️ | ||||
| REUSE | ✅ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ | ||||
| Hydra gates | ⏭️ |
Quality workflow — 2026-10-08 14:44 UTC
Download the full PDF report from the workflow artifacts.
…ect click to the renderer The pre-push check of the previous fix found the class sweep short by one kind of mount: CnPageRenderer mounts CnWidgetGrid six times (body, sidebar, header-actions, footer, modal and the `tab:*` / `section:*` slots) and only body and sidebar carried the listener, so a Related widget placed in a tab slot of a v2 page still opened nowhere. All six mounts now listen; the docs name every slot. Tests: a `tab:links` grid opens the object; the silent no-id miss asserts no warning; the unknown-route miss asserts its warning. Checks after the last edit: `npx jest` on the four renderer/page suites (53 tests green), eslint 0 errors, generated partials unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
| @geoSaved="onGeoSaved" | ||
| @openIntegration="onOpenIntegration" /> | ||
| @openIntegration="onOpenIntegration" | ||
| @selectObject="onSelectObject" /> |
There was a problem hiding this comment.
🔴 Blocker — A Related widget inside a Tabs widget (and on a v2 widget-grid page) still opened nowhere
✅ Fixed before posting in 8406d5f and 4e5bb8a; the thread stays so the record of what the review caught sits in place.
The first commit wired the click only through the three CnDetailWidgetHost mounts of CnDetailPage. CnTabsWidget nests a host of its own and forwarded only geoSaved / openIntegration, and CnWidgetGrid mounts the built-in related widget directly on a v2 page — on both paths the widget's select-object reached nobody, while the PR body promised "a related object opens its detail page".
Impact: every manifest page that shows the Related widget in a tab, or as a v2 widgets[] entry (any slot), kept dead rows.
Suggested fix: (applied) CnTabsWidget re-emits select-object; the host listens on its registry-rendered mounts as well as on the widget itself; CnWidgetGrid re-emits select-object from both of its mounts; CnPageRenderer listens on all six grid mounts (body, sidebar, header-actions, footer, modal, tab:*/section:*).
Done when:
git grep -n '<component' -- src/components/CnDetailWidgetHost src/components/CnWidgetGrid→ every:ismount that can render a registry widget carries@selectObjectgit grep -n '<CnWidgetGrid' -- src→ six mounts, each with@selectObject="onRelatedObjectOpen"npx jest tests/components/CnDetailPageRelatedObjectClick.spec.jsgoes red when one@selectObjectlistener is renamed (checked withCnTabsWidget.vue: 1 failed, 6 passed, then reverted)
Verification: git grep -n 'select-object' -- src/components/CnTabsWidget at 861d67f → no match; at 4e5bb8a → the listener and the re-emit.
WilcoLouwerse
left a comment
There was a problem hiding this comment.
Verdict: APPROVE (Thorough) — self-review posted as COMMENT (GitHub blocks a self-APPROVE)
The page-size refetch and the related-object click both do what the PR says; the analysis found one blocker (two render paths of the Related widget were still dead) and three concerns, all fixed on the branch before this verdict, with the pre-push adversarial check returning clean on the final commit.
🔴 Blockers (1)
- A Related widget inside a Tabs widget (and on a v2 widget-grid page) still opened nowhere —
src/components/CnTabsWidget/CnTabsWidget.vue:92. Fixed before posting in8406d5f+4e5bb8a; the thread stays as the record.CnTabsWidgetandCnWidgetGridnow re-emitselect-object, the host listens on its registry-rendered mounts, andCnPageRendererlistens on all six of its grid mounts.
✅ Fixed before posting (3)
- One failed describe pinned the click to nowhere — a rejected register/schema lookup was cached for good; the entry is dropped on failure and the next click retries (
8406d5f, spec "retries a describe that failed"). - Specs called methods, not the template wiring — the specs now fire the child's event through host, Tabs widget, page, grid (body and a
tab:*slot) and renderer; renaming one@selectObjectlistener turnsCnDetailPageRelatedObjectClick.spec.jsred (checked: 1 failed, 6 passed, reverted) (8406d5f,4e5bb8a). - Docstring promised a warning the code did not give — the no-router and no-id misses are silent by design and the docstring now says so; the unknown-route miss warns and has a spec; the cache is described as living for the bundle's lifetime, not the page's (
8406d5f,4e5bb8a).
🟢 Minor (1, left as-is)
- Current route params are carried into the related object's route —
buildRouteParamscopies only the non-last params of a nested target path (checked withnode:/builder/:slug/schemas/:schemaIdwith{ id }→{ schemaId }), which is the context a nested detail route needs; a single-param target like/organisaties/:idgets nothing foreign. Kept.
✅ Verified clean
- Additive only: no prop, event or slot removed or renamed (
git diff development... -- srchas no-line inemits/props/slots). @selectObjectas a fallthrough attribute on a consumer widget withoutemits: a harmless listener on its root element, the same pattern@geoSaved/@openIntegrationalready used; no library widget spreads$attrsonto a DOM node on these paths.- Dual build: camelCase listeners map to the kebab-case emits (
@pageSizeChanged↔page-size-changedpre-existed);catch {is already used insrc/. - Docs:
cd docusaurus && npm run prebuild:docsleavesdocs/clean;check:docsandcheck:jsdocgreen. - Consumer impact of the page-size change: hosts that fetch themselves still receive
page-size-changed; only the self-fetch path refetches.
Gates: CI quality / Run lane still queued on 4e5bb8a at this verdict; gate findings are not part of this round. Required checks (quality / Quality Report, Playwright (e2e), Dist sideEffects (tree-shaking)) are reported, not waited out.
Jira context: WOO-586 — CMDB-export (TOPdesk, xlsx) via Stackiq in OpenRegister; the two defects were found in its manual test round on stackiq.
Scope decision: stackiq's own fixes are in ConductionNL/stackiq#1275; stackiq bumps @conduction/nextcloud-vue after the release that carries this PR.
🤖 Review by Claude Code (/review-pr, Thorough; analysis + pre-push agents: Sonnet).
Quality Report — ConductionNL/nextcloud-vue @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ⏭️ | ||||
| phpcs | ⏭️ | ||||
| phpmd | ⏭️ | ||||
| psalm | ⏭️ | ||||
| phpstan | ⏭️ | ||||
| phpmetrics | ⏭️ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| test | ✅ | ||||
| check-build | ✅ | ||||
| check-public-safe | ✅ | ||||
| check-docs | ✅ | ||||
| check-jsdoc | ✅ | ||||
| check-integration-parity | ✅ | ||||
| check-peers | ✅ | ||||
| check-docs-fresh | ✅ | ||||
| check-a11y | ✅ | ||||
| check-smoke | ✅ | ||||
| check-vue3-compile | ✅ | ||||
| composer | ✅ | ✅ | |||
| npm | ✅ | ✅ 643/643 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ⏭️ | ||||
| REUSE | ✅ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ | ||||
| Hydra gates | ⏭️ |
Quality workflow — 2026-10-08 16:08 UTC
Download the full PDF report from the workflow artifacts.
…on verbs (#1367) * fix(CnIndexPage): built-in row actions follow OpenRegister's permission verbs OpenRegister's @self.actions block carries permission verbs (read, update, delete, ...) rather than the built-in row action ids, so a row carrying it kept only Delete. A built-in now also matches the verb that governs it: read permits View and Copy, update permits Edit, delete permits Delete. The match is additive, applies to the four built-ins only, carries the verb's refusal reason, and a verb consumed by a declared built-in is no longer reported as undeclared. Closes #1328 * fix: audit round fixes for the tour X, user pickers, header filters, install placeholder and option text (#1368) * fix: audit round fixes for the tour X, user pickers, header filters, install placeholder and option text - CnWalkthrough: the corner X pauses and keeps the step; a replay continues a paused or saved tour, Start over still begins at step 1 (C4) - userAutocomplete: the signed-in user is offered when they match the search and resolves to their display name; mentions opt out (D4) - CnFormDialog: a picked user keeps its display name after a clear and re-pick (D4) - columnFilters/CnIndexPage: header filters without a resolved schema, from the column's hints, falling back to a text filter on contains (G2) - CnDashboardPage: compact requires-app placeholder that fits a two-row tile (F4) - CnFormDialog: select, multiselect and tag options wrap between words only OpenSpec: openspec/changes/audit-round-lib-fixes * fix(walkthrough): a paused tour stays hidden across page loads until the user continues A pause (X, ESC or the dim) is stored as paused with its step. On the next load the tour does not start on its own; Continue in the user settings or the app's tour entry shows it at the saved step and clears the pause. Start over still begins at step 1 (Ruben, 7 October 2026). OpenSpec: openspec/changes/audit-round-lib-fixes * feat(setup): a closed setup wizard is recorded on the server; config-fields steps draw their intro (#1369) - setup.dismissAction (schema 2.53.0): CnAppRoot posts the app's own setup action once when the wizard is closed or finished, and reads dismissed (true or a setup version) from /api/setup/status, so the wizard stays closed in every browser. Without the key the close stays per browser. - New event setup-wizard-dismissed ({ appId, version, finished }). - A config-fields step draws its body like choice and run-action steps. OpenSpec: openspec/changes/setup-wizard-close-on-server * docs(openspec): specs for the follow control, the assistant mark and the task form dialog * docs(openspec): star and follow, unread markers, registry-backed field, drifted task steps * docs(openspec): group share on the save dialog, presentation picker, flow tasks tab, select all matching, search in files * fix(docs): escape the {page} placeholder that stopped every docs deploy MDX read the placeholder in the notFoundRouteLabel row as a JSX expression, so static rendering of cn-detail-page failed and no documentation, including the repaired styleguide, has shipped since 29 September. * docs(openspec): reference pickers and object sub-fields in the transition input dialog * docs(openspec): follow toggle asks for @self.can, tasks tab uses the flat create body and the row's can list * fix(docs): escape the {page} placeholder that stopped every docs deploy MDX read the placeholder in the notFoundRouteLabel row as a JSX expression, so static rendering of cn-detail-page failed and no documentation, including the repaired styleguide, has shipped since 29 September. * feat(docs): score every component on OpenRegister reliance, filterable on the overview scripts/openregister-reliance.js walks src/components and scores each component: direct references in its own files, plus files reached through its real import statements that carry a reference, so a wrapper inherits what its children need while importing the widget registry alone counts nothing. The tiers none, light, medium and heavy follow the sum. The script runs before docgen on every docs build and writes docs/components/_generated/reliance.json; docgen injects a reliance line into every component reference and the components overview gets a filterable, searchable table. Tier none is the shortlist of components that can move to another host first. * feat(flow): select options in the form, and send outcomes by name in the run log (#1371) * feat(flow): a select field can list its options in the form, and the run log names each send outcome A node's configForm `select` could only be filled from an `optionsFrom` url. It may now declare `options` (strings, or {value, label} pairs), read by both CnFlowNodeEditModal and CnRunNodeDialog through one helper. The field's help line now shows under the picker. New CnFlowStepOutcomes lists a send step's `report.messaging` buckets by name (delivered, opted out, opt-out check did not answer, and the rest), with count and sample. CnRunDetailSidebar renders it under each step on the Logs tab. Strings in English and Dutch. Assisted-by: Claude Code * docs(flow): generated partial for CnFlowStepOutcomes Assisted-by: Claude Code * style: sort the CnFlowStepOutcomes export Assisted-by: Claude Code * fix(flow): stack the outcome rows so they read in the narrow run sidebar Seen live: a side-by-side name and value wrapped mid-list, and a long name ran out of the sidebar. Name over value now, host dt/dd styles reset. Assisted-by: Claude Code * fix(flow): the select field takes the full width of the step form Seen live: at its natural width the picker cut every option label in half. Assisted-by: Claude Code * fix(l10n): put the outcome labels in the translations block, not plurals Seen live in Dutch: the labels were appended to the catalogue's plurals block, which t() never reads, so every label stayed English. A test now holds the en and nl translations blocks to the labels. Assisted-by: Claude Code * fix(flow): open a step's editor and its menu from the keyboard (#1378) * fix(flow): open a step's editor and its menu from the keyboard A flow step's editor opened only on double-click and its menu (Edit, Copy, Delete) only on a click. Enter on a focused step did nothing. CnFlowNode now emits `activate` for Enter or Space and `menu` for Shift+F10 or the menu key, only for a key pressed on the node itself so a port keeps its own keys. CnGraphCanvas forwards them as `node-activate` and `node-menu` (not on a read-only canvas), and CnFlowDetail opens the editor or the menu at the step. The menu was already a real menu: an a11y spec on the real NcActions now holds role="menu", menuitem, and arrow-key movement to it. Assisted-by: Claude Code * docs(flow): the keys that open a step and its menu Assisted-by: Claude Code * docs(components): regenerate the CnFlowStepOutcomes page and reliance.json (#1386) check:docs-fresh was red on development: #1371 added CnFlowStepOutcomes and #1375 added the OpenRegister reliance section, and neither regenerated the other's output. This is the output of `cd docusaurus && npm run prebuild:docs`. * docs(woo): the build queue and the decisions the Woo specs cite, in the repo (#1385) The Woo specs cite decisions D1 to D13, and the build order spans repositories. Both lived in a private planning repository that a cloud build session cannot read. These two files put them next to openspec/woo-build-rules.md. * docs(components): destination, week and screenshot per component (#1387) * docs(components): destination, week and screenshot per component in the components table The buildiq parity project on Tables decides for every component where it goes, nc-vue or Tables, in which ISO week, and whether the styleguide renders it. The table on the components index shows and filters on all three; the data is a copy of docs/project/14-component-destinations.md in ConductionNL/tables. * docs(components): CnIndexPage example does not render * fix(manifest): open a related object's detail page and refetch on a page-size pick On a manifest `type:"detail"` page the Related widget's rows looked like links and went nowhere: `CnRelatedObjectsWidget` emitted `select-object` and nothing above it listened. `CnDetailWidgetHost` now forwards it as `select-object`, `CnDetailPage` re-emits it as `related-object-click`, and `CnPageRenderer` opens the first detail page bound to the object's register and schema. `@self` names those by id while a manifest may name them by slug, so a miss on the literal pair describes both through the OpenRegister API once (cached) and matches again; no page or no route warns like a dead row click. `CnIndexPage` only emitted `page-size-changed` on a page-size pick, and a manifest page has no host listening, so the select changed and the table did not. In self-fetch mode the list now refetches page 1 at the new size before the event fires. Docs, generated partials and changelog updated; specs cover both paths. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(manifest): the related-object click reaches the renderer from every path, and a failed lookup is retried Review of #1390: the first commit wired the click only through the three CnDetailWidgetHost mounts of CnDetailPage, so two documented paths stayed dead (f1): a Related tab inside a Tabs widget (CnTabsWidget nests a host of its own and forwarded only geo-saved/open-integration) and a v2 widget-grid page, where CnWidgetGrid mounts the related widget directly. CnTabsWidget, CnWidgetGrid and the host's registry-rendered mounts now re-emit `select-object`; CnPageRenderer listens on its body and sidebar grids. A failed register/schema describe was cached as null for good, pinning the click to nowhere after one 503 (f2): the cache entry is dropped on failure and the next click retries. The docstring said every miss warns; the no-id and no-router misses are silent and the docstring now says so (f4). The cache lives for the bundle's lifetime, not the page's — docs reworded (f6). Specs now drive the template wiring instead of calling methods (f3): the widget's event through the host, a registry widget nesting a host, the Tabs widget, the page, the grid, and the renderer on both the page and the grid path; plus the retry and the silent no-router miss. Class sweep: every `<component :is>` mount that can render a related widget (host ×2, grid ×2, Tabs ×1) carries the listener. `git grep "page lifetime"` finds no other copy. Checks after the last edit: jest on the nine touched suites (109 + 60 tests green), eslint 0 errors, check:docs and check:jsdoc green, generated partials regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(openspec): pixel-parity changes for the screens (2 of 2: dialogs, wizards, dashboards, kanban, forms) (#1392) * docs(openspec): pixel-parity changes for dialogs, wizards, dashboards, kanban, forms and empty states Six changes that bring the Cn* dialogs, the wizard stepper, the dashboard header and KPI tiles, CnBoardView, the form field anatomy and the empty state to the screens on identity.conduction.nl/screens, behind one app-wide board look (cnLook). Specs only; no code. * docs(openspec): reuse the look switch from screens-chrome-parity The board look key, its page override and the cn-look-board class come from #1391. The dialog change now only provides the resolved value as cnLook, which a teleported dialog and any markup change need, and puts the class on the dialog container. The other five changes point at #1391. * fix(manifest): every widget-grid slot of a page hands the related-object click to the renderer The pre-push check of the previous fix found the class sweep short by one kind of mount: CnPageRenderer mounts CnWidgetGrid six times (body, sidebar, header-actions, footer, modal and the `tab:*` / `section:*` slots) and only body and sidebar carried the listener, so a Related widget placed in a tab slot of a v2 page still opened nowhere. All six mounts now listen; the docs name every slot. Tests: a `tab:links` grid opens the object; the silent no-id miss asserts no warning; the unknown-route miss asserts its warning. Checks after the last edit: `npx jest` on the four renderer/page suites (53 tests green), eslint 0 errors, generated partials unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(openspec): pixel-parity changes for the screens (1 of 2: lists, detail, chrome, cards) (#1391) * docs(openspec): pixel-parity changes for the screens (lists, detail, chrome, cards) Four proposed changes that move the shared library to the screens on identity.conduction.nl under one opt-in switch, look: "board": screens-chrome-parity, screens-index-list-parity, screens-detail-page-parity and screens-card-parity. * docs(openspec): apply the design owner's decisions on breadcrumb, settings save and card grid * fix(notifications): label rules in words and read the installed app version (#1393) * fix(notifications): label rules in words and read the installed app version The user-settings notification pane printed each rule key (clientUpdated, caseAssigned). It now shows the rule's own label, the app's label from the new CnAppRoot prop notificationLabels, the generic wording, or the key as words, never the raw key. The settings footer printed a build-time appVersion (pipelinq 0.1.0, dossiq 0.4.47-unstable on 0.4.48-beta). appVersionDefine() in the webpack subpath returns a DefinePlugin expression that reads the installed version from the page's version initial state at runtime. * docs(notifications): document humaniseRuleKey, notificationRuleLabel and the new label props * feat: build 56 open OpenSpec changes (#1396) * docs(flow-canvas-run-animation): mark live verification as needing a live instance Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * docs(cn-flow-runs-widget-subject): mark e2e task as needing a live instance Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * docs(brand-motif-token): mark release task as a human step Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * docs(review-round-two): task 4 needs the openregister contains operator Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(flow-layout-helpers-from-root): export flow layout helpers from the package root Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * docs(cn-tasks-entity-source): mark remaining tasks as needing other repos or a live instance Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * docs(cn-flow-runs-widget): tick the unit-test task (specs exist), note the beta backport Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(ai-panel-approved-mark): draw the thematiq approved-assistant mark in CnAiChatPanel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(dashboard-widget-catalog-at-boot): CnDashboardPage imports the widget catalog itself Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(index-search-in-files): also-search-inside-files switch and Found in line on CnIndexPage Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(object-list-create-with-initial-data): lockFilterFields and createDefaults on the object-list create form Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(ai-message-attachments): keep, render and choose attachments in the AI companion Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(cnindexpage-folder-schema): a folderSidebar folder can switch the listed register and schema Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(dashboard-notepad-widget): personal notepad dashboard widget saved to user preferences Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(detail-header-field-chips): field chips in the CnDetailPage header from config.headerFields Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-dialog-autosave): publish a stored draft, Saved indicator wording, local drafts on CnFormPage Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-field-property-source): registry type-ahead field with fill map and replace prompt Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-widgets-duration-and-subobject-table): duration and sub-objects form widgets Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(index-ref-column-labels): labelField on CnIndexPage reference columns, batched useRefLabels Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(journey-repeating-item-review): CnJourneyReviewList and the repeating-write targets (CnJourney wiring awaits journey-runtime) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(notes-on-a-file): CnNotesCard takes a file as its source, useFileComments Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(public-manifest-runtime): cnFetch public transport with bearer auth, configured base and credential redaction Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(a-saved-view-drives-a-widget): saved-view dashboard widget and its config form Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(help-texts-and-form-help): Hulp nodig dialog on forms, help text per page and per part of the area Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * fix(help-texts-and-form-help): bump the register to 0.74.0 and the pinned schema versions in the tests Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(screens-empty-state-parity): card-size empty state and board-look switch for the library empty states Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(audit-trail-restore-version): restore this version on CnAuditTrailTab and useRestoreVersion Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(personal-action-list): portalAction schema and the daily reminder three days before the end date Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(files-preview-in-place): useFileOpener, CnFilePreview and the files components open files one way Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(view-presentation-picker): CnViewPresentationPicker, presentation in the save dialog and a presentation dialog for editable views Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(flow-task-form-component): CnTaskFormDialog and form drift flags in the flow editor; fix CnFilePreview url prefix and docs coverage Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-child-records-table): CnChildRecordsField, useChildRecords and the child-records widget in CnFormDialog Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-options-from-concept-scheme): coded select fields from OpenRegister concept-scheme options in CnFormDialog Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-smart-paste): Paste to fill on CnFormPage and config.smartPaste in the manifest schemas (schema 2.60.0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(index-calendar-view-mode): calendar view mode on CnIndexPage, month range query and keyboard grid (schema 2.61.0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(index-export-follows-the-page): export follows the list query, reads configuration.exportable, mass export follows the selection or the filter Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(map-image-layer): image layer for CnMapWidget in flat pixel coordinates (schema 2.62.0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(openapi-reference-component): CnApiReference and openApiModel, a local-only OpenAPI 3 reference Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(journey-runtime): CnJourney, CnJourneyDialog, CnProcessSteps and the journey run store One route-split renderer for an OpenRegister journey, in a page or a modal. Form steps render through CnFormPage; two-level groups, conditions and branch rules go through the shared visibleWhen evaluator only; the review step groups answers by step and renders list answers with the repeating write's targets (journey-repeating-item-review); answers are saved as steps complete so a run resumes in either host. Adds the journey-vocabulary gate. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(widget-registry-public-flag): public flag on the widget registry, public host gating in CnWidgetGrid, markdown widget and gate Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(app-diagnostics-channel): CnAppRoot diagnostics listener for requests, render errors, unknown components and binding problems Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(write-feedback-toast-and-undo): useWriteFeedback, toasts on CnFormDialog, confirm and undo on CnLifecycleActions, delete undo on CnObjectListWidget Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(detail-page-object-widgets): CnObjectFilesWidget binds a detail page files widget to the object's folder; related regression test Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-file-and-camera-fields): several files, drop, upload-after-save for big files and camera capture; file properties in CnFormDialog Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(form-live-values): assign rules, token defaults, host calculate and unmet conditions on forms (schema 2.63.0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(index-column-order-and-pinning): order, pin and remember table columns per user and list (schema 2.64.0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(index-copy-with-relations): copy an entry with its links through one OpenRegister request (schema 2.65.0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(manifest-i18n-labels): manifest i18n block, label lookup in CnAppRoot and translated labels across the pages (schema 2.66.0) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * test(packaging): objectUrl is a URL helper (useObjectCopy) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(notes-replies-group-mentions-and-images): replies, group mentions and pasted images in the Notes tab and card Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(the-activity-tab-reads-the-merged-feed): CnActivityTab reads the merged feed with kind chips, remembered reads toggle, range and export Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(environment-banner): name non-production environments in a banner Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * feat(CnFieldHelper): open a schema property's x-help in place Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * chore(docs): regenerate component partials, document new events, fix lint Regenerates docs/components/_generated for every component the open-spec build touched, adds the missing event JSDoc on CnJourney, CnJourneyDialog, CnMassCopyDialog, CnNoteComposer and CnProcessSteps so check:jsdoc meets its baseline, and clears the eslint errors (export order, unused helper, fixture package.json order). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * fix(ci): replace deprecated word-break and clip declarations flagged by stylelint Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P * fix(ci): resolve async components in the smoke sweep and break the CnFormDialog import cycle The smoke sweep mounted the defineAsyncComponent shells of CnJourney and CnJourneyDialog, which have no instance (null vm), so unmount threw and the rest of the sweep cascaded. It now resolves the real component first. CnChildRecordsField statically imported CnFormDialog, which imports it back; the e2e harness hit a TDZ ReferenceError and never rendered. It now loads CnFormDialog lazily, like CnSubObjectsField. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKQYuzA9vwqFA3WMSFa63P --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Ruben van der Linde <rubenvdlinde@gmail.com> Co-authored-by: Ruben van der Linde <ruben@conduction.nl> Co-authored-by: WilcoLouwerse <wilco@louwerse.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
What
Two manifest-page bugs found on stackiq's CMDB rig (WOO-586), both in the library:
type:"detail"page the Related widget's rows looked like links and went nowhere:CnRelatedObjectsWidgetemittedselect-objectand nothing above it listened.CnDetailWidgetHostnow forwards it (select-object),CnDetailPagere-emits it asrelated-object-click, andCnPageRendereropens the firsttype:"detail"page bound to the object's register and schema, with the id under whatever param that route declares.@selfnames register and schema by id while a manifest may name them by slug (stackiq: register20resolved from@resolve:, schemaorganization), so a miss on the literal pair describes both through/apps/openregister/api/registers/{id}and/schemas/{id}once (cached per page lifetime) and matches again. No matching page or an unknown route warns, like a dead row click.CnIndexPageonly emittedpage-size-changed; a manifest page has no host listening, so the select changed and the table did not. In self-fetch mode the list now refetches page 1 at the new size before the event fires (onPageSizeEvent, mirroringonPageEvent).Additive only: new events
select-object(CnDetailWidgetHost) andrelated-object-click(CnDetailPage); hosts that fetch themselves still getpage-size-changed.Checks
CnPageRendererRelatedObjectOpen.spec.js(direct match, slug lookup, one request per id, no page, no id),CnIndexPagePageSize.spec.js,CnDetailPageRelatedObjectClick.spec.js; neighbouring suites green (67 tests in the run).npm run check:docs,npm run check:jsdocgreen; docs pages and_generatedpartials regenerated (cd docusaurus && npm run prebuild:docs); CHANGELOG under Unreleased/Fixed.Consumer follow-up: stackiq bumps
@conduction/nextcloud-vueafter the release that carries this (ConductionNL/stackiq#1275 holds the stackiq-side fixes).Jira: WOO-586 — plan: https://github.com/ConductionNL/readonly-mirror-wilco-claude-plans/blob/dev-mirror/issues/jira/WOO-586/WOO-586-plan-08-10.txt
🤖 Generated with Claude Code