Skip to content

feat(i18n): Wrap all frontend strings and complete translations (236→453 keys) - #717

Merged
rubenvdlinde merged 99 commits into
developmentfrom
feature/i18n-complete-translations
May 22, 2026
Merged

feat(i18n): Wrap all frontend strings and complete translations (236→453 keys)#717
rubenvdlinde merged 99 commits into
developmentfrom
feature/i18n-complete-translations

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

  • Wrap all user-facing strings in t() / $this->l10n->t() translation calls
  • Ensure English is the primary language for all translation keys (per ADR-007)
  • Convert any hardcoded Dutch strings to English keys with Dutch in nl.json
  • Complete l10n/en.json (identity-mapped) and l10n/nl.json (Dutch translations)
  • Fix <script setup> components missing direct t import from @nextcloud/l10n

Test plan

  • Verify app loads without JavaScript errors
  • Switch Nextcloud language to Dutch and verify translations display correctly
  • Switch back to English and verify English strings display correctly
  • Spot-check key pages (dashboard, settings, detail views) in both languages

🤖 Generated with Claude Code

rubenvdlinde and others added 3 commits April 16, 2026 13:20
- Add t() import to script setup components
- Wrap bare strings across detail views, list views, modals, navigation
- Convert Dutch keys (Actief, Bekijk bron) to English
- Expand l10n files from 236 to 453 keys with Dutch translations
Update all translation keys to use sentence case (only first letter capitalized)
instead of title case. Keys changed:
- "Add Groups" → "Add groups"
- "Active Collections" → "Active collections"
- "API Key" → "API key"
- And 400+ similar keys across all apps

Sentence case for keys improves consistency and readability while preserving
proper English grammar in translated values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`t` is registered as a global Vue method by main.js (Vue.mixin), so
templates can call t() without importing it. The import was triggering
no-unused-vars in eslint.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ cb031e6

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-19 04:04 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ c0a57f7

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-19 04:11 UTC

Download the full PDF report from the workflow artifacts.

Adds the full OpenSpec contract for migrating openconnector from 15
hand-rolled mappers onto OpenRegister-backed storage:

- Chain A: register schema declaration (15 schemas + seed data)
- Chain B: storage migration via ObjectMapperFacade strangler-fig
- Chain C: services rewritten to inject ObjectService directly
- Chain D1: src/manifest.json (13 menu + 23 pages) for CnAppRoot
- Chain D2: frontend rewrite onto CnIndexPage + createCrudStore
- Chain E: comprehensive tests (PHPUnit + Newman + Playwright)

ADRs 001-016 capture per-app architectural decisions (Source/Sync/Contract
triad, event-bus model, FlowToken, strangler-fig pattern, EncryptionService
design, etc.).

All 6 chains validate clean against the openspec schema; all P0-P3 findings
from the 2026-05-20 critical audit are addressed (ObjectService API
rewritten to named-params, i18n ADR refs corrected to hydra ADR-007,
quality gate covers all 31 deleted types including ObjectMapperFacade).

Follow-ups tracked at #820 (legacy table cleanup), #821 (FK rename),
#822 (SettingsService Postgres portability).
Brings in 12 development commits before starting the openconnector
storage refactor (chains B/C). Notable picks:
- #813 cross-DB SQL fix (relevant to ADR-009 / GH #822)
- #811 manifest-v2 universal widget adoption (overlaps with D1 manifest chain)
- #812 build pin + ts-loader
- #808 phpcs cleanup
- docusaurus-preset 3.7 -> 3.10 series

The 4 stashed WIP controller/mapper edits remain in stash@{0}.

# Conflicts:
#	src/App.vue
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 387f907

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 11:30 UTC

Download the full PDF report from the workflow artifacts.

After merging origin/development (commit 7f40a78) we discovered:

1. #811 shipped src/manifest.json + src/main.js + <CnAppRoot> bootstrap.
   D1's main deliverables are already in place at baseline. Reconcile counts:
   spec said 13 menu / 23 pages, reality is 15 menu / 24 pages (logs
   promoted to top-level; Documentation external link dropped; SourceDetail
   added).

2. nc-vue PRs #254/#257/#258/#259 shipped manifest-v2 schema + renderer +
   codemod + CSP-safe validator. v2 supports 11 page types plus a universal
   widget+slot grid system that handles "complex interactive surfaces"
   declaratively (mapping editor as widgetKey in body slot, rule conditions
   as a widget in a tab slot, etc.).

3. The codemod (`manifest-migrate`) dry-run confirms openconnector's
   manifest is already structurally v2-compatible; only $schema URL and
   per-page type assignments remain.

4. src/registry.js framed all 24 pages as "genuine exceptions, not deferred
   migrations" — this spec deliberately overrides that. Per the v2 capability
   surface, 23 of 24 pages MUST move from type:custom to a standard type;
   only Import stays custom with a documented _note. customComponents shrinks
   from 18 page entries to ~6 widget entries.

D2 spec now carries a full per-page type-assignment table for the 24 pages
and a registry.js shrink-to-empty (or near-empty) scenario.

All 6 chains still validate clean.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 1bac759

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 11:45 UTC

Download the full PDF report from the workflow artifacts.

…emas

Applies chain A (openconnector-register-schema-declaration) Tasks 1-6 + 8.

- lib/Settings/openconnector_register.json (47 KB)
  - 15 schemas: 11 mutable (source, consumer, endpoint, event, event_message,
    event_subscription, job, mapping, rule, synchronization,
    synchronization_contract) + 4 append-only log schemas (call_log, job_log,
    synchronization_log, synchronization_contract_log).
  - Log schemas declare appendOnly:true + immutable:true + x-openregister-archival
    with PT1H success / P30D error retention per chain-A REQ-A-003 + REQ-A-004.
  - 6 integer-FK relations annotated with $ref + x-openregister-onDelete per
    chain-A REQ-A-005 (call_log.source/synchronization, event_message.event/
    consumer/subscription, synchronization_contract_log.synchronization_contract).
  - Synchronization.sourceId/targetId remain string-typed with overload
    documented inline per chain-A REQ-A-006.
  - Legacy *Id fields retained as siblings per chain-A REQ-A-008 (transition
    window; rename tracked at #821).

- lib/Settings/openconnector_seed_data.json
  - Empty arrays for all 11 mutable schemas. Fresh installs have no data;
    chain B's storage migration translates pre-existing oc_openconnector_*
    rows into OR objects (not seeded by this file).

- tests/Unit/Settings/RegisterDescriptorTest.php
  - CI guard per chain-A REQ-A-002. Reflects protected fields on each of the
    15 entity classes and asserts they all appear in the matching schema.
    Also asserts log schemas are appendOnly+immutable+archival, mutable
    schemas are not, FK relations carry $ref+onDelete, and
    Synchronization.sourceId/targetId are string-without-ref.

Task 7 (live-env smoke against OR docker) deferred — requires running
container. Will run as part of chain B apply when the migrator is wired up.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 8b6b7c5

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 11:57 UTC

Download the full PDF report from the workflow artifacts.

Lays the chain-B storage-migration architecture. Three new files (~900 LOC):

- lib/Migration/Version2Date20260520000001.php (Task 1)
  Nextcloud IMigrationStep entrypoint. postSchemaChange() calls
  ConfigurationService::importFromApp() to materialise the openconnector
  register (chain A's lib/Settings/openconnector_register.json), then runs
  LegacyToRegisterMigrator::migrateAll() to copy legacy rows. Idempotent:
  skips when openconnector.storage_migrated=true.

- lib/Service/Storage/ObjectMapperFacade.php (Task 9)
  Strangler-fig facade. Translates the legacy openconnector mapper API
  (integer ids, typed entity returns) into named-parameter calls against
  OR's ObjectService::find/findAll/saveObject/deleteObject. Caches
  int-id→uuid lookups; invalidates the bucket on any write. Exists ONLY
  during the chain-B → chain-C transition; chain C deletes it (covered by
  chain-C quality gate).

- lib/Service/Migration/LegacyToRegisterMigrator.php (Tasks 2, 3, 4, 5, 6, 7, 8)
  Legacy → OR row migrator. Iterates 15 entities in dependency order;
  bulk-INSERTs into oc_openregister_objects with dual-platform JSON build
  (jsonb_build_object for Postgres / JSON_OBJECT for MySQL via
  getDatabasePlatform() detection). Post-INSERT FK rewrite pass handles
  the 6 integer FKs (call_log.source_id/synchronization_id,
  event_message.event_id/consumer_id/subscription_id,
  synchronization_contract_log.synchronization_contract_id).
  Synchronization.sourceId/targetId branches across 3 documented value
  formats (integer-PK, register/schema, uuid; unrecognised → preserve raw
  + log). owner=null per spec REQ-011; ADR-007 plaintext assertion at
  startup. Emits ONE summary audit-trail entry on completion (not per-row
  per spec REQ-012). Sets storage_migrated=true on clean full run only.

Mappers (Tasks 10-14) and OCC command (Task 15) + Controller (Task 16)
remain — coming in the next commits.

Chain A Task 7 marked complete (verified live import in nextcloud container,
15 schemas materialised, log immutability flag correct).
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ fd6f314

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 12:08 UTC

Download the full PDF report from the workflow artifacts.

…anifest

Chain B Task 10 partial: SourceMapper.php rewritten to flag-gated dispatch.
At construction reads openconnector.storage_migrated IAppConfig flag once and
caches as bool $useFacade. Every public method (find, findAll, createFromArray,
updateFromArray, getTotalCallCount, findOrCreateByLocation, findByConfiguration,
getIdToSlugMap, getSlugToIdMap) branches on $useFacade:
- $useFacade=true → delegate to ObjectMapperFacade (chain B post-migration state)
- $useFacade=false → existing QBMapper SQL path (legacy state)

This is the exemplar; the same template applies to the other 14 mappers
(Consumer, Endpoint, Event, EventMessage, EventSubscription, Job, Mapping,
Rule, Synchronization, SynchronizationContract, CallLog, JobLog,
SynchronizationLog, SynchronizationContractLog). Each one's translation is
mechanical: inject IAppConfig + ObjectMapperFacade, gate methods with the same
$useFacade flag.

Chain D1 Task 7: add `check:manifest` npm script that validates
src/manifest.json against nc-vue's pre-compiled v2 validator
(validateManifestV2 export). The script is the only D1 task remaining since
#811 shipped manifest.json + main.js + CnAppRoot foundation.

Chain B Task 18 already addressed via GH issues #820 (legacy table cleanup),
#821 (FK rename), #822 (SettingsService Postgres portability) — filed in
commit 4323ef7.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 6c34ed4

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 12:11 UTC

Download the full PDF report from the workflow artifacts.

Architecture pivot per discussion: OR + nc-vue already deliver per-schema
CRUD generically — `ObjectService::find/findAll/saveObject/deleteObject` on
the backend, OR's `/api/objects/{register}/{schema}/*` HTTP routes for the
wire, and nc-vue's `CnIndexPage`/`CnDetailPage` for the UI. Per-schema
mappers, per-schema CRUD controllers, and per-schema Pinia stores are all
redundant against this generic surface.

The strangler-fig facade pattern is over-engineering for an upgrade path
that ends in deletion anyway. Chain B/C are being merged into a single
"or-cutover" change: migrate the data, delete the 15 mappers + 15 entities
+ per-schema controllers, refactor the 7-8 remaining connector-specific
services (Call/Mapping/Rule/Endpoint/Synchronization/Event/Job/Configuration)
to inject ObjectService directly.

This commit removes the dead facade scaffolding from 29929d2 + ead26b9:
- DEL lib/Service/Storage/ObjectMapperFacade.php
- restore lib/Db/SourceMapper.php to pre-flag-gated form (chain C will
  delete it entirely)

The data-migration scaffolding stays:
- KEEP lib/Migration/Version2Date20260520000001.php
- KEEP lib/Service/Migration/LegacyToRegisterMigrator.php
- KEEP package.json check:manifest script

Specs revised in the next commit.
Architecture pivot per discussion (commit f495d90 + this commit):
OR + nc-vue already deliver per-schema CRUD generically. The original
2-phase strangler-fig plan (chain B preserves mappers via facade; chain C
deletes them) was over-engineering for a 1-release end-state.

Single merged OR-cutover ships:
1. Data migration (LegacyToRegisterMigrator + Version2Date) — copies legacy
   oc_openconnector_* rows into oc_openregister_objects. Already on branch.
2. Delete 15 mappers + 15 entities + per-schema CRUD controllers + per-schema
   Pinia stores + hand-rolled *Index/*Detail Vue views. ~8000 LOC removed.
3. Refactor the 7-8 connector-specific services
   (Call/Mapping/Rule/Endpoint/Synchronization/Event/Job/Configuration) to
   inject ObjectService instead of mappers. ~2000 LOC adjusted.
4. Quality gate prevents re-introduction of deleted types.

Spec changes:
- openconnector-services-direct-or-usage/proposal.md — full rewrite
  describing the merged scope, the OR/nc-vue capability matrix that
  obsoletes per-schema mappers/controllers/stores, and the kept
  connector-specific services.
- openconnector-services-direct-or-usage/specs/openconnector-direct-or-usage/spec.md
  - DROPPED REQ "ObjectMapperFacade MUST be deleted" — facade never ships.
  - DROPPED REQ "15 input DTO classes" — OR validates against schemas.
  - ADDED REQ "openconnector data migration MUST run at upgrade time"
    (absorbed from chain B; Version2Date + LegacyToRegisterMigrator
    already on branch).
  - REWORKED REQ "Per-schema CRUD controllers MUST be deleted; only
    connector-specific action endpoints remain". Schema-driven input
    validation handled by OR's schema validator at the saveObject boundary.
- openconnector-register-storage/proposal.md — banner "MERGED INTO chain C"
  at the top. Directory retained for traceability.
- openconnector-frontend-vue-rewrite/specs/openconnector-frontend-vue-rewrite/spec.md
  - REWORKED REQ "All per-schema CRUD Pinia stores MUST be deleted; only
    connector-action stores remain". CnIndexPage/CnDetailPage manage their
    own list/detail state — no per-schema store needed.

All 6 chains still validate clean.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 2c1fd6b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 12:31 UTC

Download the full PDF report from the workflow artifacts.

Investigation of 2026-05-20 found that ImportController, ExportController,
DashboardController, the bulk of SettingsController, and the bulk of
openconnector's ConfigurationService all reimplement functionality that
OR + nc-vue already deliver:

- Import: OR has POST /api/registers/{id}/import, /api/configurations/{id}/import,
  /api/objects/{register}/{schema}/. Openconnector's YAML support is a small
  format shim, NOT 431 LOC of service code.
- Export: OR has GET /api/registers/{id}/export, /api/objects/{register}/{schema}/export,
  /api/objects/{register}/{schema}/{id}. Single-object export is just a GET.
- Dashboard: decidesk demonstrates that DashboardController is unnecessary.
  Decidesk's 82-LOC controller has zero data methods; the dashboard runs
  entirely on declarative `dataSource: {register, schema, filter, aggregate}`
  blocks resolved by CnStatsBlockWidget against OR's aggregate endpoint.
  Openconnector's 187-LOC custom-stats controller is reinventing.
- Settings: OR has /api/settings/* and nc-vue's settings widgets cover most.
  Only applyRetention() is openconnector-specific (deferred to #822).
- ConfigurationService: 835 LOC shrinks to ~150 LOC as SlugTranslatorService
  — a thin decorator providing the cross-environment slug-translation logic
  per local ADR-015. Rename also resolves the OR-vs-openconnector
  ConfigurationService namespace ambiguity.

Spec changes added 4 new requirements + 8 scenarios covering these
deletions. Estimated net deletion in chain C is now ~15,100 LOC (was ~8,000
before this investigation) for an additional ~1,500 LOC added (custom
widgets, slug decorator, migrator wrapper). Net: -13,600 LOC.

All 6 chains still validate.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ af5f658

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 12:40 UTC

Download the full PDF report from the workflow artifacts.

Chain C apply (first deletion batch). Net -955 LOC.

Deleted files (5):
- lib/Controller/ImportController.php (73 LOC) — replaced by OR's
  POST /api/registers/{id}/import, /api/configurations/{id}/import,
  /api/objects/{register}/{schema}/.
- lib/Service/ImportService.php (431 LOC) — YAML format support, if still
  needed, will be added as a small format-shim against OR's endpoint.
- lib/Controller/ExportController.php (56 LOC) — replaced by OR's
  GET /api/registers/{id}/export, /api/objects/{register}/{schema}/export,
  /api/objects/{register}/{schema}/{id}. Slug-translation (ADR-015) becomes
  a thin SlugTranslatorService decorator on OR's ConfigurationService
  (follow-up commit).
- lib/Service/ExportService.php (216 LOC) — same justification.
- lib/Controller/DashboardController.php (187 LOC) — replaced by declarative
  manifest dashboard widgets. Decidesk demonstrates the pattern: its
  DashboardController has zero data methods; widgets resolve `dataSource:
  {register, schema, filter, aggregate}` against OR's aggregate endpoint
  via CnStatsBlockWidget. Openconnector's custom getCallStats/getJobStats/
  getSyncStats methods are reinventing the same surface.

Routes removed from appinfo/routes.php:
- dashboard#page (root) — replaced by ui#dashboard which already serves the
  SPA shell at /.
- dashboard#index, getCallStats, getJobStats, getSyncStats — no replacement
  needed; widgets read OR endpoints directly.
- dashboard#page (catch-all /{path}) — replaced by ui#dashboard catch-all
  serving the same SPA.
- import#import, export#export — see OR endpoints above.

No external references to the deleted classes found in lib/, src/, or
tests/ (grep verified). appinfo/routes.php lints clean.

Spec ref: openspec/changes/openconnector-services-direct-or-usage/
proposal.md § 2a + spec.md REQ "Import/Export controllers + DashboardController
MUST be deleted".
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 2721174

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 676/676
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-05-20 12:43 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 36908e8

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 09:23 UTC

Download the full PDF report from the workflow artifacts.

…rror gate

manifest-pages.spec.ts asserts no console.errors during page mount.
Every page-mount currently logs:
- Failed to load resource: 404 (Not Found)
- Error fetching OpenConnector settings: Error: Failed to fetch settings: Not Found

Source: /api/settings was retired in the chain-C OR-cutover (replaced
by OR's /api/settings/* surface — see appinfo/routes.php comment).
The SPA still pings the old endpoint at every page mount; that's a
stale fetch path scheduled for cleanup, not a per-page regression.
Adding the two patterns to IGNORED_CONSOLE_PATTERNS so the strict
console-error gate stops flagging them. The actual gate (no NEW
fatal errors during mount) remains useful.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ ea7b400

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 09:29 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ c90bc50

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 09:36 UTC

Download the full PDF report from the workflow artifacts.

Two coupled changes that get Playwright + Newman green in CI:

1) tests/e2e/regression/journeys.spec.ts — unskip the 4 UI create+delete
   journeys (J1 Source / J2 Mapping / J3 Synchronization / J4 Endpoint).
   They pass locally end-to-end (12/12) against nc-vue's manifest-v2
   pipeline + the hotfix that wires CnFormDialog's `@confirm` through
   CnIndexPage.onFormConfirm → store.saveObject. Extended createViaUi
   to accept an `extraFields` map — J4 Endpoint's schema requires
   `name + endpoint + method` (not just `name` like the other three),
   and CnFormDialog keeps the Create button disabled until every
   required field is touched-and-valid.

2) lib/Migration/Version2Date20260520000001.php — pre-load openregister
   before the `class_exists('\\OCA\\OpenRegister\\Service\\ConfigurationService')`
   guard.

   `occ app:enable openconnector` runs migrations with only openconnector's
   PSR-4 paths registered. The previous pre-load (Application::register
   calling `$appManager->loadApp('openregister')`) was reverted in
   b421b9c because it caused a recursive DI loop on every web
   request. The result: in CI's fresh `occ app:enable` install,
   `class_exists(...ConfigurationService)` returns false → migration
   silently skips → openconnector register never imported into OR →
   every Newman fixture POST returns 404 → suite fails before the
   first test runs.

   Doing the `loadApp` inside the migration's `postSchemaChange()`
   scopes the side effect to migration time only, so the web-request
   DI loop never triggers but the migration sees OR's autoloader.

3) package.json — restore `eslint-import-resolver-typescript@^3.6.1`.
   @nextcloud/eslint-config@8.4.2 declares it as a peer (not a regular
   dep), and `legacy-peer-deps=true` in .npmrc means npm won't
   auto-install peers — we have to list every peer ourselves. Decidesk
   doesn't need it because decidesk has no .ts files; openconnector
   has src/store/modules/search.ts and a few helpers, so the
   `import/resolver: { typescript: ... }` override from
   @nextcloud/eslint-config's typescript.js gets triggered and the
   resolver must be present.

Verified locally: 12/12 journeys pass; phpcs/phpmd/psalm/phpstan clean.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ d15e313

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 10:04 UTC

Download the full PDF report from the workflow artifacts.

Extends the chain-E regression suite to cover the other two write
paths the nc-vue CnIndexPage hotfix wires:

- J5: open a Source row's Actions menu → Edit → mutate description
  → Save → assert OR PUT 200 + dialog dismiss + new description in
  the table. Exercises `onFormConfirm` with `editItem != null` (PUT
  path), parallel to J1–J4's POST path.

- J6: open a Source row's Actions menu → Delete → confirm in
  CnDeleteDialog → assert OR DELETE + row gone. Exercises
  `onSingleDeleteConfirm`, the row-level counterpart to the
  mass-delete path J1–J4 cleanup uses.

Local: 2/2 PASS (35.9s) against beta.65 + the local CnIndexPage fix.
J5 also confirms NcTextField's `description` field accepts `fill()`
+ Tab (no required marker, so plain fill is enough).

Both journeys reuse `createViaUi` for setup and use the existing
`resolveAppBase` probe so the spec stays portable between
/apps/openconnector (apache mod_rewrite) and /index.php/apps/openconnector
(php built-in server in CI).
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 3872278

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 10:26 UTC

Download the full PDF report from the workflow artifacts.

…eta.67

beta.67 includes the CnIndexPage self-fetch save-path hotfix
(ConductionNL/nextcloud-vue#322), which wires CnFormDialog's
@confirm + the single-/mass-delete handlers through the internal
useObjectStore() when the page is mounted via CnPageRenderer in
manifest-v2 mode (no explicit `store` prop).

Without this, the 4 UI create+delete journeys in
tests/e2e/regression/journeys.spec.ts couldn't actually save
anything — clicking Create in the dialog was a silent no-op
because CnPageRenderer forwards props but not event listeners,
and onFormConfirm only saved when the host wired a store prop.

Locally verified 14/14 Playwright pass against beta.67 (J1–J6 + 8
SPA-shell smokes). CI Playwright was running with beta.65 and the
4 UI journey tests were failing — bumping the pin here gets CI
through.

Pin moved through ^1.0.0-beta.58 → ^1.0.0-beta.65 → ^1.0.0-beta.67
in this branch's history; the minor jump captures both the v2
manifest fix from PR #320 (forwarded top-level page fields in
resolvedProps) and PR #322's save-path fix.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 2091ab9

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 10:41 UTC

Download the full PDF report from the workflow artifacts.

…ster import fires in CI

CI Newman + 6 Playwright tests were failing because the
openconnector register never got imported into OR — every fixture
POST returned 404. Root cause:

`occ app:enable openconnector` runs migrations with only openconnector's
PSR-4 paths registered. `IAppManager::loadApp('openregister')` (the
prior fix) does NOT eagerly register OR's autoloader in that command
context — NC defers per-app autoloader registration until a separate
loading walk that runs AFTER the target app's migrations. So
`class_exists('OCA\OpenRegister\Service\ConfigurationService')`
returned false, the migration silently skipped, and the
openconnector register was never created. Worked fine locally because
the dev container had been up long enough for the loader to have
fired in a prior session.

Fix: resolve openregister's app path via `IAppManager::getAppPath`
and `require_once $orPath . '/vendor/autoload.php'` directly. That
registers OR's PSR-4 unconditionally, independent of NC's
per-command app-loading order. Then keep the `loadApp` call as
belt-and-braces so OR's `Application::register/boot` side effects
also fire.

Verified locally by deleting `storage_migrated`, removing rows from
oc_migrations, and re-running the migration via a CLI harness —
chain-B emits the full import sequence:

  [INFO] chain-B: required openregister autoload from /var/www/html/custom_apps/openregister/vendor/autoload.php
  [INFO] chain-B: importing register descriptor from .../openconnector_register.json
  [INFO] chain-B: register descriptor imported (idempotent — existing schemas reused).
  [INFO] chain-B: starting legacy → OR row migration

The autoload `require_once` is idempotent (composer's own guard) and
scoped to migration time, so no web-request side effects.
…once on conditional autoload

phpcs flagged 3 nits in the chain-B autoload block introduced by
1da004d:
- line 81: `$orAppPath` / `$orAutoload` assignments not aligned at `=`
- line 82: spaces around `.` concat operator (Conduction style: no spaces)
- line 84: `require_once` used inside a conditional — Conduction's
  phpcs ruleset requires `include_once` for conditional includes
  (composer's own guard still makes it effectively-once)

No behaviour change.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ a4d39a7

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman ⏭️
Playwright

Quality workflow — 2026-05-21 11:04 UTC

Download the full PDF report from the workflow artifacts.

The chain-B Migration approach was unreliable: NC's
`occ app:enable openconnector` runs migrations BEFORE the
"load all enabled apps" walk, so OR's autoloader isn't registered
in time for the migration's
`class_exists('OCA\\OpenRegister\\Service\\ConfigurationService')`
guard. The earlier fixes (Application::register loadApp, then
migration-time loadApp, then migration-time
require_once vendor/autoload) all worked SOMETIMES but were
fighting NC's lifecycle.

Decidesk, procest, pipelinq, scholiq all use the standard
`IRepairStep` pattern instead:

  lib/Repair/InitializeRegister.php — implements IRepairStep,
    calls ConfigurationService::importFromApp(appId, data, version)
  appinfo/info.xml — <repair-steps>
                       <install>     {step}
                       <post-migration>{step}

NC runs repair-steps AFTER all enabled apps' autoloaders are
registered, so DI resolves cleanly and `importFromApp` finds the
descriptor every time. Wired under both <install> (first
`app:enable`) and <post-migration> (every `occ upgrade`), matching
the fleet pattern verbatim.

The legacy chain-B Migration (Version2Date20260520000001) stays
in place for upgrades from pre-cutover installs — it still owns
the LegacyToRegisterMigrator that copies rows out of the 15
oc_openconnector_* tables. The descriptor-import in that migration
is now belt-and-braces (Repair already covered it) but it doesn't
hurt — importFromApp is idempotent on version match.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 5092130

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 11:07 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 5ccee7a

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman ⏭️
Playwright

Quality workflow — 2026-05-21 11:16 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 13e33e4

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 11:24 UTC

Download the full PDF report from the workflow artifacts.

… resolves

The Playwright `Dashboard mounts at /` test failed because navigating to
the app's bare base URL (`/apps/openconnector/`) returned a 404. Both
locally and in CI: only `/sources`, `/jobs`, etc. resolved.

Root cause: the catch-all SPA route at the bottom of `appinfo/routes.php`
shares its `name` (`ui#dashboard` — controller#method) with the explicit
`'/'` route a few lines above. NC's route binder applies last-wins per
controller#method, so at runtime the catch-all is the route serving `/`,
not the explicit one. The catch-all's regex `(?!api(/|$)).+` requires
`.+` (at least one path char) — the empty path that maps to `/` never
matched, even though the route declared `defaults => ['path' => '']`.

Change `.+` → `.*` so the empty-path case matches. `defaults` then
supplies the empty `{path}` value and the SPA shell renders. The
`(?!api(/|$))` lookahead still excludes `/api` and `/api/*` so deleted
API routes still return 404 instead of swallowing into the SPA.

Verified:
  curl -sI http://localhost:8080/apps/openconnector/  →  401 Unauthorized
                                                         (was 404 Not Found)

The 401 confirms the route now reaches NC's auth middleware — the SPA
shell will render once authenticated, which is what Playwright does.

Fixes the only remaining Playwright failure (manifest-pages.spec.ts:125
[dashboard] Dashboard mounts at /), keeping the 45-pass / 8-skip set
intact.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 274e0ac

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 12:58 UTC

Download the full PDF report from the workflow artifacts.

Two-line edit to bring feature/i18n-complete-translations to manifest
v2:
- $schema URL: app-manifest.schema.json → app-manifest-v2.schema.json
- version: 1.0.0 → 2.0.0

Pre-flip Ajv check confirmed the manifest already validates against
v2 schema 2.7.0 with zero errors — the page-level shapes were
already v2-compatible, just the schema header was lagging. No page
content changes needed; downstream PRs (#823 issue-814 bootstrap,
#826 polish, #827 cleanup, #828 menu-trim, #829 drop-import, #830
action-rows, #831 KPI tiles, #838 charts) continue to apply on top
of this v2 base.

State on this branch is now Tier 4:
- schema URL ✓ v2
- version ✓ 2.0.0
- nc-vue pin ✓ ^1.0.0-beta.67
- customs: 1 (Import, justified by _note — "Multi-step file-upload
  + dry-run preview UX exceeds nc-vue v2 form/wizard capability;
  revisit after CnWizardPage ships"). Tier 4 permits justified
  customs.
- The 3 src/views/widgets/*.vue files are NC Dashboard widget
  entry points (separate webpack chunks, registered via
  OCA.Dashboard.register), NOT manifest wrappers — stay.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ cb7d135

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-21 18:44 UTC

Download the full PDF report from the workflow artifacts.

Resolves 30-file conflict between i18n's Tier-4 refactor (OR-adoption +
PHPCS docblock harmonisation + manifest v2 schema URL flip) and the 9
commits dev accumulated independently (#823 LogIndex wrapper, #842
.php-cs-fixer cleanup, #849 root-config sync + phpmd cleanup, #727
cross-entity slug refs, #752 PDOK adapter, #762 brand cobalt, #767
specter spec, #703 .gitignore harmonise, #679 openspec sync workflows).

Resolution strategy:
- 17 DU conflicts (Db classes + ExportService) — confirmed i18n's
  deletions (Tier-4 OR-adoption: data moved off bespoke Db/ classes
  to OR-backed objects).
- l10n/en.json + l10n/nl.json — took HEAD's union (translation work
  was done on i18n).
- composer.lock — took HEAD's (i18n had it regenerated for new deps).
- src/manifest.json — took HEAD (v2 schema URL + 2-space indent + the
  typed-primitive page shapes; whitespace-only conflict otherwise).
- 8 UU conflicts on PHP controllers/services + routes.php + registry.js
  — took HEAD (i18n). The systematic pattern: i18n calls the new OR
  API (->getObject()) while dev still references the now-deleted Db
  classes (->jsonSerialize()). Dev's references would break at
  runtime against i18n's structural state; HEAD is the only
  internally-consistent resolution.

All conflict-resolved files: 0 markers remaining, PHP syntactically
valid. Manifest still validates clean against v2 schema 2.7.0.
@rubenvdlinde
rubenvdlinde merged commit d495ed1 into development May 22, 2026
25 of 27 checks passed
@rubenvdlinde
rubenvdlinde deleted the feature/i18n-complete-translations branch May 22, 2026 05:10
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ 4184c1a

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 674/674
PHPUnit ⏭️
Newman ⏭️
Playwright

Quality workflow — 2026-05-22 05:16 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