From caefcb8590301a0ebbe947a875003b33ce7d537a Mon Sep 17 00:00:00 2001 From: Younn Olivier Date: Fri, 18 Mar 2022 17:29:47 +0100 Subject: [PATCH] [IMP] website: convert configurator to client action Before this commit, the configurator was its own frontend application. With the website edition UI moved to the backend, it makes also sense to move the configurator to the backend, as a client action, so that it is easy to trigger it after installing a website (or the website module), and returning to the website_preview client action after having completed it. This commit adds a new color_palettes.scss file, added in the assets_backend, that will print the values of the color palettes (so that some js can handle it). For now, it is needed for the configurator and the editor. It will probably need to be reviewed later to not put everything in backend assets. See merge commit for more information. task-2687506 --- addons/website/__manifest__.py | 12 +- addons/website/controllers/main.py | 5 +- addons/website/models/ir_module_module.py | 2 - addons/website/models/website.py | 6 +- .../configurator/configurator.js | 501 +++++++++--------- .../configurator/configurator.xml | 20 +- .../static/src/js/theme_preview_form.js | 5 +- .../static/src/scss/color_palettes.scss | 56 ++ .../static/src/scss/website.wysiwyg.scss | 57 -- .../views/website_configurator_templates.xml | 15 - .../views/website_navbar_templates.xml | 18 - addons/website/views/website_views.xml | 8 +- 12 files changed, 321 insertions(+), 384 deletions(-) create mode 100644 addons/website/static/src/scss/color_palettes.scss delete mode 100644 addons/website/views/website_configurator_templates.xml delete mode 100644 addons/website/views/website_navbar_templates.xml diff --git a/addons/website/__manifest__.py b/addons/website/__manifest__.py index d57be3b2fc3..065a3ac4be1 100644 --- a/addons/website/__manifest__.py +++ b/addons/website/__manifest__.py @@ -33,8 +33,6 @@ 'data/digest_data.xml', 'views/assets.xml', 'views/website_templates.xml', - 'views/website_navbar_templates.xml', - 'views/website_configurator_templates.xml', 'views/snippets/snippets.xml', 'views/snippets/s_title.xml', 'views/snippets/s_cover.xml', @@ -156,6 +154,7 @@ 'website/static/tests/tours/**/*', ], 'web.assets_backend': [ + 'website/static/src/scss/color_palettes.scss', 'website/static/src/scss/view_hierarchy.scss', 'website/static/src/scss/website.backend.scss', 'website/static/src/scss/website_visitor_views.scss', @@ -291,15 +290,6 @@ 'http://test.external.link/javascript2.js', 'http://test.external.link/style2.css', ], - 'website.website_configurator_assets_js': [ - '/website/static/src/client_actions/configurator/configurator.js', - ], - 'website.website_configurator_assets_scss': [ - ('include', 'web.assets_frontend'), - '/website/static/src/client_actions/configurator/configurator.scss', - '/website/static/src/scss/website.theme_install.scss', - '/website/static/src/scss/website.wysiwyg.scss' - ] }, 'license': 'LGPL-3', } diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 201e7fd22e4..cc77158065f 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -255,7 +255,10 @@ class Website(Home): return request.redirect('/') if request.env.lang != website_id.default_lang_id.code: return request.redirect('/%s%s' % (website_id.default_lang_id.url_code, request.httprequest.path)) - return request.render('website.website_configurator') + action_url = '/web#action=website.website_configurator&menu_id=%s' % request.env.ref('website.menu_website_configuration').id + if step > 1: + action_url += '&step=' + str(step) + return request.redirect(action_url) @http.route(['/website/social/'], type='http', auth="public", website=True, sitemap=False) def social(self, social, **kwargs): diff --git a/addons/website/models/ir_module_module.py b/addons/website/models/ir_module_module.py index 1073b384d81..4423ef5bf92 100644 --- a/addons/website/models/ir_module_module.py +++ b/addons/website/models/ir_module_module.py @@ -382,8 +382,6 @@ class IrModuleModule(models.Model): 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/models/website.py b/addons/website/models/website.py index 3404bef64a4..0552b19ee8f 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -319,7 +319,7 @@ class Website(models.Model): def configurator_init(self): r = dict() company = self.get_current_website().company_id - configurator_features = self.env['website.configurator.feature'].with_context(lang=self.get_current_website().default_lang_id.code).search([]) + configurator_features = self.env['website.configurator.feature'].search([]) r['features'] = [{ 'id': feature.id, 'name': feature.name, @@ -333,7 +333,7 @@ class Website(models.Model): if company.logo and company.logo != company._get_logo(): r['logo'] = company.logo.decode('utf-8') try: - result = self._website_api_rpc('/api/website/1/configurator/industries', {'lang': self.get_current_website().default_lang_id.code}) + result = self._website_api_rpc('/api/website/1/configurator/industries', {'lang': self.env.context.get('lang')}) r['industries'] = result['industries'] except AccessError as e: logger.warning(e.args[0]) @@ -591,7 +591,7 @@ class Website(models.Model): images = custom_resources.get('images', {}) set_images(images) - return url + return {'url': url, 'website_id': website.id} # ---------------------------------------------------------- # Page Management diff --git a/addons/website/static/src/client_actions/configurator/configurator.js b/addons/website/static/src/client_actions/configurator/configurator.js index 20b18f0cb36..c273626cd47 100644 --- a/addons/website/static/src/client_actions/configurator/configurator.js +++ b/addons/website/static/src/client_actions/configurator/configurator.js @@ -2,14 +2,13 @@ import utils from 'web.utils'; import weUtils from 'web_editor.utils'; -import session from 'web.session'; import {ColorpickerWidget} from 'web.Colorpicker'; -import {_t, _lt} from 'web.core'; +import {_t, _lt, qweb} from 'web.core'; import {svgToPNG} from 'website.utils'; -import {useService} from "@web/core/utils/hooks"; -import {renderToString} from "@web/core/utils/render"; +import { useService } from "@web/core/utils/hooks"; +import { registry } from "@web/core/registry"; -const { App, Component, onMounted, reactive, useEnv, useRef, useState, whenReady } = owl; +const { Component, onMounted, reactive, useEnv, useRef, useState, useSubEnv, onWillStart } = owl; const ROUTES = { descriptionScreen: 2, @@ -61,28 +60,20 @@ const PALETTE_NAMES = [ // from CSS and added in each palette. const CUSTOM_BG_COLOR_ATTRS = ['menu', 'footer']; -const SESSION_STORAGE_ITEM_NAME = 'websiteConfigurator' + session.website_id; - //------------------------------------------------------------------------------ // Components //------------------------------------------------------------------------------ -class SkipButton extends Component { - async skip() { - await skipConfigurator(Component.env.services); - } -} - +class SkipButton extends Component {} SkipButton.template = 'website.Configurator.SkipButton'; class WelcomeScreen extends Component { setup() { this.state = useStore(); - this.router = useRouter(); } goToDescription() { - this.router.navigate(ROUTES.descriptionScreen); + this.props.navigate(ROUTES.descriptionScreen); } } @@ -95,7 +86,6 @@ class DescriptionScreen extends Component { setup() { this.industrySelection = useRef('industrySelection'); this.state = useStore(); - this.router = useRouter(); this.labelToId = {}; this.autocompleteHasResults = true; @@ -278,7 +268,7 @@ class DescriptionScreen extends Component { checkDescriptionCompletion() { const {selectedType, selectedPurpose, selectedIndustry} = this.state; if (selectedType && selectedPurpose && selectedIndustry) { - this.router.navigate(ROUTES.paletteSelectionScreen); + this.props.navigate(ROUTES.paletteSelectionScreen); } } } @@ -291,10 +281,10 @@ Object.assign(DescriptionScreen, { class PaletteSelectionScreen extends Component { setup() { this.state = useStore(); - this.router = useRouter(); this.logoInputRef = useRef('logoSelectionInput'); this.notification = useService("notification"); this.rpc = useService("rpc"); + this.orm = useService('orm'); onMounted(() => { if (this.state.logo) { @@ -312,13 +302,10 @@ class PaletteSelectionScreen extends Component { if (logoSelectInput.files.length === 1) { const file = logoSelectInput.files[0]; const data = await utils.getDataURLFromFile(file); - const attachment = await this.rpc({ - route: '/web_editor/attachment/add_data', - params: { - 'name': 'logo', - 'data': data.split(',')[1], - 'is_image': true, - }, + const attachment = await this.rpc('/web_editor/attachment/add_data', { + 'name': 'logo', + 'data': data.split(',')[1], + 'is_image': true, }); if (!attachment.error) { this.state.changeLogo(data, attachment.id); @@ -338,18 +325,17 @@ class PaletteSelectionScreen extends Component { img = await svgToPNG(img); } img = img.split(',')[1]; - const [color1, color2] = await this.rpc({ - model: 'base.document.layout', - method: 'extract_image_primary_secondary_colors', - args: [img], - kwargs: {mitigate: 255}, - }); + const [color1, color2] = await this.orm.call('base.document.layout', + 'extract_image_primary_secondary_colors', + [img], + {mitigate: 255}, + ); this.state.setRecommendedPalette(color1, color2); } selectPalette(paletteName) { this.state.selectPalette(paletteName); - this.router.navigate(ROUTES.featuresSelectionScreen); + this.props.navigate(ROUTES.featuresSelectionScreen); } } @@ -358,32 +344,78 @@ Object.assign(PaletteSelectionScreen, { template: 'website.Configurator.PaletteSelectionScreen', }); -class FeaturesSelectionScreen extends Component { +class ApplyConfiguratorScreen extends Component { + async applyConfigurator(themeName) { + if (!this.state.selectedIndustry) { + return this.props.navigate(ROUTES.descriptionScreen); + } + if (!this.state.selectedPalette) { + return this.props.navigate(ROUTES.paletteSelectionScreen); + } + if (themeName !== undefined) { + $('body').append(qweb.render('website.ThemePreview.Loader', {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) { + selectedPalette = [ + this.state.selectedPalette.color1, + this.state.selectedPalette.color2, + this.state.selectedPalette.color3, + this.state.selectedPalette.color4, + this.state.selectedPalette.color5, + ]; + } + + const resp = await this.orm.silent.call('website', + 'configurator_apply', + [], + { + 'selected_features': selectedFeatures, + 'industry_id': this.state.selectedIndustry.id, + 'selected_palette': selectedPalette, + 'theme_name': themeName, + 'website_purpose': WEBSITE_PURPOSES[this.state.selectedPurpose].name, + 'website_type': WEBSITE_TYPES[this.state.selectedType].name, + 'logo_attachment_id': this.state.logoAttachmentId, + }); + + this.props.clearStorage(); + + // 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`); + } + } +} + +class FeaturesSelectionScreen extends ApplyConfiguratorScreen { setup() { + super.setup(); + + this.orm = useService("orm"); this.state = useStore(); - this.router = useRouter(); - this.rpc = useService("rpc"); } async buildWebsite() { const industryId = this.state.selectedIndustry && this.state.selectedIndustry.id; if (!industryId) { - return this.router.navigate(ROUTES.descriptionScreen); + return this.props.navigate(ROUTES.descriptionScreen); } - const themes = await this.rpc({ - model: 'website', - method: 'configurator_recommended_themes', - kwargs: { + const themes = await this.orm.call('website', + 'configurator_recommended_themes', + [], + { 'industry_id': industryId, 'palette': this.state.selectedPalette, }, - }); + ); if (!themes.length) { - await applyConfigurator(this, 'theme_default'); + await this.applyConfigurator('theme_default'); } else { this.state.updateRecommendedThemes(themes); - this.router.navigate(ROUTES.themeSelectionScreen); + this.props.navigate(ROUTES.themeSelectionScreen); } } } @@ -393,11 +425,12 @@ Object.assign(FeaturesSelectionScreen, { template: 'website.Configurator.FeatureSelection', }); -class ThemeSelectionScreen extends Component { +class ThemeSelectionScreen extends ApplyConfiguratorScreen { setup() { + super.setup(); + + this.orm = useService('orm'); this.state = useStore(); - this.router = useRouter(); - this.rpc = useService('rpc'); this.themeSVGPreviews = [useRef('ThemePreview1'), useRef('ThemePreview2'), useRef('ThemePreview3')]; onMounted(() => { @@ -408,56 +441,19 @@ class ThemeSelectionScreen extends Component { } async chooseTheme(themeName) { - await applyConfigurator(this, themeName); + await this.applyConfigurator(themeName); } } ThemeSelectionScreen.template = 'website.Configurator.ThemeSelectionScreen'; -class Configurator extends Component { - setup() { - this.router = useRouter(); - } -} - -Object.assign(Configurator, { - components: { - WelcomeScreen, - DescriptionScreen, - PaletteSelectionScreen, - FeaturesSelectionScreen, - ThemeSelectionScreen, - }, - template: 'website.Configurator.Configurator', -}); - -//------------------------------------------------------------------------------ -// Router -//------------------------------------------------------------------------------ - -class Router { - constructor() { - this.location = window.location.pathname; - } - - navigate(id) { - this.location = `/website/configurator${id ? '/' + id : ''}`; - history.pushState({}, '', window.location.origin + this.location); - } -} - -function useRouter() { - const env = useEnv(); - return useState(env.router); -} - //------------------------------------------------------------------------------ // Store //------------------------------------------------------------------------------ class Store { - async start() { - Object.assign(this, await getInitialState(Component.env.services)); + async start(getInitialState) { + Object.assign(this, await getInitialState()); } //------------------------------------------------------------------------- @@ -572,193 +568,174 @@ class Store { } } -async function getInitialState(services) { - // Load values from python and iap - var results = await services.rpc({ - model: 'website', - method: 'configurator_init', - }); - const r = { - industries: results.industries, - logo: results.logo ? 'data:image/png;base64,' + results.logo : false, - }; - r.industries = r.industries.map((industry, index) => ({ - ...industry, - wordCount: industry.label.split(" ").length, - hitCountOrder: index, - })); - - // Load palettes from the current CSS - const palettes = {}; - const style = window.getComputedStyle(document.documentElement); - - PALETTE_NAMES.forEach((paletteName) => { - const palette = { - name: paletteName - }; - for (let j = 1; j <= 5; j += 1) { - palette[`color${j}`] = weUtils.getCSSVariableValue(`o-palette-${paletteName}-o-color-${j}`, style); - } - CUSTOM_BG_COLOR_ATTRS.forEach((attr) => { - palette[attr] = weUtils.getCSSVariableValue(`o-palette-${paletteName}-${attr}-bg`, style); - }); - palettes[paletteName] = palette; - }); - - const localState = JSON.parse(window.sessionStorage.getItem(SESSION_STORAGE_ITEM_NAME)); - if (localState) { - let themes = []; - if (localState.selectedIndustry && localState.selectedPalette) { - themes = await services.rpc({ - model: 'website', - method: 'configurator_recommended_themes', - kwargs: { - 'industry_id': localState.selectedIndustry.id, - 'palette': localState.selectedPalette, - }, - }); - } - return Object.assign(r, {...localState, palettes, themes}); - } - - const features = {}; - results.features.forEach(feature => { - features[feature.id] = Object.assign({}, feature, {selected: feature.module_state === 'installed'}); - const wtp = features[feature.id]['website_config_preselection']; - features[feature.id]['website_config_preselection'] = wtp ? wtp.split(',') : []; - }); - - // Palette color used by default as background color for menu and footer. - // Needed to build the recommended palette. - const defaultColors = {}; - CUSTOM_BG_COLOR_ATTRS.forEach((attr) => { - const color = weUtils.getCSSVariableValue(`o-default-${attr}-bg`, style); - const match = color.match(/o-color-(?[1-5])/); - const colorIdx = parseInt(match.groups['idx']); - defaultColors[attr] = `color${colorIdx}`; - }); - - return Object.assign(r, { - selectedType: undefined, - selectedPurpose: undefined, - selectedIndustry: undefined, - selectedPalette: undefined, - recommendedPalette: undefined, - defaultColors: defaultColors, - palettes: palettes, - features: features, - themes: [], - logoAttachmentId: undefined, - }); -} - function useStore() { const env = useEnv(); - return useState(env.state); + return useState(env.store); } -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ +class Configurator extends Component { + setup() { + this.orm = useService('orm'); + this.action = useService('action'); + this.router = useService('router'); -async function skipConfigurator(services) { - await services.rpc({ - model: 'website', - method: 'configurator_skip', - }); - window.sessionStorage.removeItem(SESSION_STORAGE_ITEM_NAME); - window.location = '/web#action=website.theme_install_kanban_action'; -} + const initialStep = this.props.action.context.params && this.props.action.context.params.step; + const store = reactive(new Store(), () => this.updateStorage(store)); -async function applyConfigurator(self, themeName) { - if (!self.state.selectedIndustry) { - return self.router.navigate(ROUTES.descriptionScreen); + this.state = useState({ + currentStep: initialStep, + }); + + useSubEnv({ store }); + + onWillStart(async () => { + this.websiteId = (await this.orm.call('website', 'get_current_website')).match(/\d+/)[0]; + + await store.start(() => this.getInitialState()); + this.updateStorage(store); + if (!store.industries) { + await this.skipConfigurator(); + } + }); + + // This is a hack to overwrite the history state, modified by the + // router service after executing an action. Ideally, the router + // service would let us push a state with a new pathname. + onMounted(() => { + setTimeout(() => { + this.router.cancelPushes(); + this.updateBrowserUrl(); + }); + }); } - if (!self.state.selectedPalette) { - return self.router.navigate(ROUTES.paletteSelectionScreen); + + get pathname() { + return `/website/configurator${this.state.currentStep ? `/${this.state.currentStep}` : ''}`; } - if (themeName !== undefined) { - const loader = renderToString('website.ThemePreview.Loader', {showTips: true}); - $('body').append(loader); - const selectedFeatures = Object.values(self.state.features).filter((feature) => feature.selected).map((feature) => feature.id); - let selectedPalette = self.state.selectedPalette.name; - if (!selectedPalette) { - selectedPalette = [ - self.state.selectedPalette.color1, - self.state.selectedPalette.color2, - self.state.selectedPalette.color3, - self.state.selectedPalette.color4, - self.state.selectedPalette.color5, - ]; + + get storageItemName() { + return `websiteConfigurator${this.websiteId}`; + } + + updateBrowserUrl() { + history.pushState({}, '', this.pathname); + } + + navigate(step) { + this.state.currentStep = step; + this.updateBrowserUrl(); + } + + clearStorage() { + window.sessionStorage.removeItem(this.storageItemName); + } + + async getInitialState() { + // Load values from python and iap + var results = await this.orm.call('website', 'configurator_init'); + const r = { + industries: results.industries, + logo: results.logo ? 'data:image/png;base64,' + results.logo : false, + }; + r.industries = r.industries.map((industry, index) => ({ + ...industry, + wordCount: industry.label.split(" ").length, + hitCountOrder: index, + })); + + // Load palettes from the current CSS + const palettes = {}; + const style = window.getComputedStyle(document.documentElement); + + PALETTE_NAMES.forEach((paletteName) => { + const palette = { + name: paletteName + }; + for (let j = 1; j <= 5; j += 1) { + palette[`color${j}`] = weUtils.getCSSVariableValue(`o-palette-${paletteName}-o-color-${j}`, style); + } + CUSTOM_BG_COLOR_ATTRS.forEach((attr) => { + palette[attr] = weUtils.getCSSVariableValue(`o-palette-${paletteName}-${attr}-bg`, style); + }); + palettes[paletteName] = palette; + }); + + const localState = JSON.parse(window.sessionStorage.getItem(this.storageItemName)); + if (localState) { + let themes = []; + if (localState.selectedIndustry && localState.selectedPalette) { + themes = await this.orm.call('website', 'configurator_recommended_themes', [], { + 'industry_id': localState.selectedIndustry.id, + 'palette': localState.selectedPalette, + }); + } + return Object.assign(r, {...localState, palettes, themes}); } - const resp = await self.rpc({ - model: 'website', - method: 'configurator_apply', - kwargs: { - 'selected_features': selectedFeatures, - 'industry_id': self.state.selectedIndustry.id, - 'selected_palette': selectedPalette, - 'theme_name': themeName, - 'website_purpose': WEBSITE_PURPOSES[self.state.selectedPurpose].name, - 'website_type': WEBSITE_TYPES[self.state.selectedType].name, - 'logo_attachment_id': self.state.logoAttachmentId, - }, + + const features = {}; + results.features.forEach(feature => { + features[feature.id] = Object.assign({}, feature, {selected: feature.module_state === 'installed'}); + const wtp = features[feature.id]['website_config_preselection']; + features[feature.id]['website_config_preselection'] = wtp ? wtp.split(',') : []; + }); + + // Palette color used by default as background color for menu and footer. + // Needed to build the recommended palette. + const defaultColors = {}; + CUSTOM_BG_COLOR_ATTRS.forEach((attr) => { + const color = weUtils.getCSSVariableValue(`o-default-${attr}-bg`, style); + const match = color.match(/o-color-(?[1-5])/); + const colorIdx = parseInt(match.groups['idx']); + defaultColors[attr] = `color${colorIdx}`; + }); + + return Object.assign(r, { + selectedType: undefined, + selectedPurpose: undefined, + selectedIndustry: undefined, + selectedPalette: undefined, + recommendedPalette: undefined, + defaultColors: defaultColors, + palettes: palettes, + features: features, + themes: [], + logoAttachmentId: undefined, + }); + } + + updateStorage(state) { + const newState = JSON.stringify({ + defaultColors: state.defaultColors, + features: state.features, + logo: state.logo, + logoAttachmentId: state.logoAttachmentId, + selectedIndustry: state.selectedIndustry, + selectedPalette: state.selectedPalette, + selectedPurpose: state.selectedPurpose, + selectedType: state.selectedType, + recommendedPalette: state.recommendedPalette, + }); + window.sessionStorage.setItem(this.storageItemName, newState); + } + + async skipConfigurator() { + await this.orm.call('website', 'configurator_skip'); + this.clearStorage(); + this.action.doAction('website.theme_install_kanban_action', { + clearBreadcrumbs: true, }); - window.sessionStorage.removeItem(SESSION_STORAGE_ITEM_NAME); - window.location = resp.url; } } -function updateStorage(state) { - const newState = JSON.stringify({ - defaultColors: state.defaultColors, - features: state.features, - logo: state.logo, - logoAttachmentId: state.logoAttachmentId, - selectedIndustry: state.selectedIndustry, - selectedPalette: state.selectedPalette, - selectedPurpose: state.selectedPurpose, - selectedType: state.selectedType, - recommendedPalette: state.recommendedPalette, - }); - window.sessionStorage.setItem(SESSION_STORAGE_ITEM_NAME, newState); -} +Object.assign(Configurator, { + components: { + WelcomeScreen, + DescriptionScreen, + PaletteSelectionScreen, + FeaturesSelectionScreen, + ThemeSelectionScreen, + }, + template: 'website.Configurator.Configurator', +}); -async function makeEnvironment() { - const state = reactive(new Store(), () => updateStorage(state)); - await state.start(); - updateStorage(state); - const env = { - state, - router: reactive(new Router()), - services: Component.env.services, - }; - await session.is_bound; - return env; -} - -//------------------------------------------------------------------------------ -// Setup -//------------------------------------------------------------------------------ - -async function setup() { - const env = await makeEnvironment(); - if (!env.state.industries) { - await skipConfigurator(env.services); - } else { - const templates = await (await fetch('/website/static/src/client_actions/configurator/configurator.xml')).text(); - const app = new App(Configurator, { - env, - dev: env.debug, - templates, - translatableAttributes: ["data-tooltip"], - translateFn: _t, - }); - const loaderTemplate = await (await fetch('/website/static/src/xml/theme_preview.xml')).text(); - app.addTemplates(loaderTemplate); - renderToString.app = app; - await app.mount(document.body); - } -} - -whenReady(setup); +registry.category('actions').add('website_configurator', Configurator); diff --git a/addons/website/static/src/client_actions/configurator/configurator.xml b/addons/website/static/src/client_actions/configurator/configurator.xml index 02bbbb169af..8f03d25ca0a 100644 --- a/addons/website/static/src/client_actions/configurator/configurator.xml +++ b/addons/website/static/src/client_actions/configurator/configurator.xml @@ -3,7 +3,7 @@
- +
@@ -22,7 +22,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -145,7 +145,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -238,11 +238,11 @@
- - - - - + + + + +
diff --git a/addons/website/static/src/js/theme_preview_form.js b/addons/website/static/src/js/theme_preview_form.js index aada899b7a1..593c69a3e7e 100644 --- a/addons/website/static/src/js/theme_preview_form.js +++ b/addons/website/static/src/js/theme_preview_form.js @@ -26,7 +26,10 @@ const ThemePreviewControllerCommon = { this._addLoader(); switch (action) { case 'button_choose_theme': - actionCallback = result => this.do_action(result); + actionCallback = result => { + this.do_action(result); + this._removeLoader(); + }; break; case 'button_refresh_theme': actionCallback = () => this._removeLoader(); diff --git a/addons/website/static/src/scss/color_palettes.scss b/addons/website/static/src/scss/color_palettes.scss new file mode 100644 index 00000000000..baef0487b87 --- /dev/null +++ b/addons/website/static/src/scss/color_palettes.scss @@ -0,0 +1,56 @@ +:root { + // Override css variables to influence the default style of the editor + // without duplicating the css. + @include print-variable('o-we-toolbar-height', $o-navbar-height); + + // Need the colors, name, menu background color and footer background color of each color palette + $o-palette-names: (); + $-default-cc: (); + $-bg-attrs: 'menu', 'footer'; + @each $attr in $-bg-attrs { + // Since the variables built here are currently only used for theme previews we + // decided to keep things simple and we deliberately ignore potential overrides + // from #{$-bg-attrs}-custom and #{$-bg-attrs}-gradient. + $-default-cc: map-merge($-default-cc, ($attr: map-get($o-base-color-palette, $attr))) + } + + @each $-selected-palette-name in $o-selected-color-palettes-names { + $-palette: map-get($o-color-palettes, $-selected-palette-name); + + @if $-selected-palette-name != 'user-palette' { + @each $key, $value in $-palette { + @include print-variable('o-palette-#{$-selected-palette-name}-#{$key}', $value); + } + + @each $attr-name, $default-cc-idx in $-default-cc { + $-cc-idx: $default-cc-idx; + @if map-has-key($-palette, $attr-name) { + $-cc-idx: map-get($-palette, $attr-name); + } + $-bg: $body-bg; + @if $-cc-idx != null { + $-cc: nth($o-color-combinations, $-cc-idx); + $-bg: o-safe-get($-palette, 'o-cc#{$-cc-idx}-bg', map-get($-cc, 'bg')); + @if type-of($-bg) != color { + $-bg: map-get($-palette, $-bg); + } + } + @include print-variable('o-palette-#{$-selected-palette-name}-#{$attr-name}-bg', $-bg); + } + } + } + + // Need the palette colors used as default menu and footer background color + @each $attr-name, $default-cc-idx in $-default-cc { + $-cc: nth($o-color-combinations, $default-cc-idx); + $-default-bg: map-get($-cc, 'bg'); + @include print-variable('o-default-#{$attr-name}-bg', $-default-bg); + } + + @include print-variable('palette-names', $o-selected-color-palettes-names); + + // Need info about the base grays which are used to compute the final grays + @each $name, $color in $o-base-gray-color-palette { + @include print-variable('base-#{$name}', $color); + } +} diff --git a/addons/website/static/src/scss/website.wysiwyg.scss b/addons/website/static/src/scss/website.wysiwyg.scss index 44cfd93c2bd..1de87ca13d5 100644 --- a/addons/website/static/src/scss/website.wysiwyg.scss +++ b/addons/website/static/src/scss/website.wysiwyg.scss @@ -6,63 +6,6 @@ } } -:root { - // Override css variables to influence the default style of the editor - // without duplicating the css. - @include print-variable('o-we-toolbar-height', $o-navbar-height); - - // Need the colors, name, menu background color and footer background color of each color palette - $o-palette-names: (); - $-default-cc: (); - $-bg-attrs: 'menu', 'footer'; - @each $attr in $-bg-attrs { - // Since the variables built here are currently only used for theme previews we - // decided to keep things simple and we deliberately ignore potential overrides - // from #{$-bg-attrs}-custom and #{$-bg-attrs}-gradient. - $-default-cc: map-merge($-default-cc, ($attr: map-get($o-base-color-palette, $attr))) - } - - @each $-selected-palette-name in $o-selected-color-palettes-names { - $-palette: map-get($o-color-palettes, $-selected-palette-name); - - @if $-selected-palette-name != 'user-palette' { - @each $key, $value in $-palette { - @include print-variable('o-palette-#{$-selected-palette-name}-#{$key}', $value); - } - - @each $attr-name, $default-cc-idx in $-default-cc { - $-cc-idx: $default-cc-idx; - @if map-has-key($-palette, $attr-name) { - $-cc-idx: map-get($-palette, $attr-name); - } - $-bg: $body-bg; - @if $-cc-idx != null { - $-cc: nth($o-color-combinations, $-cc-idx); - $-bg: o-safe-get($-palette, 'o-cc#{$-cc-idx}-bg', map-get($-cc, 'bg')); - @if type-of($-bg) != color { - $-bg: map-get($-palette, $-bg); - } - } - @include print-variable('o-palette-#{$-selected-palette-name}-#{$attr-name}-bg', $-bg); - } - } - } - - // Need the palette colors used as default menu and footer background color - @each $attr-name, $default-cc-idx in $-default-cc { - $-cc: nth($o-color-combinations, $default-cc-idx); - $-default-bg: map-get($-cc, 'bg'); - @include print-variable('o-default-#{$attr-name}-bg', $-default-bg); - } - - @include print-variable('palette-names', $o-selected-color-palettes-names); - - // Need info about the base grays which are used to compute the final grays - @each $name, $color in $o-base-gray-color-palette { - @include print-variable('base-#{$name}', $color); - } -} - #oe_snippets { top: 0; .oe-toolbar { diff --git a/addons/website/views/website_configurator_templates.xml b/addons/website/views/website_configurator_templates.xml deleted file mode 100644 index 299a204a9f4..00000000000 --- a/addons/website/views/website_configurator_templates.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/addons/website/views/website_navbar_templates.xml b/addons/website/views/website_navbar_templates.xml deleted file mode 100644 index c4290c336f1..00000000000 --- a/addons/website/views/website_navbar_templates.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/addons/website/views/website_views.xml b/addons/website/views/website_views.xml index b47b573ff9a..081be12098c 100644 --- a/addons/website/views/website_views.xml +++ b/addons/website/views/website_views.xml @@ -583,15 +583,15 @@ action="website.website_preview"/> - + Website Configurator - /website/configurator - self + website_configurator + fullscreen Start Website Configurator - + 0