diff --git a/addons/website/static/src/components/burger_menu/burger_menu.js b/addons/website/static/src/components/burger_menu/burger_menu.js
index f1ee3574f7d..feaa3ad0ae8 100644
--- a/addons/website/static/src/components/burger_menu/burger_menu.js
+++ b/addons/website/static/src/components/burger_menu/burger_menu.js
@@ -40,7 +40,7 @@ patch(BurgerMenu.prototype, 'website_burger_menu', {
async _onMenuClicked(menu) {
const websiteMenu = this.websiteCustomMenus.get(menu.xmlid);
if (websiteMenu) {
- this.websiteCustomMenus.open(menu.xmlid);
+ this.websiteCustomMenus.open(menu);
this._closeBurger();
} else {
this._super(menu);
diff --git a/addons/website/static/src/components/navbar/navbar.js b/addons/website/static/src/components/navbar/navbar.js
index f1db8fcaa4a..eeefc98de14 100644
--- a/addons/website/static/src/components/navbar/navbar.js
+++ b/addons/website/static/src/components/navbar/navbar.js
@@ -56,8 +56,7 @@ patch(NavBar.prototype, 'website_navbar', {
onNavBarDropdownItemSelection(menu) {
const websiteMenu = this.websiteCustomMenus.get(menu.xmlid);
if (websiteMenu) {
- return this.websiteCustomMenus.open(menu.xmlid);
-
+ return this.websiteCustomMenus.open(menu);
}
return this._super(menu);
},
diff --git a/addons/website/static/src/services/website_custom_menus.js b/addons/website/static/src/services/website_custom_menus.js
index 06d6bc43277..d7694ec5aae 100644
--- a/addons/website/static/src/services/website_custom_menus.js
+++ b/addons/website/static/src/services/website_custom_menus.js
@@ -4,6 +4,7 @@ import { registry } from "@web/core/registry";
import { EditMenuDialog } from '@website/components/dialog/edit_menu';
import { OptimizeSEODialog } from '@website/components/dialog/seo';
import {PagePropertiesDialog} from '@website/components/dialog/page_properties';
+import {sprintf} from '@web/core/utils/strings';
/**
* This service displays contextual menus, depending of the state of the
@@ -19,14 +20,20 @@ export const websiteCustomMenus = {
get(xmlId) {
return registry.category('website_custom_menus').get(xmlId, null);
},
- open(xmlId) {
- const menu = this.get(xmlId);
- if (menu.openWidget) {
- return menu.openWidget(services);
+ open(customMenu) {
+ const menuConfig = this.get(customMenu.xmlid);
+ if (menuConfig.openWidget) {
+ return menuConfig.openWidget(services);
}
+ const menuProps = {
+ ...(menuConfig.getProps && menuConfig.getProps(services)),
+ // Values on 'dynamicProps' are retrieved after the content is loaded (e.g. id of
+ // the content menu to be edited).
+ ...customMenu.dynamicProps,
+ };
return dialog.add(
- menu.Component,
- menu.getProps && menu.getProps(services),
+ menuConfig.Component,
+ menuProps,
);
},
addCustomMenus(sections) {
@@ -39,7 +46,21 @@ export const websiteCustomMenus = {
if (section.childrenTree.length) {
subSections = this.addCustomMenus(section.childrenTree);
}
- filteredSections.push(Object.assign({}, section, {childrenTree: subSections}));
+ if (section.xmlid === 'website.custom_menu_edit_menu') {
+ // Hack: this code will simulate an XML pre-configured navbar menuitem to edit each
+ // content menu found on the current page by duplicating one menuitem with
+ // different data (name, dialog props...). this will prevent breaking the current
+ // 'navbar menus' display system.
+ filteredSections.push(...website.currentWebsite.metadata.contentMenus.map((menu, index) => ({
+ ...section,
+ name: sprintf(env._t("Edit %s"), menu[0]),
+ dynamicProps: {rootID: parseInt(menu[1], 10)},
+ // Prevent a 't-foreach' duplicate key on menus template.
+ id: `${section.id}-${index}`,
+ })));
+ } else {
+ filteredSections.push(Object.assign({}, section, {childrenTree: subSections}));
+ }
}
}
return filteredSections;
@@ -84,3 +105,12 @@ registry.category('website_custom_menus').add('website.menu_page_properties', {
},
})
});
+registry.category('website_custom_menus').add('website.custom_menu_edit_menu', {
+ Component: EditMenuDialog,
+ // 'isDisplayed' === true => at least 1 content menu was found on the page. This
+ // menuitem will be cloned (in 'addCustomMenus()') to edit every content menu using
+ // the 'EditMenuDialog' component.
+ isDisplayed: (env) => env.services.website.currentWebsite
+ && env.services.website.currentWebsite.metadata.contentMenus.length
+ && !env.services.ui.isSmall,
+});
diff --git a/addons/website/static/src/services/website_service.js b/addons/website/static/src/services/website_service.js
index cfffab1ebe4..2b6d4a0b8af 100644
--- a/addons/website/static/src/services/website_service.js
+++ b/addons/website/static/src/services/website_service.js
@@ -114,7 +114,10 @@ export const websiteService = {
currentMetadata = {};
} else {
const { mainObject, seoObject, isPublished, canPublish, editableInBackend, translatable, viewXmlid } = document.documentElement.dataset;
- const contentMenuEl = document.querySelector('[data-content_menu_id]');
+ const contentMenus = [...document.querySelectorAll('[data-content_menu_id]')].map(menu => [
+ menu.dataset.menu_name,
+ menu.dataset.content_menu_id,
+ ]);
currentMetadata = {
path: document.location.href,
mainObject: unslugHtmlDataObject(mainObject),
@@ -124,7 +127,7 @@ export const websiteService = {
editableInBackend: editableInBackend === 'True',
title: document.title,
translatable: !!translatable,
- contentMenuId: contentMenuEl && contentMenuEl.dataset.content_menu_id,
+ contentMenus,
// TODO: Find a better way to figure out if
// a page is editable or not. For now, we use
// the editable selector because it's the common
diff --git a/addons/website/views/website_views.xml b/addons/website/views/website_views.xml
index 977b034858d..2970e85a718 100644
--- a/addons/website/views/website_views.xml
+++ b/addons/website/views/website_views.xml
@@ -447,6 +447,12 @@
name="HTML / CSS Editor"
action="website.website_preview"/>
+
+