diff --git a/addons/test_website_modules/static/tests/tours/configurator_flow.js b/addons/test_website_modules/static/tests/tours/configurator_flow.js index 312e25db3a83e..a9f329c68f471 100644 --- a/addons/test_website_modules/static/tests/tours/configurator_flow.js +++ b/addons/test_website_modules/static/tests/tours/configurator_flow.js @@ -71,7 +71,7 @@ tour.register('configurator_flow', { trigger: 'button.btn-primary', }, { content: "Loader should be shown", - trigger: '.o_theme_install_loader_container', + trigger: '.o_website_loader_container', run: function () {}, // it's a check }, { content: "Wait untill the configurator is finished", diff --git a/addons/website/__manifest__.py b/addons/website/__manifest__.py index cd8d1c302f93f..e0dc45e397a43 100644 --- a/addons/website/__manifest__.py +++ b/addons/website/__manifest__.py @@ -172,6 +172,8 @@ 'website/static/src/components/fields/fields.js', 'website/static/src/components/fullscreen_indication/fullscreen_indication.js', 'website/static/src/components/fullscreen_indication/fullscreen_indication.scss', + 'website/static/src/components/website_loader/website_loader.js', + 'website/static/src/components/website_loader/website_loader.scss', 'website/static/src/services/website_service.js', 'website/static/src/js/utils.js', 'website/static/src/js/website_page_list.js', @@ -259,6 +261,7 @@ 'website/static/src/components/editor/editor.xml', 'website/static/src/components/fields/fields.xml', 'website/static/src/components/translator/*.xml', + 'website/static/src/components/website_loader/*.xml', 'website/static/src/systray_items/*.xml', 'website/static/src/xml/website.backend.xml', 'website/static/src/xml/website_widget.xml', diff --git a/addons/website/models/ir_module_module.py b/addons/website/models/ir_module_module.py index 4423ef5bf9253..1073b384d8181 100644 --- a/addons/website/models/ir_module_module.py +++ b/addons/website/models/ir_module_module.py @@ -382,6 +382,8 @@ def button_choose_theme(self): result = active_todo.action_launch() else: result = website.button_go_website(mode_edit=True) + if result.get('url') and 'enable_editor' in result['url']: + result['url'] = result['url'].replace('enable_editor', 'with_loader=1&enable_editor') return result def button_remove_theme(self): diff --git a/addons/website/static/src/client_actions/configurator/configurator.js b/addons/website/static/src/client_actions/configurator/configurator.js index c273626cd47e7..127085de5c906 100644 --- a/addons/website/static/src/client_actions/configurator/configurator.js +++ b/addons/website/static/src/client_actions/configurator/configurator.js @@ -3,7 +3,7 @@ import utils from 'web.utils'; import weUtils from 'web_editor.utils'; import {ColorpickerWidget} from 'web.Colorpicker'; -import {_t, _lt, qweb} from 'web.core'; +import {_t, _lt} from 'web.core'; import {svgToPNG} from 'website.utils'; import { useService } from "@web/core/utils/hooks"; import { registry } from "@web/core/registry"; @@ -345,6 +345,10 @@ Object.assign(PaletteSelectionScreen, { }); class ApplyConfiguratorScreen extends Component { + setup() { + this.websiteService = useService('website'); + } + async applyConfigurator(themeName) { if (!this.state.selectedIndustry) { return this.props.navigate(ROUTES.descriptionScreen); @@ -353,7 +357,7 @@ class ApplyConfiguratorScreen extends Component { return this.props.navigate(ROUTES.paletteSelectionScreen); } if (themeName !== undefined) { - $('body').append(qweb.render('website.ThemePreview.Loader', {showTips: true})); + this.websiteService.showLoader({ showTips: true }); const selectedFeatures = Object.values(this.state.features).filter((feature) => feature.selected).map((feature) => feature.id); let selectedPalette = this.state.selectedPalette.name; if (!selectedPalette) { @@ -384,7 +388,7 @@ class ApplyConfiguratorScreen extends Component { // Here the website service goToWebsite method is not used because // the web client needs to be reloaded after the new modules have // been installed. - window.location.replace(`/web#action=website.website_preview&website_id=${resp.website_id}&enable_editor=1`); + window.location.replace(`/web#action=website.website_preview&website_id=${resp.website_id}&enable_editor=1&with_loader=1`); } } } diff --git a/addons/website/static/src/client_actions/website_preview/website_preview.js b/addons/website/static/src/client_actions/website_preview/website_preview.js index bd116f73f8eae..158310de6b291 100644 --- a/addons/website/static/src/client_actions/website_preview/website_preview.js +++ b/addons/website/static/src/client_actions/website_preview/website_preview.js @@ -83,6 +83,10 @@ export class WebsitePreview extends Component { this.dialogService.add(OptimizeSEODialog); }, {once: true}); } + if (this.props.action.context.params && this.props.action.context.params.with_loader) { + this.websiteService.showLoader({ showTips: true }); + } + return () => { this.websiteService.currentWebsiteId = null; this.websiteService.websiteRootInstance = undefined; diff --git a/addons/website/static/src/components/editor/editor.js b/addons/website/static/src/components/editor/editor.js index 9ff4c8d1bc116..641de495daa47 100644 --- a/addons/website/static/src/components/editor/editor.js +++ b/addons/website/static/src/components/editor/editor.js @@ -61,6 +61,7 @@ export class WebsiteEditorComponent extends Component { this.state.reloading = false; this.wysiwygOptions.invalidateSnippetCache = false; this.websiteService.unblockIframe(); + this.websiteService.hideLoader(); } /** * Prepares the editor for reload. Copies the widget element tree diff --git a/addons/website/static/src/components/website_loader/website_loader.js b/addons/website/static/src/components/website_loader/website_loader.js new file mode 100644 index 0000000000000..6af7b1fe6ff89 --- /dev/null +++ b/addons/website/static/src/components/website_loader/website_loader.js @@ -0,0 +1,28 @@ +/** @odoo-module **/ + +const { Component, useState } = owl; + +export class WebsiteLoader extends Component { + setup() { + const initialState = { + isVisible: false, + title: '', + showTips: false, + }; + + this.state = useState({ + ...initialState, + }); + this.props.bus.on('SHOW-WEBSITE-LOADER', this, (props) => { + this.state.isVisible = true; + this.state.title = props && props.title; + this.state.showTips = props && props.showTips; + }); + this.props.bus.on('HIDE-WEBSITE-LOADER', this, () => { + for (const key of Object.keys(initialState)) { + this.state[key] = initialState[key]; + } + }); + } +} +WebsiteLoader.template = 'website.website_loader'; diff --git a/addons/website/static/src/components/website_loader/website_loader.scss b/addons/website/static/src/components/website_loader/website_loader.scss new file mode 100644 index 0000000000000..bc2b20fb474e1 --- /dev/null +++ b/addons/website/static/src/components/website_loader/website_loader.scss @@ -0,0 +1,34 @@ +.o_website_loader_container { + font-family: "Montserrat", $font-family-sans-serif; + background-color: rgba($o-shadow-color, .9); + pointer-events: all; + font-size: 3.5rem; + justify-content: space-evenly; + z-index: $zindex-modal - 1; + padding: 7%; + + .o_website_loader { + position: relative; + display: inline-block; + width: 400px; + height: 220px; + background-image: url('/website/static/src/img/theme_loader.gif'); + background-size: cover; + border-radius: 6px; + } + + .o_website_loader_tip { + font-size: 0.5em; + @include media-breakpoint-down(md) { + width: 50% !important; + } + + .o_tooltip { + top: auto !important; + bottom: 11px !important; + left: 0 !important; + margin-right: 7px !important; + padding-left: 33px !important; + } + } +} diff --git a/addons/website/static/src/components/website_loader/website_loader.xml b/addons/website/static/src/components/website_loader/website_loader.xml new file mode 100644 index 0000000000000..e3a57f9769896 --- /dev/null +++ b/addons/website/static/src/components/website_loader/website_loader.xml @@ -0,0 +1,18 @@ + + + +
+ + Building your website... +
+

+ + TIP: Once loaded, follow the + +
pointer to build the perfect page in 7 steps. +
+

+
+
+ diff --git a/addons/website/static/src/js/theme_preview_kanban.js b/addons/website/static/src/js/theme_preview_kanban.js index 0244b8640d615..f6019af10f30f 100644 --- a/addons/website/static/src/js/theme_preview_kanban.js +++ b/addons/website/static/src/js/theme_preview_kanban.js @@ -21,7 +21,7 @@ var ThemePreviewKanbanController = KanbanController.extend(ThemePreviewControlle // update breacrumb const websiteLink = Object.assign(document.createElement('a'), { className: 'btn btn-secondary ms-3 text-black-75', - href: '/', + href: '/web#action=website.website_preview', innerHTML: '', }); if (!this.initialState.context.module) { // not coming from res.config.settings diff --git a/addons/website/static/src/scss/website.editor.ui.scss b/addons/website/static/src/scss/website.editor.ui.scss index 98d04a5e3b471..2e0042fd630e5 100644 --- a/addons/website/static/src/scss/website.editor.ui.scss +++ b/addons/website/static/src/scss/website.editor.ui.scss @@ -51,20 +51,3 @@ $o-we-switch-inactive-color: rgba($text-muted, 0.4) !default; } } } - -.o_new_content_loader_container { - background-color: rgba($o-shadow-color, .9); - pointer-events: all; - font-size: 3.5rem; - justify-content: center; - z-index: $zindex-modal - 1; -} -.o_new_content_loader { - position: relative; - display: inline-block; - width: 400px; - height: 220px; - background-image: url('/website/static/src/img/theme_loader.gif'); - background-size: cover; - border-radius: 6px; -} diff --git a/addons/website/static/src/services/website_service.js b/addons/website/static/src/services/website_service.js index 5f68be1837ffb..9430a8d1707c3 100644 --- a/addons/website/static/src/services/website_service.js +++ b/addons/website/static/src/services/website_service.js @@ -6,6 +6,7 @@ import ajax from 'web.ajax'; import { getWysiwygClass } from 'web_editor.loader'; import { FullscreenIndication } from '../components/fullscreen_indication/fullscreen_indication'; +import { WebsiteLoader } from '../components/website_loader/website_loader'; const { reactive, EventBus } = owl; @@ -64,6 +65,10 @@ export const websiteService = { Component: FullscreenIndication, props: { bus }, }); + registry.category('main_components').add('WebsiteLoader', { + Component: WebsiteLoader, + props: { bus }, + }); return { set currentWebsiteId(id) { setCurrentWebsiteId(id); @@ -203,6 +208,12 @@ export const websiteService = { context.snippetsLoaded = false; context.edition = false; }, + showLoader(props) { + bus.trigger('SHOW-WEBSITE-LOADER', props); + }, + hideLoader() { + bus.trigger('HIDE-WEBSITE-LOADER'); + }, }; }, }; diff --git a/addons/website/static/src/systray_items/new_content.js b/addons/website/static/src/systray_items/new_content.js index 35f47aa739f31..041c2948b8e30 100644 --- a/addons/website/static/src/systray_items/new_content.js +++ b/addons/website/static/src/systray_items/new_content.js @@ -5,6 +5,7 @@ import { useService } from '@web/core/utils/hooks'; import { WebsiteDialog, AddPageDialog } from "@website/components/dialog/dialog"; import { useHotkey } from "@web/core/hotkeys/hotkey_hook"; import wUtils from 'website.utils'; +import { sprintf } from '@web/core/utils/strings'; const { Component, xml, useState, onWillStart } = owl; @@ -151,8 +152,11 @@ export class NewContentModal extends Component { }); } - async installModule(id, redirectUrl) { - await this.orm.call( + async installModule(id, redirectUrl, moduleName) { + this.website.showLoader({ + title: sprintf(this.env._t("Building your %s"), moduleName), + }); + await this.orm.silent.call( 'ir.module.module', 'button_immediate_install', [id], @@ -187,7 +191,7 @@ export class NewContentModal extends Component { return el; }); try { - await this.installModule(id, element.redirectUrl); + await this.installModule(id, element.redirectUrl, name); } catch (error) { // Update the NewContentElement with failure icon and text. this.state.newContentElements = this.state.newContentElements.map(el => { diff --git a/addons/website/static/src/xml/website.editor.xml b/addons/website/static/src/xml/website.editor.xml index d7b93467388b8..3825c3f44b27d 100644 --- a/addons/website/static/src/xml/website.editor.xml +++ b/addons/website/static/src/xml/website.editor.xml @@ -136,14 +136,6 @@
- -
-

-

-
- - diff --git a/addons/website/static/tests/tours/configurator_translation.js b/addons/website/static/tests/tours/configurator_translation.js index fed6641fc73df..e15bde0097b7f 100644 --- a/addons/website/static/tests/tours/configurator_translation.js +++ b/addons/website/static/tests/tours/configurator_translation.js @@ -44,7 +44,7 @@ tour.register('configurator_translation', { trigger: 'button.btn-primary', }, { content: "Loader should be shown", - trigger: '.o_theme_install_loader_container', + trigger: '.o_website_loader_container', run: function () {}, // it's a check }, { content: "Wait untill the configurator is finished",