Skip to content

feat(uve): navigate to new edit content editor from Go to Full Editor when the new edit content is active#35493

Open
adrianjm-dotCMS wants to merge 3 commits intomainfrom
issue-33235-new-edit-content-experience-not-launched-from-uve
Open

feat(uve): navigate to new edit content editor from Go to Full Editor when the new edit content is active#35493
adrianjm-dotCMS wants to merge 3 commits intomainfrom
issue-33235-new-edit-content-experience-not-launched-from-uve

Conversation

@adrianjm-dotCMS
Copy link
Copy Markdown
Member

@adrianjm-dotCMS adrianjm-dotCMS commented Apr 28, 2026

Summary

  • When the user clicks Go to Full Editor in UVE, navigate to /content/:inode if the content type has FEATURE_FLAG_CONTENT_EDITOR2_ENABLED in its metadata; otherwise fall back to the existing dialog behavior
  • Update the UVE breadcrumb to use the full /dotAdmin/#/edit-page/content?... URL so users can navigate back to the exact editor page from the breadcrumb trail
  • Fix breadcrumb deduplication to search the entire trail (not just the last crumb), enabling correct truncation when navigating back to a previous UVE page
  • Fix contentEdit regex in breadcrumb utils to prevent /edit-page/content?... UVE routes from incorrectly triggering the replace-last-crumb rule
  • Add untracked() around breadcrumbs read inside the navigation effect to prevent infinite reactive loops
Screen.Recording.2026-04-28.at.4.59.44.PM.mov

Changed Files

  • libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts — core "Go to Full Editor" routing logic
  • libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.ts — UVE breadcrumb now uses full navigable URL
  • libs/global-store/src/lib/features/breadcrumb/breadcrumb.feature.ts — full-trail deduplication + untracked() fix
  • libs/global-store/src/lib/features/breadcrumb/breadcrumb.utils.ts — regex fix for UVE routes

Acceptance Criteria

  • Clicking "Go to Full Editor" navigates to /content/:inode when FEATURE_FLAG_CONTENT_EDITOR2_ENABLED is true in the content type metadata
  • Falls back to the existing dialog when the flag is absent or false
  • Falls back to dialog when the content type is not in the cache
  • Does nothing when the contentlet has no inode
  • UVE breadcrumb is clickable and navigates back to the correct editor page
  • Navigating back to a previously visited UVE page truncates the breadcrumb trail correctly

Test Plan

  • Unit tests added for all handleOpenFullEditor branches (new editor, dialog fallback, cache miss, no inode)
  • Breadcrumb tests updated and new truncation test added
  • All affected tests pass locally

Closes #33235

🤖 Generated with Claude Code

… button when CONTENT_EDITOR2_ENABLED flag is active

- When clicking Go to Full Editor in UVE, navigate to /content/:inode if the content type has FEATURE_FLAG_CONTENT_EDITOR2_ENABLED in its metadata; otherwise fall back to the existing dialog
- Update UVE breadcrumb to use the full /dotAdmin/#/edit-page/content?... URL so users can navigate back to the exact editor page from the breadcrumb trail
- Fix breadcrumb deduplication to search the entire trail instead of only the last crumb, enabling proper truncation when navigating back to a previous UVE page
- Fix contentEdit regex in breadcrumb utils to prevent /edit-page/content?... UVE routes from incorrectly triggering the replace-last-crumb rule
- Add untracked() around breadcrumbs read in the navigation effect to prevent infinite reactive loops

Closes #33235

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@adrianjm-dotCMS adrianjm-dotCMS marked this pull request as ready for review April 28, 2026 19:09
@github-actions github-actions Bot added the Area : Frontend PR changes Angular/TypeScript frontend code label Apr 28, 2026
Copilot AI review requested due to automatic review settings April 28, 2026 19:09
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 28, 2026

Claude finished @adrianjm-dotCMS's task in 5m 38s —— View job


Code Review

  • Gather context
  • Read changed files
  • Analyze for issues
  • Post review

Summary

Three fixable issues flagged below. The core routing logic (handleOpenFullEditor) and the untracked() fix inside breadcrumb.feature.ts are correct. The Copilot-reviewed items (=== true strict check, leading / on navigate) have been applied.


Issues

1. uvePage rule contradicts its own tests — tests will fail 🔴

breadcrumb.utils.ts adds a uvePage entry to REPLACE_LAST_CRUMB_RULES:

uvePage: {
    test: (item, last) => {
        const regex = /\/edit-page\/content/;
        const normalize = (url: string | undefined) => (url ?? '').replace(/^.*#/, '');
        return regex.test(normalize(item.url)) && regex.test(normalize(last.url));
    }
}

shouldReplaceLastCrumb calls all rules with Object.values(...).some(...), so whenever both the incoming and the last crumb are UVE pages, this returns true and triggers setLastBreadcrumb (replace).

But the test file says the opposite:

  • breadcrumb.utils.spec.ts line 246 (changed from .toBe(true).toBe(false) in this PR):

    it('should return false when both items match /edit-page/content?{params}', () => {
        expect(shouldReplaceLastCrumb(
            { url: '/dotAdmin/#/edit-page/content?url=page2' },
            { url: '/dotAdmin/#/edit-page/content?url=page1' }
        )).toBe(false); // uvePage.test returns true → this will fail
  • breadcrumb.feature.spec.ts line 351 (new test added in this PR):

    it('should append breadcrumb when both URLs match edit-page/content pattern', () => {
        ...
        expect(store.breadcrumbs().length).toBe(before + 1); // uvePage replace → length stays same → fails

Both tests will fail against the current production code. The spec test was changed from .toBe(true) to .toBe(false) — the intent is clearly that UVE routes should not trigger replacement. The uvePage rule should be removed from REPLACE_LAST_CRUMB_RULES. Fix this →


2. $updateBreadcrumbEffect creates an unintended reactive dependency on breadcrumbs 🟡

dot-ema-shell.component.ts (line 209–230):

readonly $updateBreadcrumbEffect = effect(() => {
    const page = this.uveStore.pageAsset()?.page;
    ...
    this.#globalStore.addNewBreadcrumb({ ... }); // reads store.breadcrumbs() internally
});

addNewBreadcrumb calls store.breadcrumbs() synchronously (line ~150 of breadcrumb.feature.ts). Since this runs inside an Angular effect context, it registers breadcrumbs as a reactive dependency. Every time any breadcrumb changes (router navigation, other pages), this effect re-fires even when the page hasn't changed.

On re-fire with unchanged page data, addNewBreadcrumb finds the same item as the last crumb (same id) and early-returns — so no infinite loop and no corruption. But it's a wasteful re-run and violates the anti-pattern called out in core-web/libs/portlets/CLAUDE.md ("Missing untracked() in effect").

Fix: wrap the addNewBreadcrumb call:

untracked(() => this.#globalStore.addNewBreadcrumb({ ... }));

Fix this →


3. truncateBreadcrumbs(0) is silently skipped 🟢

breadcrumb.feature.ts line 259–262 (pre-existing, but processSpecialRoute now also emits truncate):

case 'truncate':
    if (result.index && result.index > -1) { // 0 is falsy — index 0 is never applied
        truncateBreadcrumbs(result.index);
    }

Since 0 && ... is falsy, a truncate result targeting index 0 is silently ignored. In practice the Home crumb (index 0) has no url, so processSpecialRoute will never match it by URL — but the guard is still fragile. Change to result.index != null && result.index > -1 or result.index >= 0.


What's clean

  • handleOpenFullEditor routing logic is correct: === true strict check, absolute /content navigation, correct fallback chain (flag false → dialog, cache miss → dialog, no inode → no-op).
  • untracked() wrapping the breadcrumbs read inside the menuItems effect in breadcrumb.feature.ts — correct fix for the documented infinite loop.
  • Full-trail deduplication in addNewBreadcrumb (searching entire trail instead of just last item) — the key fix for back-navigation correctness.
  • contentEdit regex tightened to ^\/content(?:[/?].+)?$ — correctly excludes /edit-page/content UVE routes from the replace rule.
  • Breadcrumb URL built via router.createUrlTree + /dotAdmin/# prefix — makes crumbs clickable and returns users to the exact UVE state.

@adrianjm-dotCMS adrianjm-dotCMS changed the title feat(uve): navigate to new edit content editor from Go to Full Editor when CONTENT_EDITOR2_ENABLED is active feat(uve): navigate to new edit content editor from Go to Full Editor when the new edit content is active Apr 28, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates UVE (Edit EMA) navigation and breadcrumb handling so that “Go to Full Editor” launches the new Edit Content experience when the content type has the CONTENT_EDITOR2_ENABLED metadata flag, while improving breadcrumb URL correctness and deduplication/truncation behavior in the global breadcrumb store.

Changes:

  • Route “Go to Full Editor” to the new content editor (/content/:inode) when CONTENT_EDITOR2_ENABLED is enabled; otherwise keep the dialog fallback.
  • Make UVE breadcrumbs navigable back to the exact editor URL (/dotAdmin/#/edit-page/content?...).
  • Improve breadcrumb deduplication/truncation and prevent reactive loops in the breadcrumb feature; tighten content-edit matching regex to avoid UVE route collisions.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts Adds feature-flag-based routing to the new content editor from UVE’s “Go to Full Editor”.
core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts Adds unit coverage for the new routing vs dialog fallback branches.
core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.ts Builds breadcrumbs using the full /dotAdmin/#/edit-page/content?... URL for accurate back navigation.
core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.spec.ts Updates breadcrumb expectations and router mocks to reflect the full breadcrumb URL.
core-web/libs/global-store/src/lib/features/breadcrumb/breadcrumb.feature.ts Expands dedupe to the whole trail and uses untracked() inside the nav effect to avoid loops.
core-web/libs/global-store/src/lib/features/breadcrumb/breadcrumb.feature.spec.ts Updates expectations and adds a truncation test for full-trail dedupe behavior.
core-web/libs/global-store/src/lib/features/breadcrumb/breadcrumb.utils.ts Refines the contentEdit replace-last-crumb regex to exclude /edit-page/content routes.
core-web/libs/global-store/src/lib/features/breadcrumb/breadcrumb.utils.spec.ts Updates test to ensure /edit-page/content?... no longer triggers the content-edit replace rule.

adrianjm-dotCMS and others added 2 commits April 28, 2026 15:20
…and explicit leading slash in router.navigate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… UVE page rule

- Updated breadcrumb logic to handle cases where the same ID has a different URL, allowing for in-place updates.
- Introduced a new rule for UVE pages to replace the last breadcrumb when navigating between different pages, ensuring a cleaner breadcrumb trail.

This improves user navigation and maintains a more accurate breadcrumb history.
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.

New edit content experience not launched from UVE for content types that should use the new edit content

2 participants