From 69af7dcfeb3ff95c40b00ef0cc7c5c0e4021f9d2 Mon Sep 17 00:00:00 2001 From: "Arthur Detroux (ard)" Date: Tue, 7 Jun 2022 15:12:08 +0200 Subject: [PATCH] [IMP] website, web_editor: improve startup time of website editor By starting the get_switchable_related_views request when the WysiwygAdapter is started, and awaiting it only when we need to know, we can improve the initial loading time of the editor. See merge commit for more information. task-2687506 --- .../static/src/js/editor/snippets.editor.js | 15 +--- .../wysiwyg_adapter/wysiwyg_adapter.js | 20 ++++++ .../static/src/js/editor/snippets.editor.js | 71 +++++++++---------- .../static/src/js/editor/snippets.options.js | 41 +++++++++++ .../static/src/services/website_service.js | 7 +- .../tests/tours/snippet_popup_add_remove.js | 2 +- addons/website/views/snippets/snippets.xml | 3 + 7 files changed, 107 insertions(+), 52 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 688b731ebda..fe17d09060a 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -821,7 +821,7 @@ var SnippetEditor = Widget.extend({ this.$el.find('[data-toggle="dropdown"]').dropdown(); - return Promise.all(defs).then(() => { + return Promise.all(defs).then(async () => { const options = _.sortBy(this.styles, '__order'); const firstOptions = []; options.forEach(option => { @@ -2988,18 +2988,7 @@ var SnippetsMenu = Widget.extend({ if (!ev.currentTarget.classList.contains('active')) { this._activateSnippet(false); this._mutex.exec(() => { - let $pageOptionsTarget = $(); - let i = 0; - const pageOptions = this.templateOptions.filter(template => template.data.pageOptions); - while (!$pageOptionsTarget.length && i < pageOptions.length) { - $pageOptionsTarget = pageOptions[i].selector.all(); - i++; - } - if ($pageOptionsTarget.length) { - this._activateSnippet($pageOptionsTarget); - } else { - this._activateEmptyOptionsTab(); - } + this._activateEmptyOptionsTab(); }); } }, diff --git a/addons/website/static/src/components/wysiwyg_adapter/wysiwyg_adapter.js b/addons/website/static/src/components/wysiwyg_adapter/wysiwyg_adapter.js index c6c83d4e3ee..be82db3c0dc 100644 --- a/addons/website/static/src/components/wysiwyg_adapter/wysiwyg_adapter.js +++ b/addons/website/static/src/components/wysiwyg_adapter/wysiwyg_adapter.js @@ -49,6 +49,13 @@ export class WysiwygAdapterComponent extends ComponentAdapter { this.pageOptions[optionName] = new PageOption(pageOptionEl, this.websiteService.pageDocument, optionName); } this.editableElements(this.$editable).addClass('o_editable'); + + let switchableRelatedViews = []; + const viewKey = this.websiteService.pageDocument.documentElement.dataset.viewXmlid; + if (this.websiteService.isDesigner && viewKey) { + switchableRelatedViews = this.rpc('/website/get_switchable_related_views', {key: viewKey}); + } + this.switchableRelatedViews = Promise.resolve(switchableRelatedViews); }); useEffect(() => { @@ -667,6 +674,18 @@ export class WysiwygAdapterComponent extends ComponentAdapter { _onMobilePreviewRequest() { this.websiteService.context.isMobile = !this.websiteService.context.isMobile; } + /** + * Called when a child needs to know about the views that can + * be toggled on or off on a specific view related to the editable. + * + * @param event + * @returns {Promise} + * @private + */ + async _onGetSwitchableRelatedViews(event) { + const views = await this.switchableRelatedViews; + event.data.onSuccess(views); + } } WysiwygAdapterComponent.prototype.events = { 'widgets_start_request': '_onRootEventRequest', @@ -684,4 +703,5 @@ WysiwygAdapterComponent.prototype.events = { 'menu_dialog': '_onMenuDialogRequest', 'update_color_previews': '_onColorPreviewsUpdate', 'request_mobile_preview': '_onMobilePreviewRequest', + 'get_switchable_related_views': '_onGetSwitchableRelatedViews', }; diff --git a/addons/website/static/src/js/editor/snippets.editor.js b/addons/website/static/src/js/editor/snippets.editor.js index 870390411f8..c2016be4277 100644 --- a/addons/website/static/src/js/editor/snippets.editor.js +++ b/addons/website/static/src/js/editor/snippets.editor.js @@ -54,43 +54,6 @@ const wSnippetMenu = weSnippetEditor.SnippetsMenu.extend({ this.$body[0].classList.remove('o_animated_text_highlighted'); }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - /** - * Adds the "customize_show" templates to the options page of the editor - * panel. - * - * @override - */ - async loadSnippets() { - const viewName = $(this.options.wysiwyg.odooEditor.document.documentElement).data('view-xmlid'); - const snippets = await this._super(...arguments); - if (!viewName) { - return snippets; - } - const $snippets = $(snippets); - return this._rpc({ - route: '/website/get_switchable_related_views', - params: { - key: viewName, - }, - }).then(function (result) { - _.each(result, view => { - $snippets.siblings('#snippet_options').append($(` -
- -
- `)); - }); - return $('
').append($snippets).html(); - }); - }, - //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- @@ -356,6 +319,40 @@ const wSnippetMenu = weSnippetEditor.SnippetsMenu.extend({ throw e; } }, + /** + * @override + */ + _onOptionsTabClick(ev) { + if (!ev.currentTarget.classList.contains('active')) { + this._activateSnippet(false); + this._mutex.exec(async () => { + const switchableViews = await new Promise((resolve, reject) => { + this.trigger_up('get_switchable_related_views', { + onSuccess: resolve, + onFailure: reject, + }); + }); + if (switchableViews.length) { + // These do not need to be awaited as we're in teh context + // of the mutex. + this._activateSnippet(this.$body.find('#wrapwrap > main')); + return; + } + let $pageOptionsTarget = $(); + let i = 0; + const pageOptions = this.templateOptions.filter(template => template.data.pageOptions); + while (!$pageOptionsTarget.length && i < pageOptions.length) { + $pageOptionsTarget = pageOptions[i].selector.all(); + i++; + } + if ($pageOptionsTarget.length) { + this._activateSnippet($pageOptionsTarget); + } else { + this._activateEmptyOptionsTab(); + } + }); + } + }, /** * @private */ diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 1d4ed893b57..a761faf3486 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -3235,6 +3235,47 @@ options.registry.sizing.include({ } }); +options.registry.SwitchableViews = options.Class.extend({ + /** + * @override + */ + async willStart() { + const _super = this._super.bind(this); + this.switchableRelatedViews = await new Promise((resolve, reject) => { + this.trigger_up('get_switchable_related_views', { + onSuccess: resolve, + onFailure: reject, + }); + }); + return _super(...arguments); + }, + /** + * @override + */ + _renderCustomXML(uiFragment) { + for (const view of this.switchableRelatedViews) { + const weCheckboxEl = document.createElement('we-checkbox'); + weCheckboxEl.setAttribute('string', view.name); + weCheckboxEl.setAttribute('data-customize-website-views', view.key); + weCheckboxEl.setAttribute('data-no-preview', 'true'); + weCheckboxEl.setAttribute('data-reload', '/'); + uiFragment.appendChild(weCheckboxEl); + } + }, + /*** + * @override + */ + _computeVisibility() { + return !!this.switchableRelatedViews.length; + }, + /** + * @override + */ + _checkIfWidgetsUpdateNeedReload() { + return true; + } +}); + return { UrlPickerUserValueWidget: UrlPickerUserValueWidget, FontFamilyPickerUserValueWidget: FontFamilyPickerUserValueWidget, diff --git a/addons/website/static/src/services/website_service.js b/addons/website/static/src/services/website_service.js index 7b58cbcd242..1375de3370c 100644 --- a/addons/website/static/src/services/website_service.js +++ b/addons/website/static/src/services/website_service.js @@ -35,6 +35,7 @@ export const websiteService = { let websiteRootInstance; let Wysiwyg; let isPublisher; + let isDesigner; let hasMultiWebsites; const context = reactive({ showNewContentModal: false, @@ -125,6 +126,9 @@ export const websiteService = { get isPublisher() { return isPublisher === true; }, + get isDesigner() { + return isDesigner === true; + }, get hasMultiWebsites() { return hasMultiWebsites === true; }, @@ -146,8 +150,9 @@ export const websiteService = { }, async fetchWebsites() { // Fetch user groups, before fetching the websites. - [isPublisher, hasMultiWebsites] = await Promise.all([ + [isPublisher, isDesigner, hasMultiWebsites] = await Promise.all([ user.hasGroup('website.group_website_publisher'), + user.hasGroup('website.group_website_designer'), user.hasGroup('website.group_multi_website'), ]); diff --git a/addons/website/static/tests/tours/snippet_popup_add_remove.js b/addons/website/static/tests/tours/snippet_popup_add_remove.js index 7cc04aa6430..f8194f30e95 100644 --- a/addons/website/static/tests/tours/snippet_popup_add_remove.js +++ b/addons/website/static/tests/tours/snippet_popup_add_remove.js @@ -22,7 +22,7 @@ wTourUtils.registerEditionTour('snippet_popup_add_remove', { }, { content: `Remove the s_popup snippet`, in_modal: false, - trigger: '.o_we_customize_panel we-customizeblock-options we-button.oe_snippet_remove:first', + trigger: '.o_we_customize_panel we-customizeblock-options:contains("Popup") we-button.oe_snippet_remove:first', }, { content: 'Check the s_popup was removed', in_modal: false, diff --git a/addons/website/views/snippets/snippets.xml b/addons/website/views/snippets/snippets.xml index 7a6d8a80b73..4cdf7e52337 100644 --- a/addons/website/views/snippets/snippets.xml +++ b/addons/website/views/snippets/snippets.xml @@ -1463,5 +1463,8 @@ data-no-preview="true" data-reload="/"/>
+
+ +