[REF] website, web_editor: move theme customization to edit mode
Previously, theme customization was done through a modal dialog in the website module, this was not very user friendly since the rest of the customization for the website design was done from edit mode, meaning the user had to exit edit mode to customize things such as theme colors or fonts. It was also rather confusing to have these seemingly related things in completely unrelated places. This commit moves all of the options that used to be in the theme customization modal into a new tab in the editor's left panel. This commit is mainly just about rendering the old modal as a third left panel content. See next commit for deeper changes. Note: same as before, those changes do apply the color/size/layout immediately on the website, even if not saved. Changing that behavior is complex and might be the job of another task. Part of https://github.com/odoo/odoo/pull/41166 task-2088298
This commit is contained in:
committed by
qsm-odoo
parent
b3e9bfbac0
commit
3bb666c226
@@ -779,6 +779,7 @@ var SnippetsMenu = Widget.extend({
|
||||
cacheSnippetTemplate: {},
|
||||
events: {
|
||||
'click .o_install_btn': '_onInstallBtnClick',
|
||||
'click .o_we_add_snippet_btn': '_onBlocksTabClick',
|
||||
'click .o_we_invisible_entry': '_onInvisibleEntryClick',
|
||||
'click #snippet_custom .o_delete_btn': '_onDeleteBtnClick',
|
||||
},
|
||||
@@ -804,6 +805,11 @@ var SnippetsMenu = Widget.extend({
|
||||
'user_value_widget_opening': '_onUserValueWidgetOpening',
|
||||
'reload_snippet_template': '_onReloadSnippetTemplate',
|
||||
},
|
||||
// enum of the SnippetsMenu's tabs.
|
||||
tabs: {
|
||||
BLOCKS: 'blocks',
|
||||
OPTIONS: 'options',
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Widget} parent
|
||||
@@ -896,10 +902,6 @@ var SnippetsMenu = Widget.extend({
|
||||
});
|
||||
|
||||
var $target = $(srcElement);
|
||||
if ($target.closest('#snippets_menu').length) {
|
||||
this._activateSnippet(false);
|
||||
return;
|
||||
}
|
||||
if (!$target.closest('body > *').length) {
|
||||
return;
|
||||
}
|
||||
@@ -1833,6 +1835,32 @@ var SnippetsMenu = Widget.extend({
|
||||
return this.nodeType === 3 && this.textContent.match(/\S/);
|
||||
}).parent().addClass('o_default_snippet_text');
|
||||
},
|
||||
/**
|
||||
* Changes the content of the left panel and selects a tab.
|
||||
*
|
||||
* @private
|
||||
* @param {htmlString | Element | Text | Array | jQuery} [content]
|
||||
* the new content of the customizePanel
|
||||
* @param {this.tabs.VALUE} [tab='blocks'] - the tab to select
|
||||
*/
|
||||
_updateLeftPanelContent: function ({content, tab}) {
|
||||
this._closeWidgets();
|
||||
|
||||
tab = tab || this.tabs.BLOCKS;
|
||||
|
||||
while (this.customizePanel.firstChild) {
|
||||
this.customizePanel.removeChild(this.customizePanel.firstChild);
|
||||
}
|
||||
if (content) {
|
||||
$(this.customizePanel).append(content);
|
||||
}
|
||||
|
||||
this.$('#o_scroll').toggleClass('d-none', tab !== this.tabs.BLOCKS);
|
||||
this.customizePanel.classList.toggle('d-none', tab === this.tabs.BLOCKS);
|
||||
|
||||
this.$('.o_we_add_snippet_btn').toggleClass('active', tab === this.tabs.BLOCKS);
|
||||
this.$('.o_we_customize_snippet_btn').toggleClass('active', tab === this.tabs.OPTIONS);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
@@ -2000,6 +2028,16 @@ var SnippetsMenu = Widget.extend({
|
||||
.toggleClass('fa-eye-slash', !isVisible);
|
||||
return this._activateSnippet(isVisible ? $snippet : false);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onBlocksTabClick: function (ev) {
|
||||
this._activateSnippet(false);
|
||||
this._updateLeftPanelContent({
|
||||
content: [],
|
||||
tab: this.tabs.BLOCKS,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -2099,18 +2137,10 @@ var SnippetsMenu = Widget.extend({
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onUpdateCustomizeElements: function (ev) {
|
||||
this._closeWidgets();
|
||||
while (this.customizePanel.firstChild) {
|
||||
this.customizePanel.removeChild(this.customizePanel.firstChild);
|
||||
}
|
||||
ev.data.customize$Elements.forEach($el => {
|
||||
this.customizePanel.appendChild($el[0]);
|
||||
this._updateLeftPanelContent({
|
||||
content: ev.data.customize$Elements,
|
||||
tab: ev.data.customize$Elements.length ? this.tabs.OPTIONS : this.tabs.BLOCKS,
|
||||
});
|
||||
var customize = !!ev.data.customize$Elements.length;
|
||||
this.$('#o_scroll').toggleClass('d-none', customize);
|
||||
this.$('.o_we_add_snippet_btn').toggleClass('active', !customize);
|
||||
this.customizePanel.classList.toggle('d-none', !customize);
|
||||
this.$('.o_we_customize_snippet_btn').toggleClass('active', customize);
|
||||
},
|
||||
/**
|
||||
* Called when an user value widget is being opened -> close all the other
|
||||
|
||||
@@ -384,11 +384,6 @@ class Website(Home):
|
||||
|
||||
return True
|
||||
|
||||
@http.route(['/website/theme_customize_reload'], type='http', auth="public", website=True)
|
||||
def theme_customize_reload(self, href, enable, disable, tab=0, **kwargs):
|
||||
self.theme_customize(enable and enable.split(",") or [], disable and disable.split(",") or [])
|
||||
return request.redirect(href + ("&theme=true" if "#" in href else "#theme=true") + ("&tab=" + tab))
|
||||
|
||||
@http.route(['/website/make_scss_custo'], type='json', auth='user', website=True)
|
||||
def make_scss_custo(self, url, values):
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
odoo.define('website.snippet.editor', function (require) {
|
||||
'use strict';
|
||||
|
||||
const weSnippetEditor = require('web_editor.snippet.editor');
|
||||
const ThemeCustomizationMenu = require('website.theme');
|
||||
|
||||
weSnippetEditor.Class.include({
|
||||
events: _.extend({}, weSnippetEditor.Class.prototype.events, {
|
||||
'click .o_we_customize_theme_btn': '_onThemeTabClick',
|
||||
}),
|
||||
tabs: _.extend({}, weSnippetEditor.Class.prototype.tabs, {
|
||||
THEME: 'theme',
|
||||
}),
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
const prom1 = this._super(...arguments);
|
||||
this.themeCustomizationMenu = new ThemeCustomizationMenu(this);
|
||||
const prom2 = this.themeCustomizationMenu.appendTo(document.createDocumentFragment());
|
||||
return Promise.all([prom1, prom2]);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_updateLeftPanelContent: function ({content, tab}) {
|
||||
this._super(...arguments);
|
||||
this.$('.o_we_customize_theme_btn').toggleClass('active', tab === this.tabs.THEME);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onThemeTabClick: function (ev) {
|
||||
this._activateSnippet(false);
|
||||
this._updateLeftPanelContent({
|
||||
content: this.themeCustomizationMenu.el,
|
||||
tab: this.tabs.THEME,
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -6,7 +6,6 @@ var core = require('web.core');
|
||||
var Dialog = require('web.Dialog');
|
||||
var Widget = require('web.Widget');
|
||||
var weWidgets = require('wysiwyg.widgets');
|
||||
var websiteNavbarData = require('website.navbar');
|
||||
var ColorPaletteDialog = require('web_editor.ColorPalette').ColorPaletteDialog;
|
||||
const ColorpickerDialog = require('web.ColorpickerDialog');
|
||||
|
||||
@@ -107,11 +106,10 @@ var QuickEdit = Widget.extend({
|
||||
},
|
||||
});
|
||||
|
||||
var ThemeCustomizeDialog = Dialog.extend({
|
||||
xmlDependencies: (Dialog.prototype.xmlDependencies || [])
|
||||
.concat(['/website/static/src/xml/website.editor.xml']),
|
||||
var ThemeCustomizationMenu = Widget.extend({
|
||||
xmlDependencies: ['/website/static/src/xml/website.editor.xml'],
|
||||
|
||||
template: 'website.theme_customize',
|
||||
className: 'd-flex flex-column align-items-start o_theme_customization_menu p-2',
|
||||
events: {
|
||||
'change .o_theme_customize_option_input': '_onChange',
|
||||
'click .checked .o_theme_customize_option_input[type="radio"]': '_onChange',
|
||||
@@ -124,14 +122,8 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
options = options || {};
|
||||
this._super(parent, _.extend({
|
||||
title: _t("Customize Theme"),
|
||||
buttons: [],
|
||||
}, options));
|
||||
|
||||
this.defaultTab = options.tab || 0;
|
||||
init: function (parent) {
|
||||
this._super(...arguments);
|
||||
this.fontVariables = [];
|
||||
},
|
||||
/**
|
||||
@@ -156,69 +148,19 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
var self = this;
|
||||
|
||||
this.PX_BY_REM = parseFloat($(document.documentElement).css('font-size'));
|
||||
|
||||
this.$modal.addClass('o_theme_customize_modal');
|
||||
this.$modal.find('.modal-footer').append($('<a/>', {
|
||||
href: '/web#action=website.theme_install_kanban_action',
|
||||
text: _t("Choose another theme..."),
|
||||
}));
|
||||
|
||||
this.style = window.getComputedStyle(document.documentElement);
|
||||
this.nbFonts = parseInt(this.style.getPropertyValue('--number-of-fonts'));
|
||||
var googleFontsProperty = this.style.getPropertyValue('--google-fonts').trim();
|
||||
this.googleFonts = googleFontsProperty ? googleFontsProperty.split(/\s*,\s*/g) : [];
|
||||
|
||||
var $tabs;
|
||||
var loadDef = this._loadViews().then(function (data) {
|
||||
self._generateDialogHTML(data);
|
||||
$tabs = self.$('[data-toggle="tab"]');
|
||||
|
||||
// Hide the tab navigation if only one tab
|
||||
if ($tabs.length <= 1) {
|
||||
$tabs.closest('.nav').addClass('d-none');
|
||||
}
|
||||
var loadDef = this._loadViews().then(data => {
|
||||
this._generateDialogHTML(data);
|
||||
this._removeDuplicateColors();
|
||||
});
|
||||
|
||||
// Enable the first option tab or the given default tab
|
||||
this.opened().then(function () {
|
||||
$tabs.eq(self.defaultTab).tab('show');
|
||||
|
||||
// Hack to hide primary/secondary if they are equal to alpha/beta
|
||||
// (this is the case with default values but not in some themes).
|
||||
var $primary = self.$('.o_theme_customize_color[data-color="primary"]');
|
||||
var $alpha = self.$('.o_theme_customize_color[data-color="alpha"]');
|
||||
var $secondary = self.$('.o_theme_customize_color[data-color="secondary"]');
|
||||
var $beta = self.$('.o_theme_customize_color[data-color="beta"]');
|
||||
|
||||
var sameAlphaPrimary = $primary.css('background-color') === $alpha.css('background-color');
|
||||
var sameBetaSecondary = $secondary.css('background-color') === $beta.css('background-color');
|
||||
|
||||
if (!sameAlphaPrimary) {
|
||||
$alpha.prev().text(_t("Extra Color"));
|
||||
}
|
||||
if (!sameBetaSecondary) {
|
||||
$beta.prev().text(_t("Extra Color"));
|
||||
}
|
||||
|
||||
$primary = $primary.closest('.o_theme_customize_option');
|
||||
$alpha = $alpha.closest('.o_theme_customize_option');
|
||||
$secondary = $secondary.closest('.o_theme_customize_option');
|
||||
$beta = $beta.closest('.o_theme_customize_option');
|
||||
|
||||
$primary.toggleClass('d-none', sameAlphaPrimary);
|
||||
$secondary.toggleClass('d-none', sameBetaSecondary);
|
||||
|
||||
if (!sameAlphaPrimary && sameBetaSecondary) {
|
||||
$beta.insertBefore($alpha);
|
||||
} else if (sameAlphaPrimary && !sameBetaSecondary) {
|
||||
$secondary.insertAfter($alpha);
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all([this._super.apply(this, arguments), loadDef]);
|
||||
return Promise.all([this._super(...arguments), loadDef]);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -270,38 +212,21 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
*/
|
||||
_generateDialogHTML: function (data) {
|
||||
var self = this;
|
||||
var $contents = this.$el.children('content');
|
||||
var $contents = $(core.qweb.render('website.theme_customize')).children('content');
|
||||
if ($contents.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$contents.remove();
|
||||
this.$el.append(core.qweb.render('website.theme_customize_modal_layout'));
|
||||
var $navLinksContainer = this.$('.nav');
|
||||
var $navContents = this.$('.tab-content');
|
||||
|
||||
_.each($contents, function (content) {
|
||||
var $content = $(content);
|
||||
const $content = $(content);
|
||||
const contentID = _.uniqueId('content-');
|
||||
|
||||
var contentID = _.uniqueId('content-');
|
||||
|
||||
// Build the nav tab for the content
|
||||
$navLinksContainer.append($('<li/>', {
|
||||
class: 'nav-item mb-1',
|
||||
}).append($('<a/>', {
|
||||
href: '#' + contentID,
|
||||
class: 'nav-link',
|
||||
'data-toggle': 'tab',
|
||||
text: $content.attr('string'),
|
||||
})));
|
||||
|
||||
// Build the tab pane for the content
|
||||
var $navContent = $(core.qweb.render('website.theme_customize_modal_content', {
|
||||
const $menuSection = $(core.qweb.render('website.theme_customize_section', {
|
||||
id: contentID,
|
||||
title: $content.attr('title'),
|
||||
title: $content.attr('string'),
|
||||
}));
|
||||
$navContents.append($navContent);
|
||||
var $optionsContainer = $navContent.find('.o_options_container');
|
||||
self.$el.append($menuSection);
|
||||
var $optionsContainer = $menuSection.find('.o_options_container');
|
||||
|
||||
// Process content items
|
||||
_processItems($content.children(), $optionsContainer, false);
|
||||
@@ -350,7 +275,7 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
}
|
||||
|
||||
// Build the options template
|
||||
$element = $(core.qweb.render('website.theme_customize_modal_option', _.extend({
|
||||
$element = $(core.qweb.render('website.theme_customize_menu_option', _.extend({
|
||||
alone: alone,
|
||||
name: xmlid === undefined && widgetName !== 'auto' ? _.uniqueId('option-') : optionsName,
|
||||
id: $item.attr('id') || _.uniqueId('o_theme_customize_input_id_'),
|
||||
@@ -380,7 +305,7 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
break;
|
||||
|
||||
case 'LIST':
|
||||
$element = $('<div/>', {class: 'py-1 px-2 o_theme_customize_option_list'});
|
||||
$element = $('<div/>', {class: 'py-1 o_theme_customize_option_list'});
|
||||
_processItems($item.children(), $element, false);
|
||||
break;
|
||||
|
||||
@@ -418,6 +343,21 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
})));
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
$element = $item.clone();
|
||||
$element.on('click', (ev) => {
|
||||
ev.preventDefault();
|
||||
Dialog.confirm(self, _t("Switching theme cannot be done directly from edit mode, click ok to save your current changes and go to the theme selection page."), {
|
||||
confirm_callback: () => self.trigger_up('request_save', {
|
||||
reload: false,
|
||||
onSuccess: function () {
|
||||
window.location.href = ev.target.href;
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
_processItems($item.children(), $container, false);
|
||||
return;
|
||||
@@ -425,7 +365,7 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
|
||||
if ($container.hasClass('form-row')) {
|
||||
var $col = $('<div/>', {
|
||||
class: _.str.sprintf('col-%s', $item.data('col') || 6),
|
||||
class: _.str.sprintf('col-%s', $item.data('col') || 12),
|
||||
});
|
||||
|
||||
if (item.tagName === 'LIST') {
|
||||
@@ -620,6 +560,42 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
qEdit.appendTo($inputData.closest('.o_theme_customize_option'));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Hides primary/secondary if they are equal to alpha/beta
|
||||
* (this is the case with default values but not in some themes).
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_removeDuplicateColors: function () {
|
||||
var $primary = this.$el.find('.o_theme_customize_color[data-color="primary"]');
|
||||
var $alpha = this.$el.find('.o_theme_customize_color[data-color="alpha"]');
|
||||
var $secondary = this.$el.find('.o_theme_customize_color[data-color="secondary"]');
|
||||
var $beta = this.$el.find('.o_theme_customize_color[data-color="beta"]');
|
||||
|
||||
var sameAlphaPrimary = $primary.css('background-color') === $alpha.css('background-color');
|
||||
var sameBetaSecondary = $secondary.css('background-color') === $beta.css('background-color');
|
||||
|
||||
if (!sameAlphaPrimary) {
|
||||
$alpha.prev().text(_t("Extra Color"));
|
||||
}
|
||||
if (!sameBetaSecondary) {
|
||||
$beta.prev().text(_t("Extra Color"));
|
||||
}
|
||||
|
||||
$primary = $primary.closest('.o_theme_customize_option');
|
||||
$alpha = $alpha.closest('.o_theme_customize_option');
|
||||
$secondary = $secondary.closest('.o_theme_customize_option');
|
||||
$beta = $beta.closest('.o_theme_customize_option');
|
||||
|
||||
$primary.toggleClass('d-none', sameAlphaPrimary);
|
||||
$secondary.toggleClass('d-none', sameBetaSecondary);
|
||||
|
||||
if (!sameAlphaPrimary && sameBetaSecondary) {
|
||||
$beta.insertBefore($alpha);
|
||||
} else if (sameAlphaPrimary && !sameBetaSecondary) {
|
||||
$secondary.insertAfter($alpha);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -711,17 +687,37 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
_updateStyle: function (enable, disable, reload) {
|
||||
var self = this;
|
||||
|
||||
var $loading = $('<i/>', {class: 'fa fa-refresh fa-spin'});
|
||||
this.$modal.find('.modal-title').append($loading);
|
||||
|
||||
if (reload || config.isDebug('assets')) {
|
||||
window.location.href = $.param.querystring('/website/theme_customize_reload', {
|
||||
href: window.location.href,
|
||||
enable: (enable || []).join(','),
|
||||
disable: (disable || []).join(','),
|
||||
tab: this.$('.nav-link.active').parent().index(),
|
||||
return new Promise(resolve => {
|
||||
const confirm = Dialog.confirm(self, _t("This change needs to reload the page, this will save all your changes and reload the page, are you sure you want to proceed?") +
|
||||
(config.isDebug('assets') ? _t(" It appears you are in debug=assets mode, all theme customization options require a page reload in this mode.") : ''), {
|
||||
confirm_callback: () => resolve(true),
|
||||
});
|
||||
confirm.on('closed', self, () => resolve(false));
|
||||
}).then(save => {
|
||||
if (!save) {
|
||||
if (this.$lastToggled.attr('type') === 'checkbox') {
|
||||
this.$lastToggled.prop('checked', !this.$lastToggled.prop('checked'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
self.trigger_up('request_save', {
|
||||
reload: false,
|
||||
onSuccess: () => {
|
||||
this._rpc({
|
||||
route: '/website/theme_customize',
|
||||
params: {
|
||||
'enable': enable,
|
||||
'disable': disable,
|
||||
'get_bundle': true,
|
||||
},
|
||||
}).then(() => {
|
||||
window.location.href = window.location.origin + window.location.pathname + '?enable_editor=1';
|
||||
});
|
||||
},
|
||||
});
|
||||
return new Promise(resolve => {});
|
||||
});
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return this._rpc({
|
||||
@@ -762,10 +758,8 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
return linksLoaded;
|
||||
});
|
||||
return Promise.all(defs).then(function () {
|
||||
$loading.remove();
|
||||
$allLinks.remove();
|
||||
}).guardedCatch(function () {
|
||||
$loading.remove();
|
||||
$allLinks.remove();
|
||||
});
|
||||
}).then(function () {
|
||||
@@ -838,6 +832,7 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onChange: function (ev) {
|
||||
this.$lastToggled = $(ev.target);
|
||||
var self = this;
|
||||
|
||||
// Checkout the option that changed
|
||||
@@ -957,43 +952,5 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
},
|
||||
});
|
||||
|
||||
var ThemeCustomizeMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
|
||||
actions: _.extend({}, websiteNavbarData.WebsiteNavbarActionWidget.prototype.actions || {}, {
|
||||
'customize_theme': '_openThemeCustomizeDialog',
|
||||
}),
|
||||
|
||||
/**
|
||||
* Automatically opens the theme customization dialog if the corresponding
|
||||
* hash is in the page URL.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
if ((window.location.hash || '').indexOf('theme=true') > 0) {
|
||||
var tab = window.location.hash.match(/tab=(\d+)/);
|
||||
this._openThemeCustomizeDialog(tab ? tab[1] : false);
|
||||
window.location.hash = '';
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Actions
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Instantiates and opens the theme customization dialog.
|
||||
*
|
||||
* @private
|
||||
* @param {string} tab
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_openThemeCustomizeDialog: function (tab) {
|
||||
return new ThemeCustomizeDialog(this, {tab: tab}).open();
|
||||
},
|
||||
});
|
||||
|
||||
websiteNavbarData.websiteNavbarRegistry.add(ThemeCustomizeMenu, '#theme_customize');
|
||||
|
||||
return ThemeCustomizeDialog;
|
||||
return ThemeCustomizationMenu;
|
||||
});
|
||||
|
||||
@@ -4,48 +4,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.modal.o_theme_customize_modal {
|
||||
.modal-dialog {
|
||||
@include o-position-absolute(0, 2%);
|
||||
width: 96%;
|
||||
max-width: 550px;
|
||||
}
|
||||
.modal-header {
|
||||
background-color: $o-brand-odoo;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
|
||||
* {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.close:hover, .close:focus {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav {
|
||||
padding: 0;
|
||||
|
||||
.nav-item {
|
||||
background-color: $o-brand-lightsecondary;
|
||||
|
||||
.nav-link {
|
||||
color: $o-main-text-color;
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
border: 1px solid #d9d7d7;
|
||||
border-left: 1px solid #333333;
|
||||
}
|
||||
&:hover, &:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_theme_customization_menu {
|
||||
.dropdown-menu {
|
||||
position: static !important;
|
||||
transform: none !important;
|
||||
@@ -73,7 +32,6 @@
|
||||
width: 100%;
|
||||
min-height: 24px;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
@@ -90,14 +48,9 @@
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
&:not(.dropdown-item) label {
|
||||
border: 2px solid transparent;
|
||||
background-color: $o-brand-lightsecondary;
|
||||
|
||||
&.checked {
|
||||
border-color: $o-brand-odoo;
|
||||
color: $o-brand-odoo;
|
||||
}
|
||||
&:not(.dropdown-item) label.checked {
|
||||
border: 2px solid $o-brand-odoo;
|
||||
color: $o-brand-odoo;
|
||||
}
|
||||
|
||||
&.o_theme_customize_with_widget {
|
||||
@@ -115,10 +68,9 @@
|
||||
|
||||
.o_theme_customize_color {
|
||||
position: relative;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin-left: auto;
|
||||
border: 1px solid black;
|
||||
|
||||
&::before, &::after {
|
||||
content: "";
|
||||
@@ -171,10 +123,6 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.o_theme_customize_option_list {
|
||||
box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.o_theme_customize_dropdown_btn {
|
||||
background-color: $o-brand-lightsecondary;
|
||||
}
|
||||
|
||||
@@ -28,15 +28,11 @@
|
||||
</label>
|
||||
</t>
|
||||
|
||||
<div t-name="website.theme_customize_modal_layout" class="d-flex align-items-start">
|
||||
<ul class="nav flex-column flex-shrink-0 w-25"/>
|
||||
<div class="tab-content pl-3 pb-2 flex-grow-1"/>
|
||||
</div>
|
||||
<div t-name="website.theme_customize_modal_content" t-att-id="id" class="tab-pane">
|
||||
<div t-name="website.theme_customize_section" t-att-id="id">
|
||||
<h5 class="mt-0"><t t-esc="title"/></h5>
|
||||
<div class="form-row justify-content-between o_options_container"/>
|
||||
</div>
|
||||
<t t-name="website.theme_customize_modal_option">
|
||||
<t t-name="website.theme_customize_menu_option">
|
||||
<div t-attf-class="o_theme_customize_option my-1 flex-grow-0 #{font ? 'o_theme_customize_option_font_' + font : ''} #{widget and widget != 'auto' ? 'o_theme_customize_with_widget' : ''}">
|
||||
<img t-if="icon" t-att-src="icon"/>
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/website.edit_mode.scss"/>
|
||||
|
||||
<script type="text/javascript" src="/website/static/src/js/editor/editor.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/js/editor/snippets.editor.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/js/editor/rte.summernote.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/js/editor/snippets.options.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/snippets/s_facebook_page/options.js"/>
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
|
||||
<!-- Snippets menu -->
|
||||
<template id="snippets" inherit_id="web_editor.snippets" primary="True">
|
||||
<xpath expr="//div[@id='snippets_menu']" position="inside">
|
||||
<button type="button" class="o_we_customize_theme_btn"
|
||||
data-title="Customize your theme">
|
||||
Theme
|
||||
</button>
|
||||
</xpath>
|
||||
<xpath expr="//t[@id='default_snippets']" position="replace">
|
||||
<t id="default_snippets">
|
||||
<div id="snippet_mega_menu" class="o_panel d-none">
|
||||
|
||||
@@ -412,6 +412,9 @@
|
||||
-> data-col (optional, default 6) = bootstrap column size for the option
|
||||
(ignored for options in a <list/>)
|
||||
|
||||
<a>: Declares a link, because this leaves the page, it will prompt the user
|
||||
to confirm that they're leaving.
|
||||
|
||||
Other elements will be ignored and their children will be processed as if
|
||||
that element was omitted, except that those children will be considered as
|
||||
in a new set of option. That allows to wrap an option in a fake element to
|
||||
@@ -422,8 +425,12 @@
|
||||
-->
|
||||
<template id="theme_customize">
|
||||
<div>
|
||||
<!-- Switch theme button -->
|
||||
<content id="theme_customize_content_switch_theme">
|
||||
<a class="btn btn-primary" href="/web#action=website_theme_install.theme_install_kanban_action">Switch theme</a>
|
||||
</content>
|
||||
<!-- Color options -->
|
||||
<content id="theme_customize_content_colors" string="Colors" title="Choose the theme colors">
|
||||
<content id="theme_customize_content_colors" string="Colors">
|
||||
<list string="Main">
|
||||
<opt data-widget="color" data-color-type="theme" data-color="primary" string="Primary"/>
|
||||
<opt data-widget="color" data-color-type="theme" data-color="secondary" string="Secondary"/>
|
||||
@@ -456,7 +463,7 @@
|
||||
</content>
|
||||
|
||||
<!-- Menu options -->
|
||||
<content id="theme_customize_content_navbar" string="Navbar" title="Choose your navbar">
|
||||
<content id="theme_customize_content_navbar" string="Navbar">
|
||||
<list string="Main Layout">
|
||||
<checkbox><opt data-xmlid="website.affix_top_menu" data-reload="/"/></checkbox>
|
||||
<checkbox><opt data-xmlid="portal.portal_show_sign_in" data-reload="/"/></checkbox>
|
||||
@@ -469,7 +476,7 @@
|
||||
</content>
|
||||
|
||||
<!-- Layout Options -->
|
||||
<content id="theme_customize_content_layout" string="Layout" title="Choose your layout">
|
||||
<content id="theme_customize_content_layout" string="Layout">
|
||||
<list string="Body">
|
||||
<opt string="Full" data-xmlid="" data-icon="/website/static/src/img/options/layout-full.png"/>
|
||||
<opt id="option_layout_boxed" string="Boxed" data-xmlid="website.option_layout_boxed_variables" data-icon="/website/static/src/img/options/layout-boxed.png"/>
|
||||
@@ -482,7 +489,7 @@
|
||||
</content>
|
||||
|
||||
<!-- Font options -->
|
||||
<content id="theme_customize_content_fonts" string="Fonts" title="Choose your fonts">
|
||||
<content id="theme_customize_content_fonts" string="Fonts">
|
||||
<list string="Title">
|
||||
<fontselection data-variable="headings-font-number"/>
|
||||
</list>
|
||||
|
||||
Reference in New Issue
Block a user