feat(dashboard): give stackiq the KPI tiles it never had - #892
Merged
Conversation
Stackiq's dashboard was the one fleet dashboard with no KPI cards at all. Not a rendering fault: the page was type:"custom" rendering a 675-line hand-written view whose entire widget list was an info box and two object-statistics tables. The app's five manifest KPI widgets all sit on detail pages, never on the dashboard. The page is now type:"dashboard" with four declarative "stat" widgets -- Organisaties, Modules, Diensten, Contracten -- counted by OpenRegister through @resolve:voorzieningen_register, the same register/schema pairs every other page in this manifest already uses. The non-KPI content is preserved exactly. The info box and both tables move to src/components/CatalogPanels.vue (template restructured, script untouched) and mount as the "catalog-panels" widget. Worth knowing for the next app: 1. A dashboard widget TYPE resolves against the LIBRARY's widget catalog (registerDashboardWidget / getWidgetTypeEntry), not the app's registry prop and not the page's slots map -- both of those are for page components and slot overrides. An unregistered type renders "Widget not available" and logs nothing, so it looks exactly like a wiring mistake. 2. eslint-suppressions.json is keyed by FILE PATH. Renaming a suppressed file orphans its entries, and --prune-suppressions then deletes them, so every previously-suppressed error surfaces at once. The entry moved to the new path deliberately, minus two suppressions the rename genuinely fixed: vue/multi-word-component-names (Dashboard -> CatalogPanels) and an unused arg (route -> _route, docblock updated). Verified in the browser against the published @conduction/nextcloud-vue (USE_LOCAL_LIB=false): four cards render in the canonical horizontal white card, zero grey, no "Widget not available", the info box and both tables still render. The tiles read 0/0/0/0 and that is CORRECT -- the statistics tables beside them independently report Organization 0, Service 0, Contract 0 in this environment, so the tiles agree with the tables rather than reporting a confident zero on a failed fetch. eslint exits 0, matching the pre-change baseline; webpack compiles.
Contributor
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ❌ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 711/711 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred — runs on the promotion into beta/main, not on a pull request into development | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-31 21:12 UTC
Download the full PDF report from the workflow artifacts.
rubenvdlinde
pushed a commit
that referenced
this pull request
Sep 1, 2026
The icon PR could not go green because stackiq development is red on its own account. All three are pre-existing, not introduced here. 1. Frontend Check (format): prettier flagged src/components/CatalogPanels.vue, a file this PR never touched. It has been failing on development since #892. Reformatted with the repo own config; the whole tree now reports "All matched files use Prettier code style!". 2. gate-60 icon-vocabulary FAILED, not warned: FileDocument and Web are named by src/manifest.json but were absent from src/icons.js, so both rendered as NOTHING. Registered. 3. gate-102 manifest-l10n-coverage: three manifest strings had no nl.json key, so they rendered English to a Dutch user. Two of them were the opposite problem, hardcoded DUTCH in a manifest whose menu labels are all English (Dashboard, Organisations, Applications, Suites, Services), so an English user saw Dutch: "Diensten" -> "Services" nl.json already had Services: Diensten "Object statistieken" -> "Object statistics" + new key "Modules" + new key, same word either way Only title and label were touched. The id, route and name values keep "Diensten" because they are identifiers, not copy.⚠️ The keys were added to BOTH l10n/nl.json and l10n/nl.js. The browser reads the .js; a key in the .json alone is invisible to the user and check:l10n would still call the two in sync. Verified by loading nl.js and diffing the key sets: 760 each, 0 in one and not the other. Sentence case per the Conduction voice rules, not Title Case.
rubenvdlinde
added a commit
that referenced
this pull request
Sep 1, 2026
* chore(icons): adopt the Tier B vocabulary in full gate-60 reported 8 Tier B warnings, four concepts duplicated across the real and mock register. All adopted. 8 -> 0. Vulnerability ShieldAlert -> ShieldAlertOutline Contract FileDocumentEdit -> FileSign Connection Link -> TransitConnectionVariant View Eye -> EyeOutline Contract is the substantive one: FileDocumentEdit is a document being EDITED, which is the opposite of what a signed contract is. FileSign says signed.⚠️ TransitConnectionVariant and EyeOutline had to be REGISTERED in src/icons.js in the same commit. Neither was there, and an icon a manifest names but the registry does not hold renders as NOTHING, not a fallback. * fix(quality): clear the three failures development was already carrying The icon PR could not go green because stackiq development is red on its own account. All three are pre-existing, not introduced here. 1. Frontend Check (format): prettier flagged src/components/CatalogPanels.vue, a file this PR never touched. It has been failing on development since #892. Reformatted with the repo own config; the whole tree now reports "All matched files use Prettier code style!". 2. gate-60 icon-vocabulary FAILED, not warned: FileDocument and Web are named by src/manifest.json but were absent from src/icons.js, so both rendered as NOTHING. Registered. 3. gate-102 manifest-l10n-coverage: three manifest strings had no nl.json key, so they rendered English to a Dutch user. Two of them were the opposite problem, hardcoded DUTCH in a manifest whose menu labels are all English (Dashboard, Organisations, Applications, Suites, Services), so an English user saw Dutch: "Diensten" -> "Services" nl.json already had Services: Diensten "Object statistieken" -> "Object statistics" + new key "Modules" + new key, same word either way Only title and label were touched. The id, route and name values keep "Diensten" because they are identifiers, not copy.⚠️ The keys were added to BOTH l10n/nl.json and l10n/nl.js. The browser reads the .js; a key in the .json alone is invisible to the user and check:l10n would still call the two in sync. Verified by loading nl.js and diffing the key sets: 760 each, 0 in one and not the other. Sentence case per the Conduction voice rules, not Title Case. --------- Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
rubenvdlinde
added a commit
that referenced
this pull request
Sep 1, 2026
…on a Dutch instance (#915) development E2E has been red for a day with six failures in two clusters. Both are the suite describing a world the app left behind. Neither was introduced by the icon work merged earlier today; the same six fail on the 08-31 21:06 run, checked. ## dashboard.spec.ts, three tests They assert an info box: the sentence "Overzicht van uw softwarecatalogus", a heading "Beheer van Organisaties", a "Vernieuwen" button on the surface and a "Ga naar Organisaties" quick-nav. None of that string set exists anywhere in src/ or l10n/nl.json any more. The dashboard is now four stat tiles plus the catalog-panels widget, since the KPI tiles landed in #892, and the spec was never updated. - the overview test now asserts the four tiles and the object-statistics panel; - the refresh test now opens the PAGE ACTIONS menu, where CnDashboardPage puts Refresh (showRefresh defaults true), instead of looking for a button on the surface; - the "Ga naar Organisaties" test is REMOVED rather than retargeted. Its own comment already recorded that the button was a no-op in the shared shell and that the user real path is the Organisations nav entry, which is the very next test in the file. Rewriting it would have tested that path twice while pretending to cover a control that no longer exists.⚠️ The tile labels are asserted in DUTCH, and they are not all the manifest source. The manifest says "Services"; nl.json maps it to "Diensten". An English assertion would pass only on an English instance. ## sbom-import.spec.ts, two tests await page.getByRole("tab", { name: "Components" }).click() The manifest labels that tab "Components" and nl.json maps it to "Componenten". The e2e instance runs Dutch, so the tab never matched and both tests died on a 60s click timeout that reads like a missing feature rather than a wrong string. The matcher now accepts either spelling, as does the "Open sidebar" button above it. 🔑 The underlying debt is that this suite mixes locales: the dashboard tests asserted Dutch, the sbom tests asserted English, against one Dutch instance. Locale-tolerant matchers are the cheap fix; a decided convention is the real one. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stackiq was the one fleet dashboard with no KPI cards at all. Not a rendering fault: the page was
type:"custom"rendering a 675-line hand-written view whose entire widget list was an info box and two object-statistics tables. The app's five manifest KPI widgets all sit on detail pages, never on the dashboard.What changed
The page is now
type:"dashboard"with four declarativestatwidgets — Organisaties, Modules, Diensten, Contracten — counted by OpenRegister through@resolve:voorzieningen_register, the same register/schema pairs every other page in this manifest already uses.The non-KPI content is preserved exactly: the info box and both tables move to
src/components/CatalogPanels.vue(template restructured, script untouched) and mount as thecatalog-panelswidget.Two things worth carrying forward
1. A dashboard widget TYPE resolves against the LIBRARY's catalog (
registerDashboardWidget/getWidgetTypeEntry) — not the app'sregistryprop, and not the page'sslotsmap; both of those are for page components and slot overrides. An unregistered type renders "Widget not available" and logs nothing, so it looks exactly like a wiring mistake.2.
eslint-suppressions.jsonis keyed by FILE PATH. Renaming a suppressed file orphans its entries, and--prune-suppressionsthen deletes them, so every previously-suppressed error surfaces at once — that briefly took this repo fromeslintexit 0 to 12 errors. The entry is moved to the new path deliberately, minus two suppressions the rename genuinely fixed:vue/multi-word-component-names(Dashboard → CatalogPanels) and an unused arg (route→_route, docblock updated).Verification
Built and checked against the published
@conduction/nextcloud-vue(USE_LOCAL_LIB=false).eslint srcexits 0, matching the pre-change baseline (warnings 219 → 217); webpack compiles.