feat(admin-templates): template re-sync to existing copies + archive#11
Merged
Merged
Conversation
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
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
July 23, 2026 23:02
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.
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:POST /api/admin/templates/{id}/resyncwithstrategy+dryRun, guarded byAuthorizedAdminSettingand an explicitassertAdmin().dryRunreports the full plan and mutates nothing.Version002006Date20260723000000adds atemplate_placement_idorigin column so a copy's widgets can be traced back to the template.docs/features/admin-template-resync.md.Verification (local, no CI wait)
phpunitfull suite after rebase → 1417 tests, 3475 assertions, OK (3 pre-existing skips).npx vitest run→ 45 files / 413 tests pass.A pre-existing bug fixed in passing
TemplateServicefirst-access cloning was droppingcontent/customIcon/tile fields. Fixed, since re-sync depends on the clone being faithful.Coordination note
This change and
tile-usage-analyticsboth generatedVersion002006Date20260723000000. I renumbered the analytics one toVersion002007Date20260724000000; both now coexist and the full suite passes.Still open (left unchecked in the archived tasks.md)
Notifications use Nextcloud
INotificationonly — thex-openregister-notificationsdialect branch is not wired in, because no OR-dialect code exists anywhere in this app yet. Flagged rather than faked.