[IMP] web_editor, *: add new zone in left panel to handle invisible DOM

* website, website_mass_mailing

We only have one invisible snippet (newsletter popup) which is handled
by adding a yellow alert in the DOM in edit mode to be able to click
somewhere to open the snippet options.

As we will add some new invisible snippet (generic popup, cookies bar,
and probably more) this needed to be improved.

Now, any snippet having the `o_snippet_invisible` class will have an
entry in the left panel in a dedicated zone to edit itself. This also
allows to get rid of the yellow alert, making sure that "what you see
is what you get" in the editor zone.

task-2150966

closes odoo/odoo#41420

Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
Romain Derie
2019-12-08 18:03:30 +00:00
committed by qsm-odoo
parent 92fdbec889
commit 1915fe3598
5 changed files with 100 additions and 22 deletions
@@ -686,6 +686,7 @@ var SnippetsMenu = Widget.extend({
cacheSnippetTemplate: {},
events: {
'click .o_install_btn': '_onInstallBtnClick',
'click .o_we_invisible_entry': '_onInvisibleEntryClick',
},
custom_events: {
'activate_insertion_zones': '_onActivateInsertionZones',
@@ -697,6 +698,7 @@ var SnippetsMenu = Widget.extend({
'go_to_parent': '_onGoToParent',
'remove_snippet': '_onRemoveSnippet',
'snippet_removed': '_onSnippetRemoved',
'snippet_cloned': '_onSnippetCloned',
'reload_snippet_dropzones': '_disableUndroppableSnippets',
'update_customize_elements': '_onUpdateCustomizeElements',
'hide_overlay': '_onHideOverlay',
@@ -754,6 +756,19 @@ var SnippetsMenu = Widget.extend({
this.customizePanel = document.createElement('div');
this.customizePanel.classList.add('o_we_customize_panel', 'd-none');
this.$el.append(this.customizePanel);
this.invisibleDOMPanelEl = document.createElement('div');
this.invisibleDOMPanelEl.classList.add('o_we_invisible_el_panel');
this.invisibleDOMPanelEl.appendChild(
$('<div/>', {
text: _t('Invisible'),
class: 'o_panel_header',
}).prepend(
$('<i/>', {class: 'fa fa-eye-slash'})
)[0]
);
this.$el.append(this.invisibleDOMPanelEl);
this._updateInvisibleDOM();
}));
// Prepare snippets editor environment
@@ -1073,6 +1088,28 @@ var SnippetsMenu = Widget.extend({
}
});
},
/**
* Adds an entry for every invisible snippet in the left panel box.
* The entries will contains an 'Edit' button to activate their snippet.
*
* @private
*/
_updateInvisibleDOM: function () {
this.invisibleDOMMap = new Map();
const $invisibleDOMPanelEl = $(this.invisibleDOMPanelEl);
$invisibleDOMPanelEl.find('.o_we_invisible_entry').remove();
const $invisibleSnippets = this.getEditableArea().find('.o_snippet_invisible');
_.each($invisibleSnippets, el => {
const $invisEntry = $('<div/>', {
class: 'o_we_invisible_entry d-flex align-items-center',
text: el.title,
}).append($('<i/>', {class: 'fa fa-edit ml-2'}));
$invisibleDOMPanelEl.append($invisEntry);
this.invisibleDOMMap.set($invisEntry[0], el);
});
$invisibleDOMPanelEl.toggleClass('d-none', !$invisibleSnippets.length);
},
/**
* Disable the overlay editor of the active snippet and activate the new one
* if given.
@@ -1613,6 +1650,8 @@ var SnippetsMenu = Widget.extend({
self.trigger_up('snippet_dropped', {$target: $target});
self._disableUndroppableSnippets();
self._updateInvisibleDOM();
self._callForEachChildSnippet($target, function (editor, $snippet) {
editor.buildSnippet();
}).then(function () {
@@ -1792,6 +1831,21 @@ var SnippetsMenu = Widget.extend({
}],
}).open();
},
/**
* @private
* @param {Event} ev
*/
_onInvisibleEntryClick: function (ev) {
ev.preventDefault();
const $snippet = $(this.invisibleDOMMap.get(ev.currentTarget));
let prom = null;
$snippet.trigger('invisible_snippet_activation', {
onSuccess: _prom => prom = _prom,
});
Promise.resolve(prom).then(() => {
return this._activateSnippet($snippet);
});
},
/**
* @private
*/
@@ -1814,6 +1868,12 @@ var SnippetsMenu = Widget.extend({
editor.removeSnippet();
});
},
/**
* @private
*/
_onSnippetCloned: function (ev) {
this._updateInvisibleDOM();
},
/**
* Called when a snippet is removed -> checks if there is draggable snippets
* to enable/disable as the DOM changed.
@@ -1822,6 +1882,7 @@ var SnippetsMenu = Widget.extend({
*/
_onSnippetRemoved: function () {
this._disableUndroppableSnippets();
this._updateInvisibleDOM();
},
/**
* @private
@@ -92,21 +92,20 @@ body.editor_enable.editor_has_snippets {
overflow: auto;
}
> #o_scroll {
.o_panel_header {
display: flex;
align-items: center;
justify-content: center;
padding: 3%;
color: inherit;
margin-bottom: 3%;
.o_panel_header {
display: flex;
align-items: center;
justify-content: center;
padding: 3%;
color: inherit;
margin-bottom: 3%;
i {
margin-right: 5px;
}
i {
margin-right: 5px;
}
}
> #o_scroll {
.o_panel_body {
&:after {
content: " ";
@@ -506,6 +505,23 @@ body.editor_enable.editor_has_snippets {
}
}
}
> .o_we_invisible_el_panel {
flex: 0 0 auto;
max-height: 220px;
overflow-y: auto;
background-color: var(--o-we-bg-color);
border-top: 2px solid;
.o_we_invisible_entry {
padding: 0.5rem;
cursor: pointer;
&:hover {
background-color: var(--o-we-snippets-bg-color);
}
}
}
}
.oe_snippet {
@@ -35,12 +35,13 @@ options.Class.include({
*
* @private
* @param {jQuery} [$el=this.$target]
* @param {Object} [options]
*/
_refreshPublicWidgets: function ($el) {
this.trigger_up('widgets_start_request', {
_refreshPublicWidgets: function ($el, options) {
this.trigger_up('widgets_start_request', _.extend({
editableMode: true,
$target: $el || this.$target,
});
}, options || {}));
},
});
@@ -66,11 +66,15 @@ options.registry.newsletter_popup = options.registry.mailing_list_subscribe.exte
*/
start: function () {
var self = this;
this.$target.on('click.newsletter_popup_option', '.o_edit_popup', function (ev) {
this.$target.on('invisible_snippet_activation', function (ev, options) {
// So that the snippet is not enabled again by the editor
ev.stopPropagation();
self.$target.data('quick-open', true);
self._refreshPublicWidgets();
options.onSuccess(new Promise(resolve => {
self._refreshPublicWidgets(self.$target, {
onSuccess: () => resolve(),
});
}));
});
this.$target.on('shown.bs.modal.newsletter_popup_option hide.bs.modal.newsletter_popup_option', function () {
self.$target.closest('.o_editable').trigger('content_changed');
@@ -51,11 +51,7 @@
</template>
<template id="s_newsletter_subscribe_popup" name="Newsletter Popup">
<div class="o_newsletter_popup" data-list-id="0">
<div class="alert alert-warning css_non_editable_mode_hidden o_not_editable" role="alert">
<strong>Newsletter Popup!</strong> The newsletter popup is active on this page. <a class="o_edit_popup" data-toggle="modal" href="#">Edit Popup</a>
</div>
</div>
<div class="o_newsletter_popup o_snippet_invisible" data-list-id="0" title="A newsletter popup is active on this page."/>
</template>
<template id="newsletter_subscribe_options" name="Newsletter Subscribe Options" inherit_id="website.snippet_options">