odoo18/addons/website/static/src/services/website_custom_menus.js

141 lines
6.8 KiB
JavaScript

/** @odoo-module **/
import { _t } from "@web/core/l10n/translation";
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';
/**
* This service displays contextual menus, depending of the state of the
* website. These menus are defined in xml with the "website_preview" action,
* which is overriden here for displaying dialogs, or regular components that
* are not client actions.
*/
export const websiteCustomMenus = {
dependencies: ['website', 'orm', 'dialog', 'ui'],
start(env, { website, orm, dialog, ui }) {
const services = { website, orm, dialog, ui };
return {
get(xmlId) {
return registry.category('website_custom_menus').get(xmlId, null);
},
async open(customMenu) {
const menuConfig = this.get(customMenu.xmlid);
if (menuConfig.openWidget) {
return menuConfig.openWidget(services);
}
const menuProps = {
...(menuConfig.getProps && (await 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(
menuConfig.Component,
menuProps,
);
},
addCustomMenus(sections) {
const filteredSections = [];
for (const section of sections) {
const isWebsiteCustomMenu = !!this.get(section.xmlid);
const displayWebsiteCustomMenu = isWebsiteCustomMenu && website.isRestrictedEditor && this.get(section.xmlid).isDisplayed(env);
if (!isWebsiteCustomMenu || displayWebsiteCustomMenu) {
let subSections = [];
if (section.childrenTree.length) {
subSections = this.addCustomMenus(section.childrenTree);
}
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: _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}));
}
}
}
for (const section of filteredSections) {
section.childrenTree = section.childrenTree.filter(
// Exclude non-leaf node having no visible sub-element.
tree => !(tree.children.length && !tree.childrenTree.length)
);
}
return filteredSections;
},
};
}
};
registry.category('services').add('website_custom_menus', websiteCustomMenus);
registry.category('website_custom_menus').add('website.menu_edit_menu', {
Component: EditMenuDialog,
isDisplayed: (env) => !!env.services.website.currentWebsite
&& env.services.website.isDesigner
&& !env.services.website.currentWebsite.metadata.translatable,
});
registry.category('website_custom_menus').add('website.menu_optimize_seo', {
Component: OptimizeSEODialog,
isDisplayed: (env) => env.services.website.currentWebsite
&& env.services.website.isRestrictedEditor
&& !!env.services.website.currentWebsite.metadata.canOptimizeSeo,
});
registry.category('website_custom_menus').add('website.menu_ace_editor', {
openWidget: (services) => services.website.context.showResourceEditor = true,
isDisplayed: (env) => env.services.website.currentWebsite
&& env.services.website.currentWebsite.metadata.viewXmlid
&& !env.services.ui.isSmall,
});
registry.category('website_custom_menus').add('website.menu_page_properties', {
Component: PagePropertiesDialog,
isDisplayed: (env) => env.services.website.currentWebsite
&& env.services.website.isDesigner
&& !!env.services.website.currentWebsite.metadata.mainObject,
getProps: async ({ orm, website }) => {
const mainObject = website.currentWebsite.metadata.mainObject;
const isPage = mainObject.model === "website.page";
const model = isPage ? "website.page.properties" : "website.page.properties.base";
return {
resId: await orm.call(model, "create", [
isPage
? {
target_model_id: mainObject.id,
website_id: website.currentWebsite.id,
}
: {
target_model_id: `${mainObject.model},${mainObject.id}`,
url: window.location.pathname,
website_id: website.currentWebsite.id,
},
]),
resModel: model,
onRecordSaved: async (record) => {
const page = isPage
? (await orm.read("website.page", [mainObject.id], ["website_id", "url"]))[0]
: undefined;
return website.goToWebsite({
websiteId: page?.website_id?.[0] ?? website.currentWebsite.id,
path: page?.url ?? website.currentWebsite.metadata.path,
});
},
};
},
});
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
&& env.services.website.currentWebsite.metadata.contentMenus.length,
});