Skip to content

feat(edit-content): related-content navigation via agnostic EditContentHost (#36349)#36491

Open
adrianjm-dotCMS wants to merge 10 commits into
mainfrom
issue-36349-related-content-breadcrumb-navigation
Open

feat(edit-content): related-content navigation via agnostic EditContentHost (#36349)#36491
adrianjm-dotCMS wants to merge 10 commits into
mainfrom
issue-36349-related-content-breadcrumb-navigation

Conversation

@adrianjm-dotCMS

Copy link
Copy Markdown
Member

Proposed Changes

Restores navigating between related content in the new Edit Contentlet and, to enable it cleanly, makes the editor presentation-agnostic.

Fixes #36349

Related-content navigation (the feature)

  • Clicking a related content's title opens it; a "Relating content" breadcrumb banner tracks the trail (grows/trims, click an earlier crumb to go back).
  • The existing unsaved-changes prompt still fires when navigating with a dirty form.
  • Works full-screen (URL-driven trail via the rc query param) and inside a dialog (in-place reload, in-memory trail).

Agnostic editor via EditContentHost (the mechanism)

The editor and its store no longer branch on isDialogMode — that conditional is removed entirely. Everything presentation-specific goes through an injected EditContentHost port:

Concern RouterEditContentHost (full-screen) DialogEditContentHost (dialog)
Identity route params dialog config
Navigation (related/crumb/locale/post-save/restore) router in-place reload
Title / breadcrumb document title + shell trail no-op
Save result URL is source of truth reported to opener via saved$

The shell provides the router host; the dialog component provides the dialog host. Adding a new presentation (e.g. side panel) is then just a new adapter + a thin host wrapper — no editor changes.

How to test

Full-screen (/content/:id): open a content with a relationship field → click a related content's title → it opens with the "Relating content" banner → click a crumb to go back. Verify locale switch, version restore, and post-save navigation still work; and that unsaved changes prompt.

Dialog (UVE or "create new related content"): edit/create content in the dialog → click a related content in a relationship field → the editor reloads in place within the dialog with the breadcrumb → go back via a crumb → save reports back to the opener.

Checklist

  • Tests: pnpm nx test edit-content — 107 suites green
  • Lint + typecheck clean
  • Manual QA (full-screen + dialog)

🤖 Generated with Claude Code

…ntHost (#36349)

Restore navigating between related content in the new Edit Contentlet: clicking
a related content's title opens it and a "Relating content" breadcrumb tracks
the trail (grows/trims, click to go back, unsaved-changes prompt preserved).

Makes the editor presentation-agnostic via an `EditContentHost` port so the same
editor works full-screen and inside a dialog (and, later, a side panel) with no
`isDialogMode` conditionals:

- `RouterEditContentHost` (full-screen): identity from the route, router
  navigation, document title + shell breadcrumb, URL-driven trail (`rc` param).
- `DialogEditContentHost` (dialog): identity from the dialog config, in-place
  reloads, in-memory trail, save result reported to the opener via `saved$`.

Identity (`resolveIdentity`), navigation (related content, crumbs, locale switch,
post-save/restore), the save result (`reportSaved`) and title/breadcrumb all go
through the host; `isDialogMode` is removed entirely.

Related-content navigation now also works from within a dialog (in-place reload).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @adrianjm-dotCMS's task in 9m 56s —— View job


Code Review — PR #36349

  • Gather context (diff, commits, changed files)
  • Review host abstraction & navigation store
  • Review store/feature refactors
  • Review relationship field & dialog changes
  • Post review

This is a clean, well-abstracted refactor. The EditContentHost port cleanly removes the scattered isDialogMode branching, and dead state/methods (isDialogMode, pendingLocaleInode, confirm/cancelPendingLocaleSwitch, enable/disableDialogMode, DialogInitializationOptions) were fully cleaned up — no dangling references. Test coverage is solid (nav store, both hosts, relationship field navigation, layout). A few observations below, none blocking.

New Issues

  • 🟡 Medium: core-web/libs/edit-content/src/lib/services/host/router-edit-content-host.ts:67-72 — On a locale switch inside an active related-content trail, reloadContent() navigates with queryParamsHandling: 'preserve', so rc keeps the pre-switch inode as the last (current) crumb. The switched-to locale has a different inode, so the breadcrumb's current crumb keeps labeling the previous language's version (and its cached title), while the editor shows the new one. goToSavedContent/buildTrailForSavedInode reconcile the last crumb on save, but locale switch has no equivalent.
    Assumption: the trail's last crumb should track the content actually open.
    What to verify: open A › B (related), then switch B's locale — does the breadcrumb's current crumb still read B's old-locale title? Same class applies to goToRestoredVersion (:108-117) if a restore mints a new inode mid-trail. If keeping the trail untouched on locale switch is intentional (the overlay host documents this at overlay-edit-content-host.ts:75-78), this is a non-issue — worth a confirming comment.

  • 🟡 Medium: core-web/libs/edit-content/src/lib/store/dot-related-content-navigation.store.ts:39,152titleCache is a providedIn: 'root' record persisted to sessionStorage and never trimmed — every visited content's inode→title accumulates for the tab's lifetime. Unbounded in a long editing session with many related jumps. Low practical impact (small strings, session-scoped, quota failure is swallowed by writeTitleCache), but there's no eviction. Fix this →

Notes (non-blocking)

  • dot-collapse-breadcrumb.component.html:16 — the collapsed-state separator was swapped from <ChevronRightIcon /> to <i class="pi pi-angle-right">, matching the existing pTemplate="separator" at line 25. Confirmed ChevronRightIcon is not an unused import in the component TS. Good consistency fix.
  • relationship-field.store.ts lastChangeSource ('load' vs 'user') is a clean solution to the async-load re-dirtying the form; the untracked read in updateValueField correctly avoids a reactive dependency.
  • overlay-edit-content-host.ts:128-131 correctly completes both subjects in ngOnDestroy — no leak.
  • dot-relationship-field.component.html:137 — the title link is a real <button> with focus-visible ring and type="button", which is the right accessible choice over a clickable <p>.

Verdict: 🟢 approve-worthy pending the two Medium items (both plausibly by-design). No 🔴/🟠 found.
issue-36349-related-content-breadcrumb-navigation

…36349)

Update stale JSDoc/comments that still described the old "dialog mode vs route
mode" branching: the nav store now holds a URL-or-in-memory trail and does not
navigate (the host does), and workflow/layout comments reflect host delegation.
Comment-only; no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ath (#36349)

Resolve the two behavioral findings from the PR review plus the smaller ones:

- Dialog "Keep editing" no longer leaves a stale breadcrumb: the in-place trail
  is now emitted with the reload request and committed by the layout (host.setTrail)
  ONLY after the unsaved-changes check passes, instead of being written up-front.
- The dialog no longer blanks a full-screen editor's breadcrumb behind it: the
  in-memory trail moved off the root nav store onto a per-instance signal on
  DialogEditContentHost. The nav store is URL-only again; the host owns its trail
  (host.trail) and the layout reads that.
- Guard the `rc` query param against a repeated-param string[] before .split.
- Rename layout `relatedNavItems` → `$relatedNavItems` (signal convention).
- Explicit `: void` on relationship-field `openRelated`.

Tests: cover the in-place reload dirty-guard (clean/keep-editing/discard/locale),
the breadcrumb `command` branch, RouterEditContentHost.resolveIdentity route walk,
and DialogEditContentHost identity/saved$/deferred-trail. edit-content suite green
(107 suites), lint + typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tent dialog

- Adjusted CSS classes for error and loading states in the edit content dialog to enhance layout consistency.
- Updated test specifications for `DotEditContentLayoutComponent` to improve readability and maintainability.
- Enhanced `DotRelatedContentNavigationStore` to persist title cache in sessionStorage, ensuring titles are retained across page refreshes.
- Added tests for title cache persistence and hydration to ensure reliability in various scenarios.

These changes collectively improve the user experience and maintainability of the edit content features.
…tentHost (#36349)

The overlay host backs any overlay presentation (dialog or side panel), not just
the dialog, so the name now reflects that. Pure rename — class, file, and
references; no behavior change. edit-content suite green, lint + typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dge cases (#36349)

Two related-content breadcrumb fixes:

- Locale switch to an untranslated locale left the content without an inode, so
  clicking a related content did nothing. Now navigation seeds the trail origin
  with the version we came from (new `translationSourceInode` state), falling back
  to a fresh trail when there is none.
- In an overlay (dialog/side panel), saving mints a new inode but the overlay host
  did not repoint its in-memory trail, so a title change never showed in the
  breadcrumb. OverlayEditContentHost.goToSavedContent now repoints the current
  crumb to the saved inode — mirroring RouterEditContentHost's `rc` update.

edit-content suite green (107 suites), lint + typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@adrianjm-dotCMS adrianjm-dotCMS marked this pull request as ready for review July 13, 2026 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : Frontend PR changes Angular/TypeScript frontend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Navigate between related content via breadcrumb banner (Edit Contentlet)

1 participant