From 2239d1d335cf02dc2316e021ad4f2eb170023464 Mon Sep 17 00:00:00 2001 From: Kevin Davila <144152756+KevinDavilaDotCMS@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:36:28 -0500 Subject: [PATCH] fix(uve): Change reload store to render the correct template/page data (#30672) ### Showcase https://github.com/user-attachments/assets/934c4861-238d-4e7a-b831-7fd9b1b70c77 This pull request includes several changes to enhance the `EditEmaLayoutComponent` and related store features, mainly focusing on the addition of the `isClientReady` state property and fixing a typo in the `DotCMSPagesComponent`. ### Enhancements to `EditEmaLayoutComponent` and Store Features: * **Addition of `isClientReady` State Property:** * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.ts`](diffhunk://#diff-42fdc01a4da73b6ecede38045c03fd631badeb73e299fbb4ed6442eb1f3ad963L27-R28): Added `isClientReady` to the initial state of `UVEState`. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/client/withClient.spec.ts`](diffhunk://#diff-6015ff5bfc4608aa1f9dc0941a319b5758b71856d9f216db24a3ffeefc0c53f7L26-R27): Added `isClientReady` to the initial state of `UVEState` in the client feature. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts`](diffhunk://#diff-48915538475425e5656151bb2a73df7a99b4c80c2817c085f96352ef3252d5cbL68-R69): Added `isClientReady` to the initial state of `UVEState` in the editor feature. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/flags/withFlags.spec.ts`](diffhunk://#diff-973c1ce26e6d1de00e9be74ddf0d7429626e299ab59acb646ce21f6567f8af33L27-R28): Added `isClientReady` to the initial state of `UVEState` in the flags feature. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts`](diffhunk://#diff-c4b441749ccd043be6d95340a54fbc26c7466acfc6e2d4ae4672f043170f7008L28-R29): Added `isClientReady` to the initial state of `UVEState` in the layout feature. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts`](diffhunk://#diff-cdf3dddb12d973780196e0402f92c62736024ca9fc5b5b649f104565849d4d0eL72-R73): Added `isClientReady` to the initial state of `UVEState` in the load feature. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.ts`](diffhunk://#diff-0cbc04b5047422551dde0970e4ea1d0e1fcce3d9d8f4e0b4612fbc30b1658487L169-R184): Updated the `reload` method to accept `isClientReady` and set its value accordingly. [[1]](diffhunk://#diff-0cbc04b5047422551dde0970e4ea1d0e1fcce3d9d8f4e0b4612fbc30b1658487L169-R184) [[2]](diffhunk://#diff-0cbc04b5047422551dde0970e4ea1d0e1fcce3d9d8f4e0b4612fbc30b1658487L209-R217) * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/models.ts`](diffhunk://#diff-da4d194131d7dd8d04e0fdefbf262d1d8b9f7841f39f0d702ff6c61b0f078216R21): Added `isClientReady` to the `UVEState` interface. * **Component and Store Behavior Adjustments:** * [`core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.ts`](diffhunk://#diff-73afe394cdee7b073c22d1f6f049b10c09a7315678a3d22c5ed6f9a1c4518afaL153-R153): Modified the `saveTemplate` method to reload the store with `isClientReady: false`. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-layout/edit-ema-layout.component.spec.ts`](diffhunk://#diff-bb8e289f778f062af74dededdbde614d6458884afa3454e84cfc581dd0ea70efR183-R189): Added a test to check that `isClientReady` is set to false after saving. ### Fixes and Improvements: * **Typo Fix in `DotCMSPagesComponent`:** * [`examples/angular/src/app/pages/pages.component.html`](diffhunk://#diff-4ed5c1356105b0d846976ce8be24ea6935edfef1bde787aee5793e74ed50e726L21-R21): Corrected the typo in the `editorConfig` binding. * [`examples/angular/src/app/pages/pages.component.ts`](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L70-R70): Fixed the typo in the `editorConfig` property and its usage. [[1]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L70-R70) [[2]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L84-R84) * **Template Update in `dotcms-layout.component.ts`:** * [`core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts`](diffhunk://#diff-5b008f3e625106e1cb24930f8700a9f82eae16957699b46dcefc0dbe58b5e49dL41-R41): Simplified the template by using the correct variable for page layout rows. Co-authored-by: Kevin Davila --- .../edit-ema-layout.component.spec.ts | 7 +++++++ .../edit-ema-layout/edit-ema-layout.component.ts | 2 +- .../portlet/src/lib/store/dot-uve.store.ts | 3 ++- .../lib/store/features/client/withClient.spec.ts | 3 ++- .../lib/store/features/editor/withEditor.spec.ts | 3 ++- .../src/lib/store/features/flags/withFlags.spec.ts | 3 ++- .../lib/store/features/layout/wihtLayout.spec.ts | 3 ++- .../src/lib/store/features/load/withLoad.spec.ts | 9 ++++++++- .../src/lib/store/features/load/withLoad.ts | 14 +++++++++++--- .../edit-ema/portlet/src/lib/store/models.ts | 1 + .../dotcms-layout/dotcms-layout.component.ts | 2 +- .../angular/src/app/pages/pages.component.html | 2 +- examples/angular/src/app/pages/pages.component.ts | 4 ++-- 13 files changed, 42 insertions(+), 14 deletions(-) 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 }) => {