[IMP] web_editor, website: add edit menu

This commit also suggests a way to conditionnaly display menus. Here the
website edit menu should only be visible when the website is displayed.

There may be a better way to filter out some menus. That feature will
be reviewed anyway as part of a `patch` the framework team would like to
avoid.

See merge commit for more information.

task-2687506
This commit is contained in:
Younn Olivier
2022-06-24 10:28:05 +02:00
committed by qsm-odoo
parent c4a8f86265
commit 2c77b90eee
7 changed files with 248 additions and 1141 deletions
@@ -287,7 +287,11 @@ ul.oe_menu_editor {
list-style: none;
}
li div {
cursor: move;
@include o-grab-cursor;
:active {
cursor: grabbing;
}
}
}
+3 -3
View File
@@ -174,8 +174,8 @@
'website/static/src/client_actions/*/*.scss',
'website/static/src/services/website_service.js',
'website/static/src/components/navbar/navbar.js',
'website/static/src/components/dialog/dialog.js',
'website/static/src/components/dialog/dialog.scss',
'website/static/src/components/dialog/*.js',
'website/static/src/components/dialog/*.scss',
'website/static/src/components/switch/switch.js',
'website/static/src/components/switch/switch.scss',
'website/static/src/components/fullscreen_indication/fullscreen_indication.js',
@@ -251,7 +251,7 @@
'website/static/src/xml/website.backend.xml',
'website/static/src/xml/website_widget.xml',
'website/static/src/xml/theme_preview.xml',
'website/static/src/components/dialog/dialog.xml',
'website/static/src/components/dialog/*',
'website/static/src/client_actions/*/*.xml',
'website/static/src/systray_items/*.xml',
],
File diff suppressed because it is too large Load Diff
@@ -1,59 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="website.contentMenu.dialog.submenu">
<li t-att-data-menu-id="submenu.fields['id']" t-att-data-mega-menu="submenu.fields['is_mega_menu'] ? true : undefined">
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="website.MenuDialog" owl="1">
<div class="form-group row">
<label class="col-form-label col-md-3">
Name
</label>
<div class="col-md-9">
<input type="text" t-model="state.name" class="form-control" required="required"/>
</div>
</div>
<div t-if="!props.isMegaMenu" class="form-group row">
<label class="col-form-label col-md-3">
Url or Email
</label>
<div class="col-md-9">
<input type="text" t-model="state.url" class="form-control" required="required"/>
</div>
</div>
</t>
<t t-name="website.MenuRow" owl="1">
<li t-att-data-menu-id="props.menu.fields['id']" t-att-data-is-mega-menu="props.menu.fields['is_mega_menu'] ? 'true' : undefined">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text fa fa-bars" role="img" aria-label="Dropdown menu" title="Dropdown menu"/>
</div>
<span class="form-control d-flex align-items-center">
<span class="js_menu_label o_text_overflow flex-grow-1">
<t t-esc="submenu.fields['name']"/>
<t t-esc="props.menu.fields['name']"/>
</span>
<span t-if="submenu.fields['is_mega_menu']" class="badge badge-primary">Mega Menu</span>
<i t-if="submenu.is_homepage" class="fa fa-home ml-3" role="img" aria-label="Home" title="Home"/>
<span t-if="props.menu.fields['is_mega_menu']" class="badge badge-primary">Mega Menu</span>
<i t-if="props.menu.is_homepage" class="fa fa-home ml-3" role="img" aria-label="Home" title="Home"/>
</span>
<span class="input-group-append">
<button type="button" class="btn btn-primary js_edit_menu fa fa-pencil-square-o" aria-label="Edit Menu Item" title="Edit Menu Item"/>
<button type="button" class="btn btn-danger js_delete_menu fa fa-trash-o" aria-label="Delete Menu Item" title="Delete Menu Item"/>
<button t-on-click="edit" type="button" class="btn btn-primary js_edit_menu fa fa-pencil-square-o" aria-label="Edit Menu Item" title="Edit Menu Item"/>
<button t-on-click="delete" type="button" class="btn btn-danger js_delete_menu fa fa-trash-o" aria-label="Delete Menu Item" title="Delete Menu Item"/>
</span>
</div>
<t t-set="children" t-value="submenu.children"/>
<ul t-if="children">
<t t-foreach="children" t-as="submenu">
<t t-call="website.contentMenu.dialog.submenu"/>
<ul t-if="props.menu.children">
<t t-foreach="props.menu.children" t-as="submenu" t-key="submenu.fields['id']">
<MenuRow menu="submenu" edit="props.edit" delete="props.delete"/>
</t>
</ul>
</li>
</t>
<div t-name="website.contentMenu.dialog.select">
<select class="form-control mb16" t-if="widget.roots">
<t t-foreach="widget.roots" t-as="root">
<option t-att-value="root.id"><t t-esc="root.name"/></option>
</t>
</select>
</div>
<div t-name="website.contentMenu.dialog.edit">
<select class="form-control mb16" t-if="widget.roots">
<t t-foreach="widget.roots" t-as="root">
<option t-att-value="root.id"><t t-esc="root.name"/></option>
</t>
</select>
<ul class="oe_menu_editor list-unstyled">
<t t-foreach="widget.menu.children" t-as="submenu">
<t t-call="website.contentMenu.dialog.submenu"/>
<t t-name="website.EditMenuDialog" owl="1">
<ul t-ref="menu-editor" class="oe_menu_editor list-unstyled">
<t t-foreach="state.rootMenu.children" t-as="menu" t-key="menu.fields['id']">
<MenuRow menu="menu" edit="(id) => this.editMenu(id)" delete="(id) => this.deleteMenu(id)"/>
</t>
</ul>
<div class="mt32">
<small class="float-right text-muted">
Drag to the right to get a submenu
</small>
<a href="#" class="js_add_menu">
<a href="#" t-on-click="() => this.addMenu(false)">
<i class="fa fa-plus-circle"/> Add Menu Item
</a><br/>
<a href="#" class="js_add_menu" data-type="mega">
<a href="#" t-on-click="() => this.addMenu(true)">
<i class="fa fa-plus-circle"/> Add Mega Menu Item
</a>
</div>
</div>
</t>
</templates>
@@ -4,6 +4,7 @@ import { NavBar } from '@web/webclient/navbar/navbar';
import { useService, useBus } from '@web/core/utils/hooks';
import { registry } from "@web/core/registry";
import { patch } from 'web.utils';
import { EditMenuDialog } from '@website/components/dialog/edit_menu';
const websiteSystrayRegistry = registry.category('website_systray');
@@ -11,6 +12,7 @@ patch(NavBar.prototype, 'website_navbar', {
setup() {
this._super();
this.websiteService = useService('website');
this.dialogService = useService('dialog');
// The navbar is rerendered with an event, as it can not naturally be
// with props/state (the WebsitePreview client action and the navbar
@@ -22,6 +24,24 @@ patch(NavBar.prototype, 'website_navbar', {
}
useBus(websiteSystrayRegistry, 'CONTENT-UPDATED', () => this.render(true));
this.websiteDialogMenus = {
'website.menu_edit_menu': EditMenuDialog,
};
},
filterWebsiteMenus(sections) {
const filteredSections = [];
for (const section of sections) {
if (!this.websiteDialogMenus[section.xmlid]) {
let subSections = [];
if (section.childrenTree.length) {
subSections = this.filterWebsiteMenus(section.childrenTree);
}
filteredSections.push(Object.assign({}, section, {childrenTree: subSections}));
}
}
return filteredSections;
},
/**
@@ -37,4 +57,25 @@ patch(NavBar.prototype, 'website_navbar', {
}
return this._super();
},
/**
* @override
*/
get currentAppSections() {
const currentAppSections = this._super();
if (this.currentApp && this.currentApp.xmlid === 'website.menu_website_configuration' && !this.websiteService.currentWebsite) {
return this.filterWebsiteMenus(currentAppSections).filter(section => section.childrenTree.length);
}
return currentAppSections;
},
/**
* @override
*/
onNavBarDropdownItemSelection(menu) {
if (this.websiteDialogMenus[menu.xmlid]) {
return this.dialogService.add(this.websiteDialogMenus[menu.xmlid]);
}
return this._super(menu);
}
});
@@ -68,7 +68,7 @@ export const websiteService = {
get context() {
return context;
},
goToWebsite({ websiteId = currentWebsiteId || websites[0].id, path = '/' }) {
goToWebsite({ websiteId = currentWebsiteId || websites[0].id, path = '/' } = {}) {
action.doAction('website.website_preview', {
clearBreadcrumbs: true,
additionalContext: {
+6
View File
@@ -552,6 +552,12 @@
name="Pages"
action="action_website_pages_list"/>
<menuitem id="menu_edit_menu"
parent="menu_site"
sequence="30"
name="Edit Menu"
action="website.website_preview"/>
<menuitem id="menu_website_dashboard"
name="eCommerce"
sequence="1"