From d934b81aaae8d68b5579d1489b1fbe8ea347b4ed Mon Sep 17 00:00:00 2001 From: Antoine Guenet Date: Tue, 18 May 2021 10:02:56 +0000 Subject: [PATCH] [IMP] web_editor: move icon and image tools to snippet option Wherever there is a sidebar, this moves all icon and image options to their own section of it. This also enables previews. The "spin" option was deemed unnecessary and therefore removed. TODO: restore the link option for icons. It wasn't working properly before this and was removed until it is fixed so as not to do any unnecessary coding for a broken option. closes odoo/odoo#70952 Signed-off-by: David Monjoie (dmo) --- .../static/src/js/editor/snippets.editor.js | 4 +- .../static/src/js/editor/snippets.options.js | 197 ++++++++++++++++++ .../src/js/wysiwyg/widgets/alt_tools.js | 68 ------ .../static/src/js/wysiwyg/widgets/widgets.js | 2 - .../static/src/js/wysiwyg/wysiwyg.js | 27 +-- addons/web_editor/static/src/xml/wysiwyg.xml | 28 --- addons/web_editor/views/snippets.xml | 70 ++++++- 7 files changed, 269 insertions(+), 127 deletions(-) delete mode 100644 addons/web_editor/static/src/js/wysiwyg/widgets/alt_tools.js diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js index 4baf10f565b..44b10c38fc9 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -3010,7 +3010,9 @@ var SnippetsMenu = Widget.extend({ const range = selection && selection.rangeCount && selection.getRangeAt(0); if (!range || !$(range.commonAncestorContainer).parents('#wrapwrap, .iframe-editor-wrapper .o_editable').length || - $(range.commonAncestorContainer).parent('[data-oe-model]:not([data-oe-type="html"]):not([data-oe-field="arch"])').length + $(range.commonAncestorContainer).parent('[data-oe-model]:not([data-oe-type="html"]):not([data-oe-field="arch"])').length || + (e && $(e.target).closest('.fa, img').length || + this.options.wysiwyg.lastMediaClicked && $(this.options.wysiwyg.lastMediaClicked).is('.fa, img')) ) { $toolbarContainer.hide(); } else { diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js index 5eb0c759c01..373d95f02db 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -4154,6 +4154,203 @@ registry.ReplaceMedia = SnippetOptionWidget.extend({ } }); +/** + * General options that are common to a font awesome icon and an image. + */ +registry.StaticMediaTools = SnippetOptionWidget.extend({ + currentShapes: {}, + alignments: { + left: ['float-left'], + center: ['d-block', 'mx-auto'], + right: ['float-right'], + }, + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + toggleShapeRounded(previewMode) { + this._toggleShape(previewMode, 'rounded'); + }, + toggleShapeCircle(previewMode) { + this._toggleShape(previewMode, 'rounded-circle'); + }, + toggleShapeShadow(previewMode) { + this._toggleShape(previewMode, 'shadow'); + }, + toggleShapeThumbnail(previewMode) { + this._toggleShape(previewMode, 'img-thumbnail'); + }, + setPadding(previewMode, padding, params) { + if (previewMode === true) { + this.currentPadding = params.possibleValues.find(c => this.$target.hasClass(c)) || ''; + } + for (const value of params.possibleValues) { + if (previewMode === 'reset') { + this.$target.toggleClass(value, value === this.currentPadding); + } else { + this.$target.toggleClass(value, value === padding) + } + } + if (previewMode === false) { + this.currentPadding = padding; + } + }, + align(previewMode, alignment, params) { + if (previewMode === true) { + this.currentAlignment = this._getAlignment(); + } + const targetAlignment = previewMode === 'reset' ? this.currentAlignment : alignment; + for (const value of params.possibleValues) { + this.$target.toggleClass(this.alignments[value] || '', value === targetAlignment); + } + if (previewMode === false) { + this.currentAlignment = alignment; + } + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + */ + _computeWidgetState(methodName, params) { + if (['toggleShapeRounded', 'toggleShapeCircle', 'toggleShapeShadow', 'toggleShapeThumbnail'].includes(methodName)) { + return params.possibleValues.find(c => this.$target.hasClass(c)) || ''; + } else if (methodName === 'setPadding') { + return params.possibleValues.find(c => this.$target.hasClass(c)) || ''; + } else if (methodName === 'align') { + return this._getAlignment(); + } + return this._super(...arguments); + }, + _getAlignment() { + for (const [alignment, [alignClass]] of Object.entries(this.alignments)) { + if (this.$target.hasClass(alignClass)) { + return alignment; + } + } + return ''; + }, + _toggleShape(previewMode, shape) { + if (previewMode === true) { + this.currentShapes[shape] = this.$target.hasClass(shape); + this.$target.toggleClass(shape, true); + } else if (previewMode === 'reset') { + this.$target.toggleClass(shape, this.currentShapes[shape]); + } else if (previewMode === false) { + this.$target.toggleClass(shape, !this.currentShapes[shape]); + this.currentShapes[shape] = this.$target.hasClass(shape); + } + }, +}); + +/** + * General options of a font awesome icon. + */ +registry.FontawesomeTools = SnippetOptionWidget.extend({ + setSize(previewMode, size, params) { + if (previewMode === true) { + this.currentSize = params.possibleValues.find(c => this.$target.hasClass(c)) || ''; + } + for (const value of params.possibleValues) { + if (previewMode === 'reset') { + this.$target.toggleClass(value, value === this.currentSize); + } else { + this.$target.toggleClass(value, value === size) + } + } + if (previewMode === false) { + this.currentSize = size; + } + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + */ + _computeWidgetState(methodName, params) { + if (methodName === 'setSize') { + return params.possibleValues.find(c => this.$target.hasClass(c)) || ''; + } else if (methodName === 'align') { + return this._getAlignment(); + } + return this._super(...arguments); + }, +}); + +/** + * General options of an image. + */ +registry.ImageTools = SnippetOptionWidget.extend({ + setWidth(previewMode, width, params) { + if (previewMode === true) { + this.currentWidth = this.$target.css('width'); + } + if (previewMode === 'reset') { + this.$target.css('width', this.currentWidth); + } else { + this.$target.css('width', width); + } + if (previewMode === false) { + this.currentWidth = width; + } + }, + setAlt(previewMode, alt) { + this.$target.attr('alt', alt); + }, + setTitle(previewMode, title) { + this.$target.attr('title', title); + }, + crop() { + new weWidgets.ImageCropWidget(this, this.$target[0]).appendTo(this.options.wysiwyg.$editable); + }, + transform() { + if (this.$target.data('transfo-destroy')) { + this.$target.removeData('transfo-destroy'); + return; + } + const document = this.$target[0].ownerDocument + this.$target.transfo({ document }); + const mousedown = mousedownEvent => { + if (!$(mousedownEvent.target).closest('.transfo-container').length) { + this.$target.transfo('destroy'); + $(document).off('mousedown', mousedown); + } + if ($(mousedownEvent.target).closest('#image-transform').length) { + this.$target + .data('transfo-destroy', true) + .attr('style', (this.$target.attr('style') || '') + .replace(/[^;]*transform[\w:]*;?/g, '')); + } + this.$target.trigger('content_changed'); + }; + $(document).on('mousedown', mousedown); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + */ + _computeWidgetState(methodName, params) { + if (methodName === 'setWidth') { + return this.$target[0].style.width || ''; + } else if (methodName === 'setAlt') { + return this.$target.attr('alt'); + } else if (methodName === 'setTitle') { + return this.$target.attr('title'); + } + return this._super(...arguments); + }, +}); + /* * Abstract option to be extended by the ImageOptimize and BackgroundOptimize * options that handles all the common parts. diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/alt_tools.js b/addons/web_editor/static/src/js/wysiwyg/widgets/alt_tools.js deleted file mode 100644 index ae63e1206f3..00000000000 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/alt_tools.js +++ /dev/null @@ -1,68 +0,0 @@ -odoo.define('wysiwyg.widgets.AltTools', function (require) { -'use strict'; - -var core = require('web.core'); -var Widget = require('web.Widget'); - -var _t = core._t; - -/** - * Let users change the alt & title of a media. - */ -const AltTools = Widget.extend({ - template: 'wysiwyg.widgets.altTools', - xmlDependencies: ['/web_editor/static/src/xml/wysiwyg.xml'], - - /** - * @constructor - */ - init: function (parent, options, media, $button) { - options = options || {}; - this._super(parent, _.extend({}, { - title: _t("Change media description and tooltip") - }, options)); - - this.$button = $button; - this.media = media; - const allEscQuots = /"/g; - this.alt = ($(this.media).attr('alt') || "").replace(allEscQuots, '"'); - const title = $(this.media).attr('title') || $(this.media).data('original-title') || ""; - this.tag_title = (title).replace(allEscQuots, '"'); - }, - /** - * @override - */ - start: async function () { - const def = await this._super.apply(this, arguments); - this.$button.addClass('active'); - this.$el.find('#alt').on('input', this._onChange.bind(this)); - this.$el.find('#title').on('input', this._onChange.bind(this)); - return def; - }, - /** - * @override - */ - destroy: function () { - this.$button.removeClass('active'); - this._super(...arguments); - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - _onChange: function (ev) { - const attributeName = ev.target.id; - const $target = $(ev.target); - const $media = $(this.media); - const allNonEscQuots = /"/g; - const value = $target.val(); - $media.attr(attributeName, value ? value.replace(allNonEscQuots, """) : null); - $media.trigger('content_changed'); - this.final_data = this.media; - }, -}); - - -return AltTools; -}); diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/widgets.js b/addons/web_editor/static/src/js/wysiwyg/widgets/widgets.js index 5da9d35ad87..e70fe9ec9fb 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/widgets.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/widgets.js @@ -3,7 +3,6 @@ odoo.define('wysiwyg.widgets', function (require) { var Dialog = require('wysiwyg.widgets.Dialog'); var AltDialog = require('wysiwyg.widgets.AltDialog'); -var AltTools = require('wysiwyg.widgets.AltTools'); var MediaDialog = require('wysiwyg.widgets.MediaDialog'); var LinkDialog = require('wysiwyg.widgets.LinkDialog'); var LinkTools = require('wysiwyg.widgets.LinkTools'); @@ -16,7 +15,6 @@ var media = require('wysiwyg.widgets.media'); return { Dialog: Dialog, AltDialog: AltDialog, - AltTools: AltTools, MediaDialog: MediaDialog, LinkDialog: LinkDialog, LinkTools: LinkTools, diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index b240e146550..cab7d0abf85 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -523,28 +523,6 @@ const Wysiwyg = Widget.extend({ observerData.observer.disconnect(); } }, - /** - * Toggle the Alt tools in the toolbar to edit alt and title attributes. - * - * @param {object} params - * @param {Node} [params.node] - */ - toggleAltTools(params) { - const image = (params && params.node) || this.lastMediaClicked; - if (this.snippetsMenu) { - if (this.altTools) { - this.altTools.destroy(); - this.altTools = undefined; - } else { - const $btn = this.toolbar.$el.find('#media-description'); - this.altTools = new weWidgets.AltTools(this, params, image, $btn); - this.altTools.appendTo(this.toolbar.$el); - } - } else { - const altDialog = new weWidgets.AltDialog(this, params, image); - altDialog.open(); - } - }, /** * Toggle the Link tools/dialog to edit links. If a snippet menu is present, * use the link tools, otherwise use the dialog. @@ -686,7 +664,7 @@ const Wysiwyg = Widget.extend({ this.openMediaDialog(); break; case 'media-description': - this.toggleAltTools(); + new weWidgets.AltDialog(this, {}, this.lastMediaClicked).open(); break; } }; @@ -952,9 +930,6 @@ const Wysiwyg = Widget.extend({ const $target = e ? editorWindow.$(e.target) : editorWindow.$(); // Restore paragraph dropdown button's default ID. this.toolbar.$el.find('#mediaParagraphDropdownButton').attr('id', 'paragraphDropdownButton'); - // Remove the alt tools. - this.altTools && this.altTools.destroy(); - this.altTools = undefined; // Hide the create-link button if the selection spans several blocks. const selection = this.odooEditor.document.getSelection(); const range = selection.rangeCount && selection.getRangeAt(0); diff --git a/addons/web_editor/static/src/xml/wysiwyg.xml b/addons/web_editor/static/src/xml/wysiwyg.xml index 49090d179c3..8529c052e10 100644 --- a/addons/web_editor/static/src/xml/wysiwyg.xml +++ b/addons/web_editor/static/src/xml/wysiwyg.xml @@ -79,34 +79,6 @@ - - - - - - ⌙ Description - - -
- -
-
-
- - - ⌙ Tooltip - - -
- -
-
-
-
-
-