diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 7f60a976a35..bfd15d4b7c1 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -1673,4 +1673,139 @@ options.registry.anchorName = options.Class.extend({ this.$target.trigger('content_changed'); }, }); + +/** + * Allows edition of 'cover_properties' in website models which have such + * fields (blogs, posts, events, ...). + */ +options.registry.CoverProperties = options.Class.extend({ + /** + * @constructor + */ + init: function () { + this._super.apply(this, arguments); + + this.$image = this.$target.find('.o_record_cover_image'); + this.$filter = this.$target.find('.o_record_cover_filter'); + }, + /** + * @override + */ + start: function () { + this.$filterValueOpts = this.$el.find('[data-filter-value]'); + this.$filterColorOpts = this.$el.find('[data-filter-color]'); + this.filterColorClasses = this.$filterColorOpts.map(function () { + return $(this).data('filterColor'); + }).get().join(' '); + + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Options + //-------------------------------------------------------------------------- + + /** + * @see this.selectClass for parameters + */ + clear: function (previewMode, value, $opt) { + this.selectClass(previewMode, '', $()); + this.$image.css('background-image', ''); + }, + /** + * @see this.selectClass for parameters + */ + change: function (previewMode, value, $opt) { + var $image = $(''); + var background = this.$image.css('background-image'); + if (background && background !== 'none') { + $image.attr('src', background.match(/^url\(["']?(.+?)["']?\)$/)[1]); + } + + var editor = new weWidgets.MediaDialog(this, { + mediaWidth: 1920, + onlyImages: true, + firstFilters: ['background'] + }, $image[0]).open(); + editor.on('save', this, function (image) { + var src = image.src; + this.$image.css('background-image', src ? ('url(' + src + ')') : ''); + if (!this.$target.hasClass('o_record_has_cover')) { + var $opt = this.$el.find('.o_record_cover_opt_size_default[data-select-class]'); + this.selectClass(previewMode, $opt.data('selectClass'), $opt); + } + this._setActive(); + }); + }, + /** + * @see this.selectClass for parameters + */ + filterValue: function (previewMode, value, $opt) { + this.$filter.css('opacity', value); + }, + /** + * @see this.selectClass for parameters + */ + filterColor: function (previewMode, value, $opt) { + this.$filter.removeClass(this.filterColorClasses); + if (value) { + this.$filter.addClass(value); + } + + var $firstVisibleFilterOpt = this.$filterValueOpts.eq(1); + if (parseFloat(this.$filter.css('opacity')) < parseFloat($firstVisibleFilterOpt.data('filterValue'))) { + this.filterValue(previewMode, $firstVisibleFilterOpt.data('filterValue'), $firstVisibleFilterOpt); + } + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + * @override + */ + _setActive: function () { + this._super.apply(this, arguments); + + _.each(this.$el.children(), el => { + var $el = $(el); + + if (!$el.is('[data-change]')) { + $el.removeClass('d-none'); + + ['size', 'filters', 'text_size', 'text_align'].forEach(optName => { + var $opts = $el.find('[data-cover-opt="' + optName + '"]'); + var notAllowed = (this.$target.data('use_' + optName) !== 'True'); + + if ($opts.length && (!this.$target.hasClass('o_record_has_cover') || notAllowed)) { + $el.addClass('d-none'); + } + }); + } + }); + + this.$el.find('[data-clear]').toggleClass('d-none', !this.$target.hasClass('o_record_has_cover')); + + this.$filterValueOpts.removeClass('active'); + this.$filterColorOpts.removeClass('active'); + + var activeFilterValue = this.$filterValueOpts + .filter(el => { + return (parseFloat($(el).data('filterValue')).toFixed(1) === parseFloat(this.$filter.css('opacity')).toFixed(1)); + }).addClass('active').data('filterValue'); + + var activeFilterColor = this.$filterColorOpts + .filter(el => { + return this.$filter.hasClass($(el).data('filterColor')); + }).addClass('active').data('filterColor'); + + this.$target[0].dataset.coverClass = this.$el.find('.active[data-cover-opt="size"]').data('selectClass') || ''; + this.$target[0].dataset.textSizeClass = this.$el.find('.active[data-cover-opt="text_size"]').data('selectClass') || ''; + this.$target[0].dataset.textAlignClass = this.$el.find('.active[data-cover-opt="text_align"]').data('selectClass') || ''; + this.$target[0].dataset.filterValue = activeFilterValue || 0.0; + this.$target[0].dataset.filterColor = activeFilterColor || ''; + }, +}); }); diff --git a/addons/website/static/src/js/editor/wysiwyg_multizone.js b/addons/website/static/src/js/editor/wysiwyg_multizone.js index 8c7fbfb2e0c..3c34033b933 100644 --- a/addons/website/static/src/js/editor/wysiwyg_multizone.js +++ b/addons/website/static/src/js/editor/wysiwyg_multizone.js @@ -112,6 +112,49 @@ var WysiwygMultizone = Wysiwyg.extend({ _getEditableArea: function () { return $(':o_editable'); }, + /** + * @private + * @param {HTMLElement} editable + */ + _saveCoverProperties: function (editable) { + var el = editable.closest('.o_record_cover_container'); + if (!el) { + return; + } + + var resModel = el.dataset.resModel; + var resID = parseInt(el.dataset.resId); + if (!resModel || !resID) { + throw new Error('There should be a model and id associated to the cover'); + } + + this.__savedCovers = this.__savedCovers || {}; + this.__savedCovers[resModel] = this.__savedCovers[resModel] || []; + + if (this.__savedCovers[resModel].includes(resID)) { + return; + } + this.__savedCovers[resModel].push(resID); + + var cssBgImage = $(el.querySelector('.o_record_cover_image')).css('background-image'); + var coverProps = { + 'background-image': cssBgImage.replace(/"/g, '').replace(window.location.protocol + "//" + window.location.host, ''), + 'background-color': el.dataset.filterColor, + 'opacity': el.dataset.filterValue, + 'resize_class': el.dataset.coverClass, + 'text_size_class': el.dataset.textSizeClass, + 'text_align_class': el.dataset.textAlignClass, + }; + + return this._rpc({ + model: resModel, + method: 'write', + args: [ + resID, + {'cover_properties': JSON.stringify(coverProps)} + ], + }); + }, /** * Saves one (dirty) element of the page. * @@ -127,6 +170,7 @@ var WysiwygMultizone = Wysiwyg.extend({ var $el = $(editable); + // Saving a view content var viewID = $el.data('oe-id'); if (viewID) { promises.push(this._rpc({ @@ -141,6 +185,7 @@ var WysiwygMultizone = Wysiwyg.extend({ })); } + // Saving mega menu options 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 @@ -160,6 +205,12 @@ var WysiwygMultizone = Wysiwyg.extend({ })); } + // Saving cover properties on related model if any + var prom = this._saveCoverProperties(editable); + if (prom) { + promises.push(prom); + } + return Promise.all(promises); }, /** diff --git a/addons/website/static/src/scss/website.scss b/addons/website/static/src/scss/website.scss index 79f516fed64..2db0bdeacd2 100644 --- a/addons/website/static/src/scss/website.scss +++ b/addons/website/static/src/scss/website.scss @@ -1222,3 +1222,16 @@ table.table_desc tr td { .modal-footer > .float-left { margin-right: auto; } + +// CoverProperties +.o_record_cover_container { + position: relative; + + .o_record_cover_component { + @include o-position-absolute(0, 0, 0, 0); + + background-size: cover; + background-position: center; + background-repeat: no-repeat; + } +} diff --git a/addons/website/views/snippets.xml b/addons/website/views/snippets.xml index 5d6059c2c35..167f3084b5d 100644 --- a/addons/website/views/snippets.xml +++ b/addons/website/views/snippets.xml @@ -1466,5 +1466,66 @@
+ +
+ Change Cover + Remove Cover + + Size + + + Full Screen + + + Half Screen + + + Fit text + + + + + Filter Intensity + + None + Low + Medium + High + + + + Filter Color + + Black + White + Primary + Secondary + Blue + Yellow + Red + Purple + Green + + + + Text Size + + Hero + Huge + Big + Regular + Small + Tiny + + + + Text Alignment + + Left + Centered + Right + + +
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 41455c649a0..b38a850405c 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -434,6 +434,21 @@ + + diff --git a/addons/website_blog/views/website_blog_components.xml b/addons/website_blog/views/website_blog_components.xml index 689cbd1ed43..f67a86bf440 100644 --- a/addons/website_blog/views/website_blog_components.xml +++ b/addons/website_blog/views/website_blog_components.xml @@ -43,22 +43,6 @@ - - -