diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.spec.ts index 296e25dba6b4..425c9c923c47 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.spec.ts @@ -180,6 +180,13 @@ describe('EditEmaLayoutComponent', () => { expect(dotRouter.allowRouteDeactivation).toHaveBeenCalled(); })); + it('should set isClientReady false after saving', fakeAsync(() => { + templateBuilder.templateChange.emit(); + tick(6000); + + expect(store.isClientReady()).toBe(false); + })); + it('should save right away if we request page leave before the 5 secs', () => { const saveTemplate = jest.spyOn(component, 'saveTemplate'); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.ts index b9ee5da5fbdd..08d75a7c225e 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.ts @@ -150,7 +150,7 @@ export class EditEmaLayoutComponent implements OnInit, OnDestroy { summary: 'Success', detail: this.dotMessageService.get('dot.common.message.saved') }); - this.uveStore.reload(); + this.uveStore.reload({ isClientReady: false }); } /** diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.ts index ff51cc8631f8..c876a14d4e3b 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.ts @@ -24,7 +24,8 @@ const initialState: UVEState = { status: UVE_STATUS.LOADING, isTraditionalPage: true, canEditPage: false, - pageIsLocked: true + pageIsLocked: true, + isClientReady: false }; export const UVEStore = signalStore( diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/client/withClient.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/client/withClient.spec.ts index 306dde4ccd74..188a8653c984 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/client/withClient.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/client/withClient.spec.ts @@ -23,7 +23,8 @@ const initialState: UVEState = { status: UVE_STATUS.LOADING, isTraditionalPage: true, canEditPage: false, - pageIsLocked: true + pageIsLocked: true, + isClientReady: false }; export const uveStoreMock = signalStore(withState(initialState), withClient()); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts index a56151ad5636..2506dbe4f5bc 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts @@ -65,7 +65,8 @@ const initialState: UVEState = { status: UVE_STATUS.LOADED, isTraditionalPage: false, canEditPage: true, - pageIsLocked: true + pageIsLocked: true, + isClientReady: false }; export const uveStoreMock = signalStore( diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/flags/withFlags.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/flags/withFlags.spec.ts index 6bd7d6947d4f..ab717e8ec675 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/flags/withFlags.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/flags/withFlags.spec.ts @@ -24,7 +24,8 @@ const initialState: UVEState = { status: UVE_STATUS.LOADING, isTraditionalPage: true, canEditPage: false, - pageIsLocked: true + pageIsLocked: true, + isClientReady: false }; export const uveStoreMock = signalStore( diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts index 5a87bf8c2882..2f04b8c0f763 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts @@ -25,7 +25,8 @@ const initialState: UVEState = { status: UVE_STATUS.LOADING, isTraditionalPage: true, canEditPage: false, - pageIsLocked: true + pageIsLocked: true, + isClientReady: false }; export const uveStoreMock = signalStore(withState(initialState), withLayout()); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts index d753c4ffd7fe..afb28f5d27d0 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts @@ -69,7 +69,8 @@ const initialState: UVEState = { status: UVE_STATUS.LOADING, isTraditionalPage: true, canEditPage: false, - pageIsLocked: true + pageIsLocked: true, + isClientReady: false }; export const uveStoreMock = signalStore(withState(initialState), withLoad()); @@ -350,5 +351,11 @@ describe('withLoad', () => { expect(getPageSpy).toHaveBeenCalledWith(store.params()); }); + + it('should reload the store with a specific property value', () => { + store.reload({ isClientReady: false }); + + expect(store.isClientReady()).toBe(false); + }); }); }); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.ts index 5a427ca546ef..ebaed55b104b 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.ts @@ -162,14 +162,22 @@ export function withLoad() { }) ) ), - reload: rxMethod( + /** + * When the state is "reloaded" outside the editor component, we need to set `isClientReady` to `false`. + * This is particularly relevant for Single Page Applications (SPA) or client-side applications, + * as these apps do not have access to the PREVIEW or EDIT modes. + * If the store updates without resetting `isClientReady` to `false`, + * returning to the editor component will not trigger a data re-fetch, + * causing outdated data to persist. + */ + reload: rxMethod | void>( pipe( tap(() => { patchState(store, { status: UVE_STATUS.LOADING }); }), - switchMap(() => { + switchMap((partialState: Pick) => { return dotPageApiService .getClientPage(store.params(), store.clientRequestProps()) .pipe( @@ -202,7 +210,7 @@ export function withLoad() { canEditPage, pageIsLocked, status: UVE_STATUS.LOADED, - isClientReady: true, + isClientReady: partialState?.isClientReady ?? true, isTraditionalPage: !store.params().clientHost // If we don't send the clientHost we are using as VTL page }); }, diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/models.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/models.ts index 18b329ffe40a..8c781ea0b504 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/models.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/models.ts @@ -18,6 +18,7 @@ export interface UVEState { isTraditionalPage: boolean; canEditPage: boolean; pageIsLocked: boolean; + isClientReady: boolean; } export interface ShellProps { diff --git a/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts b/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts index d94dc0ec2fa4..2988d0a66558 100644 --- a/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts +++ b/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts @@ -38,7 +38,7 @@ import { RowComponent } from '../row/row.component'; imports: [RowComponent, AsyncPipe], template: ` @if (pageAsset$ | async; as page) { - @for (row of this.page?.layout?.body?.rows; track $index) { + @for (row of page?.layout?.body?.rows; track $index) { } } diff --git a/examples/angular/src/app/pages/pages.component.html b/examples/angular/src/app/pages/pages.component.html index 4016b8aa156f..0ac54b4044dd 100644 --- a/examples/angular/src/app/pages/pages.component.html +++ b/examples/angular/src/app/pages/pages.component.html @@ -18,7 +18,7 @@ + [editor]="editorConfig" /> } @else {

Unexpected state encountered.

diff --git a/examples/angular/src/app/pages/pages.component.ts b/examples/angular/src/app/pages/pages.component.ts index f57e58be2c52..a44db20510db 100644 --- a/examples/angular/src/app/pages/pages.component.ts +++ b/examples/angular/src/app/pages/pages.component.ts @@ -67,7 +67,7 @@ export class DotCMSPagesComponent implements OnInit { protected readonly components = signal(DYNAMIC_COMPONENTS); // This should be PageApiOptions from @dotcms/client - protected readonly editorCofig: any = { params: { depth: 2 } }; + protected readonly editorConfig: any = { params: { depth: 2 } }; ngOnInit() { if (isInsideEditor()) { @@ -81,7 +81,7 @@ export class DotCMSPagesComponent implements OnInit { ), startWith(null), // Trigger initial load tap(() => this.#setLoading()), - switchMap(() => this.#pageService.getPageAndNavigation(this.#route, this.editorCofig)), + switchMap(() => this.#pageService.getPageAndNavigation(this.#route, this.editorConfig)), takeUntilDestroyed(this.#destroyRef) ) .subscribe(({ page = {}, nav, error }) => {