diff options
Diffstat (limited to 'addons/website/static/src')
19 files changed, 591 insertions, 704 deletions
diff --git a/addons/website/static/src/img/snippets_thumbs/s_mega_menu_menu_image_menu.png b/addons/website/static/src/img/snippets_thumbs/s_mega_menu_menu_image_menu.png Binary files differnew file mode 100755 index 00000000000..47a0c3a0d0a --- /dev/null +++ b/addons/website/static/src/img/snippets_thumbs/s_mega_menu_menu_image_menu.png diff --git a/addons/website/static/src/img/snippets_thumbs/s_mega_menu_multi_menus.png b/addons/website/static/src/img/snippets_thumbs/s_mega_menu_multi_menus.png Binary files differnew file mode 100755 index 00000000000..28832219719 --- /dev/null +++ b/addons/website/static/src/img/snippets_thumbs/s_mega_menu_multi_menus.png diff --git a/addons/website/static/src/js/backend/dashboard.js b/addons/website/static/src/js/backend/dashboard.js index dda40102904..28b9a55c8a4 100644 --- a/addons/website/static/src/js/backend/dashboard.js +++ b/addons/website/static/src/js/backend/dashboard.js @@ -185,7 +185,7 @@ var Dashboard = AbstractAction.extend({ }; }); - var ctx = document.getElementById(chart_id); + var ctx = this.$canvas[0]; this.chart = new Chart(ctx, { type: 'line', data: { diff --git a/addons/website/static/src/js/content/menu.js b/addons/website/static/src/js/content/menu.js index 9d3d5621f65..1b6fa07a5c0 100644 --- a/addons/website/static/src/js/content/menu.js +++ b/addons/website/static/src/js/content/menu.js @@ -19,6 +19,7 @@ publicWidget.registry.affixMenu = publicWidget.Widget.extend({ this.$headerClone.insertAfter(this.$target); this.$headers = this.$target.add(this.$headerClone); this.$dropdowns = this.$headers.find('.dropdown'); + this.$dropdownMenus = this.$headers.find('.dropdown-menu'); this.$navbarCollapses = this.$headers.find('.navbar-collapse'); this._adaptDefaultOffset(); @@ -100,7 +101,7 @@ publicWidget.registry.affixMenu = publicWidget.Widget.extend({ this.$headerClone.toggleClass('affixed', wOffset > (hOffset + 300)); // Reset opened menus - this.$dropdowns.removeClass('show'); + this.$dropdowns.add(this.$dropdownMenus).removeClass('show'); this.$navbarCollapses.removeClass('show').attr('aria-expanded', false); }, }); diff --git a/addons/website/static/src/js/content/website_root.js b/addons/website/static/src/js/content/website_root.js index 4b61a33d779..a8e208f1408 100644 --- a/addons/website/static/src/js/content/website_root.js +++ b/addons/website/static/src/js/content/website_root.js @@ -105,7 +105,7 @@ var WebsiteRoot = publicRootData.PublicRoot.extend({ var $target = $(ev.target); // retrieve the hash before the redirect var redirect = { - lang: $target.data('lang'), + lang: $target.data('url_code'), url: encodeURIComponent($target.attr('href').replace(/[&?]edit_translations[^&?]+/, '')), hash: encodeURIComponent(window.location.hash) }; diff --git a/addons/website/static/src/js/editor/editor_menu.js b/addons/website/static/src/js/editor/editor_menu.js index 72c2e6bee81..87422efdb1f 100644 --- a/addons/website/static/src/js/editor/editor_menu.js +++ b/addons/website/static/src/js/editor/editor_menu.js @@ -113,7 +113,7 @@ var EditorMenu = Widget.extend({ save: function (reload) { var self = this; this.trigger_up('edition_will_stopped'); - return this.wysiwyg.save(true).then(function (result) { + return this.wysiwyg.save(false).then(function (result) { var $wrapwrap = $('#wrapwrap'); self.editable($wrapwrap).removeClass('o_editable'); if (result.isDirty && reload !== false) { diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index d659677c478..baa1d8c5a7c 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -1297,35 +1297,51 @@ options.registry.gallery = options.Class.extend({ * @override */ _setActive: function () { - this._super(); - var classes = _.uniq((this.$target.attr('class').replace(/(^|\s)o_/g, ' ') || '').split(/\s+/)); - this.$el.find('[data-mode]') - .removeClass('active') - .filter('[data-mode="' + classes.join('"], [data-mode="') + '"]').addClass('active'); - var mode = this.$el.find('[data-mode].active').data('mode'); + this._super(...arguments); - classes = _.uniq((this.$('img:first').attr('class') || '').split(/\s+/)); - this.$el.find('[data-styling]') + var activeModeSelectors = []; + for (const className of this.$target[0].classList) { + if (className.startsWith('o_')) { + activeModeSelectors.push('[data-mode="' + className.substring(2) + '"]'); + } + } + var activeMode = this.$el.find('[data-mode]') .removeClass('active') - .filter('[data-styling="' + classes.join('"], [data-styling="') + '"]').addClass('active'); - - this.$el.find('[data-interval]').removeClass('active') - .filter('[data-interval='+this.$target.find('.carousel:first').attr('data-interval')+']') + .filter(activeModeSelectors.join(', ')) + .addClass('active') + .data('mode'); + + var carousel = this.$target[0].querySelector('.carousel'); + var activeInterval = carousel ? carousel.dataset.interval : undefined; + var $intervalOptions = this.$el.find('[data-interval]'); + $intervalOptions.removeClass('active') + .filter('[data-interval="' + activeInterval + '"]') .addClass('active'); - - var interval = this.$target.find('.carousel:first').attr('data-interval'); - this.$el.find('[data-interval]') - .removeClass('active') - .filter('[data-interval=' + interval + ']').addClass('active'); + $intervalOptions.closest('we-collapse-area')[0] + .classList.toggle('d-none', activeMode !== 'slideshow'); var columns = this._getColumns(); - this.$el.find('[data-columns]') - .removeClass('active') - .filter('[data-columns=' + columns + ']').addClass('active'); - - this.$el.find('[data-columns]:first, [data-select-class="spc-none"]') - .parent().parent().toggle(['grid', 'masonry'].indexOf(mode) !== -1); - this.$el.find('[data-interval]:first').parent().parent().toggle(mode === 'slideshow'); + var $columnOptions = this.$el.find('[data-columns]'); + $columnOptions.removeClass('active') + .filter('[data-columns="' + columns + '"]') + .addClass('active'); + $columnOptions.closest('we-collapse-area')[0] + .classList.toggle('d-none', !(activeMode === 'grid' || activeMode === 'masonry')); + + this.el.querySelector('.o_w_image_spacing_option') + .classList.toggle('d-none', activeMode === 'slideshow'); + + var $stylingOptions = this.$el.find('[data-styling]'); + $stylingOptions.removeClass('active'); + var img = this.$target[0].querySelector('img'); + if (img) { + var activeStyleSelectors = []; + for (const className of img.classList) { + activeStyleSelectors.push('[data-styling="' + className + '"]'); + } + $stylingOptions.filter(activeStyleSelectors.join(', ')) + .addClass('active'); + } }, }); @@ -1410,7 +1426,7 @@ options.registry.topMenuTransparency = options.Class.extend({ enabled = value; }, }); - this.$el.find('[data-transparent]').addBack('[data-transparent]').toggleClass('active', !!enabled); + this.$el.find('[data-transparent]').toggleClass('active', !!enabled); }, }); @@ -1465,7 +1481,6 @@ options.registry.topMenuColor = options.registry.colorpicker.extend({ */ options.registry.anchorName = options.Class.extend({ xmlDependencies: ['/website/static/src/xml/website.editor.xml'], - preventChildPropagation: true, //-------------------------------------------------------------------------- // Public @@ -1493,6 +1508,13 @@ options.registry.anchorName = options.Class.extend({ click: function () { var $input = this.$('.o_input_anchor_name'); var anchorName = $input.val().trim().replace(/\s/g, '_'); + if (self.$target[0].id === anchorName) { + // If the chosen anchor name is already the one used by the + // element, close the dialog and do nothing else + this.close(); + return; + } + var isValid = /^[\w-]+$/.test(anchorName); var alreadyExists = isValid && $('#' + anchorName).length > 0; var anchorOK = isValid && !alreadyExists; @@ -1520,7 +1542,7 @@ options.registry.anchorName = options.Class.extend({ }); } new Dialog(this, { - title: _t("Anchor Name"), + title: _t("Link Anchor"), $content: $(qweb.render('website.dialog.anchorName', { currentAnchor: this.$target.attr('id'), })), diff --git a/addons/website/static/src/js/editor/wysiwyg_multizone.js b/addons/website/static/src/js/editor/wysiwyg_multizone.js index 202257857d2..9ed31d3afe5 100644 --- a/addons/website/static/src/js/editor/wysiwyg_multizone.js +++ b/addons/website/static/src/js/editor/wysiwyg_multizone.js @@ -1,7 +1,38 @@ odoo.define('web_editor.wysiwyg.multizone', function (require) { 'use strict'; + var Wysiwyg = require('web_editor.wysiwyg'); +var snippetsEditor = require('web_editor.snippet.editor'); +/** + * Show/hide the dropdowns associated to the given toggles and allows to wait + * for when it is fully shown/hidden. + * + * Note: this also takes care of the fact the 'toggle' method of bootstrap does + * not properly work in all cases. + * + * @param {jQuery} $toggles + * @param {boolean} [show] + * @returns {Promise<jQuery>} + */ +function toggleDropdown($toggles, show) { + return Promise.all(_.map($toggles, toggle => { + var $toggle = $(toggle); + var $dropdown = $toggle.parent(); + var shown = $dropdown.hasClass('show'); + if (shown === show) { + return; + } + var toShow = !shown; + return new Promise(resolve => { + $dropdown.one( + toShow ? 'shown.bs.dropdown' : 'hidden.bs.dropdown', + () => resolve() + ); + $toggle.dropdown(toShow ? 'show' : 'hide'); + }); + })).then(() => $toggles); +} /** * HtmlEditor @@ -13,7 +44,6 @@ var Wysiwyg = require('web_editor.wysiwyg'); * */ var WysiwygMultizone = Wysiwyg.extend({ - /** * @override */ @@ -24,7 +54,35 @@ var WysiwygMultizone = Wysiwyg.extend({ var outerHTML = this._getEscapedElement($el).prop('outerHTML'); return self._saveElement(outerHTML, self.options.recordInfo, $el[0]); }; - return this._super(); + + // Mega menu initialization: handle dropdown openings by hand + var $megaMenuToggles = this.$('.o_mega_menu_toggle'); + $megaMenuToggles.removeAttr('data-toggle').dropdown('dispose'); + $megaMenuToggles.on('click.wysiwyg_multizone', ev => { + var $toggle = $(ev.currentTarget); + + // Each time we toggle a dropdown, we will destroy the dropdown + // behavior afterwards to keep manual control of it + var dispose = ($els => $els.dropdown('dispose')); + + // First hide all other mega menus + toggleDropdown($megaMenuToggles.not($toggle), false).then(dispose); + + // Then toggle the clicked one + toggleDropdown($toggle) + .then(dispose) + .then($el => { + var isShown = $el.parent().hasClass('show'); + this.editor.snippetsMenu.toggleMegaMenuSnippets(isShown); + }); + }); + + return this._super.apply(this, arguments).then(() => { + // Showing Mega Menu snippets if one dropdown is already opened + if (this.$('.o_mega_menu').hasClass('show')) { + this.editor.snippetsMenu.toggleMegaMenuSnippets(true); + } + }); }, /** * @override @@ -32,20 +90,26 @@ var WysiwygMultizone = Wysiwyg.extend({ */ save: function () { if (this.isDirty()) { - return this.editor.save().then(function() { - return {isDirty: true}; - }); + return this._restoreMegaMenus() + .then(() => this.editor.save(false)) + .then(() => ({isDirty: true})); } else { return {isDirty: false}; } }, - + /** + * @override + */ + destroy: function () { + this._restoreMegaMenus(); + this._super.apply(this, arguments); + }, //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- - _getEditableArea: function() { + _getEditableArea: function () { return $(':o_editable'); }, /** @@ -59,8 +123,9 @@ var WysiwygMultizone = Wysiwyg.extend({ * page element) */ _saveElement: function (outerHTML, recordInfo, editable) { + var promises = []; var $el = $(editable); - return this._rpc({ + promises.push(this._rpc({ model: 'ir.ui.view', method: 'save', args: [ @@ -69,7 +134,66 @@ var WysiwygMultizone = Wysiwyg.extend({ $el.data('oe-xpath') || null, ], context: recordInfo.context, - }); + })); + if ($el.data('oe-field') === 'mega_menu_content') { + // On top of saving the mega menu content like any other field + // content, we must save the custom classes that were set on the + // menu itself. + // FIXME normally removing the 'show' class should not be necessary here + // TODO check that editor classes are removed here as well + var classes = _.without($el.attr('class').split(' '), 'dropdown-menu', 'o_mega_menu', 'show'); + promises.push(this._rpc({ + model: 'website.menu', + method: 'write', + args: [ + [parseInt($el.data('oe-id'))], + { + 'mega_menu_classes': classes.join(' '), + }, + ], + })); + } + return Promise.all(promises); + }, + /** + * Restores mega menu behaviors and closes them (important to do before + * saving otherwise they would be saved opened). + * + * @private + * @returns {Promise} + */ + _restoreMegaMenus: function () { + var $megaMenuToggles = this.$('.o_mega_menu_toggle'); + $megaMenuToggles.off('.wysiwyg_multizone') + .attr('data-toggle', 'dropdown') + .dropdown({}); + return toggleDropdown($megaMenuToggles, false); + }, +}); + +snippetsEditor.Class.include({ + /** + * @private + * @param {boolean} show + */ + toggleMegaMenuSnippets: function (show) { + setTimeout(() => this._activateSnippet(false)); + this.$('#snippet_mega_menu').toggleClass('d-none', !show); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + */ + _insertDropzone: function ($hook) { + var $hookParent = $hook.parent(); + var $dropzone = this._super(...arguments); + $dropzone.attr('data-editor-message', $hookParent.attr('data-editor-message')); + $dropzone.attr('data-editor-sub-message', $hookParent.attr('data-editor-sub-message')); + return $dropzone; }, }); diff --git a/addons/website/static/src/js/menu/content.js b/addons/website/static/src/js/menu/content.js index 9582e0f4778..c0daa93925f 100644 --- a/addons/website/static/src/js/menu/content.js +++ b/addons/website/static/src/js/menu/content.js @@ -369,14 +369,15 @@ var MenuEntryDialog = weWidgets.LinkDialog.extend({ * @constructor */ init: function (parent, options, data) { - data.text = data.name || ''; - data.isNewWindow = data.new_window; - this._super(parent, _.extend({ title: _t("Add a menu item"), }, options || {}), _.extend({ needLabel: true, + text: data.name || '', + isNewWindow: data.new_window, }, data || {})); + + this.menuType = data.menuType; }, /** * @override @@ -391,6 +392,13 @@ var MenuEntryDialog = weWidgets.LinkDialog.extend({ // Adapt URL label this.$('label[for="o_link_dialog_label_input"]').text(_t("Menu Label")); + // Auto add '#' URL and hide the input if for mega menu + if (this.menuType === 'mega') { + var $url = this.$('input[name="url"]'); + $url.val('#').trigger('change'); + $url.closest('.form-group').addClass('d-none'); + } + return this._super.apply(this, arguments); }, @@ -469,7 +477,6 @@ var EditMenuDialog = weWidgets.Dialog.extend({ */ willStart: function () { var defs = [this._super.apply(this, arguments)]; - var self = this; var context; this.trigger_up('context_get', { callback: function (ctx) { @@ -480,11 +487,11 @@ var EditMenuDialog = weWidgets.Dialog.extend({ model: 'website.menu', method: 'get_tree', args: [context.website_id, this.rootID], - }).then(function (menu) { - self.menu = menu; - self.root_menu_id = menu.id; - self.flat = self._flatenize(menu); - self.to_delete = []; + }).then(menu => { + this.menu = menu; + this.rootMenuID = menu.fields['id']; + this.flat = this._flatenize(menu); + this.toDelete = []; })); return Promise.all(defs); }, @@ -505,6 +512,10 @@ var EditMenuDialog = weWidgets.Dialog.extend({ tolerance: 'pointer', attribute: 'data-menu-id', expression: '()(.+)', // nestedSortable takes the second match of an expression (*sigh*) + isAllowed: (placeholder, placeholderParent, currentItem) => { + return !placeholderParent + || !currentItem[0].dataset.megaMenu && !placeholderParent[0].dataset.megaMenu; + }, }); return r; }, @@ -518,8 +529,7 @@ var EditMenuDialog = weWidgets.Dialog.extend({ */ save: function () { var _super = this._super.bind(this); - var self = this; - var new_menu = this.$('.oe_menu_editor').nestedSortable('toArray', {startDepthCount: 0}); + var newMenus = this.$('.oe_menu_editor').nestedSortable('toArray', {startDepthCount: 0}); var levels = []; var data = []; var context; @@ -529,20 +539,25 @@ var EditMenuDialog = weWidgets.Dialog.extend({ }, }); // Resequence, re-tree and remove useless data - new_menu.forEach(function (menu) { + newMenus.forEach(menu => { if (menu.id) { levels[menu.depth] = (levels[menu.depth] || 0) + 1; - var mobj = self.flat[menu.id]; - mobj.sequence = levels[menu.depth]; - mobj.parent_id = (menu.parent_id|0) || menu.parent_id || self.root_menu_id; - delete(mobj.children); - data.push(mobj); + var menuFields = this.flat[menu.id].fields; + menuFields['sequence'] = levels[menu.depth]; + menuFields['parent_id'] = menu['parent_id'] || this.rootMenuID; + data.push(menuFields); } }); - this._rpc({ + return this._rpc({ model: 'website.menu', method: 'save', - args: [context.website_id, { data: data, to_delete: self.to_delete }], + args: [ + context.website_id, + { + 'data': data, + 'to_delete': this.toDelete, + } + ], }).then(function () { return _super(); }); @@ -563,10 +578,9 @@ var EditMenuDialog = weWidgets.Dialog.extend({ */ _flatenize: function (node, _dict) { _dict = _dict || {}; - var self = this; - _dict[node.id] = node; - node.children.forEach(function (child) { - self._flatenize(child, _dict); + _dict[node.fields['id']] = node; + node.children.forEach(child => { + this._flatenize(child, _dict); }); return _dict; }, @@ -580,23 +594,31 @@ var EditMenuDialog = weWidgets.Dialog.extend({ * dialog to edit this new menu. * * @private + * @param {Event} ev */ - _onAddMenuButtonClick: function () { - var self = this; - var dialog = new MenuEntryDialog(this, {}, {}); - dialog.on('save', this, function (link) { - var new_menu = { - id: _.uniqueId('new-'), - name: link.text, - url: link.url, - new_window: link.isNewWindow, - parent_id: false, - sequence: 0, - children: [], + _onAddMenuButtonClick: function (ev) { + var menuType = ev.currentTarget.dataset.type; + var dialog = new MenuEntryDialog(this, {}, { + menuType: menuType, + }); + dialog.on('save', this, link => { + var newMenu = { + 'fields': { + 'id': _.uniqueId('new-'), + 'name': link.text, + 'url': link.url, + 'new_window': link.isNewWindow, + 'is_mega_menu': menuType === 'mega', + 'sequence': 0, + 'parent_id': false, + }, + 'children': [], + 'is_homepage': false, }; - self.flat[new_menu.id] = new_menu; - self.$('.oe_menu_editor').append( - qweb.render('website.contentMenu.dialog.submenu', { submenu: new_menu })); + this.flat[newMenu.fields['id']] = newMenu; + this.$('.oe_menu_editor').append( + qweb.render('website.contentMenu.dialog.submenu', {submenu: newMenu}) + ); }); dialog.open(); }, @@ -607,9 +629,9 @@ var EditMenuDialog = weWidgets.Dialog.extend({ */ _onDeleteMenuButtonClick: function (ev) { var $menu = $(ev.currentTarget).closest('[data-menu-id]'); - var menuID = $menu.data('menu-id')|0; + var menuID = parseInt($menu.data('menu-id')); if (menuID) { - this.to_delete.push(menuID); + this.toDelete.push(menuID); } $menu.remove(); }, @@ -620,21 +642,20 @@ var EditMenuDialog = weWidgets.Dialog.extend({ * @private */ _onEditMenuButtonClick: function (ev) { - var self = this; - var menu_id = $(ev.currentTarget).closest('[data-menu-id]').data('menu-id'); - var menu = self.flat[menu_id]; + var $menu = $(ev.currentTarget).closest('[data-menu-id]'); + var menuID = $menu.data('menu-id'); + var menu = this.flat[menuID]; if (menu) { - var dialog = new MenuEntryDialog(this, {}, menu); - dialog.on('save', this, function (link) { - var id = link.id; - var menu_obj = self.flat[id]; - _.extend(menu_obj, { + var dialog = new MenuEntryDialog(this, {}, _.extend({ + menuType: menu.fields['is_mega_menu'] ? 'mega' : undefined, + }, menu.fields)); + dialog.on('save', this, link => { + _.extend(menu.fields, { 'name': link.text, 'url': link.url, 'new_window': link.isNewWindow, }); - var $menu = self.$('[data-menu-id="' + id + '"]'); - $menu.find('.js_menu_label').first().text(menu_obj.name); + $menu.find('.js_menu_label').first().text(menu.fields['name']); }); dialog.open(); } else { diff --git a/addons/website/static/src/js/menu/seo.js b/addons/website/static/src/js/menu/seo.js index 3844a1d4731..60bc2318955 100644 --- a/addons/website/static/src/js/menu/seo.js +++ b/addons/website/static/src/js/menu/seo.js @@ -20,7 +20,7 @@ var Suggestion = Widget.extend({ template: 'website.seo_suggestion', xmlDependencies: ['/website/static/src/xml/website.seo.xml'], events: { - 'click .js_seo_suggestion': 'select', + 'click .o_seo_suggestion': 'select', }, init: function (parent, options) { @@ -106,7 +106,7 @@ var Keyword = Widget.extend({ }, start: function () { var self = this; - this.$('.js_seo_keyword_suggestion').empty(); + this.$('.o_seo_keyword_suggestion').empty(); this.suggestionList = new SuggestionList(this, { root: this.keyword, language: this.language, @@ -115,7 +115,7 @@ var Keyword = Widget.extend({ this.suggestionList.on('selected', this, function (word, language) { this.trigger('selected', word, language); }); - return this.suggestionList.appendTo(this.$('.js_seo_keyword_suggestion')).then(function() { + return this.suggestionList.appendTo(this.$('.o_seo_keyword_suggestion')).then(function() { self.htmlPage.on('title-changed', self, self._updateTitle); self.htmlPage.on('description-changed', self, self._updateDescription); self._updateTitle(); @@ -497,9 +497,7 @@ var MetaKeywords = Widget.extend({ }, }); this._rpc({ - model: 'website', - method: 'get_languages', - args: [[context.website_id]], + route: '/website/get_languages', }).then(function (data) { self.$('#language-box').html(core.qweb.render('Configurator.language_promote', { 'language': data, diff --git a/addons/website/static/src/js/menu/translate.js b/addons/website/static/src/js/menu/translate.js index 043a900fff6..cab37bf3473 100644 --- a/addons/website/static/src/js/menu/translate.js +++ b/addons/website/static/src/js/menu/translate.js @@ -46,14 +46,11 @@ var TranslatePageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({ * @returns {Promise} */ _goToMasterPage: function () { - var lang = '/' + utils.get_cookie('frontend_lang'); - var current = document.createElement('a'); current.href = window.location.toString(); current.search += (current.search ? '&' : '?') + 'enable_editor=1'; - if (current.pathname.indexOf(lang) === 0) { - current.pathname = current.pathname.replace(lang, ''); - } + // we are in translate mode, the pathname starts with '/<url_code/' + current.pathname = current.pathname.substr(current.pathname.indexOf('/', 1)); var link = document.createElement('a'); link.href = '/website/lang/default'; diff --git a/addons/website/static/src/js/tours/banner.js b/addons/website/static/src/js/tours/banner.js index 5febdf1c749..f4ddc040c69 100644 --- a/addons/website/static/src/js/tours/banner.js +++ b/addons/website/static/src/js/tours/banner.js @@ -24,10 +24,14 @@ tour.register("banner", { position: "bottom", run: "text", }, { - trigger: ".oe_overlay_options .oe_options", + trigger: ".o_we_customize_panel", extra_trigger: "#wrapwrap .s_cover h1:not(:containsExact(\"Catchy Headline\"))", content: _t("Customize any block through this menu. Try to change the background color of this block."), - position: "top", + position: "right", +}, { + trigger: '.o_we_add_snippet_btn', + content: _t("Go back to the blocks menu."), + position: 'bottom', }, { trigger: "#snippet_structure .oe_snippet:eq(3) .oe_snippet_thumbnail", content: _t("Drag another block in your page, below the cover."), @@ -35,7 +39,6 @@ tour.register("banner", { run: "drag_and_drop #wrap", }, { trigger: "button[data-action=save]", - extra_trigger: ".oe_overlay_options .oe_options", content: _t("Click the <b>Save</b> button."), position: "bottom", }, { @@ -69,7 +72,6 @@ tour.register("banner", { run: "drag_and_drop #wrap", }, { trigger: "button[data-action=save]", - extra_trigger: ".oe_overlay_options .oe_options", content: _t("Click the <b>Save</b> button."), position: "bottom", }, { diff --git a/addons/website/static/src/scss/website.edit_mode.scss b/addons/website/static/src/scss/website.edit_mode.scss index 17c3ee13bb3..5693f6e7526 100644 --- a/addons/website/static/src/scss/website.edit_mode.scss +++ b/addons/website/static/src/scss/website.edit_mode.scss @@ -1,223 +1,20 @@ +$-editor-messages-margin-x: 2%; +%o-editor-messages { + width: 100% - $-editor-messages-margin-x * 2; // Need to be forced here to avoid flickering + margin: 20px $-editor-messages-margin-x; + border: 2px dashed $o-we-color-text-normal; + padding: 112px 0px; + text-align: center; + color: $o-we-color-text-normal; -@each $url in $o-theme-font-urls { - @if $url { - @import url("https://fonts.googleapis.com/css?family=#{unquote($url)}"); + &:before { + content: attr(data-editor-message); + display: block; + font-size: 20px; } -} - -.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; - } - } - } - } - - .dropdown-menu { - position: static !important; - transform: none !important; - min-width: 100%; - } - - .o_theme_customize_option { - position: relative; - width: 100%; - - > img { - width: 100%; - - + label { - @include o-position-absolute(0, 0, 0, 0); - width: auto; - background: transparent !important; - } - } - - label { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - min-height: 24px; - margin: 0; - padding: 8px; - text-align: center; - font-size: 14px; - line-height: 1; - cursor: pointer; - - &:hover::after { - content: ""; - pointer-events: none; - @include o-position-absolute(0, 0, 0, 0); - background-color: rgba(0, 32, 64, 0.03); - } - - &.o_switch { - 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; - } - } - - &.o_theme_customize_with_widget { - label { - justify-content: flex-start; - text-align: left; - - &.checked { - border-color: transparent; - color: inherit; - } - } - } - } - - .o_theme_customize_color { - position: relative; - width: 30px; - height: 20px; - margin-left: auto; - border: 1px solid black; - - &::before, &::after { - content: ""; - @include o-position-absolute(0, 0, 0, 0); - } - &::before { - background-image: url('/web_editor/static/src/img/transparent.png'); - } - &::after { - background-color: inherit; - } - } - - .o_theme_customize_input { - flex: 1 1 auto; - text-align: right; - - .fa-edit { - visibility: hidden; - color: $o-brand-primary; - } - } - .o_theme_customize_option:hover .o_theme_customize_input .fa-edit { - visibility: visible; - } - - .o_theme_customize_active_input { - @include o-position-absolute(0, 0, 0, 0); - width: auto; - padding: 3px; - - > * { - height: 100% !important; - - &.form-control { - background: white !important; - } - - &.form-control, .btn { - padding: 2px 8px !important; - text-align: right !important; - font-size: $font-size-sm !important; - } - } - } - - .o_theme_customize_option_input { - position: absolute; - clip: rect(0, 0, 0, 0); - 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; - } - - $i: 1; - @each $font in $o-theme-fonts { - .o_theme_customize_option_font_#{$i} { - font-family: if($font, $font, $font-family-base); - - &.o_theme_customize_option > label > span, - &.dropdown-toggle { - &::before { - content: nth($o-theme-font-names, $i); - } - } - } - $i: $i + 1; - } - - .o_theme_customize_delete_google_font { - @include o-position-absolute(1px, 1px, 1px, auto); - padding: 0 8px !important; - } -} - - -.o_homepage_editor_welcome_message { - padding-top: 128px; - padding-bottom: 128px; - font-family: Roboto, $font-family-sans-serif; - - .o_tooltip_container { - transition: opacity 1s linear; - - > .o_tooltip { - @include o-position-absolute; - position: relative; - display: inline-block; - margin: 0 8px; - opacity: 1; - z-index: auto; - } + &:after { + content: attr(data-editor-sub-message); + display: block; } } @@ -249,19 +46,12 @@ &.oe_structure.oe_empty, &[data-oe-type=html] { &:empty { - border: 2px dashed gray('400'); - margin: 20px; - padding: 112px 0px; - text-align: center; - color: gray('400'); - &:before { - content: attr(data-editor-message); - font-size: 20px; - } - &:after { - display: block; - content: attr(data-editor-sub-message); - } + @extend %o-editor-messages; + } + > .oe_drop_zone.oe_insert:not(.oe_vertical):only-child { + @extend %o-editor-messages; + height: auto; + color: $o-brand-odoo; } > p:empty:only-child { color: #aaa; diff --git a/addons/website/static/src/scss/website.editor.ui.scss b/addons/website/static/src/scss/website.editor.ui.scss index 403b7929a92..5071e2f8b90 100644 --- a/addons/website/static/src/scss/website.editor.ui.scss +++ b/addons/website/static/src/scss/website.editor.ui.scss @@ -1,3 +1,224 @@ +@each $url in $o-theme-font-urls { + @if $url { + @import url("https://fonts.googleapis.com/css?family=#{unquote($url)}"); + } +} + +.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; + } + } + } + } + + .dropdown-menu { + position: static !important; + transform: none !important; + min-width: 100%; + } + + .o_theme_customize_option { + position: relative; + width: 100%; + + > img { + width: 100%; + + + label { + @include o-position-absolute(0, 0, 0, 0); + width: auto; + background: transparent !important; + } + } + + label { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + min-height: 24px; + margin: 0; + padding: 8px; + text-align: center; + font-size: 14px; + line-height: 1; + cursor: pointer; + + &:hover::after { + content: ""; + pointer-events: none; + @include o-position-absolute(0, 0, 0, 0); + background-color: rgba(0, 32, 64, 0.03); + } + + &.o_switch { + 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; + } + } + + &.o_theme_customize_with_widget { + label { + justify-content: flex-start; + text-align: left; + + &.checked { + border-color: transparent; + color: inherit; + } + } + } + } + + .o_theme_customize_color { + position: relative; + width: 30px; + height: 20px; + margin-left: auto; + border: 1px solid black; + + &::before, &::after { + content: ""; + @include o-position-absolute(0, 0, 0, 0); + } + &::before { + background-image: url('/web_editor/static/src/img/transparent.png'); + } + &::after { + background-color: inherit; + } + } + + .o_theme_customize_input { + flex: 1 1 auto; + text-align: right; + + .fa-edit { + visibility: hidden; + color: $o-brand-primary; + } + } + .o_theme_customize_option:hover .o_theme_customize_input .fa-edit { + visibility: visible; + } + + .o_theme_customize_active_input { + @include o-position-absolute(0, 0, 0, 0); + width: auto; + padding: 3px; + + > * { + height: 100% !important; + + &.form-control { + background: white !important; + } + + &.form-control, .btn { + padding: 2px 8px !important; + text-align: right !important; + font-size: $font-size-sm !important; + } + } + } + + .o_theme_customize_option_input { + position: absolute; + clip: rect(0, 0, 0, 0); + 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; + } + + $i: 1; + @each $font in $o-theme-fonts { + .o_theme_customize_option_font_#{$i} { + font-family: if($font, $font, $font-family-base); + + &.o_theme_customize_option > label > span, + &.dropdown-toggle { + &::before { + content: nth($o-theme-font-names, $i); + } + } + } + $i: $i + 1; + } + + .o_theme_customize_delete_google_font { + @include o-position-absolute(1px, 1px, 1px, auto); + padding: 0 8px !important; + } +} + +.o_homepage_editor_welcome_message { + padding-top: 128px; + padding-bottom: 128px; + font-family: Roboto, $font-family-sans-serif; + + .o_tooltip_container { + transition: opacity 1s linear; + + > .o_tooltip { + @include o-position-absolute; + position: relative; + display: inline-block; + margin: 0 8px; + opacity: 1; + z-index: auto; + } + } +} + // INPUTS .o_switch { display: flex; @@ -8,7 +229,7 @@ >input { display: none; - +span { + + span { background-color: $o-we-switch-inactive-color; box-shadow: inset 0 0 0px 1px darken($o-we-switch-inactive-color, 10%); border-radius: 100rem; @@ -20,7 +241,7 @@ &:after { content: ""; - background: $o-we-color-paper; + background: $o-we-bg-color; display: block; width: $o-we-switch-size - 0.2; height: $o-we-switch-size - 0.2; diff --git a/addons/website/static/src/scss/website.scss b/addons/website/static/src/scss/website.scss index cb919db80d4..b5ce0126afb 100644 --- a/addons/website/static/src/scss/website.scss +++ b/addons/website/static/src/scss/website.scss @@ -840,10 +840,15 @@ table.table_desc tr td { &.o_slideshow { .carousel { height: 100%; + .carousel-inner { height: 100%; } - .carousel-item { + .carousel-item.active, + .carousel-item-next, + .carousel-item-prev { + display: flex; + align-items: center; height: 100%; padding-bottom: 64px; } @@ -909,8 +914,14 @@ table.table_desc tr td { background-color: inherit; } } - &.s_parallax_is_fixed > .s_parallax_bg { - background-attachment: fixed; + @include media-breakpoint-up(xl) { + // Fixed backgrounds are disabled when using a mobile/tablet device, + // which is not a big deal but, on some of them (iOS...), defining the + // background as fixed breaks the background-size/position props. + // So we enable this only for >= XL devices. + &.s_parallax_is_fixed > .s_parallax_bg { + background-attachment: fixed; + } } } @@ -1089,6 +1100,34 @@ table.table_desc tr td { } } +// Mega menu +.o_mega_menu { + width: 100%; + padding: 0; + margin-top: 0; + + .container, .container-fluid { + // Need to reforce those because they are removed since its a container + // inside another container (the one in the navbar) + padding-left: $grid-gutter-width / 2; + padding-right: $grid-gutter-width / 2; + } +} +.o_mega_menu_container_size { + @include media-breakpoint-up(md) { + left: 50%; + transform: translateX(-50%); + } + + $-mm-max-widths: (); + @each $k, $v in $container-max-widths { + $-mm-max-widths: map-merge($-mm-max-widths, ( + #{$k}: $v - $grid-gutter-width, + )); + } + @include make-container-max-widths($-mm-max-widths); +} + // Copyright .o_footer_copyright { padding: 8px; diff --git a/addons/website/static/src/scss/website.ui.scss b/addons/website/static/src/scss/website.ui.scss index 0acd4c36cd0..e2f4cf7f3b6 100644 --- a/addons/website/static/src/scss/website.ui.scss +++ b/addons/website/static/src/scss/website.ui.scss @@ -284,6 +284,10 @@ body .modal { } } } + + td.o_seo_keyword_suggestion span.o_seo_suggestion.badge { + cursor: pointer; + } } } diff --git a/addons/website/static/src/scss/website.wysiwyg.scss b/addons/website/static/src/scss/website.wysiwyg.scss index 1f5151f5da8..3206e4b027a 100644 --- a/addons/website/static/src/scss/website.wysiwyg.scss +++ b/addons/website/static/src/scss/website.wysiwyg.scss @@ -1,48 +1,27 @@ -//------------------------------------------------------------------------------ -// Modifications applied on normal website DOM while being in the editor. -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -// Editor components style. -//------------------------------------------------------------------------------ - -body.editor_enable { - padding-top: $o-navbar-height !important; +// Override css variables to influence the default style of the editor without +// duplicating the css. +:root { + --o-we-toolbar-height: #{$o-navbar-height}; + --o-we-bg-color: #{$o-we-color-dark}; + --o-we-bg-color-dark: #{$o-we-color-darker}; + --o-we-color: #{$o-we-color-text-normal}; + --o-we-color-accent: #{$o-we-color-text-light}; + + --o-we-dropdown-bg-color: #{$o-we-color-darker}; + --o-we-dropdown-color: #{$o-we-color-text-normal}; + + --o-we-snippets-bg-color: #{$o-we-color-normal}; + --o-we-snippets-color: #{$o-we-color-text-light}; } -#wrapwrap { - height: calc(100vh - #{$o-navbar-height}); -} - -// TOP BAR (EDIT) +// EDITOR TOP BAR AND POPOVER #web_editor-top-edit { - height: $o-navbar-height; - background-color: $o-we-color-dark; - border: 0; - z-index: $zindex-modal - 9; - - .note-popover .popover { - width: 100%; - height: $o-navbar-height; - text-align: left; - - .popover-body { - height: $o-navbar-height; - - .btn { - height: $o-navbar-height; - } - } - } - form.navbar-form { + @include o-position-absolute(0, 0, 0, auto); + z-index: $zindex-popover + 5; height: $o-navbar-height; - z-index: 1060; margin: 0; padding: 0; - position: absolute; - top: -1px; - right: -1px; transition: right 0.4s $o-we-md-ease 0s; border-left: 1px solid $o-we-color-divider; @@ -96,19 +75,11 @@ body.editor_enable { } } -body:not(.editor_enable) form.navbar-form { +.note-statusbar { display: none; } -// SNIPPETS -#oe_snippets { - border: 0; - #snippets_menu { - height: $o-navbar-height; - } -} - -// Translations +// TRANSLATIONS .oe_translate_examples li { margin: 10px; padding: 4px; @@ -126,60 +97,10 @@ html[lang] > body.editor_enable [data-oe-translation-state] { } } -// NOTE EDITOR - -// SNIPPET PANEL -#oe_snippets { - @include o-w-preserve-btn; - position: fixed; - width: $o-we-sidebar-width; - z-index: 1042; - - border-top: 0; - border-right: 1px solid $o-we-color-divider; - transition: left 400ms $o-we-md-ease 0s; - background-image: linear-gradient(45deg, $o-we-color-normal, darken($o-we-color-normal, 10%)); - - #snippets_menu { - color: #999999; - background: $o-we-color-dark; - font-family: $o-we-font-family; - height: $o-navbar-height; - line-height: $o-navbar-height; - } - - #o_scroll { - .o_panel_header { - color: #999999; - } - } -} - -.oe_snippet { - background-color: $o-we-color-normal; - - .oe_snippet_thumbnail { - .oe_snippet_thumbnail_img { - border: 1px solid $o-we-color-normal; - } - - img.oe_snippet_thumbnail_img {} - - .oe_snippet_thumbnail_title { - border: 1px solid $o-we-color-dark; - color: $o-we-color-text-light; - } - - &:hover .oe_snippet_thumbnail_title { - color: $o-we-color-text-lighter; - } - } -} - // SNIPPET OPTIONS .colorpicker { .o_colorpicker_sections { - .note-color-palette>div { + .note-color-palette > div { color: $o-we-color-text-light; } } @@ -191,7 +112,7 @@ html[lang] > body.editor_enable [data-oe-translation-state] { clear: both; } - >button { + > button { &:hover, &.selected { @@ -223,173 +144,22 @@ html[lang] > body.editor_enable [data-oe-translation-state] { } } -// DROPZONES -#wrapwrap .oe_drop_zone { - &.oe_insert { - height: $o-we-dropzone-size; - margin: (-$o-we-dropzone-size/2) 0; - - &:after { - border-bottom: $o-we-dropzone-border; - } - - &.oe_vertical { - width: $o-we-dropzone-size; - margin: 0 (-$o-we-dropzone-size/2); - - &:after { - border-right: $o-we-dropzone-border; - } - } - } -} - -// MANIPULATORS -#oe_manipulators { - - // SNIPPET MANIPULATORS - .oe_overlay { - - // OVERLAY OPTIONS - >.oe_overlay_options { - font-family: $o-we-font-family; - - >.btn-group { - .btn { - height: $o-we-overlay-option-size; - border: 1px solid $o-we-color-dark; - line-height: #{$o-we-overlay-option-size - 2px}; - - color: $o-we-color-text-light; - background-color: $o-we-color-light; - - &:hover { - background-color: lighten($o-we-color-dark, 10%); - } - - &.oe_snippet_remove { - background-color: $o-we-color-danger; - border-color: darken($o-we-color-danger, 20%); - - &:hover { - background-color: darken($o-we-color-danger, 20%); - } - } - - >.fa { - color: $o-we-color-text-light; - } - } - - // CUSTOMIZE MENU BUTTON - >.oe_options { - .btn { - background-color: $o-we-color-dark; - color: $o-we-color-text-light; - - &:hover, - &:active, - &:focus { - background-color: lighten($o-we-color-dark, 5%); - border-color: lighten($o-we-color-dark, 10%); - } - - &:before, - &:after { - background-color: $o-we-color-text-light; - } - } - - // Open menu - &.show .btn { - // background-color: $o-we-color-light; - } - - // CUSTOMIZE MENU - .dropdown-menu { - border: 1px solid $o-we-color-dark; - background-color: $o-we-color-light; - - .dropdown-item { - color: $o-we-color-text-light; - - &:hover { - background-color: fade-out($o-we-color-dark, 0.5); - } - - &.active { - background-color: fade-out($o-we-color-dark, 0.5); - } - } - - .dropdown-header { - color: wheat; - - &.o_parent_editor_header { - color: wheat; - } - } - - .dropdown-submenu { - &::before { - border-left-color: $o-we-color-text-light; - } - } - } - } - } - } - - &.o_top_cover>.oe_overlay_options { - top: $o-we-handle-border-width; - right: $o-we-handle-border-width; - } - - } -} - -// Animations -@keyframes fadeInDownSmall { - 0% { - opacity: 0; - transform: translate(0, -5px); - } - - 100% { - opacity: 1; - transform: translate(0, 0); - } -} - +// ANIMATIONS @keyframes fadeInOut { 0% { opacity: 0; } - 25% { opacity: 1; } - 75% { opacity: 1; } - 100% { opacity: 0; } } -@keyframes inputHighlighter { - from { - background: $o-brand-primary; - } - - to { - width: 0; - background: transparent; - } -} - // MODALS body .modal { @@ -547,109 +317,3 @@ body .modal { } } } - -.note-editor { - &>.note-toolbar-wrapper .note-toolbar { - height: $o-navbar-height; - - .btn { - height: $o-navbar-height !important; // force this because of themes - } - } - - &>.note-statusbar { - display: none; - } - - &>.note-editing-area { - overflow: visible; - } -} - -#web_editor-toolbars .popover, -.note-popover, -.note-editor>.note-toolbar-wrapper .note-toolbar { - // force this because of themes - background-color: $o-we-color-dark !important; - - .btn { - background-color: $o-we-color-dark !important; - color: $o-we-color-text-normal !important; - border: none !important; - padding: 0.0625rem 0.3125rem !important; - - >.fa { - color: $o-we-color-text-normal !important; - } - - &:hover { - color: $o-we-color-text-light !important; - - >.fa { - color: $o-we-color-text-light !important; - } - } - - &.active { - background-color: $o-we-color-dark !important; - color: $o-we-color-text-light !important; - - >.fa { - color: $o-we-color-text-light !important; - } - } - } - - >.btn-group { - margin-top: 0 !important; - - &.show, - .btn-group.show { - .dropdown-toggle { - border-top: 2px solid white !important; - background-color: $o-we-color-darker !important; - color: white !important; - box-shadow: none !important; - - >.fa, - >span { - color: white !important; - } - } - } - } - - .dropdown-menu { - margin: 0 !important; - border-radius: 0 !important; - background-color: $o-we-color-darker !important; - color: $o-we-color-text-normal !important; - white-space: normal !important; - - .dropdown-item { - width: 100% !important; - color: $o-we-color-text-light !important; - - >.fa { - color: $o-we-color-text-light !important; - } - - &:hover { - background-color: $o-we-tab-active-bg !important; - color: white !important; - - >.fa { - color: white !important; - } - } - } - } - - .note-para .dropdown-menu { - min-width: 147px !important; - } - - .note-style .dropdown-item * { - color: $o-we-color-text-light !important; - } -} diff --git a/addons/website/static/src/xml/website.contentMenu.xml b/addons/website/static/src/xml/website.contentMenu.xml index edf166b946d..af318703b5c 100644 --- a/addons/website/static/src/xml/website.contentMenu.xml +++ b/addons/website/static/src/xml/website.contentMenu.xml @@ -1,15 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <templates id="template" xml:space="preserve"> <t t-name="website.contentMenu.dialog.submenu"> - <li t-att-data-menu-id="submenu.id"> + <li t-att-data-menu-id="submenu.fields['id']" t-att-data-mega-menu="submenu.fields['is_mega_menu'] ? true : undefined"> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text fa fa-bars" role="img" aria-label="Dropdown menu" title="Dropdown menu"/> </div> <span class="form-control d-flex align-items-center"> <span class="js_menu_label o_text_overflow flex-grow-1"> - <t t-esc="submenu.name"/> + <t t-esc="submenu.fields['name']"/> </span> + <span t-if="submenu.fields['is_mega_menu']" class="badge badge-primary">Mega Menu</span> <i t-if="submenu.is_homepage" class="fa fa-home ml-3" role="img" aria-label="Home" title="Home"/> </span> <span class="input-group-append"> @@ -49,6 +50,9 @@ </small> <a href="#" class="js_add_menu"> <i class="fa fa-plus-circle"/> Add Menu Item + </a><br/> + <a href="#" class="js_add_menu" data-type="mega"> + <i class="fa fa-plus-circle"/> Add Mega Menu Item </a> </div> </div> diff --git a/addons/website/static/src/xml/website.seo.xml b/addons/website/static/src/xml/website.seo.xml index e3c442d8f32..de1fc86fa23 100644 --- a/addons/website/static/src/xml/website.seo.xml +++ b/addons/website/static/src/xml/website.seo.xml @@ -2,7 +2,7 @@ <templates id="template" xml:space="preserve"> <t t-name="Configurator.language_promote"> <t t-foreach="language" t-as="lang"> - <option t-att-value="lang[0]" t-att-selected="lang[0] == def_lang ? 'selected' : null"><t t-esc="lang[1]" /></option> + <option t-att-value="lang[0]" t-att-selected="lang[0] == def_lang ? 'selected' : null"><t t-esc="lang[2]" /></option> </t> </t> @@ -32,14 +32,14 @@ <td class="text-center"><i class="js_seo_keyword_title fa fa-check" style="visibility: hidden;" t-attf-title="{{ widget.keyword }} is used in page title"/></td> <td class="text-center"><i class="js_seo_keyword_description fa fa-check" style="visibility: hidden;" t-attf-title="{{ widget.keyword }} is used in page description"/></td> <td class="text-center"><i t-if="widget.used_content" class="fa fa-check" t-attf-title="{{ widget.keyword }} is used in page content"/></td> - <td class="js_seo_keyword_suggestion"/> + <td class="o_seo_keyword_suggestion"/> <td class="text-center"><a href="#" class="oe_remove" data-action="remove-keyword" t-attf-title="Remove {{ widget.keyword }}"><i class="fa fa-trash"/></a></td> </tr> </t> <t t-name="website.seo_suggestion"> <li class="list-inline-item"> - <span class="js_seo_suggestion badge badge-info" t-att-data-keyword="widget.keyword" t-esc="widget.keyword"/> + <span class="o_seo_suggestion badge badge-info" t-att-data-keyword="widget.keyword" t-attf-title="Add {{ widget.keyword }}" t-esc="widget.keyword"/> </li> </t> |
