Skip to content

Release: merge development into beta - #512

Open
github-actions[bot] wants to merge 20 commits into
betafrom
development
Open

Release: merge development into beta#512
github-actions[bot] wants to merge 20 commits into
betafrom
development

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated PR to sync development changes to beta for beta release.

Merging this PR will trigger the beta release workflow.

Reminder: Add a major, minor, or patch label to this PR to control the version bump. Default is patch.

github-actions Bot and others added 5 commits August 31, 2026 16:05
Co-authored-by: Ruben van der Linde <rubenvdlinde@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The 0.2.17 release bumped the version on main. Without this,
development stays behind main and the next development -> main promotion
conflicts on the version file.

Version files resolve to development's side, which is the higher line,
so this never moves a version backwards.
…260831154331

chore(sync): carry beta back into development
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ d15c1bf

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 558/558
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 15:56 UTC

Download the full PDF report from the workflow artifacts.

Dependabot cannot update these packages. Its npm updater fails with:

  npm error code EOVERRIDE
  npm error Override for <pkg> conflicts with direct dependency

The package is listed BOTH as a direct dependency and as a literal overrides
entry pinned to the same range. Dependabot bumps the direct dependency and
does not move the override, npm rejects the mismatched pair, and the update
is abandoned -- so these packages can never be updated, security advisories
included.

npm's self-reference is the idiom for exactly this: $<name> tells the
override to follow whatever the direct dependency resolves to, instead of a
range that has to be kept in lockstep by hand. This repo already uses it (see
the vue entry under @vue/test-utils).

Transitive consumers still get pinned to one version -- the direct
dependency's -- which is what the override was there to do. What changes is
that the pin tracks the dependency instead of duplicating it.

Verified in a clean container: bumping the direct dependency with the literal
override reproduces the EOVERRIDE above; with the self-reference the same
bump resolves.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ec45c03

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 558/558
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 16:29 UTC

Download the full PDF report from the workflow artifacts.

Bumps [@eslint/config-helpers](https://github.com/eslint/rewrite/tree/HEAD/packages/config-helpers) from 0.4.2 to 0.7.0.
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/packages/config-helpers/CHANGELOG.md)
- [Commits](https://github.com/eslint/rewrite/commits/core-v0.7.0/packages/config-helpers)

---
updated-dependencies:
- dependency-name: "@eslint/config-helpers"
  dependency-version: 0.7.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ f19edf0

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 558/558
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 17:06 UTC

Download the full PDF report from the workflow artifacts.

…2.17

chore(release): sync main back into development
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 9fd270e

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 558/558
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 17:13 UTC

Download the full PDF report from the workflow artifacts.

…527)

planninq was the last app in the fleet on eslint 8. Dependabot's
@nextcloud/eslint-config 8.4.2 -> 9.0.1 bump could not install at all:
that release declares `peer eslint: ">=10"`, so twelve checks went red at
npm ci, before a single file was linted.

Bumping the config alone was never going to work. eslint 8 was held in
three more places at once:

  @typescript-eslint/parser@7  peers eslint ^8.56.0
  eslint-plugin-import@2.32.0  peers eslint up to ^9
  @eslint/eslintrc             exists only to bridge the eslintrc era

So the stack moves together, to the versions hermiq, versioniq and keepiq
already run green: eslint ^10.9.1, @nextcloud/eslint-config ^9.0.1,
@typescript-eslint/parser ^8.68.0. eslint-plugin-vue is dropped because
v9 bundles its own v10, and a stale ^9 hoists over it and makes every SFC
parse as TypeScript. conductionVue3Fixes is dropped too: it patched a
Vue-2 ruleset, and against v9's recommended all 21 vue/no-deprecated-*
rules are already on while the two it existed to disable are not enabled
at all. Spreading it does not merely duplicate work, it BREAKS the run,
naming vue/* rules while registering no plugin.

THE CHECK THAT MATTERS HERE IS THE FILE COUNT, NOT THE ERROR COUNT.
An eslint 10 install pointed at a config it cannot read lints NOTHING and
exits 2 in a way that reads as a lint failure. That is how versioniq's
whole Vue and TypeScript layer went unchecked with 266 real problems
behind it. This migration hit exactly that on the first attempt, exit 2
and zero files, and it was caught because the file count was the check.
eslint 8 linted 46 files; this lints 47.

Those 47 files carried 284 errors nobody could see. --fix cleared 222.
The remaining 62 are fixed here rather than deferred:

  21 no-console        all console.error/warn, i.e. real diagnostics, so
                       the rule now allows those two by name instead of
                       being switched off. A stray console.log is still
                       an error, which is what the rule is for.
  18 max-statements    single-line `if (c) { stmt }` expanded.
  14 unused catch      every one of the 8 blocks handles the failure and
                       simply does not read the binding, so they become
                       optional catch binding. None was an empty swallow.
   5 multi-word-names  route views only. They are mounted by path and
                       never written as a tag, so they cannot collide
                       with an HTML element, which is the rule's purpose.
                       Scoped off for views/, kept everywhere else.
   2 deprecated props  can-close -> no-close, which is its INVERSE, so
                       `:canClose="!loading"` becomes `:noClose="loading"`.
                       And Vue Router 4 removed `exact`.
   2 jsdoc tags        {@see X} is not a valid inline tag, {@link X} is.
   1 event casing      MainMenu emitted 'open-settings' while App.vue
                       listens with @OpenSettings. That matched only
                       through Vue 3's camelize fallback in emit(); the
                       emit is now camelCase and the two agree directly.
   1 dead assignment   every branch assigns or returns, so the null
                       initializer was never read.

Verified: eslint 47 files 0/0, build exits 0, stylelint exits 0, and the
unit suite is 98/98 both before and after, run on the same checkout.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 5fa3854

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 17:47 UTC

Download the full PDF report from the workflow artifacts.

planninq was the last fleet app whose shell was hand-written: a router
with 11 routes in src/router/index.js, a MainMenu.vue listing the same
five destinations again, an own-rolled "OpenRegister is required" gate,
and a Dashboard.vue that computed its three KPI counts by filtering an
already-fetched project list in the browser. The manifest carried only
observability keys and said so: "planninq renders no manifest-driven UI".

It does now. The manifest owns the routes, the navigation, the dependency
gate and the dashboard:

  dependencies  -> CnAppRoot's dependency phase, keeping planninq's own
                   empty state through the #dependency-missing slot
  menu          -> CnAppNav (5 destinations + a Documentation footer link)
  pages         -> 9 pages; main.js builds the vue-router config from
                   them, one route per page with name === page.id
  Dashboard     -> type:"dashboard" with three declarative "stat" widgets
                   counted BY OPENREGISTER instead of in the browser

MainMenu.vue, router/index.js and views/Dashboard.vue are deleted. The
dashboard's two non-KPI panels move to components/DashboardPanels.vue
unchanged; UserSettings.vue loses its own dialog wrapper and becomes a
bare NcAppSettingsSection in CnAppRoot's #user-settings slot. The sidebar
outlet and its provide()d setSidebar/closeSidebar stay in App.vue — that
is app behaviour the shell does not own.

Two things worth knowing for the next app that does this:

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. A type with no catalog entry
   renders "Widget not available" with nothing logged, so the panels
   widget is registered in main.js, not in registry.js.
2. CnStatWidget resolves its "icon" through the library's own widget-icon
   catalog too, which is ~57 names and does not include every MDI icon —
   AccountGroupOutline and ArchiveOutline silently became the default
   grid glyph. The registered names are AccountGroup and History.

Also fixes a pre-existing display bug the move surfaced: the project list
printed project.icon raw, so a stored icon NAME rendered as text
("AccountMultiplePlusOnboarding Automation"). A name now goes through
CnIcon; an emoji still renders as text.

Verified in the browser against the published @conduction/nextcloud-vue
(USE_LOCAL_LIB=false, not the sibling checkout): all 9 routes resolve to
the right page id with real content and no JS errors, including the
parameterised project board / backlog / timeline; the three KPI tiles
read 3 / 3 / 0 from OpenRegister in the canonical horizontal card; both
panels render and navigate. 98 unit tests pass, eslint is clean.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ee48191

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 19:39 UTC

Download the full PDF report from the workflow artifacts.

github-actions Bot and others added 2 commits August 31, 2026 22:14
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
check:manifest failed on development after #530, and took Hydra Gates, E2E and
Quality Report down with it:

  /pages/1..8 must have required property '_note'

The schema requires a custom page to say why decomposition into a standard page
type was not feasible. It relaxes that only when the component matches the
library's ^Cn[A-Z]\w+$ pattern, because then the component name documents the
choice itself. All eight pages use host-app SFCs, so none qualified.

Each note is derived from what the component actually does, read from its
template, not from the page id:

  ProjectBoard    column-per-status board with drag-to-transition
  ProjectTimeline task bars plus dependency edges, fed by /api/timeline
  Timesheet       entries grouped per day, inline edit
  TaskDetail      detail plus an embedded time-entry log
  Portfolio       per-assignee aggregate with no single backing record
  Projects        card list with a client-side status chip filter
  ProjectBacklog  parent-scoped list under a breadcrumb
  Boards          board picker: entry points rather than records

⚠️ Three of these are worth a second look rather than treating this as settled.
Projects, ProjectBacklog and Boards are thin list surfaces (113 to 424 lines)
that may well fit CnIndexPage once the chip filter and the parent breadcrumb
have primitives. The notes record what each is and what the primitive lacks, so
converting them later is a smaller decision than rediscovering why they were
custom.

Verified: check:manifest, lint and build all exit 0, and the diff is exactly
eight changed lines. An earlier attempt round-tripped the JSON and reformatted
218 lines while still passing the gate.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 747d5ca

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 20:47 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 82bc71d

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 20:57 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde and others added 2 commits August 31, 2026 23:34
Both were failing on development before the manifest work, and both are
user-visible rather than bookkeeping.

gate-102 manifest-l10n-coverage: 9 manifest strings had no translation, so a
Dutch user saw English navigation. The parity checker requires the official
language of every European country, so the strings are added across all 36
required locales, not only nl. Dutch follows this app's own catalogue, where
board is already 'bord' (Kanban-bord, Bordweergave) and Archived is
'Gearchiveerd'.

gate-60 icon-vocabulary, two findings:
  - src/icons.js did not register AccountGroup or History while the manifests
    name them. An unregistered name renders NO icon, not a fallback, so those
    entries were shipping a blank.
  - the Dashboard entry used 'Home' where ADR-077 Tier A requires
    ViewDashboardOutline for the dashboard concept. Tier A is a MUST.

The remaining Tier B warning (Portfolio on ChartBar rather than
BriefcaseOutline) is a SHOULD and is left alone.

⚠️ Twice while doing this a scripted edit passed the gate and produced a wrong
diff. Round-tripping the manifest through json.dumps reformatted 218 lines, and
sorting the locale dicts rewrote every existing key in all 37 files: 13,635
added lines for 333 real ones. Both were reverted and redone as order-preserving
edits. The diff is now 745 added over 76 files, which is the 9 keys per locale
plus the generated .js.

Verified: check:l10n, check:l10n-js, check:manifest, lint and build all exit 0,
and icon-vocabulary reports 0 failures.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
… swallowing clicks (#536)

due-date-reminder-settings.spec.ts failed with a 60s click timeout on the
Planninq settings button. The button was never the problem. The call log reads:

  - locator resolved to <button ... aria-controls="nc-vue-7">
  - element is visible, enabled and stable
  - <div role="dialog" ... data-testid-modal="cn-support-dialog"> subtree
    intercepts pointer events

nc-vue opens the support dialog on first visit and records that the user has
seen it in a per-user preference. Playwright starts from a fresh browser
profile every run, but that preference lives on the SERVER, so it is never
there and the dialog mounts as a full modal mask over the app in every spec.

The seed now writes it once for the admin the suite runs as, which is what
buildiq's seed already does for the same reason.

Verified against the dev instance rather than assumed: deleting the preference
and replaying the exact call the seed makes returns HTTP 200 and the preference
reads back as present. bash -n passes.

This addresses the E2E job only. The app itself was never broken here: the
settings dialog works, it was covered.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ee5f879

Check PHP Vue Security License Tests
lint ⏭️
phpcs ⏭️
phpmd ⏭️
psalm ⏭️
phpstan ⏭️
phpmetrics ⏭️
eslint ⏭️
stylelint ⏭️
build ⏭️
composer ⏭️ ⏭️
npm ⏭️ ⏭️
app:check-code ⏭️
info.xml ⏭️
REUSE ⏭️
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 21:50 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 264f8d6

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 22:08 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde and others added 2 commits September 1, 2026 07:00
… label (#540)

With the support-dialog fix in, due-date-reminder-settings.spec.ts stopped
failing on an intercepted click and started failing on a locator that resolves
to nothing:

  waiting for locator('#app-navigation-vue').locator('a[title="Settings"]')

There is no such element. CnAppNav auto-prepends the entry that opens the app's
NcAppSettingsDialog and names it "Personal settings", and that name is
translated, so a title selector is a language assertion this suite has no
business making. It is the same defect class as the vault unlock button, which
matched /^(Unlock|Set up vault)$/ and found nothing on a Dutch instance.

The library carries stable ids for exactly this: data-testid="cn-nav-settings"
on the foldout and data-testid="cn-nav-personal-settings" on the entry. Both
are present in the installed bundle (2.27.2), verified rather than assumed.

🔴 The click targets the <a> INSIDE the entry, not the test id itself.
data-testid lands on NcAppNavigationItem's ROOT, which is an <li>; clicking
that is a silent no-op and the failure then surfaces several lines later on
whatever the dialog was supposed to show.

planninq declares no section:"settings" menu entries, so the foldout exists
solely because includePersonalSettings defaults true. That is why the entry is
the auto-prepended one rather than an app-declared item.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
gate-60 reported 1 Tier B warning. Adopted. 1 -> 0.

  Portfolio  ChartBar -> BriefcaseOutline

A portfolio of projects is not a bar chart. ChartBar described one VIEW of a
portfolio rather than the thing itself.

⚠️ BriefcaseOutline had to be REGISTERED in src/icons.js in the same commit.
It was not there, and an icon a manifest names but the registry does not hold
renders as NOTHING, not a fallback.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 6bb2ede

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 05:19 UTC

Download the full PDF report from the workflow artifacts.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ac99c51

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 05:34 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 3b81340

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 05:59 UTC

Download the full PDF report from the workflow artifacts.

`npm run lint` was `eslint src`, so two whole trees were never linted. Across
the fleet that hid roughly 3,900 errors, none of which any CI leg had shown.

Most of it was the config, not the code, and the same two defects were in
every app.

**scripts/ had no config block at all.** These are CommonJS Node CLI checkers,
and flat config defaults every `.js` to ESM with browser-ish globals, so eslint
read the CommonJS wrapper itself as undefined identifiers: `require`,
`process`, `__dirname`, `__filename`, `module`. A `scripts/**` block now
declares the environment. Declaring beats suppressing here: `no-undef` is the
rule that catches a genuinely misspelled identifier, and dozens of fake
findings would bury a real one. A second block covers `scripts/**/*.mjs`, which
is ESM and needs Node's globals without the CommonJS wrapper.

**The tests block applied a non-TypeScript-aware rule to TypeScript.** It named
`tests/**/*.ts` while setting the CORE `no-unused-vars`, which v9 deliberately
turns off for `.ts` in favour of the `@typescript-eslint` version. The core
rule reads the parameter names inside a function TYPE as bindings, so

    t?: (app: string, key: string) => string

reports `app` and `key` as unused variables, and every unused `catch (e)` in a
`.ts` spec reports twice. The block is split now: `.js`/`.mjs` on the core
rule, `.ts`/`.tsx` on the TypeScript one, same patterns on both.

Also: stale `eslint-disable` comments naming plugins eslint 10 no longer
registers, which are themselves errors ("Definition for rule ... was not
found"), and a rule that must not parse shell scripts.

The genuinely real findings were the useful part: dead locals, unused imports,
dead helper functions, unused `catch` bindings, extensionless relative imports,
and a handful of `== null` comparisons spelled out so they still match null AND
undefined.

Verified per app: `npm run lint` 0 errors over src + tests + scripts,
`prettier --check` clean, and the unit suite still green.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 5a3aa74

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 10:40 UTC

Download the full PDF report from the workflow artifacts.

Nextcloud serves an app under both /apps/planninq/... and
/index.php/apps/planninq/..., but generateUrl() returns only the form the
instance is configured for. Used as the vue-router base, that means a visitor
arriving on the other form has a pathname the router cannot strip its base
from. No route matches, the catch-all takes over, and they land on the
dashboard with no error at all.

Measured live on learniq, which had the identical base, across all 282 of its
routes: /apps/learniq/courses resolved to Courses, and
/index.php/apps/learniq/courses resolved to the dashboard. Not one broken page,
every deep link in that URL form.

routerBase() derives the base from the pathname, so it always matches the URL
the visitor actually arrived on. openregister, opencatalogi, stackiq, larpinq,
zaakafhandelapp, pipelinq and keepiq already do exactly this.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 4e21942

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 19:14 UTC

Download the full PDF report from the workflow artifacts.

… inside (#548)

its own card.

⚠️ THE CAUSE IS AN INSET, NOT A COMPONENT. A card widget renders `flush` and
then has its padding put BACK by the card-fit rule (`padding: 8px 14px`), so
the KPI sits inside the wrapper while the WRAPPER draws the border, radius
and background the user reads as "the card". The library's
`--clickable:hover` rule then drew a 2px border and a drop shadow on the KPI
itself, 8-14px in from the edge being hovered.

Measured live on dossiq, while genuinely hovered: the tile carried a 2px
rgb(0,103,158) border and its own shadow, inset 9px from the wrapper's top
and 15px from its left. A non-card-fit tile sits at 1px, so its border lands
on the wrapper's own edge and reads as one card. That inset is the whole
difference, which is why it looked app-specific and was not.

nextcloud-vue#932 moves the affordance to the wrapper. No layout change:
nothing moves, one card outlines. Verified in the browser with a real pointer
hover:

  before   inner 2px rgb(0,103,158) + shadow   wrapper grey, no shadow
  after    inner transparent, no shadow        wrapper rgb(0,103,158) + shadow

Every app with clickable stat, gauge or delta tiles had this. This bump is
one of the fleet sweep that clears it.

Dependency change only: package.json and the nextcloud-vue entry in
package-lock.json.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 9467ed6

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 536/536
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 19:11 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant