Skip to content

feat(admin-templates): template re-sync to existing copies + archive#11

Merged
rubenvdlinde merged 3 commits into
developmentfrom
wip/build-template-resync-2026-07-23
Jul 23, 2026
Merged

feat(admin-templates): template re-sync to existing copies + archive#11
rubenvdlinde merged 3 commits into
developmentfrom
wip/build-template-resync-2026-07-23

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Implements and archives admin-template-resync. Distributed templates create independent personal copies, so until now correcting a template only reached future first-logins — a beheerder who fixed a wrong link still left 40 colleagues on the old layout.

What

  • TemplateResyncService — diffs a template against each provisioned copy and applies a strategy:
    • merge — template widgets updated, user-added widgets kept
    • overwrite — layout replaced wholesale
    • compulsory widgets reconciled under both
  • POST /api/admin/templates/{id}/resync with strategy + dryRun, guarded by AuthorizedAdminSetting and an explicit assertAdmin().
  • dryRun reports the full plan and mutates nothing.
  • Idempotent; writes an audit record; notifies affected users; hands large groups to a background job.
  • Version002006Date20260723000000 adds a template_placement_id origin column so a copy's widgets can be traced back to the template.
  • docs/features/admin-template-resync.md.

Verification (local, no CI wait)

  • phpunit full suite after rebase → 1417 tests, 3475 assertions, OK (3 pre-existing skips).
  • npx vitest run45 files / 413 tests pass.
  • Directly tested: dry-run mutates nothing; merge preserves user additions; overwrite replaces; compulsory reconciled in both strategies; audit written; idempotency.

A pre-existing bug fixed in passing

TemplateService first-access cloning was dropping content/customIcon/tile fields. Fixed, since re-sync depends on the clone being faithful.

Coordination note

This change and tile-usage-analytics both generated Version002006Date20260723000000. I renumbered the analytics one to Version002007Date20260724000000; both now coexist and the full suite passes.

Still open (left unchecked in the archived tasks.md)

Notifications use Nextcloud INotification only — the x-openregister-notifications dialect branch is not wired in, because no OR-dialect code exists anywhere in this app yet. Flagged rather than faked.

Adds an explicit, admin-initiated re-sync action that pushes an updated
admin template onto its already-provisioned user copies, with an
overwrite (replace layout) or merge (reconcile template changes while
keeping user-added widgets) strategy. Dry-run computes and reports the
plan without mutating; a real run is transactional per copy, writes one
audit record via ActivityPublisher, notifies affected users, and applies
inline for small target groups or via a new TemplateResyncJob for large
ones.

- TemplateResyncService diffs each copy against the template using a new
  WidgetPlacement.templatePlacementId origin key (stamped by
  TemplateService::clonePlacement at first-access) to tell template-origin
  placements apart from user additions. Compulsory widgets get no special
  code path — they're ordinary template placements, so both strategies
  reconcile them identically.
- POST /api/admin/templates/{id}/resync on the existing AdminController,
  admin-guarded, registered in appinfo/routes.php ahead of the {id}
  wildcard routes.
- TemplateResyncModal.vue (src/modals/) gates Apply behind a reviewed
  dry-run for the selected strategy.
- Fixed a pre-existing gap in TemplateService::clonePlacement: first-access
  template distribution was dropping content/customIcon/tile* fields.

Notification uses this app's existing Nextcloud INotification pattern
only; the x-openregister-notifications dialect branch is not wired in
(no OR dependency exists anywhere in this app yet) — left as a follow-up.
… tags

A change-dir @SPEC target breaks the moment the change is archived, so all
tags now point at openspec/specs/admin-templates/spec.md. Adds the three
missing tags gate-16 flagged (TemplateResyncJob::run, modal handleClose/handler).
Documents merge-vs-overwrite, why dry-run first, the compulsory-widget
guarantee and the INotification-only limitation. Change archived.

OR-notification-dialect branch remains open and is left unchecked.
@rubenvdlinde
rubenvdlinde merged commit 8ed9c40 into development Jul 23, 2026
1 check failed
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