summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2019-12-16 17:17:43 +0000
committerqsm-odoo <qsm@odoo.com>2019-12-19 15:30:06 +0000
commit2a0a0e52dd1d97941b118c4ae9112b6a890e19de (patch)
treecbfe0de1f0344e0ef24ed59f8a6921b94af8f3e2
parent32e294e7dae298edb4d421d78a309f583b2c4fed (diff)
[REF] web_editor, *: review invisible element click action
* website, website_mass_mailing Instead of triggering an event on the invisible element when its related button in the left panel is clicked, the invisible element's options are now toggled (shown if were hidden and hidden if were shown). To do that the new 'onTargetShow' and 'onTargetHide' methods are called, and the appropriate action can be done there. Those two new methods are also automatically called in other cases: - When dropped in the page, after onBuild, 'onTargetShow' is called for any snippet. - Before cleanForSave: 'onTargetHide' is called for snippets with the 'o_snippet_invisible' and 'onTargetShow' is called for the others. In case the element visibility should be toggled another way (like the close button of a modal), the option can trigger_up an event named 'snippet_option_visibility_update' with a 'show' parameter so that the the UI is updated accordingly (and so that the options are hidden if necessary). Part of https://github.com/odoo/odoo/pull/41789
-rw-r--r--addons/web_editor/static/src/js/editor/snippets.editor.js111
-rw-r--r--addons/web_editor/static/src/js/editor/snippets.options.js16
-rw-r--r--addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js32
3 files changed, 123 insertions, 36 deletions
diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js
index 34701a34034..4a02f890bb4 100644
--- a/addons/web_editor/static/src/js/editor/snippets.editor.js
+++ b/addons/web_editor/static/src/js/editor/snippets.editor.js
@@ -27,6 +27,7 @@ var SnippetEditor = Widget.extend({
'option_update': '_onOptionUpdate',
'user_value_widget_request': '_onUserValueWidgetRequest',
'snippet_option_update': '_onSnippetOptionUpdate',
+ 'snippet_option_visibility_update': '_onSnippetOptionVisibilityUpdate',
},
/**
@@ -158,10 +159,11 @@ var SnippetEditor = Widget.extend({
* Notifies all the associated snippet options that the snippet has just
* been dropped in the page.
*/
- buildSnippet: function () {
+ buildSnippet: async function () {
for (var i in this.styles) {
this.styles[i].onBuilt();
}
+ await this.toggleTargetVisibility(true);
},
/**
* Notifies all the associated snippet options that the template which
@@ -171,6 +173,7 @@ var SnippetEditor = Widget.extend({
if (this.isDestroyed()) {
return;
}
+ await this.toggleTargetVisibility(!this.$target.hasClass('o_snippet_invisible'));
const proms = _.map(this.styles, option => {
return option.cleanForSave();
});
@@ -213,6 +216,12 @@ var SnippetEditor = Widget.extend({
return this.$el && this.$el.parent().length && this.$el.hasClass('oe_active');
},
/**
+ * @returns {boolean}
+ */
+ isTargetVisible: function () {
+ return (this.$target[0].dataset.invisible !== '1');
+ },
+ /**
* Removes the associated snippet from the DOM and destroys the associated
* editor (itself).
*/
@@ -330,6 +339,19 @@ var SnippetEditor = Widget.extend({
});
},
/**
+ * @param {boolean} [show]
+ * @returns {Promise<boolean>}
+ */
+ toggleTargetVisibility: async function (show) {
+ show = this._toggleVisibilityStatus(show);
+ var styles = _.values(this.styles);
+ const proms = _.sortBy(styles, '__order').map(style => {
+ return show ? style.onTargetShow() : style.onTargetHide();
+ });
+ await Promise.all(proms);
+ return show;
+ },
+ /**
* @param {boolean} [isTextEdition=false]
*/
toggleTextEdition: function (isTextEdition) {
@@ -482,6 +504,21 @@ var SnippetEditor = Widget.extend({
$optionsSection.toggleClass('d-none', options.length === 0);
});
},
+ /**
+ * @private
+ * @param {boolean} [show]
+ */
+ _toggleVisibilityStatus: function (show) {
+ if (show === undefined) {
+ show = !this.isTargetVisible();
+ }
+ if (show) {
+ delete this.$target[0].dataset.invisible;
+ } else {
+ this.$target[0].dataset.invisible = '1';
+ }
+ return show;
+ },
//--------------------------------------------------------------------------
// Handlers
@@ -716,6 +753,13 @@ var SnippetEditor = Widget.extend({
},
/**
* @private
+ * @param {OdooEvent} ev
+ */
+ _onSnippetOptionVisibilityUpdate: function (ev) {
+ ev.data.show = this._toggleVisibilityStatus(ev.data.show);
+ },
+ /**
+ * @private
* @param {Event} ev
*/
_onUserValueWidgetRequest: function (ev) {
@@ -752,6 +796,7 @@ var SnippetsMenu = Widget.extend({
'snippet_edition_request': '_onSnippetEditionRequest',
'snippet_removed': '_onSnippetRemoved',
'snippet_cloned': '_onSnippetCloned',
+ 'snippet_option_visibility_update': '_onSnippetOptionVisibilityUpdate',
'reload_snippet_dropzones': '_disableUndroppableSnippets',
'update_customize_elements': '_onUpdateCustomizeElements',
'hide_overlay': '_onHideOverlay',
@@ -834,7 +879,7 @@ var SnippetsMenu = Widget.extend({
)[0]
);
this.$el.append(this.invisibleDOMPanelEl);
- this._updateInvisibleDOM();
+ return this._updateInvisibleDOM();
}));
// Prepare snippets editor environment
@@ -1157,22 +1202,28 @@ var SnippetsMenu = Widget.extend({
* The entries will contains an 'Edit' button to activate their snippet.
*
* @private
+ * @returns {Promise}
*/
_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: _t(el.getAttribute('string')),
- }).append($('<i/>', {class: 'fa fa-edit ml-2'}));
- $invisibleDOMPanelEl.append($invisEntry);
- this.invisibleDOMMap.set($invisEntry[0], el);
+ return this._mutex.exec(() => {
+ this.invisibleDOMMap = new Map();
+ const $invisibleDOMPanelEl = $(this.invisibleDOMPanelEl);
+ $invisibleDOMPanelEl.find('.o_we_invisible_entry').remove();
+ const $invisibleSnippets = this.getEditableArea().find('.o_snippet_invisible');
+
+ $invisibleDOMPanelEl.toggleClass('d-none', !$invisibleSnippets.length);
+
+ const proms = _.map($invisibleSnippets, async el => {
+ const editor = await this._createSnippetEditor($(el));
+ const $invisEntry = $('<div/>', {
+ class: 'o_we_invisible_entry d-flex align-items-center justify-content-between',
+ text: _t(el.getAttribute('string')),
+ }).append($('<i/>', {class: `fa ${editor.isTargetVisible() ? 'fa-eye' : 'fa-eye-slash'} ml-2`}));
+ $invisibleDOMPanelEl.append($invisEntry);
+ this.invisibleDOMMap.set($invisEntry[0], el);
+ });
+ return Promise.all(proms);
});
- $invisibleDOMPanelEl.toggleClass('d-none', !$invisibleSnippets.length);
},
/**
* Disable the overlay editor of the active snippet and activate the new one
@@ -1722,12 +1773,11 @@ var SnippetsMenu = Widget.extend({
self.trigger_up('snippet_dropped', {$target: $target});
self._disableUndroppableSnippets();
- self._updateInvisibleDOM();
-
self._callForEachChildSnippet($target, function (editor, $snippet) {
- editor.buildSnippet();
+ return editor.buildSnippet();
}).then(function () {
$target.trigger('content_changed');
+ return self._updateInvisibleDOM();
});
});
} else {
@@ -1911,16 +1961,17 @@ var SnippetsMenu = Widget.extend({
* @private
* @param {Event} ev
*/
- _onInvisibleEntryClick: function (ev) {
+ _onInvisibleEntryClick: async 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);
+ const isVisible = await this._mutex.exec(async () => {
+ const editor = await this._createSnippetEditor($snippet);
+ return editor.toggleTargetVisibility();
});
+ $(ev.currentTarget).find('.fa')
+ .toggleClass('fa-eye', isVisible)
+ .toggleClass('fa-eye-slash', !isVisible);
+ return this._activateSnippet(isVisible ? $snippet : false);
},
/**
* @private
@@ -1973,6 +2024,16 @@ var SnippetsMenu = Widget.extend({
* @private
* @param {OdooEvent} ev
*/
+ _onSnippetOptionVisibilityUpdate: async function (ev) {
+ if (!ev.data.show) {
+ await this._activateSnippet(false);
+ }
+ await this._updateInvisibleDOM(); // Re-render to update status
+ },
+ /**
+ * @private
+ * @param {OdooEvent} ev
+ */
_onUpdateCustomizeElements: function (ev) {
this._closeWidgets();
while (this.customizePanel.firstChild) {
diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js
index 7e7a7f830c1..7fd71645b47 100644
--- a/addons/web_editor/static/src/js/editor/snippets.options.js
+++ b/addons/web_editor/static/src/js/editor/snippets.options.js
@@ -1290,6 +1290,22 @@ const SnippetOptionWidget = Widget.extend({
*/
onRemove: function () {},
/**
+ * Called when the target is shown, only meaningful if the target was hidden
+ * at some point (typically used for 'invisible' snippets).
+ *
+ * @abstract
+ * @returns {Promise|undefined}
+ */
+ onTargetShow: async function () {},
+ /**
+ * Called when the target is hidden (typically used for 'invisible'
+ * snippets).
+ *
+ * @abstract
+ * @returns {Promise|undefined}
+ */
+ onTargetHide: async function () {},
+ /**
* Called when the template which contains the associated snippet is about
* to be saved.
*
diff --git a/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js b/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js
index 83957980e8a..76de1c4b674 100644
--- a/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js
+++ b/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js
@@ -65,18 +65,28 @@ options.registry.newsletter_popup = options.registry.mailing_list_subscribe.exte
* @override
*/
start: function () {
- var self = this;
- 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);
- options.onSuccess(self._refreshPublicWidgets());
- });
- this.$target.on('shown.bs.modal.newsletter_popup_option hide.bs.modal.newsletter_popup_option', function () {
- self.$target.closest('.o_editable').trigger('content_changed');
- self.trigger_up('deactivate_snippet');
+ this.$target.on('hidden.bs.modal.newsletter_popup_option', () => {
+ this.trigger_up('snippet_option_visibility_update', {show: false});
});
- return this._super.apply(this, arguments);
+ return this._super(...arguments);
+ },
+ /**
+ * @override
+ */
+ onTargetShow: function () {
+ // Open the modal
+ this.$target.data('quick-open', true);
+ return this._refreshPublicWidgets();
+ },
+ /**
+ * @override
+ */
+ onTargetHide: function () {
+ // Close the modal
+ const $modal = this.$('.modal');
+ if ($modal.length && $modal.is('.modal_shown')) {
+ $modal.modal('hide');
+ }
},
/**
* @override