[REF] web_editor, website: refactor dialogs to new API
After the core Dialog API was refactored in [1], the web_editor and website dialogs had to be reworked. These dialogs are using a base WebsiteDialog component, that allows for a default footer and adds the o_website_dialog content class. [1]: https://github.com/odoo/odoo/commit/7c4f200b8edf0bc695c623c7afc62288f838db36 See merge commit for more information. task-2687506
This commit is contained in:
@@ -25,28 +25,31 @@ class RemoveButton extends Component {
|
||||
}
|
||||
RemoveButton.template = xml`<i class="fa fa-trash o_existing_attachment_remove p-2" t-att-title="removeTitle" role="img" t-att-aria-label="removeTitle" t-on-click="this.remove"/>`;
|
||||
|
||||
export class AttachmentError extends Dialog {
|
||||
export class AttachmentError extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.title = this.env._t("Alert");
|
||||
}
|
||||
}
|
||||
AttachmentError.bodyTemplate = xml `
|
||||
<div class="form-text">
|
||||
<p>The image could not be deleted because it is used in the
|
||||
following pages or views:</p>
|
||||
<ul t-foreach="props.views" t-as="view" t-key="view.id">
|
||||
<li>
|
||||
<a t-att-href="'/web#model=ir.ui.view&id=' + view.id">
|
||||
<t t-esc="view.name"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>`;
|
||||
AttachmentError.footerTemplate = xml`
|
||||
<button class="btn btn-primary" t-on-click="() => this.close()">
|
||||
Ok
|
||||
</button>`;
|
||||
AttachmentError.components = { Dialog };
|
||||
AttachmentError.template = xml `
|
||||
<Dialog title="title">
|
||||
<div class="form-text">
|
||||
<p>The image could not be deleted because it is used in the
|
||||
following pages or views:</p>
|
||||
<ul t-foreach="props.views" t-as="view" t-key="view.id">
|
||||
<li>
|
||||
<a t-att-href="'/web#model=ir.ui.view&id=' + view.id">
|
||||
<t t-esc="view.name"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<t t-set-slot="footer">
|
||||
<button class="btn btn-primary" t-on-click="() => this.props.close()">
|
||||
Ok
|
||||
</button>
|
||||
</t>
|
||||
</Dialog>`;
|
||||
|
||||
export class Attachment extends Component {
|
||||
setup() {
|
||||
@@ -69,7 +72,6 @@ export class Attachment extends Component {
|
||||
});
|
||||
}
|
||||
},
|
||||
cancel: () => {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,9 @@ export const TABS = {
|
||||
},
|
||||
};
|
||||
|
||||
export class MediaDialog extends Dialog {
|
||||
export class MediaDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.size = 'modal-xl';
|
||||
this.size = 'xl';
|
||||
this.contentClass = 'o_select_media_dialog';
|
||||
this.title = this.env._t("Select a media");
|
||||
|
||||
@@ -173,16 +172,16 @@ export class MediaDialog extends Dialog {
|
||||
this.props.save(elements[0]);
|
||||
}
|
||||
}
|
||||
this.close();
|
||||
this.props.close();
|
||||
}
|
||||
}
|
||||
MediaDialog.bodyTemplate = 'web_editor.MediaDialogBody';
|
||||
MediaDialog.footerTemplate = 'web_editor.MediaDialogFooter';
|
||||
MediaDialog.template = 'web_editor.MediaDialog';
|
||||
MediaDialog.defaultProps = {
|
||||
useMediaLibrary: true,
|
||||
};
|
||||
MediaDialog.components = {
|
||||
...Object.keys(TABS).map(key => TABS[key].Component),
|
||||
Dialog,
|
||||
};
|
||||
|
||||
export class MediaDialogWrapper extends Component {
|
||||
@@ -190,16 +189,7 @@ export class MediaDialogWrapper extends Component {
|
||||
this.dialogs = useWowlService('dialog');
|
||||
|
||||
onRendered(() => {
|
||||
this.dialogs.add(MediaDialog, {
|
||||
...this.props,
|
||||
close: () => {
|
||||
if (this.props.close) {
|
||||
this.props.close();
|
||||
}
|
||||
this.destroy();
|
||||
|
||||
},
|
||||
});
|
||||
this.dialogs.add(MediaDialog, this.props);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="web_editor.MediaDialogBody" owl="1">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<t t-foreach="tabs" t-as="tab" t-key="tab.id">
|
||||
<li class="nav-item"><a class="nav-link" t-att-class="{ active: tab.id === state.activeTab }" t-on-click="() => state.activeTab = tab.id"><t t-esc="tab.title"/></a></li>
|
||||
<t t-name="web_editor.MediaDialog" owl="1">
|
||||
<Dialog contentClass="contentClass"
|
||||
size="size"
|
||||
title="title">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<t t-foreach="tabs" t-as="tab" t-key="tab.id">
|
||||
<li class="nav-item"><a class="nav-link" t-att-class="{ active: tab.id === state.activeTab }" t-on-click="() => state.activeTab = tab.id"><t t-esc="tab.title"/></a></li>
|
||||
</t>
|
||||
</ul>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<t t-foreach="tabs" t-as="tab" t-key="tab.id">
|
||||
<div class="tab-pane fade" t-att-class="tab.id === state.activeTab ? 'active show' : ''"><t t-component="tab.Component" t-props="tab.props"/></div>
|
||||
</t>
|
||||
</div>
|
||||
<t t-set-slot="footer">
|
||||
<button class="btn btn-primary" t-on-click="() => this.save()">Add</button>
|
||||
<button class="btn btn-secondary" t-on-click="() => this.props.close()">Discard</button>
|
||||
</t>
|
||||
</ul>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<t t-foreach="tabs" t-as="tab" t-key="tab.id">
|
||||
<div class="tab-pane fade" t-att-class="tab.id === state.activeTab ? 'active show' : ''"><t t-component="tab.Component" t-props="tab.props"/></div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="web_editor.MediaDialogFooter" owl="1">
|
||||
<button class="btn btn-primary" t-on-click="save">Add</button>
|
||||
<button class="btn btn-secondary" t-on-click="close">Discard</button>
|
||||
</Dialog>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -2,65 +2,66 @@
|
||||
|
||||
import { Dialog } from '@web/core/dialog/dialog';
|
||||
import { Switch } from '@website/components/switch/switch';
|
||||
import { _t } from 'web.core';
|
||||
|
||||
const { xml, useState } = owl;
|
||||
const { xml, useState, Component } = owl;
|
||||
|
||||
export class WebsiteDialog extends Dialog {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.title = this.props.title || this.env._t("Confirmation");
|
||||
this.primaryTitle = this.props.primaryTitle || this.env._t("Ok");
|
||||
this.secondaryTitle = this.props.secondaryTitle || this.env._t("Cancel");
|
||||
this.closeOnClick = this.props.closeOnClick === false ? false : true;
|
||||
}
|
||||
|
||||
get showSecondaryButton() {
|
||||
return this.props.showSecondaryButton;
|
||||
}
|
||||
|
||||
primaryClick() {
|
||||
export class WebsiteDialog extends Component {
|
||||
async primaryClick() {
|
||||
if (this.props.primaryClick) {
|
||||
this.props.primaryClick();
|
||||
await this.props.primaryClick();
|
||||
}
|
||||
if (this.closeOnClick) {
|
||||
this.close();
|
||||
if (this.props.closeOnClick) {
|
||||
this.props.close();
|
||||
}
|
||||
}
|
||||
|
||||
secondaryClick() {
|
||||
async secondaryClick() {
|
||||
if (this.props.secondaryClick) {
|
||||
this.props.secondaryClick();
|
||||
await this.props.secondaryClick();
|
||||
}
|
||||
if (this.closeOnClick) {
|
||||
this.close();
|
||||
if (this.props.closeOnClick) {
|
||||
this.props.close();
|
||||
}
|
||||
}
|
||||
|
||||
get contentClasses() {
|
||||
const websiteDialogClass = 'o_website_dialog';
|
||||
if (this.props.contentClass) {
|
||||
return `${websiteDialogClass} ${this.props.contentClass}`;
|
||||
}
|
||||
return websiteDialogClass;
|
||||
}
|
||||
}
|
||||
WebsiteDialog.components = { Dialog };
|
||||
WebsiteDialog.props = {
|
||||
...Dialog.props,
|
||||
title: { type: String, optional: true },
|
||||
body: { type: String, optional: true },
|
||||
primaryTitle: { type: String, optional: true },
|
||||
primaryClick: { type: Function, optional: true },
|
||||
secondaryTitle: { type: String, optional: true },
|
||||
secondaryClick: { type: Function, optional: true },
|
||||
showSecondaryButton: { type: Boolean, optional: true },
|
||||
close: Function,
|
||||
closeOnClick: { type: Boolean, optional: true },
|
||||
close: { type: Function, optional: true },
|
||||
};
|
||||
WebsiteDialog.defaultProps = {
|
||||
...Dialog.defaultProps,
|
||||
title: _t("Confirmation"),
|
||||
primaryTitle: _t("Ok"),
|
||||
secondaryTitle: _t("Cancel"),
|
||||
showSecondaryButton: true,
|
||||
size: "md",
|
||||
closeOnClick: true,
|
||||
};
|
||||
WebsiteDialog.bodyTemplate = "website.DialogBody";
|
||||
WebsiteDialog.footerTemplate = "website.DialogFooter";
|
||||
WebsiteDialog.size = "modal-md";
|
||||
WebsiteDialog.contentClass = "o_website_dialog";
|
||||
WebsiteDialog.template = "website.WebsiteDialog";
|
||||
|
||||
export class AddPageDialog extends WebsiteDialog {
|
||||
export class AddPageDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.title = this.env._t("New Page");
|
||||
this.primaryTitle = this.env._t("Create");
|
||||
this.switchLabel = this.env._t("Add to menu");
|
||||
|
||||
this.state = useState({
|
||||
addMenu: true,
|
||||
@@ -72,20 +73,20 @@ export class AddPageDialog extends WebsiteDialog {
|
||||
this.state.addMenu = value;
|
||||
}
|
||||
|
||||
async primaryClick() {
|
||||
async addPage() {
|
||||
await this.props.addPage(this.state.name, this.state.addMenu);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
AddPageDialog.props = {
|
||||
...WebsiteDialog.props,
|
||||
addPage: Function,
|
||||
};
|
||||
AddPageDialog.components = {
|
||||
Switch,
|
||||
WebsiteDialog,
|
||||
};
|
||||
AddPageDialog.bodyTemplate = xml`
|
||||
<div>
|
||||
AddPageDialog.template = xml`
|
||||
<WebsiteDialog
|
||||
title="title"
|
||||
primaryTitle="primaryTitle"
|
||||
primaryClick="() => this.addPage()"
|
||||
close="props.close">
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label col-md-3">
|
||||
Page Title
|
||||
@@ -94,6 +95,6 @@ AddPageDialog.bodyTemplate = xml`
|
||||
<input type="text" t-model="state.name" class="form-control" required="required"/>
|
||||
</div>
|
||||
</div>
|
||||
<Switch extraClasses="'offset-md-3 col-md-9 text-left'" label="'Add to menu'" value="state.addMenu" onChange="(value) => this.onChangeAddMenu(value)"/>
|
||||
</div>
|
||||
<Switch extraClasses="'offset-md-3 col-md-9 text-left'" label="switchLabel" value="state.addMenu" onChange="(value) => this.onChangeAddMenu(value)"/>
|
||||
</WebsiteDialog>
|
||||
`;
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="website.DialogBody" owl="1">
|
||||
<t t-esc="props.body"/>
|
||||
</t>
|
||||
|
||||
<t t-name="website.DialogFooter" owl="1">
|
||||
<button class="btn btn-primary" t-on-click="primaryClick">
|
||||
<t t-esc="primaryTitle"/>
|
||||
</button>
|
||||
<button t-if="showSecondaryButton" class="btn btn-secondary" t-on-click="secondaryClick">
|
||||
<t t-esc="secondaryTitle"/>
|
||||
</button>
|
||||
<t t-name="website.WebsiteDialog" owl="1">
|
||||
<Dialog contentClass="contentClasses"
|
||||
size="props.size"
|
||||
title="props.title">
|
||||
<t t-slot="default"/>
|
||||
<t t-set-slot="footer">
|
||||
<t t-if="props.slots and props.slots.footer" t-slot="footer"/>
|
||||
<t t-else="">
|
||||
<button class="btn btn-primary" t-on-click="primaryClick">
|
||||
<t t-esc="props.primaryTitle"/>
|
||||
</button>
|
||||
<button t-if="props.showSecondaryButton" class="btn btn-secondary" t-on-click="secondaryClick">
|
||||
<t t-esc="props.secondaryTitle"/>
|
||||
</button>
|
||||
</t>
|
||||
</t>
|
||||
</Dialog>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -5,10 +5,8 @@ import { WebsiteDialog } from './dialog';
|
||||
|
||||
const { Component, useState, useEffect, onWillStart, useRef, onMounted } = owl;
|
||||
|
||||
export class MenuDialog extends WebsiteDialog {
|
||||
export class MenuDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.title = this.env._t("Add a menu item");
|
||||
|
||||
this.state = useState({
|
||||
@@ -17,23 +15,23 @@ export class MenuDialog extends WebsiteDialog {
|
||||
});
|
||||
}
|
||||
|
||||
primaryClick() {
|
||||
onClickOk() {
|
||||
this.props.save(this.state.name, this.state.url);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
MenuDialog.bodyTemplate = 'website.MenuDialog';
|
||||
MenuDialog.template = 'website.MenuDialog';
|
||||
MenuDialog.props = {
|
||||
...WebsiteDialog.props,
|
||||
name: { type: String, optional: true },
|
||||
url: { type: String, optional: true },
|
||||
isMegaMenu: { type: Boolean, optional: true },
|
||||
save: Function,
|
||||
close: Function,
|
||||
};
|
||||
MenuDialog.defaultProps = {
|
||||
name: '',
|
||||
url: '/',
|
||||
};
|
||||
MenuDialog.components = { WebsiteDialog };
|
||||
|
||||
class MenuRow extends Component {
|
||||
edit() {
|
||||
@@ -54,15 +52,14 @@ MenuRow.components = {
|
||||
MenuRow,
|
||||
};
|
||||
|
||||
export class EditMenuDialog extends WebsiteDialog {
|
||||
export class EditMenuDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.orm = useService('orm');
|
||||
this.website = useService('website');
|
||||
this.dialogs = useService('dialog');
|
||||
|
||||
this.title = this.env._t("Edit Menu");
|
||||
this.primaryTitle = this.env._t("Save");
|
||||
this.saveButton = this.env._t("Save");
|
||||
|
||||
this.menuEditor = useRef('menu-editor');
|
||||
|
||||
@@ -152,7 +149,7 @@ export class EditMenuDialog extends WebsiteDialog {
|
||||
this.toDelete.push(id);
|
||||
}
|
||||
|
||||
async primaryClick() {
|
||||
async onClickSave() {
|
||||
const newMenus = this.$sortables.nestedSortable('toArray', {startDepthCount: 0});
|
||||
const levels = [];
|
||||
const data = [];
|
||||
@@ -178,7 +175,6 @@ export class EditMenuDialog extends WebsiteDialog {
|
||||
'to_delete': this.toDelete,
|
||||
}
|
||||
]);
|
||||
this.close();
|
||||
if (this.props.save) {
|
||||
this.props.save();
|
||||
} else {
|
||||
@@ -186,7 +182,8 @@ export class EditMenuDialog extends WebsiteDialog {
|
||||
}
|
||||
}
|
||||
}
|
||||
EditMenuDialog.bodyTemplate = 'website.EditMenuDialog';
|
||||
EditMenuDialog.template = 'website.EditMenuDialog';
|
||||
EditMenuDialog.components = {
|
||||
MenuRow,
|
||||
WebsiteDialog,
|
||||
};
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
<?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"/>
|
||||
<WebsiteDialog close="props.close" title="title" primaryClick="() => this.onClickOk()">
|
||||
<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>
|
||||
<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 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>
|
||||
</div>
|
||||
</WebsiteDialog>
|
||||
</t>
|
||||
|
||||
<t t-name="website.MenuRow" owl="1">
|
||||
@@ -46,21 +48,23 @@
|
||||
</t>
|
||||
|
||||
<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="#" t-on-click="() => this.addMenu(false)">
|
||||
<i class="fa fa-plus-circle"/> Add Menu Item
|
||||
</a><br/>
|
||||
<a href="#" t-on-click="() => this.addMenu(true)">
|
||||
<i class="fa fa-plus-circle"/> Add Mega Menu Item
|
||||
</a>
|
||||
</div>
|
||||
<WebsiteDialog close="props.close" title="title" primaryTitle="saveButton" primaryClick="() => this.onClickSave()">
|
||||
<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="#" t-on-click="() => this.addMenu(false)">
|
||||
<i class="fa fa-plus-circle"/> Add Menu Item
|
||||
</a><br/>
|
||||
<a href="#" t-on-click="() => this.addMenu(true)">
|
||||
<i class="fa fa-plus-circle"/> Add Mega Menu Item
|
||||
</a>
|
||||
</div>
|
||||
</WebsiteDialog>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -80,14 +80,13 @@ PageDependencies.props = {
|
||||
},
|
||||
};
|
||||
|
||||
export class DeletePageDialog extends WebsiteDialog {
|
||||
export class DeletePageDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.orm = useService('orm');
|
||||
this.website = useService('website');
|
||||
this.title = this.env._t("Delete Page");
|
||||
this.primaryTitle = this.env._t("Ok");
|
||||
this.deleteButton = this.env._t("Ok");
|
||||
this.cancelButton = this.env._t("Cancel");
|
||||
|
||||
this.state = useState({
|
||||
confirm: false,
|
||||
@@ -98,28 +97,29 @@ export class DeletePageDialog extends WebsiteDialog {
|
||||
this.state.confirm = checked;
|
||||
}
|
||||
|
||||
async primaryClick() {
|
||||
async onClickDelete() {
|
||||
await this.orm.unlink("website.page", [
|
||||
this.props.pageId,
|
||||
]);
|
||||
this.website.goToWebsite();
|
||||
this.close();
|
||||
this.props.close();
|
||||
this.props.onClose();
|
||||
}
|
||||
}
|
||||
DeletePageDialog.components = {PageDependencies, CheckBox};
|
||||
DeletePageDialog.bodyTemplate = 'website.DeletePageContent';
|
||||
DeletePageDialog.footerTemplate = 'website.DeletePageAction';
|
||||
DeletePageDialog.components = {
|
||||
PageDependencies,
|
||||
CheckBox,
|
||||
WebsiteDialog
|
||||
};
|
||||
DeletePageDialog.template = 'website.DeletePageDialog';
|
||||
DeletePageDialog.props = {
|
||||
...WebsiteDialog.props,
|
||||
pageId: Number,
|
||||
onClose: Function,
|
||||
close: Function,
|
||||
};
|
||||
|
||||
export class DuplicatePageDialog extends WebsiteDialog {
|
||||
export class DuplicatePageDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.orm = useService('orm');
|
||||
this.website = useService('website');
|
||||
|
||||
@@ -128,7 +128,7 @@ export class DuplicatePageDialog extends WebsiteDialog {
|
||||
});
|
||||
}
|
||||
|
||||
async primaryClick() {
|
||||
async duplicate() {
|
||||
if (this.state.name) {
|
||||
const res = await this.orm.call(
|
||||
'website.page',
|
||||
@@ -137,11 +137,12 @@ export class DuplicatePageDialog extends WebsiteDialog {
|
||||
);
|
||||
this.website.goToWebsite({path: res, edition: true});
|
||||
}
|
||||
this.close();
|
||||
this.props.onClose();
|
||||
}
|
||||
}
|
||||
DuplicatePageDialog.bodyTemplate = xml`
|
||||
DuplicatePageDialog.components = {WebsiteDialog};
|
||||
DuplicatePageDialog.template = xml`
|
||||
<WebsiteDialog close="props.close" primaryClick="() => this.duplicate()">
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label col-md-3">
|
||||
Page Name
|
||||
@@ -150,10 +151,12 @@ DuplicatePageDialog.bodyTemplate = xml`
|
||||
<input type="text" t-model="state.name" class="form-control" required="required"/>
|
||||
</div>
|
||||
</div>
|
||||
</WebsiteDialog>
|
||||
`;
|
||||
DuplicatePageDialog.props = {
|
||||
...WebsiteDialog.props,
|
||||
onClose: Function,
|
||||
close: Function,
|
||||
pageId: Number,
|
||||
};
|
||||
|
||||
export class PagePropertiesDialogWrapper extends Component {
|
||||
|
||||
@@ -55,19 +55,24 @@
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="website.DeletePageContent" owl="1">
|
||||
<p>Are you sure you want to delete this page ?</p>
|
||||
<p class="text-warning">Don't forget to update all links referring to this page.</p>
|
||||
<PageDependencies pageId="props.pageId" mode="'collapse'"/>
|
||||
<CheckBox onChange.bind="onConfirmCheckboxChange">
|
||||
<p class="text-warning">I am sure about this.</p>
|
||||
</CheckBox>
|
||||
</t>
|
||||
<t t-name="website.DeletePageDialog" owl="1">
|
||||
<WebsiteDialog title="title" close="props.close">
|
||||
<p>Are you sure you want to delete this page ?</p>
|
||||
<p class="text-warning">Don't forget to update all links referring to this page.</p>
|
||||
<PageDependencies pageId="props.pageId" mode="'collapse'"/>
|
||||
<CheckBox onChange.bind="onConfirmCheckboxChange">
|
||||
<p class="text-warning">I am sure about this.</p>
|
||||
</CheckBox>
|
||||
|
||||
<t t-name="website.DeletePageAction" t-inherit="website.DialogFooter" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//button[hasclass('btn-primary')]" position="attributes">
|
||||
<attribute name="t-att-disabled">!state.confirm</attribute>
|
||||
</xpath>
|
||||
<t t-set-slot="footer">
|
||||
<button class="btn btn-primary" t-on-click="() => this.onClickDelete()" t-att-disabled="!this.state.confirm">
|
||||
Ok
|
||||
</button>
|
||||
<button class="btn btn-secondary" t-on-click="() => this.props.close()">
|
||||
Cancel
|
||||
</button>
|
||||
</t>
|
||||
</WebsiteDialog>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { useService, useListener } from '@web/core/utils/hooks';
|
||||
import { useService } from '@web/core/utils/hooks';
|
||||
import { MediaDialog } from '@web_editor/components/media_dialog/media_dialog';
|
||||
import { WebsiteDialog } from './dialog';
|
||||
|
||||
@@ -327,18 +327,17 @@ TitleDescription.components = {
|
||||
SEOPreview,
|
||||
};
|
||||
|
||||
export class OptimizeSEODialog extends WebsiteDialog {
|
||||
export class OptimizeSEODialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.rpc = useService('rpc');
|
||||
this.website = useService('website');
|
||||
this.dialogs = useService('dialog');
|
||||
this.orm = useService('orm');
|
||||
|
||||
this.title = this.env._t("Optimize SEO");
|
||||
this.primaryTitle = this.env._t("Save");
|
||||
this.size = 'modal-lg';
|
||||
this.contentClass = `${this.contentClass} oe_seo_configuration`;
|
||||
this.saveButton = this.env._t("Save");
|
||||
this.size = 'lg';
|
||||
this.contentClass = "oe_seo_configuration";
|
||||
|
||||
onWillStart(async () => {
|
||||
const { metadata: { mainObject, seoObject, path } } = this.website.currentWebsite;
|
||||
@@ -405,7 +404,7 @@ export class OptimizeSEODialog extends WebsiteDialog {
|
||||
return el && el.content;
|
||||
}
|
||||
|
||||
async primaryClick() {
|
||||
async save() {
|
||||
const data = {};
|
||||
if (this.canEditTitle) {
|
||||
data.website_meta_title = seoContext.title;
|
||||
@@ -423,12 +422,12 @@ export class OptimizeSEODialog extends WebsiteDialog {
|
||||
}
|
||||
data.website_meta_og_img = seoContext.metaImage;
|
||||
await this.orm.write(this.object.model, [this.object.id], data);
|
||||
this.close();
|
||||
this.website.goToWebsite({path: this.url.replace(this.previousSeoName || this.seoNameDefault, seoContext.seoName)});
|
||||
}
|
||||
}
|
||||
OptimizeSEODialog.bodyTemplate = 'website.OptimizeSEODialog';
|
||||
OptimizeSEODialog.template = 'website.OptimizeSEODialog';
|
||||
OptimizeSEODialog.components = {
|
||||
WebsiteDialog,
|
||||
TitleDescription,
|
||||
ImageSelector,
|
||||
MetaKeywords,
|
||||
|
||||
@@ -166,20 +166,27 @@
|
||||
</t>
|
||||
|
||||
<t t-name="website.OptimizeSEODialog" owl="1">
|
||||
<TitleDescription canEditDescription="canEditDescription"
|
||||
canEditUrl="canEditUrl"
|
||||
canEditTitle="canEditTitle"
|
||||
seoNameHelp="seoNameHelp"
|
||||
seoNameDefault="seoNameDefault"
|
||||
isIndexed="isIndexed"
|
||||
defaultTitle="defaultTitle"
|
||||
previewDescription="previewDescription"
|
||||
url="url"/>
|
||||
<MetaKeywords/>
|
||||
<ImageSelector previewDescription="socialPreviewDescription"
|
||||
defaultTitle="defaultTitle"
|
||||
hasSocialDefaultImage="hasSocialDefaultImage"
|
||||
pageImages="pageImages"
|
||||
url="url"/>
|
||||
<WebsiteDialog close="props.close"
|
||||
title="title"
|
||||
size="size"
|
||||
primaryClick="() => this.save()"
|
||||
primaryTitle="saveButton"
|
||||
contentClass="contentClass">
|
||||
<TitleDescription canEditDescription="canEditDescription"
|
||||
canEditUrl="canEditUrl"
|
||||
canEditTitle="canEditTitle"
|
||||
seoNameHelp="seoNameHelp"
|
||||
seoNameDefault="seoNameDefault"
|
||||
isIndexed="isIndexed"
|
||||
defaultTitle="defaultTitle"
|
||||
previewDescription="previewDescription"
|
||||
url="url"/>
|
||||
<MetaKeywords/>
|
||||
<ImageSelector previewDescription="socialPreviewDescription"
|
||||
defaultTitle="defaultTitle"
|
||||
hasSocialDefaultImage="hasSocialDefaultImage"
|
||||
pageImages="pageImages"
|
||||
url="url"/>
|
||||
</WebsiteDialog>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -4,13 +4,12 @@ import { WebsiteEditorComponent } from '../editor/editor';
|
||||
import { WebsiteDialog } from '../dialog/dialog';
|
||||
import localStorage from 'web.local_storage';
|
||||
|
||||
const { useEffect, useRef } = owl;
|
||||
const { useEffect, useRef, Component } = owl;
|
||||
|
||||
const localStorageNoDialogKey = 'website_translator_nodialog';
|
||||
|
||||
class AttributeTranslateDialog extends WebsiteDialog {
|
||||
class AttributeTranslateDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.title = this.env._t("Translate Attribute");
|
||||
|
||||
this.formEl = useRef('form-container');
|
||||
@@ -38,10 +37,21 @@ class AttributeTranslateDialog extends WebsiteDialog {
|
||||
}, () => [this.props.node]);
|
||||
}
|
||||
}
|
||||
AttributeTranslateDialog.bodyTemplate = 'website.AttributeTranslateDialog';
|
||||
AttributeTranslateDialog.components = { WebsiteDialog };
|
||||
AttributeTranslateDialog.template = 'website.AttributeTranslateDialog';
|
||||
|
||||
class TranslatorInfoDialog extends WebsiteDialog {}
|
||||
TranslatorInfoDialog.bodyTemplate = 'website.TranslatorInfoDialog';
|
||||
class TranslatorInfoDialog extends Component {
|
||||
setup() {
|
||||
this.strongOkButton = this.env._t("Ok, never show me this again");
|
||||
this.okButton = this.env._t("Ok");
|
||||
}
|
||||
|
||||
onStrongOkClick() {
|
||||
localStorage.setItem(localStorageNoDialogKey, true);
|
||||
}
|
||||
}
|
||||
TranslatorInfoDialog.components = { WebsiteDialog };
|
||||
TranslatorInfoDialog.template = 'website.TranslatorInfoDialog';
|
||||
|
||||
const savableSelector = '[data-oe-translation-id], ' +
|
||||
'[data-oe-model][data-oe-id][data-oe-field], ' +
|
||||
@@ -183,11 +193,7 @@ export class WebsiteTranslator extends WebsiteEditorComponent {
|
||||
});
|
||||
|
||||
if (!localStorage.getItem(localStorageNoDialogKey)) {
|
||||
this.dialogService.add(TranslatorInfoDialog, {
|
||||
primaryClick: () => localStorage.setItem(localStorageNoDialogKey, true),
|
||||
primaryTitle: this.env._t("Ok, never show me this again"),
|
||||
secondaryTitle: this.env._t("Ok"),
|
||||
});
|
||||
this.dialogService.add(TranslatorInfoDialog);
|
||||
}
|
||||
|
||||
// Apply data-oe-readonly on nested data.
|
||||
@@ -228,7 +234,7 @@ export class WebsiteTranslator extends WebsiteEditorComponent {
|
||||
});
|
||||
|
||||
this.$translations.prependEvent('click.translator', (ev) => {
|
||||
this.dialogService.add(AttributeTranslateDialog, { node: ev.target, showSecondaryButton: false });
|
||||
this.dialogService.add(AttributeTranslateDialog, { node: ev.target });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
margin: 10px;
|
||||
padding: 4px;
|
||||
|
||||
[data-oe-translation-state] {
|
||||
&[data-oe-translation-state] {
|
||||
background: $o-we-translated-content-color;
|
||||
}
|
||||
[data-oe-translation-state="to_translate"] {
|
||||
&[data-oe-translation-state="to_translate"] {
|
||||
background: $o-we-content-to-translate-color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<div t-name="website.TranslatorInfoDialog" owl="1">
|
||||
<p>You are about to enter the translation mode.</p>
|
||||
<p>Here are the visuals used to help you translate efficiently:</p>
|
||||
<ul class="oe_translate_examples">
|
||||
<li data-oe-translation-state="to_translate">Content to translate</li>
|
||||
<li data-oe-translation-state="translated">Translated content</li>
|
||||
</ul>
|
||||
<p>
|
||||
In this mode, you can only translate texts. To change the structure of the page, you must edit the master page.
|
||||
Each modification on the master page is automatically applied to all translated versions.
|
||||
</p>
|
||||
<WebsiteDialog close="props.close"
|
||||
title="title"
|
||||
primaryTitle="strongOkButton"
|
||||
secondaryTitle="okButton"
|
||||
primaryClick="() => this.onStrongOkClick()">
|
||||
<p>You are about to enter the translation mode.</p>
|
||||
<p>Here are the visuals used to help you translate efficiently:</p>
|
||||
<ul class="oe_translate_examples">
|
||||
<li data-oe-translation-state="to_translate">Content to translate</li>
|
||||
<li data-oe-translation-state="translated">Translated content</li>
|
||||
</ul>
|
||||
<p>
|
||||
In this mode, you can only translate texts. To change the structure of the page, you must edit the master page.
|
||||
Each modification on the master page is automatically applied to all translated versions.
|
||||
</p>
|
||||
</WebsiteDialog>
|
||||
</div>
|
||||
|
||||
<div t-name="website.AttributeTranslateDialog" owl="1">
|
||||
<div t-ref="form-container"/>
|
||||
</div>
|
||||
<t t-name="website.AttributeTranslateDialog" owl="1">
|
||||
<WebsiteDialog close="props.close"
|
||||
title="title"
|
||||
showSecondaryButton="false">
|
||||
<div t-ref="form-container"/>
|
||||
</WebsiteDialog>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -128,8 +128,8 @@ export const websiteService = {
|
||||
clearBreadcrumbs: true,
|
||||
additionalContext: {
|
||||
params: {
|
||||
website_id: websiteId,
|
||||
path,
|
||||
website_id: websiteId || currentWebsiteId,
|
||||
path: path || (contentWindow && contentWindow.location.href) || '/',
|
||||
enable_editor: edition,
|
||||
edit_translations: translation,
|
||||
},
|
||||
|
||||
@@ -37,6 +37,19 @@ NewContentElement.defaultProps = {
|
||||
status: MODULE_STATUS.INSTALLED,
|
||||
};
|
||||
|
||||
class InstallModuleDialog extends Component {
|
||||
setup() {
|
||||
this.installButton = this.env._t("Install");
|
||||
}
|
||||
|
||||
onClickInstall() {
|
||||
this.props.close();
|
||||
this.props.installModule();
|
||||
}
|
||||
}
|
||||
InstallModuleDialog.components = { WebsiteDialog };
|
||||
InstallModuleDialog.template = "website.InstallModuleDialog";
|
||||
|
||||
export class NewContentModal extends Component {
|
||||
setup() {
|
||||
this.user = useService('user');
|
||||
@@ -158,9 +171,8 @@ export class NewContentModal extends Component {
|
||||
const {id, name} = this.modulesInfo[element.moduleXmlId];
|
||||
const dialogProps = {
|
||||
title: element.title,
|
||||
body: _.str.sprintf(this.newContentText.installNeeded, name),
|
||||
primaryTitle: this.env._t("Install"),
|
||||
primaryClick: async () => {
|
||||
installationText: _.str.sprintf(this.newContentText.installNeeded, name),
|
||||
installModule: async () => {
|
||||
// Update the NewContentElement with installing icon and text.
|
||||
this.state.newContentElements = this.state.newContentElements.map(el => {
|
||||
if (el.moduleXmlId === element.moduleXmlId) {
|
||||
@@ -186,7 +198,7 @@ export class NewContentModal extends Component {
|
||||
}
|
||||
},
|
||||
};
|
||||
this.dialogs.add(WebsiteDialog, dialogProps);
|
||||
this.dialogs.add(InstallModuleDialog, dialogProps);
|
||||
}
|
||||
}
|
||||
NewContentModal.template = "website.NewContentModal";
|
||||
|
||||
@@ -41,4 +41,13 @@
|
||||
<NewContentModal t-if="websiteContext.showNewContentModal"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.InstallModuleDialog" owl="1">
|
||||
<WebsiteDialog close="props.close"
|
||||
title="props.title"
|
||||
primaryTitle="installButton"
|
||||
primaryClick="() => this.onClickInstall()">
|
||||
<t t-esc="props.installationText"/>
|
||||
</WebsiteDialog>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
Reference in New Issue
Block a user