diff options
| author | Christophe Simonis <chs@odoo.com> | 2019-10-09 02:08:17 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2019-10-09 02:08:17 +0200 |
| commit | d74b4518052066446e2a1975a91ce53c745ca75a (patch) | |
| tree | c08180f88a512d15e37fbec628931f02b3825f65 /addons/web_editor/static/src | |
| parent | ec162dd0cb5622ab6e56db1a63dab5f531a96f4a (diff) | |
| parent | f4105eb9c7010f8693e5d2fd20c0bd9d9cc2e483 (diff) | |
[MERGE] forward port branch 13.0 up to f4105eb9c70
Diffstat (limited to 'addons/web_editor/static/src')
12 files changed, 217 insertions, 38 deletions
diff --git a/addons/web_editor/static/src/js/editor/rte.summernote.js b/addons/web_editor/static/src/js/editor/rte.summernote.js index 95ce86572ae..d8338fd622d 100644 --- a/addons/web_editor/static/src/js/editor/rte.summernote.js +++ b/addons/web_editor/static/src/js/editor/rte.summernote.js @@ -452,8 +452,11 @@ eventHandler.modules.linkDialog.showLinkDialog = function ($editable, $dialog, l $editable.data('range').select(); $editable.data('NoteHistory').recordUndo(); - var link = linkInfo.range.commonAncestor().closest('a'); - linkInfo.className = link && link.className; + var commonAncestor = linkInfo.range.commonAncestor(); + if (commonAncestor && commonAncestor.closest) { + var link = commonAncestor.closest('a'); + linkInfo.className = link && link.className; + } var def = new $.Deferred(); core.bus.trigger('link_dialog_demand', { 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 b94c7108122..775165354ea 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -77,14 +77,13 @@ var SnippetEditor = Widget.extend({ return $clone; }, start: this._onDragAndDropStart.bind(this), - stop: function () { + stop: (...args) => { // Delay our stop handler so that some summernote handlers // which occur on mouseup (and are themself delayed) are // executed first (this prevents the library to crash // because our stop handler may change the DOM). - var args = arguments; - setTimeout(function () { - self._onDragAndDropStop.apply(self, args); + setTimeout(() => { + this._onDragAndDropStop(...args); }, 0); }, }); @@ -355,7 +354,7 @@ var SnippetEditor = Widget.extend({ })).data('editor', this); $optionsSection.on('mouseover', this._onOptionsSectionMouseOver.bind(this)); $optionsSection.on('mouseleave', this._onOptionsSectionMouseLeave.bind(this)); - $optionsSection.on('click', this._onOptionsSectionClick.bind(this)); + $optionsSection.on('click', 'we-title > span', this._onOptionsSectionClick.bind(this)); $optionsSection.on('click', '.oe_snippet_clone', this._onCloneClick.bind(this)); $optionsSection.on('click', '.oe_snippet_remove', this._onRemoveClick.bind(this)); this._customize$Elements.push($optionsSection); diff --git a/addons/web_editor/static/src/js/editor/summernote.js b/addons/web_editor/static/src/js/editor/summernote.js index c2cf0d68d6c..4228d353d1a 100644 --- a/addons/web_editor/static/src/js/editor/summernote.js +++ b/addons/web_editor/static/src/js/editor/summernote.js @@ -3,6 +3,7 @@ odoo.define('web_editor.summernote', function (require) { var core = require('web.core'); require('summernote/summernote'); // wait that summernote is loaded +var weDefaultOptions = require('web_editor.wysiwyg.default_options'); var _t = core._t; @@ -1044,7 +1045,7 @@ options.keyMap.mac['ESCAPE'] = 'cancel'; options.keyMap.mac['UP'] = 'up'; options.keyMap.mac['DOWN'] = 'down'; -options.styleTags = ['p', 'pre', 'small', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote']; +options.styleTags = weDefaultOptions.styleTags; $.summernote.pluginEvents.insertTable = function (event, editor, layoutInfo, sDim) { var $editable = layoutInfo.editable(); @@ -2083,7 +2084,7 @@ eventHandler.modules.editor.currentStyle = function (target) { return styleInfo; }; -options.fontSizes = [_t('Default'), 8, 9, 10, 11, 12, 14, 18, 24, 36, 48, 62]; +options.fontSizes = weDefaultOptions.fontSizes; $.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color, bgcolor, size) { var r = range.create(); if (!r) return; @@ -2237,7 +2238,7 @@ $.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color // select nodes to clean (to remove empty font and merge same nodes) nodes = []; dom.walkPoint(startPoint, endPoint, function (point) { - nodes.push(point.node); + nodes.push(point.node.childNodes[point.offset] || point.node); }); nodes = list.unique(nodes); @@ -2256,10 +2257,8 @@ $.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color for (i=0; i<nodes.length; i++) { node = nodes[i]; - if ((dom.isText(node) || dom.isBR(node)) && !dom.isVisibleText(node)) { + if (dom.isText(node) && !node.nodeValue) { remove(node); - nodes.splice(i,1); - i--; continue; } @@ -2276,18 +2275,14 @@ $.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color if (!className && !style) { remove(node, node.parentNode); - nodes.splice(i,1); - i--; continue; } - if (i>0 && (font = dom.ancestor(nodes[i-1], dom.isFont))) { + if (font = dom.ancestor(node.previousSibling, dom.isFont)) { className2 = font.getAttribute('class'); style2 = font.getAttribute('style'); if (node !== font && className === className2 && style === style2) { remove(node, font); - nodes.splice(i,1); - i--; continue; } } @@ -2492,7 +2487,7 @@ function mouseDownChecklist (e) { $lis.addClass('o_checked'); } while ($lis.length); } -}; +} var fn_attach = eventHandler.attach; eventHandler.attach = function (oLayoutInfo, options) { diff --git a/addons/web_editor/static/src/js/wysiwyg/root.js b/addons/web_editor/static/src/js/wysiwyg/root.js index c2b3d703733..e5c225e646d 100644 --- a/addons/web_editor/static/src/js/wysiwyg/root.js +++ b/addons/web_editor/static/src/js/wysiwyg/root.js @@ -60,3 +60,25 @@ var WysiwygRoot = Widget.extend({ return WysiwygRoot; }); + +odoo.define('web_editor.wysiwyg.default_options', function (require) { +'use strict'; + +/** + * TODO this should be refactored to be done another way, same as the 'root' + * module that should be done another way. + * + * This allows to have access to default options that are used in the summernote + * editor so that they can be tweaked (instead of entirely replaced) when using + * the editor on an editable content. + */ + +var core = require('web.core'); + +var _lt = core._lt; + +return { + styleTags: ['p', 'pre', 'small', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote'], + fontSizes: [_lt('Default'), 8, 9, 10, 11, 12, 14, 18, 24, 36, 48, 62], +}; +}); diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/dialog.js b/addons/web_editor/static/src/js/wysiwyg/widgets/dialog.js index b46e43ab051..48828b68e0c 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/dialog.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/dialog.js @@ -1,6 +1,7 @@ odoo.define('wysiwyg.widgets.Dialog', function (require) { 'use strict'; +var config = require('web.config'); var core = require('web.core'); var Dialog = require('web.Dialog'); @@ -15,6 +16,9 @@ var SummernoteDialog = Dialog.extend({ */ init: function (parent, options) { this.options = options || {}; + if (config.device.isMobile) { + options.fullscreen = true; + } this._super(parent, _.extend({}, { buttons: [{ text: this.options.save_text || _t("Save"), @@ -36,10 +40,19 @@ var SummernoteDialog = Dialog.extend({ self.$el.closest('.modal').on('hidden.bs.modal', self.options.onClose); }); this.on('closed', this, function () { + self._toggleFullScreen(); this.trigger(this.destroyAction, this.final_data || null); }); }, - + /** + * Only use on config.device.isMobile, it's used by mass mailing to allow the dialog opening on fullscreen + * @private + */ + _toggleFullScreen: function() { + if (config.device.isMobile && !this.hasFullScreen) { + $('#iframe_target[isMobile="true"] #web_editor-top-edit .o_fullscreen').click(); + } + }, //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- @@ -52,6 +65,15 @@ var SummernoteDialog = Dialog.extend({ this.destroyAction = "save"; this.close(); }, + /** + * @override + * @returns {*} + */ + open: function() { + this.hasFullScreen = $(window.top.document.body).hasClass('o_field_widgetTextHtml_fullscreen'); + this._toggleFullScreen(); + return this._super.apply(this, arguments); + }, }); return SummernoteDialog; diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/link_dialog.js b/addons/web_editor/static/src/js/wysiwyg/widgets/link_dialog.js index 236725dcace..6e8ec03f1f8 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/link_dialog.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/link_dialog.js @@ -71,6 +71,7 @@ var LinkDialog = Dialog.extend({ if (this.data.url) { var match = /mailto:(.+)/.exec(this.data.url); this.$('input[name="url"]').val(match ? match[1] : this.data.url); + this._onURLInput(); } // Hide the duplicate color buttons (most of the times, primary = alpha @@ -184,6 +185,8 @@ var LinkDialog = Dialog.extend({ if (url.indexOf('@') >= 0 && url.indexOf('mailto:') < 0 && !url.match(/^http[s]?/i)) { url = ('mailto:' + url); + } else if (url.indexOf(location.origin) === 0 && this.$('#o_link_dialog_url_strip_domain').prop("checked")) { + url = url.slice(location.origin.length); } var allWhitespace = /\s+/gi; var allStartAndEndSpace = /^\s+|\s+$/gi; @@ -211,8 +214,10 @@ var LinkDialog = Dialog.extend({ _onURLInput: function () { var $linkUrlInput = this.$('#o_link_dialog_url_input'); $linkUrlInput.closest('.form-group').removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid'); - var isLink = $linkUrlInput.val().indexOf('@') < 0; + let value = $linkUrlInput.val(); + let isLink = value.indexOf('@') < 0; this.$('input[name="is_new_window"]').closest('.form-group').toggleClass('d-none', !isLink); + this.$('.o_strip_domain').toggleClass('d-none', value.indexOf(window.location.origin) !== 0); }, }); diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/media.js b/addons/web_editor/static/src/js/wysiwyg/widgets/media.js index c291a00a0c7..e3463e238bb 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/media.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/media.js @@ -261,7 +261,7 @@ var FileWidget = SearchableMediaWidget.extend({ * @override */ _clear: function () { - if (!this.$media.is('img')) { + if (this.$media.is('img')) { return; } var allImgClasses = /(^|\s+)((img(\s|$)|img-(?!circle|rounded|thumbnail))[^\s]*)/g; diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js index c0709a2c90e..6757797c82c 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js @@ -4,6 +4,7 @@ odoo.define('web_editor.wysiwyg.iframe', function (require) { var Wysiwyg = require('web_editor.wysiwyg'); var ajax = require('web.ajax'); var core = require('web.core'); +var config = require('web.config'); var qweb = core.qweb; var promiseCommon; @@ -87,6 +88,7 @@ Wysiwyg.include({ } delete window.top[self._onUpdateIframeId]; var $iframeTarget = self.$iframe.contents().find('#iframe_target'); + $iframeTarget.attr("isMobile", config.device.isMobile); $iframeTarget.find('.o_editable').html(self.$target.val()); self.options.toolbarHandler = $('#web_editor-top-edit', self.$iframe[0].contentWindow.document); $(qweb.render('web_editor.FieldTextHtml.fullscreen')) diff --git a/addons/web_editor/static/src/scss/web_editor.common.scss b/addons/web_editor/static/src/scss/web_editor.common.scss index 43f174e2862..ddc6efd50b6 100644 --- a/addons/web_editor/static/src/scss/web_editor.common.scss +++ b/addons/web_editor/static/src/scss/web_editor.common.scss @@ -81,7 +81,7 @@ ul.o_checklist { } } } -ul > li.o_indent { +ol > li.o_indent, ul > li.o_indent { margin-left: 0; list-style: none; &::before { @@ -401,3 +401,102 @@ a.o_underline { @extend %o-nocontent-empty-document; } } + +@include media-breakpoint-down(sm) { + odoo-wysiwyg-container { + .panel-heading.note-toolbar { + overflow-x: auto; + } + .btn-group { + position: static; + } + } + // modal select media + .o_technical_modal { + // see template 'web_editor.FieldTextHtml.fullscreen' + z-index: 2001; + + > .o_select_media_dialog { + max-width: inherit !important; + z-index: 2001; + + .modal-dialog, .model-content { + height: 100%; + } + + .modal-body { + .nav .nav-item.search { + width: 100%; + + .btn-group { + display: flex; + justify-content: space-around; + padding: 5px; + } + } + + // center pictogram + .font-icons-icons { + text-align: center; + } + + // fix search image + .form-control.o_we_search { + height: inherit; + } + + .form-inline { + .btn-group { + width: 100%; + + .btn.btn-primary:not(.dropdown-toggle) { + width: 90%; + } + } + + > .input-group.ml-2 { + margin-left: 0 !important; + + > .input-group-append { + width: 100%; + + > .btn { + width: 100%; + } + + > .ml-2 { + margin-left: 0 !important; + } + } + } + } + + // attachment cells + .o_we_existing_attachments > .row { + flex-direction: column; + + > .o_existing_attachment_cell { + flex: initial; + max-width: 100%; + + > .o_existing_attachment_remove { + opacity: inherit; + top: 10px; + } + } + } + + // select media dialog unsplash error + #editor-media-image .unsplash_img_container .unsplash_error .mx-auto { + width: 100%; + + .form-group { + input.w-100 { + min-width: 100px; + } + } + } + } + } + } +} diff --git a/addons/web_editor/static/src/scss/wysiwyg.scss b/addons/web_editor/static/src/scss/wysiwyg.scss index bfef4658081..db5db858727 100644 --- a/addons/web_editor/static/src/scss/wysiwyg.scss +++ b/addons/web_editor/static/src/scss/wysiwyg.scss @@ -176,10 +176,6 @@ $o-we-zindex: $o-we-overlay-zindex + 1 !default; min-width: 172px !important; } -.panel-heading.note-toolbar { - white-space: nowrap; -} - // ANIMATIONS @keyframes fadeInDownSmall { 0% { @@ -261,12 +257,12 @@ body .modal { box-shadow: 0px 0px 2px 2px $card-border-color; } } + } - &.o_we_attachment_selected { - &.o_we_attachment_highlight, .o_we_attachment_highlight { - border-color: $o-brand-primary; - box-shadow: 0px 0px 2px 2px $o-brand-primary; - } + .o_we_attachment_selected { + &.o_we_attachment_highlight, .o_we_attachment_highlight, &.font-icons-icon { + border-color: $o-brand-primary; + box-shadow: 0px 0px 2px 2px $o-brand-primary; } } @@ -279,12 +275,6 @@ body .modal { height: 50px; padding: 15px; cursor: pointer; - - &.o_selected { - cursor: auto; - background-color: $o-we-bg-color-dark; - box-shadow: 0px 0px 0px 1px $o-we-color-success; - } } } @@ -420,3 +410,22 @@ img.o_we_selected_image { img.o_we_custom_image.mx-auto { display: block; } + +@include media-breakpoint-down(md) { + #web_editor-top-edit { + position: initial !important; + height: initial !important; + top: initial !important; + left: initial !important; + + #web_editor-toolbars .popover-body { + display: flex; + width: 100%; + overflow-x: auto; + + .btn-group { + position: static; + } + } + } +} diff --git a/addons/web_editor/static/src/scss/wysiwyg_snippets.scss b/addons/web_editor/static/src/scss/wysiwyg_snippets.scss index d3f10ebd526..e7ceae4284f 100644 --- a/addons/web_editor/static/src/scss/wysiwyg_snippets.scss +++ b/addons/web_editor/static/src/scss/wysiwyg_snippets.scss @@ -18,6 +18,23 @@ body.editor_enable.editor_has_snippets { } } +// Mobile fix for mass mailing +@include media-breakpoint-down(md) { + body.editor_enable.editor_has_snippets { + padding-left: inherit !important; + + #web_editor-top-edit { + position: initial !important; + height: initial !important; + top: initial !important; + left: initial !important; + + .note-popover .popover { + left: 0 !important; + } + } + } +} // SNIPPET PANEL #oe_snippets { @include o-w-preserve-btn; diff --git a/addons/web_editor/static/src/xml/wysiwyg.xml b/addons/web_editor/static/src/xml/wysiwyg.xml index bcf3a480a93..f48f2474672 100644 --- a/addons/web_editor/static/src/xml/wysiwyg.xml +++ b/addons/web_editor/static/src/xml/wysiwyg.xml @@ -440,6 +440,12 @@ <label class="col-form-label col-md-3" for="o_link_dialog_url_input">URL or Email</label> <div class="col-md-9"> <input type="text" name="url" class="form-control" id="o_link_dialog_url_input" required="required"/> + <div class="form-check o_strip_domain d-none"> + <input type="checkbox" id="o_link_dialog_url_strip_domain" checked="checked" class="form-check-input"/> + <label for="o_link_dialog_url_strip_domain" class="form-check-label font-weight-normal"> + Autoconvert to relative link + </label> + </div> </div> </div> <div class="form-group row"> |
