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 @@
+
+
+
pointer to build the perfect page in 7 steps.
+