From 9efcdabf453332451a7cc3a5a683cae75afc69ae Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Mon, 11 Nov 2024 15:13:08 -0500 Subject: [PATCH 01/16] Added sort navigation logic to nextjs example --- .../edit-ema-editor.component.ts | 16 +++++++- .../edit-ema/portlet/src/lib/utils/index.ts | 25 ++++++++++++ .../portlet/src/lib/utils/utils.spec.ts | 19 ++++++++- core-web/libs/sdk/client/src/index.ts | 2 + .../sdk/client/src/lib/editor/sdk-editor.ts | 19 +++++++++ .../nextjs/src/components/layout/header.js | 39 +++++++++++++++++++ 6 files changed, 118 insertions(+), 2 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index db7df5131ed4..0e296e41d1a5 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -87,6 +87,7 @@ import { ClientRequestProps } from '../store/features/client/withClient'; import { SDK_EDITOR_SCRIPT_SOURCE, TEMPORAL_DRAG_ITEM, + addMissingParamsToReorderMenuURL, compareUrlPaths, deleteContentletFromContainer, getDragItemData, @@ -796,6 +797,13 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.uveStore.reload(); this.dialog.resetDialog(); + + this.contentWindow?.postMessage( + { + name: NOTIFY_CLIENT.UVE_RELOAD_PAGE + }, + this.host + ); }, [NG_CUSTOM_EVENTS.ERROR_SAVING_MENU_ORDER]: () => { this.messageService.add({ @@ -991,8 +999,14 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.dialog.editContentlet({ ...contentlet, clientAction: action }); }, [CLIENT_ACTIONS.REORDER_MENU]: ({ reorderUrl }: ReorderPayload) => { + const urlObject = addMissingParamsToReorderMenuURL({ + url: reorderUrl, + pagePath: this.uveStore.params().url, + hostId: this.uveStore.pageAPIResponse().site.identifier + }); + this.dialog.openDialogOnUrl( - reorderUrl, + urlObject.toString(), this.dotMessageService.get('editpage.content.contentlet.menu.reorder.title') ); }, diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts index 454291d9b337..d632d71b7426 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts @@ -510,3 +510,28 @@ export const getDragItemData = ({ type, item }: DOMStringMap) => { return null; } }; + +/** + * Adds missing query parameters `pagePath` and `hostId` to the given URL if they are not already present. + * + * @param {Object} params - The parameters object. + * @param {string} params.url - The URL to which the parameters will be added. + * @param {string} params.pagePath - The page path to be added as a query parameter if missing. + * @param {string} params.hostId - The host ID to be added as a query parameter if missing. + * @returns {string} - The updated URL with the missing parameters added. + */ +export const addMissingParamsToReorderMenuURL = ({url, pagePath, hostId}: {url: string, pagePath: string, hostId: string}) => { + const urlObject = new URL(url, window.location.origin); + + const params = urlObject.searchParams; + + if (!params.has('pagePath')) { + params.set('pagePath', pagePath); + } + + if (!params.has('hostId')) { + params.set('hostId', hostId); + } + + return urlObject.toString(); +} diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts index 9415046598f4..e67c9a5123ee 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts @@ -15,7 +15,8 @@ import { areContainersEquals, compareUrlPaths, createFullURL, - getDragItemData + getDragItemData, + addMissingParamsToReorderMenuURL } from '.'; import { dotPageContainerStructureMock } from '../shared/mocks'; @@ -709,4 +710,20 @@ describe('utils functions', () => { expect(result).toBeNull(); }); }); + + describe('addMissingParamsToReorderMenuURL', () => { + it('should add the missing params', () => { + const url = "some-url?language_id=1"; + const result = addMissingParamsToReorderMenuURL({url, pagePath: '123', hostId: '456'}); + + expect(result).toEqual("http://localhost/some-url?language_id=1&pagePath=123&hostId=456"); + }) + + it('should not add the missing params', () => { + const url = "some-url?language_id=1&pagePath=111&hostId=333"; + const result = addMissingParamsToReorderMenuURL({url, pagePath: '123', hostId: '456'}); + + expect(result).toEqual("http://localhost/some-url?language_id=1&pagePath=111&hostId=333"); + }) + }) }); diff --git a/core-web/libs/sdk/client/src/index.ts b/core-web/libs/sdk/client/src/index.ts index d95a975f1375..a9a64c13fb60 100644 --- a/core-web/libs/sdk/client/src/index.ts +++ b/core-web/libs/sdk/client/src/index.ts @@ -9,6 +9,7 @@ import { NOTIFY_CLIENT } from './lib/editor/models/listeners.model'; import { destroyEditor, editContentlet, + reorderMenu, initEditor, isInsideEditor, updateNavigation @@ -20,6 +21,7 @@ export { getPageRequestParams, isInsideEditor, editContentlet, + reorderMenu, DotCmsClient, DotCMSPageEditorConfig, CLIENT_ACTIONS, diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts index 02480c0fbbdb..376289dfebb7 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts @@ -43,6 +43,25 @@ export function editContentlet(contentlet: Contentlet) { }); } + +/** + * You can use this function to reorder the menu in the editor. + * + * Calling this function inside the editor, will prompt the UVE to open the reorder menu page. + * + * @export + */ +export function reorderMenu() { + // This is the URL for the reorder menu page + // All params are hardcoded on the jsp, so here we just need to send the same URL + const reorderUrl = '/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=1&depth=2'; + + postMessageToEditor({ + action: CLIENT_ACTIONS.REORDER_MENU, + payload: { reorderUrl } + }); +} + /** * Checks if the code is running inside an editor. * diff --git a/examples/nextjs/src/components/layout/header.js b/examples/nextjs/src/components/layout/header.js index 988f9619e3d1..ddcca31863f9 100644 --- a/examples/nextjs/src/components/layout/header.js +++ b/examples/nextjs/src/components/layout/header.js @@ -1,4 +1,5 @@ import Link from 'next/link'; +import { reorderMenu } from '@dotcms/client'; function Header({ children }) { return ( @@ -8,9 +9,47 @@ function Header({ children }) { TravelLux in NextJS + {children} ); } +function ReorderButton() { + const buttonStyles = { + backgroundColor: '#426BF0', + borderRadius: '3px', + display: 'flex', + flexDirection: 'row', + cursor: 'pointer', + border: 'none' + }; + + const iconStyles = { + backgroundRepeat: 'no-repeat', + backgroundSize: 'contain', + display: 'block', + height: '36px', + width: '36px' + }; + + const firstIconStyle = { + ...iconStyles, + backgroundImage: 'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDMwLjgzbDkuMTcsLTkuMTdsOS4xNyw5LjE3bDIuODMsLTIuODNsLTEyLC0xMmwtMTIsMTJsMi44MywyLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0zMC42OTQ1NTcsOS40MjU4ODdsNDgsMGwwLDQ4bC00OCwwbDAsLTQ4eiIvPgogPC9nPgo8L3N2Zz4=)' + }; + + const secondIconStyle = { + ...iconStyles, + backgroundImage: 'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDE2LjQybDkuMTcsOS4xN2w5LjE3LC05LjE3bDIuODMsMi44M2wtMTIsMTJsLTEyLC0xMmwyLjgzLC0yLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0xOC4zOTk4OTksMTcuMDc4NDczbDQ4LDBsMCw0OGwtNDgsMGwwLC00OHoiLz4KIDwvZz4KPC9zdmc+)' + }; + + return ( + + ); +} + + export default Header; From 196a91fbe8c9b90702c879c9b50464bca8ba292e Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Mon, 11 Nov 2024 15:21:34 -0500 Subject: [PATCH 02/16] Removed unnecessary parse --- .../src/lib/edit-ema-editor/edit-ema-editor.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 0e296e41d1a5..d3437acaaebe 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -1006,7 +1006,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { }); this.dialog.openDialogOnUrl( - urlObject.toString(), + urlObject, this.dotMessageService.get('editpage.content.contentlet.menu.reorder.title') ); }, From c8239040da78f8c571a410e3a45607575336bf78 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Mon, 11 Nov 2024 15:30:27 -0500 Subject: [PATCH 03/16] Fixed linter issues --- .../edit-ema/portlet/src/lib/utils/index.ts | 12 ++++++-- .../portlet/src/lib/utils/utils.spec.ts | 30 +++++++++++++------ .../sdk/client/src/lib/editor/sdk-editor.ts | 6 ++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts index d632d71b7426..6d175715bd06 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts @@ -520,7 +520,15 @@ export const getDragItemData = ({ type, item }: DOMStringMap) => { * @param {string} params.hostId - The host ID to be added as a query parameter if missing. * @returns {string} - The updated URL with the missing parameters added. */ -export const addMissingParamsToReorderMenuURL = ({url, pagePath, hostId}: {url: string, pagePath: string, hostId: string}) => { +export const addMissingParamsToReorderMenuURL = ({ + url, + pagePath, + hostId +}: { + url: string; + pagePath: string; + hostId: string; +}) => { const urlObject = new URL(url, window.location.origin); const params = urlObject.searchParams; @@ -534,4 +542,4 @@ export const addMissingParamsToReorderMenuURL = ({url, pagePath, hostId}: {url: } return urlObject.toString(); -} +}; diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts index e67c9a5123ee..52ff18d7b5a3 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts @@ -713,17 +713,29 @@ describe('utils functions', () => { describe('addMissingParamsToReorderMenuURL', () => { it('should add the missing params', () => { - const url = "some-url?language_id=1"; - const result = addMissingParamsToReorderMenuURL({url, pagePath: '123', hostId: '456'}); + const url = 'some-url?language_id=1'; + const result = addMissingParamsToReorderMenuURL({ + url, + pagePath: '123', + hostId: '456' + }); - expect(result).toEqual("http://localhost/some-url?language_id=1&pagePath=123&hostId=456"); - }) + expect(result).toEqual( + 'http://localhost/some-url?language_id=1&pagePath=123&hostId=456' + ); + }); it('should not add the missing params', () => { - const url = "some-url?language_id=1&pagePath=111&hostId=333"; - const result = addMissingParamsToReorderMenuURL({url, pagePath: '123', hostId: '456'}); + const url = 'some-url?language_id=1&pagePath=111&hostId=333'; + const result = addMissingParamsToReorderMenuURL({ + url, + pagePath: '123', + hostId: '456' + }); - expect(result).toEqual("http://localhost/some-url?language_id=1&pagePath=111&hostId=333"); - }) - }) + expect(result).toEqual( + 'http://localhost/some-url?language_id=1&pagePath=111&hostId=333' + ); + }); + }); }); diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts index 376289dfebb7..4041e070ddc0 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts @@ -43,10 +43,9 @@ export function editContentlet(contentlet: Contentlet) { }); } - /** * You can use this function to reorder the menu in the editor. - * + * * Calling this function inside the editor, will prompt the UVE to open the reorder menu page. * * @export @@ -54,7 +53,8 @@ export function editContentlet(contentlet: Contentlet) { export function reorderMenu() { // This is the URL for the reorder menu page // All params are hardcoded on the jsp, so here we just need to send the same URL - const reorderUrl = '/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=1&depth=2'; + const reorderUrl = + '/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=1&depth=2'; postMessageToEditor({ action: CLIENT_ACTIONS.REORDER_MENU, From 0df10d1d59520b335c57be4048e814e24e13db61 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Mon, 11 Nov 2024 16:40:36 -0500 Subject: [PATCH 04/16] Changed name on util function --- .../src/lib/edit-ema-editor/edit-ema-editor.component.ts | 4 ++-- .../libs/portlets/edit-ema/portlet/src/lib/utils/index.ts | 2 +- .../portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index d3437acaaebe..7100b72bf2a8 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -87,7 +87,7 @@ import { ClientRequestProps } from '../store/features/client/withClient'; import { SDK_EDITOR_SCRIPT_SOURCE, TEMPORAL_DRAG_ITEM, - addMissingParamsToReorderMenuURL, + createReorderMenuURL, compareUrlPaths, deleteContentletFromContainer, getDragItemData, @@ -999,7 +999,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.dialog.editContentlet({ ...contentlet, clientAction: action }); }, [CLIENT_ACTIONS.REORDER_MENU]: ({ reorderUrl }: ReorderPayload) => { - const urlObject = addMissingParamsToReorderMenuURL({ + const urlObject = createReorderMenuURL({ url: reorderUrl, pagePath: this.uveStore.params().url, hostId: this.uveStore.pageAPIResponse().site.identifier diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts index 6d175715bd06..71a728d2ac6a 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts @@ -520,7 +520,7 @@ export const getDragItemData = ({ type, item }: DOMStringMap) => { * @param {string} params.hostId - The host ID to be added as a query parameter if missing. * @returns {string} - The updated URL with the missing parameters added. */ -export const addMissingParamsToReorderMenuURL = ({ +export const createReorderMenuURL = ({ url, pagePath, hostId diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts index 52ff18d7b5a3..17f986bd682c 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts @@ -16,7 +16,7 @@ import { compareUrlPaths, createFullURL, getDragItemData, - addMissingParamsToReorderMenuURL + createReorderMenuURL } from '.'; import { dotPageContainerStructureMock } from '../shared/mocks'; @@ -711,10 +711,10 @@ describe('utils functions', () => { }); }); - describe('addMissingParamsToReorderMenuURL', () => { + describe('createReorderMenuURL', () => { it('should add the missing params', () => { const url = 'some-url?language_id=1'; - const result = addMissingParamsToReorderMenuURL({ + const result = createReorderMenuURL({ url, pagePath: '123', hostId: '456' @@ -727,7 +727,7 @@ describe('utils functions', () => { it('should not add the missing params', () => { const url = 'some-url?language_id=1&pagePath=111&hostId=333'; - const result = addMissingParamsToReorderMenuURL({ + const result = createReorderMenuURL({ url, pagePath: '123', hostId: '456' From 7c7dbaceefb1ba53f0baf8dc847a8c7208dc6236 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Mon, 11 Nov 2024 16:50:59 -0500 Subject: [PATCH 05/16] Migrated ReorderButton to tailwind --- .../nextjs/src/components/layout/header.js | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/examples/nextjs/src/components/layout/header.js b/examples/nextjs/src/components/layout/header.js index ddcca31863f9..f739784ee8f1 100644 --- a/examples/nextjs/src/components/layout/header.js +++ b/examples/nextjs/src/components/layout/header.js @@ -16,37 +16,18 @@ function Header({ children }) { } function ReorderButton() { - const buttonStyles = { - backgroundColor: '#426BF0', - borderRadius: '3px', - display: 'flex', - flexDirection: 'row', - cursor: 'pointer', - border: 'none' - }; - - const iconStyles = { - backgroundRepeat: 'no-repeat', - backgroundSize: 'contain', - display: 'block', - height: '36px', - width: '36px' - }; - - const firstIconStyle = { - ...iconStyles, + const arrowUp = { backgroundImage: 'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDMwLjgzbDkuMTcsLTkuMTdsOS4xNyw5LjE3bDIuODMsLTIuODNsLTEyLC0xMmwtMTIsMTJsMi44MywyLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0zMC42OTQ1NTcsOS40MjU4ODdsNDgsMGwwLDQ4bC00OCwwbDAsLTQ4eiIvPgogPC9nPgo8L3N2Zz4=)' }; - const secondIconStyle = { - ...iconStyles, + const arrowDown = { backgroundImage: 'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDE2LjQybDkuMTcsOS4xN2w5LjE3LC05LjE3bDIuODMsMi44M2wtMTIsMTJsLTEyLC0xMmwyLjgzLC0yLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0xOC4zOTk4OTksMTcuMDc4NDczbDQ4LDBsMCw0OGwtNDgsMGwwLC00OHoiLz4KIDwvZz4KPC9zdmc+)' }; return ( - ); } From 1ef47ccb7a19c3a677f349a2ba4ad3e35ae2931a Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Tue, 12 Nov 2024 14:04:06 -0500 Subject: [PATCH 06/16] Now use the reorderMenu() on traditional and headless --- .../src/lib/editor/models/client.model.ts | 4 +- .../client/src/lib/editor/sdk-editor.spec.ts | 2 + .../sdk/client/src/lib/editor/sdk-editor.ts | 12 +++--- .../WEB-INF/velocity/VM_global_library.vm | 38 ++----------------- .../webapp/html/js/editor-js/sdk-editor.js | 2 +- .../nextjs/src/components/layout/header.js | 15 +++----- .../nextjs/src/utils/publicImageLoader.js | 11 ++++++ 7 files changed, 31 insertions(+), 53 deletions(-) create mode 100644 examples/nextjs/src/utils/publicImageLoader.js diff --git a/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts b/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts index a0c5fa98ea04..0bb902ae7372 100644 --- a/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts +++ b/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts @@ -1,4 +1,4 @@ -import { editContentlet } from '../sdk-editor'; +import { editContentlet, reorderMenu } from '../sdk-editor'; declare global { interface Window { dotUVE: DotUVE; @@ -7,6 +7,7 @@ declare global { export const INITIAL_DOT_UVE: DotUVE = { editContentlet, + reorderMenu, lastScrollYPosition: 0 }; @@ -101,5 +102,6 @@ export function postMessageToEditor(message: PostMessageProps) { export interface DotUVE { editContentlet: typeof editContentlet; + reorderMenu: typeof reorderMenu; lastScrollYPosition: number; } diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts index 9090ee5c5049..82ae089e8b99 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts @@ -27,6 +27,7 @@ jest.mock('./models/client.model', () => { }, INITIAL_DOT_UVE: { editContentlet: jest.fn(), + reorderMenu: jest.fn(), lastScrollYPosition: 0 } }; @@ -102,6 +103,7 @@ describe('DotCMSPageEditor', () => { expect(scrollHandler).toHaveBeenCalled(); expect(window.dotUVE).toEqual({ editContentlet: expect.any(Function), + reorderMenu: expect.any(Function), lastScrollYPosition: 0 }); }); diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts index 4041e070ddc0..2ca5e389c1b0 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts @@ -44,17 +44,17 @@ export function editContentlet(contentlet: Contentlet) { } /** - * You can use this function to reorder the menu in the editor. + * Reorders the menu starting from a specified level. * - * Calling this function inside the editor, will prompt the UVE to open the reorder menu page. + * @param {number} [startLevel=1] - The level from which to start reordering the menu. Defaults to 1. * - * @export + * This function constructs a URL for the reorder menu page with the given start level and a fixed depth of 2. + * It then sends a message to the editor with the action to reorder the menu and the constructed URL as the payload. */ -export function reorderMenu() { +export function reorderMenu(startLevel = 1) { // This is the URL for the reorder menu page // All params are hardcoded on the jsp, so here we just need to send the same URL - const reorderUrl = - '/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=1&depth=2'; + const reorderUrl = `/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=${startLevel}&depth=2`; postMessageToEditor({ action: CLIENT_ACTIONS.REORDER_MENU, diff --git a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm index 53c06573d61e..afd4ab3786bd 100644 --- a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm +++ b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm @@ -172,29 +172,18 @@ #if ($EDIT_MODE && $PUBLISH_HTMLPAGE_PERMISSION) #set($menuLevel = $VTLSERVLET_URI.split('/').size() - 1) - + - #end #end #macro(sortNavigation) #if ($EDIT_MODE && $PUBLISH_HTMLPAGE_PERMISSION) + #set($menuLevel = $VTLSERVLET_URI.split('/').size() - 1) - #end #end diff --git a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js index 853270c30ed4..189ae350ef59 100644 --- a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js +++ b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js @@ -1 +1 @@ -function u(t){i({action:"edit-contentlet",payload:t})}function T(){return typeof window>"u"?!1:window.parent!==window}function f(){window.dotUVE=a}function m(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(n=>{n.clientHeight||n.classList.add("empty-contentlet")})}var a={editContentlet:u,lastScrollYPosition:0};function i(t){window.parent.postMessage(t,"*")}function g(t){return t.map(n=>{let e=n.getBoundingClientRect(),o=Array.from(n.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:v(n)}),contentlets:I(e,o)}})}function I(t,n){return n.map(e=>{let o=e.getBoundingClientRect();return{x:0,y:o.y-t.y,width:o.width,height:o.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function v(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function E(t){let n=t.closest('[data-dot-object="container"]');return n?v(n):(console.warn("No container found for the contentlet"),null)}function p(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:p(t?.parentElement):null}function y(t){let n=t.querySelectorAll('[data-dot-object="vtl-file"]');return n.length?Array.from(n).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function _(){let t=document.documentElement.scrollHeight,n=window.innerHeight;return window.scrollY+n>=t}var r=[];function h(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),n=g(t);i({action:"set-bounds",payload:n})}function d(){let t=n=>{({"uve-reload-page":()=>{window.location.reload()},"uve-request-bounds":()=>{h()},"uve-scroll-inside-iframe":()=>{let o=n.data.direction;if(window.scrollY===0&&o==="up"||_()&&o==="down")return;let s=o==="up"?-120:120;window.scrollBy({left:0,top:s,behavior:"smooth"})}})[n.data.name]?.()};window.addEventListener("message",t),r.push({type:"listener",event:"message",callback:t})}function l(){let t=n=>{let e=p(n.target);if(!e)return;let{x:o,y:s,width:C,height:M}=e.getBoundingClientRect(),w=e.dataset?.dotObject==="container",P={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},b={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},L=y(e),O={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:w?P:b,vtlFiles:L};i({action:"set-contentlet",payload:{x:o,y:s,width:C,height:M,payload:O}})};document.addEventListener("pointermove",t),r.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{i({action:"scroll"}),window.dotUVE={...window.dotUVE??a,lastScrollYPosition:window.scrollY}},n=()=>{i({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",n),r.push({type:"listener",event:"scroll",callback:n}),r.push({type:"listener",event:"scroll",callback:t})}function D(){let t=()=>{window.scrollTo(0,window.dotUVE?.lastScrollYPosition)};window.addEventListener("load",t),r.push({type:"listener",event:"scroll",callback:t})}T()&&(f(),d(),c(),D(),l(),m()); +function u(t){r({action:"edit-contentlet",payload:t})}function T(t=1){console.log("Called reorderMenu");let o=`/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=${t}&depth=2`;r({action:"reorder-menu",payload:{reorderUrl:o}})}function f(){return typeof window>"u"?!1:window.parent!==window}function m(){console.log("Called initDotUVE"),window.dotUVE=a}function g(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(o=>{o.clientHeight||o.classList.add("empty-contentlet")})}var a={editContentlet:u,reorderMenu:T,lastScrollYPosition:0};function r(t){window.parent.postMessage(t,"*")}function _(t){return t.map(o=>{let e=o.getBoundingClientRect(),n=Array.from(o.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:y(o)}),contentlets:h(e,n)}})}function h(t,o){return o.map(e=>{let n=e.getBoundingClientRect();return{x:0,y:n.y-t.y,width:n.width,height:n.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function y(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function E(t){let o=t.closest('[data-dot-object="container"]');return o?y(o):(console.warn("No container found for the contentlet"),null)}function p(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:p(t?.parentElement):null}function v(t){let o=t.querySelectorAll('[data-dot-object="vtl-file"]');return o.length?Array.from(o).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function M(){let t=document.documentElement.scrollHeight,o=window.innerHeight;return window.scrollY+o>=t}var i=[];function S(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),o=_(t);r({action:"set-bounds",payload:o})}function s(){let t=o=>{({"uve-reload-page":()=>{window.location.reload()},"uve-request-bounds":()=>{S()},"uve-scroll-inside-iframe":()=>{let n=o.data.direction;if(window.scrollY===0&&n==="up"||M()&&n==="down")return;let d=n==="up"?-120:120;window.scrollBy({left:0,top:d,behavior:"smooth"})}})[o.data.name]?.()};window.addEventListener("message",t),i.push({type:"listener",event:"message",callback:t})}function l(){let t=o=>{let e=p(o.target);if(!e)return;let{x:n,y:d,width:C,height:b}=e.getBoundingClientRect(),w=e.dataset?.dotObject==="container",P={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},L={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},O=v(e),N={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:w?P:L,vtlFiles:O};r({action:"set-contentlet",payload:{x:n,y:d,width:C,height:b,payload:N}})};document.addEventListener("pointermove",t),i.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{r({action:"scroll"}),window.dotUVE={...window.dotUVE??a,lastScrollYPosition:window.scrollY}},o=()=>{r({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",o),i.push({type:"listener",event:"scroll",callback:o}),i.push({type:"listener",event:"scroll",callback:t})}function D(){let t=()=>{window.scrollTo(0,window.dotUVE?.lastScrollYPosition)};window.addEventListener("load",t),i.push({type:"listener",event:"scroll",callback:t})}f()&&(m(),s(),c(),D(),l(),g()); diff --git a/examples/nextjs/src/components/layout/header.js b/examples/nextjs/src/components/layout/header.js index f739784ee8f1..731fdfe1b05b 100644 --- a/examples/nextjs/src/components/layout/header.js +++ b/examples/nextjs/src/components/layout/header.js @@ -1,5 +1,7 @@ import Link from 'next/link'; import { reorderMenu } from '@dotcms/client'; +import Image from 'next/image'; +import PublicImageLoader from '@/utils/publicImageLoader'; function Header({ children }) { return ( @@ -16,18 +18,11 @@ function Header({ children }) { } function ReorderButton() { - const arrowUp = { - backgroundImage: 'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDMwLjgzbDkuMTcsLTkuMTdsOS4xNyw5LjE3bDIuODMsLTIuODNsLTEyLC0xMmwtMTIsMTJsMi44MywyLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0zMC42OTQ1NTcsOS40MjU4ODdsNDgsMGwwLDQ4bC00OCwwbDAsLTQ4eiIvPgogPC9nPgo8L3N2Zz4=)' - }; - - const arrowDown = { - backgroundImage: 'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDE2LjQybDkuMTcsOS4xN2w5LjE3LC05LjE3bDIuODMsMi44M2wtMTIsMTJsLTEyLC0xMmwyLjgzLC0yLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0xOC4zOTk4OTksMTcuMDc4NDczbDQ4LDBsMCw0OGwtNDgsMGwwLC00OHoiLz4KIDwvZz4KPC9zdmc+)' - }; return ( - ); } diff --git a/examples/nextjs/src/utils/publicImageLoader.js b/examples/nextjs/src/utils/publicImageLoader.js new file mode 100644 index 000000000000..6354699caaf1 --- /dev/null +++ b/examples/nextjs/src/utils/publicImageLoader.js @@ -0,0 +1,11 @@ +"use client"; + +import { useEffect, useState } from "react"; + +const PublicImageLoader = ({ src }) => { + const [imageSrc, setImageSrc] = useState(null); + useEffect(() => setImageSrc(`${window.location.origin}${src}`), [src]); + return imageSrc ?? "/"; +}; + +export default PublicImageLoader; \ No newline at end of file From 4041414d8c2efb84aa8cd64e5a4092b0eb55effa Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Tue, 12 Nov 2024 14:09:18 -0500 Subject: [PATCH 07/16] Updated sdk-editor script for traditional --- dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js index 189ae350ef59..7b11ba54ad0f 100644 --- a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js +++ b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js @@ -1 +1 @@ -function u(t){r({action:"edit-contentlet",payload:t})}function T(t=1){console.log("Called reorderMenu");let o=`/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=${t}&depth=2`;r({action:"reorder-menu",payload:{reorderUrl:o}})}function f(){return typeof window>"u"?!1:window.parent!==window}function m(){console.log("Called initDotUVE"),window.dotUVE=a}function g(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(o=>{o.clientHeight||o.classList.add("empty-contentlet")})}var a={editContentlet:u,reorderMenu:T,lastScrollYPosition:0};function r(t){window.parent.postMessage(t,"*")}function _(t){return t.map(o=>{let e=o.getBoundingClientRect(),n=Array.from(o.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:y(o)}),contentlets:h(e,n)}})}function h(t,o){return o.map(e=>{let n=e.getBoundingClientRect();return{x:0,y:n.y-t.y,width:n.width,height:n.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function y(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function E(t){let o=t.closest('[data-dot-object="container"]');return o?y(o):(console.warn("No container found for the contentlet"),null)}function p(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:p(t?.parentElement):null}function v(t){let o=t.querySelectorAll('[data-dot-object="vtl-file"]');return o.length?Array.from(o).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function M(){let t=document.documentElement.scrollHeight,o=window.innerHeight;return window.scrollY+o>=t}var i=[];function S(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),o=_(t);r({action:"set-bounds",payload:o})}function s(){let t=o=>{({"uve-reload-page":()=>{window.location.reload()},"uve-request-bounds":()=>{S()},"uve-scroll-inside-iframe":()=>{let n=o.data.direction;if(window.scrollY===0&&n==="up"||M()&&n==="down")return;let d=n==="up"?-120:120;window.scrollBy({left:0,top:d,behavior:"smooth"})}})[o.data.name]?.()};window.addEventListener("message",t),i.push({type:"listener",event:"message",callback:t})}function l(){let t=o=>{let e=p(o.target);if(!e)return;let{x:n,y:d,width:C,height:b}=e.getBoundingClientRect(),w=e.dataset?.dotObject==="container",P={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},L={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},O=v(e),N={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:w?P:L,vtlFiles:O};r({action:"set-contentlet",payload:{x:n,y:d,width:C,height:b,payload:N}})};document.addEventListener("pointermove",t),i.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{r({action:"scroll"}),window.dotUVE={...window.dotUVE??a,lastScrollYPosition:window.scrollY}},o=()=>{r({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",o),i.push({type:"listener",event:"scroll",callback:o}),i.push({type:"listener",event:"scroll",callback:t})}function D(){let t=()=>{window.scrollTo(0,window.dotUVE?.lastScrollYPosition)};window.addEventListener("load",t),i.push({type:"listener",event:"scroll",callback:t})}f()&&(m(),s(),c(),D(),l(),g()); +function u(t){i({action:"edit-contentlet",payload:t})}function T(t=1){let n=`/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=${t}&depth=2`;i({action:"reorder-menu",payload:{reorderUrl:n}})}function f(){return typeof window>"u"?!1:window.parent!==window}function m(){window.dotUVE=a}function g(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(n=>{n.clientHeight||n.classList.add("empty-contentlet")})}var a={editContentlet:u,reorderMenu:T,lastScrollYPosition:0};function i(t){window.parent.postMessage(t,"*")}function _(t){return t.map(n=>{let e=n.getBoundingClientRect(),o=Array.from(n.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:y(n)}),contentlets:h(e,o)}})}function h(t,n){return n.map(e=>{let o=e.getBoundingClientRect();return{x:0,y:o.y-t.y,width:o.width,height:o.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function y(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function E(t){let n=t.closest('[data-dot-object="container"]');return n?y(n):(console.warn("No container found for the contentlet"),null)}function p(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:p(t?.parentElement):null}function v(t){let n=t.querySelectorAll('[data-dot-object="vtl-file"]');return n.length?Array.from(n).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function M(){let t=document.documentElement.scrollHeight,n=window.innerHeight;return window.scrollY+n>=t}var r=[];function S(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),n=_(t);i({action:"set-bounds",payload:n})}function s(){let t=n=>{({"uve-reload-page":()=>{window.location.reload()},"uve-request-bounds":()=>{S()},"uve-scroll-inside-iframe":()=>{let o=n.data.direction;if(window.scrollY===0&&o==="up"||M()&&o==="down")return;let d=o==="up"?-120:120;window.scrollBy({left:0,top:d,behavior:"smooth"})}})[n.data.name]?.()};window.addEventListener("message",t),r.push({type:"listener",event:"message",callback:t})}function l(){let t=n=>{let e=p(n.target);if(!e)return;let{x:o,y:d,width:b,height:C}=e.getBoundingClientRect(),w=e.dataset?.dotObject==="container",P={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},L={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},O=v(e),N={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:w?P:L,vtlFiles:O};i({action:"set-contentlet",payload:{x:o,y:d,width:b,height:C,payload:N}})};document.addEventListener("pointermove",t),r.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{i({action:"scroll"}),window.dotUVE={...window.dotUVE??a,lastScrollYPosition:window.scrollY}},n=()=>{i({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",n),r.push({type:"listener",event:"scroll",callback:n}),r.push({type:"listener",event:"scroll",callback:t})}function D(){let t=()=>{window.scrollTo(0,window.dotUVE?.lastScrollYPosition)};window.addEventListener("load",t),r.push({type:"listener",event:"scroll",callback:t})}f()&&(m(),s(),c(),D(),l(),g()); From d174074667ca78bcbf5eedf94ff0c0bdd956f909 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Tue, 12 Nov 2024 16:18:24 -0500 Subject: [PATCH 08/16] Put comment about temporary solution --- .../src/lib/edit-ema-editor/edit-ema-editor.component.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 23e90e6a8686..15bcbec74d12 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -803,6 +803,8 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.uveStore.reload(); this.dialog.resetDialog(); + // This is a temporary solution to "reload" the content by reloading the window + // we should change this with a new SDK reload strategy this.contentWindow?.postMessage( { name: NOTIFY_CLIENT.UVE_RELOAD_PAGE From dc20abfd7577e29429c441a8845c6e610991241a Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 11:11:22 -0500 Subject: [PATCH 09/16] Added depth param on reorderMenu function. Changed images to inline images (without loader) --- .../src/lib/editor/models/editor.model.ts | 15 +++++++++++++++ .../sdk/client/src/lib/editor/sdk-editor.ts | 18 +++++++++++------- .../nextjs/src/components/layout/header.js | 9 +++++---- examples/nextjs/src/utils/publicImageLoader.js | 11 ----------- 4 files changed, 31 insertions(+), 22 deletions(-) delete mode 100644 examples/nextjs/src/utils/publicImageLoader.js diff --git a/core-web/libs/sdk/client/src/lib/editor/models/editor.model.ts b/core-web/libs/sdk/client/src/lib/editor/models/editor.model.ts index a064809e3017..07f28b7784be 100644 --- a/core-web/libs/sdk/client/src/lib/editor/models/editor.model.ts +++ b/core-web/libs/sdk/client/src/lib/editor/models/editor.model.ts @@ -51,3 +51,18 @@ export interface DotCMSPageEditorConfig { */ onReload?: () => void; } + +/** + * Configuration for reordering a menu. + */ +export interface ReorderMenuConfig { + /** + * The starting level of the menu to be reordered. + */ + startLevel: number; + + /** + * The depth of the menu levels to be reordered. + */ + depth: number; +} diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts index 2ca5e389c1b0..5310a5189b92 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts @@ -6,7 +6,7 @@ import { subscriptions } from './listeners/listeners'; import { CLIENT_ACTIONS, INITIAL_DOT_UVE, postMessageToEditor } from './models/client.model'; -import { DotCMSPageEditorConfig } from './models/editor.model'; +import { DotCMSPageEditorConfig, ReorderMenuConfig } from './models/editor.model'; import { Contentlet } from '../client/content/shared/types'; @@ -44,17 +44,21 @@ export function editContentlet(contentlet: Contentlet) { } /** - * Reorders the menu starting from a specified level. + * Reorders the menu based on the provided configuration. * - * @param {number} [startLevel=1] - The level from which to start reordering the menu. Defaults to 1. + * @param {ReorderMenuConfig} [config] - Optional configuration for reordering the menu. + * @param {number} [config.startLevel=1] - The starting level of the menu to reorder. + * @param {number} [config.depth=2] - The depth of the menu to reorder. * - * This function constructs a URL for the reorder menu page with the given start level and a fixed depth of 2. - * It then sends a message to the editor with the action to reorder the menu and the constructed URL as the payload. + * This function constructs a URL for the reorder menu page with the specified + * start level and depth, and sends a message to the editor to perform the reorder action. */ -export function reorderMenu(startLevel = 1) { +export function reorderMenu(config?: ReorderMenuConfig): void { + const { startLevel = 1, depth = 2 } = config || {}; + // This is the URL for the reorder menu page // All params are hardcoded on the jsp, so here we just need to send the same URL - const reorderUrl = `/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=${startLevel}&depth=2`; + const reorderUrl = `/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=${startLevel}&depth=${depth}`; postMessageToEditor({ action: CLIENT_ACTIONS.REORDER_MENU, diff --git a/examples/nextjs/src/components/layout/header.js b/examples/nextjs/src/components/layout/header.js index 731fdfe1b05b..f8b2bdf89315 100644 --- a/examples/nextjs/src/components/layout/header.js +++ b/examples/nextjs/src/components/layout/header.js @@ -1,7 +1,5 @@ import Link from 'next/link'; import { reorderMenu } from '@dotcms/client'; -import Image from 'next/image'; -import PublicImageLoader from '@/utils/publicImageLoader'; function Header({ children }) { return ( @@ -19,10 +17,13 @@ function Header({ children }) { function ReorderButton() { + const arrowUP = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDMwLjgzbDkuMTcsLTkuMTdsOS4xNyw5LjE3bDIuODMsLTIuODNsLTEyLC0xMmwtMTIsMTJsMi44MywyLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0zMC42OTQ1NTcsOS40MjU4ODdsNDgsMGwwLDQ4bC00OCwwbDAsLTQ4eiIvPgogPC9nPgo8L3N2Zz4="; + const arrowDown = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CgogPGc+CiAgPHRpdGxlPmJhY2tncm91bmQ8L3RpdGxlPgogIDxyZWN0IGZpbGw9Im5vbmUiIGlkPSJjYW52YXNfYmFja2dyb3VuZCIgaGVpZ2h0PSI0MDIiIHdpZHRoPSI1ODIiIHk9Ii0xIiB4PSItMSIvPgogPC9nPgogPGc+CiAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMSIgZD0ibTE0LjgzLDE2LjQybDkuMTcsOS4xN2w5LjE3LC05LjE3bDIuODMsMi44M2wtMTIsMTJsLTEyLC0xMmwyLjgzLC0yLjgzeiIvPgogIDxwYXRoIGlkPSJzdmdfMiIgZmlsbD0ibm9uZSIgZD0ibS0xOC4zOTk4OTksMTcuMDc4NDczbDQ4LDBsMCw0OGwtNDgsMGwwLC00OHoiLz4KIDwvZz4KPC9zdmc+"; + return ( ); } diff --git a/examples/nextjs/src/utils/publicImageLoader.js b/examples/nextjs/src/utils/publicImageLoader.js deleted file mode 100644 index 6354699caaf1..000000000000 --- a/examples/nextjs/src/utils/publicImageLoader.js +++ /dev/null @@ -1,11 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; - -const PublicImageLoader = ({ src }) => { - const [imageSrc, setImageSrc] = useState(null); - useEffect(() => setImageSrc(`${window.location.origin}${src}`), [src]); - return imageSrc ?? "/"; -}; - -export default PublicImageLoader; \ No newline at end of file From ee8954f8e59ae76c0766153979e6a70e70fff881 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 14:11:37 -0500 Subject: [PATCH 10/16] Applying feedback. Centralize the createMenuURL on one place. --- .../edit-ema-editor.component.ts | 7 +- .../edit-ema/portlet/src/lib/utils/index.ts | 19 +++- .../sdk/client/src/lib/editor/sdk-editor.ts | 6 +- .../WEB-INF/velocity/VM_global_library.vm | 4 +- .../webapp/html/js/editor-js/sdk-editor.js | 3 +- .../nextjs/src/components/layout/header.js | 91 ++++++++++++++++++- 6 files changed, 110 insertions(+), 20 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 15bcbec74d12..9a9934dea583 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -1,4 +1,5 @@ import { tapResponse } from '@ngrx/operators'; +import { ReorderMenuConfig } from 'libs/sdk/client/src/lib/editor/models/editor.model'; import { EMPTY, Observable, Subject, fromEvent, of } from 'rxjs'; import { NgClass, NgStyle } from '@angular/common'; @@ -80,7 +81,6 @@ import { VTLFile, DeletePayload, InsertPayloadFromDelete, - ReorderPayload, DialogAction, PostMessage } from '../shared/models'; @@ -1005,9 +1005,10 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { [CLIENT_ACTIONS.EDIT_CONTENTLET]: (contentlet: DotCMSContentlet) => { this.dialog.editContentlet({ ...contentlet, clientAction: action }); }, - [CLIENT_ACTIONS.REORDER_MENU]: ({ reorderUrl }: ReorderPayload) => { + [CLIENT_ACTIONS.REORDER_MENU]: ({ startLevel, depth }: ReorderMenuConfig) => { const urlObject = createReorderMenuURL({ - url: reorderUrl, + startLevel, + depth, pagePath: this.uveStore.params().url, hostId: this.uveStore.pageAPIResponse().site.identifier }); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts index 71a728d2ac6a..0ff707260159 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts @@ -24,6 +24,9 @@ import { export const SDK_EDITOR_SCRIPT_SOURCE = '/html/js/editor-js/sdk-editor.js'; +const REORDER_MENU_BASE_URL = + 'c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu'; + export const TEMPORAL_DRAG_ITEM: EmaDragItem = { baseType: 'dotAsset', contentType: 'dotAsset', @@ -521,18 +524,28 @@ export const getDragItemData = ({ type, item }: DOMStringMap) => { * @returns {string} - The updated URL with the missing parameters added. */ export const createReorderMenuURL = ({ - url, + startLevel, + depth, pagePath, hostId }: { - url: string; + startLevel: number; + depth: number; pagePath: string; hostId: string; }) => { - const urlObject = new URL(url, window.location.origin); + const urlObject = new URL(REORDER_MENU_BASE_URL, window.location.origin); const params = urlObject.searchParams; + if (!params.has('startLevel')) { + params.set('startLevel', startLevel.toString()); + } + + if (!params.has('depth')) { + params.set('depth', depth.toString()); + } + if (!params.has('pagePath')) { params.set('pagePath', pagePath); } diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts index 5310a5189b92..7c648c15c462 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts @@ -56,13 +56,9 @@ export function editContentlet(contentlet: Contentlet) { export function reorderMenu(config?: ReorderMenuConfig): void { const { startLevel = 1, depth = 2 } = config || {}; - // This is the URL for the reorder menu page - // All params are hardcoded on the jsp, so here we just need to send the same URL - const reorderUrl = `/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=${startLevel}&depth=${depth}`; - postMessageToEditor({ action: CLIENT_ACTIONS.REORDER_MENU, - payload: { reorderUrl } + payload: { startLevel, depth } }); } diff --git a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm index afd4ab3786bd..32f3659cc510 100644 --- a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm +++ b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm @@ -172,7 +172,7 @@ #if ($EDIT_MODE && $PUBLISH_HTMLPAGE_PERMISSION) #set($menuLevel = $VTLSERVLET_URI.split('/').size() - 1) - + @@ -183,7 +183,7 @@ #if ($EDIT_MODE && $PUBLISH_HTMLPAGE_PERMISSION) #set($menuLevel = $VTLSERVLET_URI.split('/').size() - 1) ); } From eecb1debca80865b9920f7aa909f25e77d65e085 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 14:23:56 -0500 Subject: [PATCH 11/16] Changed icon and fix lint issue --- .../edit-ema-editor.component.ts | 9 +- .../nextjs/src/components/graphql-page.js | 2 +- .../nextjs/src/components/layout/header.js | 113 ------------------ .../layout/header/components/reorderMenu.js | 38 ++++++ .../src/components/layout/header/header.js | 21 ++++ examples/nextjs/src/components/my-page.js | 2 +- 6 files changed, 68 insertions(+), 117 deletions(-) delete mode 100644 examples/nextjs/src/components/layout/header.js create mode 100644 examples/nextjs/src/components/layout/header/components/reorderMenu.js create mode 100644 examples/nextjs/src/components/layout/header/header.js diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 9a9934dea583..006439ba9a85 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -1,5 +1,4 @@ import { tapResponse } from '@ngrx/operators'; -import { ReorderMenuConfig } from 'libs/sdk/client/src/lib/editor/models/editor.model'; import { EMPTY, Observable, Subject, fromEvent, of } from 'rxjs'; import { NgClass, NgStyle } from '@angular/common'; @@ -1005,7 +1004,13 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { [CLIENT_ACTIONS.EDIT_CONTENTLET]: (contentlet: DotCMSContentlet) => { this.dialog.editContentlet({ ...contentlet, clientAction: action }); }, - [CLIENT_ACTIONS.REORDER_MENU]: ({ startLevel, depth }: ReorderMenuConfig) => { + [CLIENT_ACTIONS.REORDER_MENU]: ({ + startLevel, + depth + }: { + startLevel: number; + depth: number; + }) => { const urlObject = createReorderMenuURL({ startLevel, depth, diff --git a/examples/nextjs/src/components/graphql-page.js b/examples/nextjs/src/components/graphql-page.js index d79f90dabb40..97d347c2e091 100644 --- a/examples/nextjs/src/components/graphql-page.js +++ b/examples/nextjs/src/components/graphql-page.js @@ -8,7 +8,7 @@ import CalendarEvent from "./content-types/calendarEvent"; import Product from "./content-types/product"; import ImageComponent from "./content-types/image"; -import Header from "./layout/header"; +import Header from "./layout/header/header"; import Footer from "./layout/footer/footer"; import Navigation from "./layout/navigation"; import { usePathname, useRouter } from "next/navigation"; diff --git a/examples/nextjs/src/components/layout/header.js b/examples/nextjs/src/components/layout/header.js deleted file mode 100644 index fdacd440433f..000000000000 --- a/examples/nextjs/src/components/layout/header.js +++ /dev/null @@ -1,113 +0,0 @@ -import Link from 'next/link'; -import { reorderMenu } from '@dotcms/client'; - -function Header({ children }) { - return ( -
-
-

- TravelLux in NextJS -

-
- - {children} -
- ); -} - -function ReorderButton() { - const ArrowDown = () => ( - - - - - - ) - - const ArrowUp = () => ( - - - - - - ) - return ( - - ); -} - - -export default Header; diff --git a/examples/nextjs/src/components/layout/header/components/reorderMenu.js b/examples/nextjs/src/components/layout/header/components/reorderMenu.js new file mode 100644 index 000000000000..e5596a4d3b1d --- /dev/null +++ b/examples/nextjs/src/components/layout/header/components/reorderMenu.js @@ -0,0 +1,38 @@ +import { reorderMenu } from '@dotcms/client'; + +export default function ReorderButton() { + const OrderIcon = () => ( + + + + + + + ) + return ( + + ); +} \ No newline at end of file diff --git a/examples/nextjs/src/components/layout/header/header.js b/examples/nextjs/src/components/layout/header/header.js new file mode 100644 index 000000000000..07315bbc3c5c --- /dev/null +++ b/examples/nextjs/src/components/layout/header/header.js @@ -0,0 +1,21 @@ +import Link from 'next/link'; +import ReorderButton from './components/reorderMenu'; + +function Header({ children }) { + return ( +
+
+

+ TravelLux in NextJS +

+
+ + {children} +
+ ); +} + + + + +export default Header; diff --git a/examples/nextjs/src/components/my-page.js b/examples/nextjs/src/components/my-page.js index e9f0d33ce5f8..0286616a01ab 100644 --- a/examples/nextjs/src/components/my-page.js +++ b/examples/nextjs/src/components/my-page.js @@ -8,7 +8,7 @@ import CalendarEvent from "./content-types/calendarEvent"; import Product from "./content-types/product"; import ImageComponent from "./content-types/image"; -import Header from "./layout/header"; +import Header from "./layout/header/header"; import Footer from "./layout/footer/footer"; import Navigation from "./layout/navigation"; import { usePathname, useRouter } from "next/navigation"; From a5b2aff6bc900db28641e85e48bd1dc5cbeeca49 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 16:09:44 -0500 Subject: [PATCH 12/16] Added support of sort navigation to old editor --- .../portlet/src/lib/utils/utils.spec.ts | 21 ++--------- .../WEB-INF/velocity/VM_global_library.vm | 37 ++++++++++++++++++- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts index 17f986bd682c..30fa12e16945 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts @@ -712,29 +712,16 @@ describe('utils functions', () => { }); describe('createReorderMenuURL', () => { - it('should add the missing params', () => { - const url = 'some-url?language_id=1'; + it('should create the correct URL', () => { const result = createReorderMenuURL({ - url, + startLevel: 1, + depth: 1, pagePath: '123', hostId: '456' }); expect(result).toEqual( - 'http://localhost/some-url?language_id=1&pagePath=123&hostId=456' - ); - }); - - it('should not add the missing params', () => { - const url = 'some-url?language_id=1&pagePath=111&hostId=333'; - const result = createReorderMenuURL({ - url, - pagePath: '123', - hostId: '456' - }); - - expect(result).toEqual( - 'http://localhost/some-url?language_id=1&pagePath=111&hostId=333' + 'http://localhost/c/portal/layout?p_l_id=2df9f117-b140-44bf-93d7-5b10a36fb7f9&p_p_id=site-browser&p_p_action=1&p_p_state=maximized&_site_browser_struts_action=%2Fext%2Ffolders%2Forder_menu&startLevel=1&depth=1&pagePath=123&hostId=456' ); }); }); diff --git a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm index 32f3659cc510..fb54306af8e3 100644 --- a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm +++ b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm @@ -172,10 +172,27 @@ #if ($EDIT_MODE && $PUBLISH_HTMLPAGE_PERMISSION) #set($menuLevel = $VTLSERVLET_URI.split('/').size() - 1) - + + + #end #end @@ -183,7 +200,7 @@ #if ($EDIT_MODE && $PUBLISH_HTMLPAGE_PERMISSION) #set($menuLevel = $VTLSERVLET_URI.split('/').size() - 1) + #end #end From 277e898ceecf392ba75a276eb2f61a1552e9d337 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 16:12:53 -0500 Subject: [PATCH 13/16] Added model to ReorderMenu payload --- .../src/lib/edit-ema-editor/edit-ema-editor.component.ts | 8 +++----- .../portlets/edit-ema/portlet/src/lib/shared/models.ts | 5 +++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 006439ba9a85..3d57e78ea379 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -81,7 +81,8 @@ import { DeletePayload, InsertPayloadFromDelete, DialogAction, - PostMessage + PostMessage, + ReorderMenuPayload } from '../shared/models'; import { UVEStore } from '../store/dot-uve.store'; import { ClientRequestProps } from '../store/features/client/withClient'; @@ -1007,10 +1008,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { [CLIENT_ACTIONS.REORDER_MENU]: ({ startLevel, depth - }: { - startLevel: number; - depth: number; - }) => { + }: ReorderMenuPayload) => { const urlObject = createReorderMenuURL({ startLevel, depth, diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts index 721a2451c10b..35997aac5ba3 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts @@ -240,3 +240,8 @@ export interface PostMessage { action: CLIENT_ACTIONS; payload: unknown; } + +export interface ReorderMenuPayload { + startLevel: number; + depth: number; +} From c032afc199f2d2e3e046bbc0e493c874e7c67465 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 16:24:09 -0500 Subject: [PATCH 14/16] Fixed lint issue --- .../edit-ema-editor/edit-ema-editor.component.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 3d57e78ea379..fd04759b45b0 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -45,15 +45,9 @@ import { SeoMetaTagsResult } from '@dotcms/dotcms-models'; import { DotResultsSeoToolComponent } from '@dotcms/portlets/dot-ema/ui'; -import { - SafeUrlPipe, - DotSpinnerModule, - DotMessagePipe, - DotCopyContentModalService -} from '@dotcms/ui'; +import { SafeUrlPipe, DotSpinnerModule, DotCopyContentModalService } from '@dotcms/ui'; import { isEqual } from '@dotcms/utils'; -import { DotEmaBookmarksComponent } from './components/dot-ema-bookmarks/dot-ema-bookmarks.component'; import { EditEmaPaletteComponent } from './components/edit-ema-palette/edit-ema-palette.component'; import { EditEmaToolbarComponent } from './components/edit-ema-toolbar/edit-ema-toolbar.component'; import { EmaContentletToolsComponent } from './components/ema-contentlet-tools/ema-contentlet-tools.component'; @@ -111,11 +105,9 @@ import { DotEmaDialogComponent, ConfirmDialogModule, EditEmaToolbarComponent, - DotMessagePipe, EmaPageDropzoneComponent, EditEmaPaletteComponent, EmaContentletToolsComponent, - DotEmaBookmarksComponent, ProgressBarModule, DotResultsSeoToolComponent, DotBlockEditorSidebarComponent @@ -1005,10 +997,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { [CLIENT_ACTIONS.EDIT_CONTENTLET]: (contentlet: DotCMSContentlet) => { this.dialog.editContentlet({ ...contentlet, clientAction: action }); }, - [CLIENT_ACTIONS.REORDER_MENU]: ({ - startLevel, - depth - }: ReorderMenuPayload) => { + [CLIENT_ACTIONS.REORDER_MENU]: ({ startLevel, depth }: ReorderMenuPayload) => { const urlObject = createReorderMenuURL({ startLevel, depth, From 5fd78d5cc2cc35ca638b170a405b582df6eba41a Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 16:27:36 -0500 Subject: [PATCH 15/16] Manually updated sdk-editor js file --- dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js index 4f49a80668ec..2eabae15b1c9 100644 --- a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js +++ b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js @@ -1 +1 @@ -function u(t){i({action:"edit-contentlet",payload:t})}function T(t){console.log("reorderMenu v2 called",t);let{startLevel:n=1,depth:e=2}=t||{};i({action:"reorder-menu",payload:{startLevel:n,depth:e}})}function f(){return typeof window>"u"?!1:window.parent!==window}function m(){window.dotUVE=a}function g(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(n=>{n.clientHeight||n.classList.add("empty-contentlet")})}var a={editContentlet:u,reorderMenu:T,lastScrollYPosition:0};function i(t){window.parent.postMessage(t,"*")}function v(t){return t.map(n=>{let e=n.getBoundingClientRect(),o=Array.from(n.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:y(n)}),contentlets:S(e,o)}})}function S(t,n){return n.map(e=>{let o=e.getBoundingClientRect();return{x:0,y:o.y-t.y,width:o.width,height:o.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function y(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function E(t){let n=t.closest('[data-dot-object="container"]');return n?y(n):(console.warn("No container found for the contentlet"),null)}function p(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:p(t?.parentElement):null}function M(t){let n=t.querySelectorAll('[data-dot-object="vtl-file"]');return n.length?Array.from(n).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function D(){let t=document.documentElement.scrollHeight,n=window.innerHeight;return window.scrollY+n>=t}var r=[];function x(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),n=v(t);i({action:"set-bounds",payload:n})}function l(){let t=n=>{({"uve-reload-page":()=>{window.location.reload()},"uve-request-bounds":()=>{x()},"uve-scroll-inside-iframe":()=>{let o=n.data.direction;if(window.scrollY===0&&o==="up"||D()&&o==="down")return;let d=o==="up"?-120:120;window.scrollBy({left:0,top:d,behavior:"smooth"})}})[n.data.name]?.()};window.addEventListener("message",t),r.push({type:"listener",event:"message",callback:t})}function s(){let t=n=>{let e=p(n.target);if(!e)return;let{x:o,y:d,width:I,height:w}=e.getBoundingClientRect(),N=e.dataset?.dotObject==="container",O={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},P={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},b=M(e),h={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:N?O:P,vtlFiles:b};i({action:"set-contentlet",payload:{x:o,y:d,width:I,height:w,payload:h}})};document.addEventListener("pointermove",t),r.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{i({action:"scroll"}),window.dotUVE={...window.dotUVE??a,lastScrollYPosition:window.scrollY}},n=()=>{i({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",n),r.push({type:"listener",event:"scroll",callback:n}),r.push({type:"listener",event:"scroll",callback:t})}function C(){let t=()=>{window.scrollTo(0,window.dotUVE?.lastScrollYPosition)};window.addEventListener("load",t),r.push({type:"listener",event:"scroll",callback:t})}var L=()=>{let t=()=>{let n=document.querySelectorAll("[data-block-editor-content]");n.length&&n.forEach(e=>{e.classList.add("dotcms__inline-edit-field"),e.addEventListener("click",()=>{let o={...e.dataset};window.parent.postMessage({payload:o,action:"init-editor-inline-editing"},"*")})})};document.readyState==="complete"?t():window.addEventListener("load",()=>t())};f()&&(m(),l(),c(),C(),s(),g(),L()); +function u(t){i({action:"edit-contentlet",payload:t})}function T(t){let{startLevel:n=1,depth:e=2}=t||{};i({action:"reorder-menu",payload:{startLevel:n,depth:e}})}function f(){return typeof window>"u"?!1:window.parent!==window}function m(){window.dotUVE=a}function g(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(n=>{n.clientHeight||n.classList.add("empty-contentlet")})}var a={editContentlet:u,reorderMenu:T,lastScrollYPosition:0};function i(t){window.parent.postMessage(t,"*")}function v(t){return t.map(n=>{let e=n.getBoundingClientRect(),o=Array.from(n.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:y(n)}),contentlets:S(e,o)}})}function S(t,n){return n.map(e=>{let o=e.getBoundingClientRect();return{x:0,y:o.y-t.y,width:o.width,height:o.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function y(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function E(t){let n=t.closest('[data-dot-object="container"]');return n?y(n):(console.warn("No container found for the contentlet"),null)}function p(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:p(t?.parentElement):null}function M(t){let n=t.querySelectorAll('[data-dot-object="vtl-file"]');return n.length?Array.from(n).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function D(){let t=document.documentElement.scrollHeight,n=window.innerHeight;return window.scrollY+n>=t}var r=[];function x(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),n=v(t);i({action:"set-bounds",payload:n})}function l(){let t=n=>{({"uve-reload-page":()=>{window.location.reload()},"uve-request-bounds":()=>{x()},"uve-scroll-inside-iframe":()=>{let o=n.data.direction;if(window.scrollY===0&&o==="up"||D()&&o==="down")return;let d=o==="up"?-120:120;window.scrollBy({left:0,top:d,behavior:"smooth"})}})[n.data.name]?.()};window.addEventListener("message",t),r.push({type:"listener",event:"message",callback:t})}function s(){let t=n=>{let e=p(n.target);if(!e)return;let{x:o,y:d,width:I,height:w}=e.getBoundingClientRect(),N=e.dataset?.dotObject==="container",O={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},P={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},b=M(e),h={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:N?O:P,vtlFiles:b};i({action:"set-contentlet",payload:{x:o,y:d,width:I,height:w,payload:h}})};document.addEventListener("pointermove",t),r.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{i({action:"scroll"}),window.dotUVE={...window.dotUVE??a,lastScrollYPosition:window.scrollY}},n=()=>{i({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",n),r.push({type:"listener",event:"scroll",callback:n}),r.push({type:"listener",event:"scroll",callback:t})}function C(){let t=()=>{window.scrollTo(0,window.dotUVE?.lastScrollYPosition)};window.addEventListener("load",t),r.push({type:"listener",event:"scroll",callback:t})}var L=()=>{let t=()=>{let n=document.querySelectorAll("[data-block-editor-content]");n.length&&n.forEach(e=>{e.classList.add("dotcms__inline-edit-field"),e.addEventListener("click",()=>{let o={...e.dataset};window.parent.postMessage({payload:o,action:"init-editor-inline-editing"},"*")})})};document.readyState==="complete"?t():window.addEventListener("load",()=>t())};f()&&(m(),l(),c(),C(),s(),g(),L()); From a476ab8afcb5abe11240483232b074096a0f04e0 Mon Sep 17 00:00:00 2001 From: Kevin Davila Date: Wed, 13 Nov 2024 18:06:27 -0500 Subject: [PATCH 16/16] Fixed test on ema-editor --- .../lib/edit-ema-editor/edit-ema-editor.component.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts index 5e00f2309252..4afc04e9c771 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts @@ -750,7 +750,8 @@ describe('EditEmaEditorComponent', () => { data: { action: CLIENT_ACTIONS.REORDER_MENU, payload: { - reorderUrl: 'http://localhost:3000/reorder-menu' + startLevel: 1, + depth: 2 } } }) @@ -825,7 +826,8 @@ describe('EditEmaEditorComponent', () => { data: { action: CLIENT_ACTIONS.REORDER_MENU, payload: { - reorderUrl: 'http://localhost:3000/reorder-menu' + startLevel: 1, + depth: 2 } } })