[IMP] web_editor: lazy load the wysiwyg

Issue: wysiwyg asset slow down the loading of the website, error
inadvertently introduced: https://github.com/odoo/odoo/pull/29775

The assets are now loaded assynchroneously, when the editor is needed,
its assets will be loaded.

closes odoo/odoo#30700
This commit is contained in:
Christophe Matthieu
2019-02-14 15:11:19 +00:00
parent 7daa85dd12
commit b49745e52d
32 changed files with 961 additions and 808 deletions
@@ -12,6 +12,9 @@ var _t = core._t;
var MassMailingFieldHtml = FieldHtml.extend({
xmlDependencies: (FieldHtml.prototype.xmlDependencies || []).concat(["/mass_mailing/static/src/xml/mass_mailing.xml"]),
jsLibs: [
'/mass_mailing/static/src/js/mass_mailing_snippets.js',
],
custom_events: _.extend({}, FieldHtml.prototype.custom_events, {
snippets_loaded: '_onSnippetsLoaded',
@@ -305,7 +308,7 @@ var MassMailingFieldHtml = FieldHtml.extend({
this.$content.focusIn();
}
}
this.wysiwyg.snippets.trigger('reload_snippet_dropzones');
this.wysiwyg.trigger('reload_snippet_dropzones');
},
//--------------------------------------------------------------------------
@@ -442,7 +445,7 @@ var MassMailingFieldHtml = FieldHtml.extend({
selectedTheme = themeParams;
// Notify form view
self.wysiwyg._onChange();
self.wysiwyg.getEditable().trigger('change');
$dropdown.find('.dropdown-menu').removeClass('show');
$dropdown.find('.dropdown-item.selected').removeClass('selected');
$dropdown.find('.dropdown-item:eq(' + themesParams.indexOf(selectedTheme) + ')').addClass('selected');
@@ -46,7 +46,7 @@ QUnit.module('field html', {
}
if (xmlId === 'template.assets_all_style') {
return $.when({
cssLibs: $('head link[href]:not([type="image/x-icon"])').map(function () {
cssLibs: $('link[href]:not([type="image/x-icon"])').map(function () {
return $(this).attr('href');
}).get(),
cssContents: ['.field_body {background-color: red;}']
@@ -7,15 +7,17 @@
</template>
<template id="assets_mail_themes_edition"> <!-- maybe to remove and convert into a field dumy with attr invisible if the template is not selected -->
<t t-call="web._assets_helpers"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/webclient.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
<t t-call="web._assets_helpers">
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
</t>
<link rel="stylesheet" type="text/scss" href="/mass_mailing/static/src/scss/mass_mailing.ui.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/webclient.scss"/>
</template>
<template id="iframe_css_assets_edit">
<t t-call-assets="web.assets_common" t-js="false"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<t t-call-assets="web_editor.assets_wysiwyg" t-js="false"/>
<t t-call-assets="mass_mailing.assets_mail_themes" t-js="false"/>
<t t-call-assets="mass_mailing.assets_mail_themes_edition" t-js="false"/>
</template>
@@ -26,6 +28,14 @@
<template id="qunit_suite" inherit_id="web.qunit_suite">
<xpath expr="." position="inside">
<script type="text/javascript">
odoo.define('mass_mailing.FieldHtml.test', function (require) {
'use strict';
var MassMailingFieldHtml = require('mass_mailing.FieldHtml');
MassMailingFieldHtml.include({jsLibs: []});
});
</script>
<script type="text/javascript" src="/mass_mailing/static/src/js/mass_mailing_snippets.js"/>
<script type="text/javascript" src="/mass_mailing/static/tests/mass_mailing_html_tests.js"/>
</xpath>
</template>
@@ -7,7 +7,6 @@
<script type="text/javascript" src="/mass_mailing/static/src/js/mass_mailing.js"></script>
<script type="text/javascript" src="/mass_mailing/static/src/js/mass_mailing_widget.js"></script>
<script type="text/javascript" src="/mass_mailing/static/src/js/mass_mailing_snippets.js"></script>
</xpath>
<xpath expr="//script[last()]" position="after">
<script type="text/javascript" src="/mass_mailing/static/src/js/mass_mailing_campaign_kanban_record.js"></script>
+33 -4
View File
@@ -84,6 +84,32 @@ var Widget = core.Class.extend(mixins.PropertiesMixin, ServicesMixin, {
* @type {null|string[]}
*/
xmlDependencies: null,
/**
* List of paths to css files that need to be loaded before the widget can
* be rendered. This will not induce loading anything that has already been
* loaded.
*
* @type {null|string[]}
*/
cssLibs: null,
/**
* List of paths to js files that need to be loaded before the widget can
* be rendered. This will not induce loading anything that has already been
* loaded.
*
* @type {null|string[]}
*/
jsLibs: null,
/**
* List of xmlID that need to be loaded before the widget can be rendered.
* The content css (link file or style tag) and js (file or inline) of the
* assets are loaded.
* This will not induce loading anything that has already been
* loaded.
*
* @type {null|string[]}
*/
assetLibs: null,
/**
* Constructs the widget and sets its parent if a parent is given.
@@ -115,13 +141,16 @@ var Widget = core.Class.extend(mixins.PropertiesMixin, ServicesMixin, {
* @returns {Deferred}
*/
willStart: function () {
var defs = [];
if (this.xmlDependencies) {
var defs = _.map(this.xmlDependencies, function (xmlPath) {
defs.push.apply(defs, _.map(this.xmlDependencies, function (xmlPath) {
return ajax.loadXML(xmlPath, core.qweb);
});
return $.when.apply($, defs);
}));
}
return $.when();
if (this.jsLibs || this.cssLibs || this.assetLibs) {
defs.push(ajax.loadLibs(this));
}
return $.when.apply($, defs);
},
/**
* Method called after rendering. Mostly used to bind actions, perform
@@ -35,8 +35,6 @@ var field_utils = require('web.field_utils');
var Widget = require('web.Widget');
var AbstractField = Widget.extend({
cssLibs: [],
jsLibs: [],
events: {
'keydown': '_onKeydown',
},
@@ -182,14 +180,6 @@ var AbstractField = Widget.extend({
this.resetOnAnyFieldChange = true;
}
},
/**
* Loads the libraries listed in this.jsLibs and this.cssLibs
*
* @override
*/
willStart: function () {
return $.when(ajax.loadLibs(this), this._super.apply(this, arguments));
},
/**
* When a field widget is appended to the DOM, its start method is called,
* and will automatically call render. Most widgets should not override this.
@@ -1,7 +1,6 @@
odoo.define('web_editor.convertInline', function (require) {
'use strict';
var fonts = require('wysiwyg.fonts');
var FieldHtml = require('web_editor.field.html');
/**
@@ -189,6 +188,8 @@ function getMatchedCSSRules(a) {
* converted to images
*/
function fontToImg($editable) {
var fonts = odoo.__DEBUG__.services["wysiwyg.fonts"];
$editable.find('.fa').each(function () {
var $font = $(this);
var icon, content;
@@ -4,12 +4,12 @@ odoo.define('web_editor.field.html', function (require) {
var ajax = require('web.ajax');
var basic_fields = require('web.basic_fields');
var core = require('web.core');
var Wysiwyg = require('web_editor.wysiwyg');
var Wysiwyg = require('web_editor.wysiwyg.root');
var field_registry = require('web.field_registry');
var TranslatableFieldMixin = basic_fields.TranslatableFieldMixin;
var QWeb = core.qweb;
var assetsLoaded = false;
/**
* FieldHtml Widget
@@ -40,8 +40,23 @@ var FieldHtml = basic_fields.DebouncedField.extend(TranslatableFieldMixin, {
*/
willStart: function () {
this._onUpdateIframeId = 'onLoad_' + _.uniqueId('FieldHtml');
var defAsset = this.nodeOptions.cssReadonly && ajax.loadAsset(this.nodeOptions.cssReadonly);
return $.when(this._super().then(Wysiwyg.prepare.bind(Wysiwyg, this)), defAsset);
var defAsset = null;
if (this.nodeOptions.cssReadonly) {
defAsset = ajax.loadAsset(this.nodeOptions.cssReadonly);
}
if (!assetsLoaded) { // avoid flickering when begin to edit
assetsLoaded = $.Deferred();
var wysiwyg = new Wysiwyg(this, {});
wysiwyg.attachTo($('<textarea>')).then(function () {
wysiwyg.destroy();
var def = assetsLoaded;
assetsLoaded = true;
def.resolve();
});
}
return $.when(this._super(), assetsLoaded, defAsset);
},
/**
* @override
@@ -147,7 +162,7 @@ var FieldHtml = basic_fields.DebouncedField.extend(TranslatableFieldMixin, {
// by default this is synchronous because the assets are already loaded in willStart
// but it can be async in the case of options such as iframe, snippets...
return this.wysiwyg.attachTo(this.$target).then(function () {
self.$content = self.wysiwyg.$el;
self.$content = self.wysiwyg.$editor;
self._onLoadWysiwyg();
});
},
@@ -444,7 +459,7 @@ var FieldHtml = basic_fields.DebouncedField.extend(TranslatableFieldMixin, {
position: 'absolute',
right: '+5px',
});
var $toolbar = this.$content.closest('.note-editor').find('.note-toolbar');
var $toolbar = this.$content.find('.note-toolbar');
$toolbar.css('position', 'relative');
$toolbar.append($button);
},
@@ -191,7 +191,6 @@ var ViewEditor = Widget.extend({
willStart: function () {
return $.when(
this._super.apply(this, arguments),
ajax.loadLibs(this),
this._loadResources()
);
},
@@ -534,6 +534,11 @@ registry.addJob(function (wysiwyg) {
if ('web_editor.colorpicker' in QWeb.templates) {
return;
}
if (wysiwyg.isDestroyed()) {
throw new Error('The Wysiwyg are destroyed before this loading');
}
var options = {};
wysiwyg.trigger_up('getRecordInfo', {
recordInfo: options,
@@ -0,0 +1,62 @@
odoo.define('web_editor.wysiwyg.root', function (require) {
'use strict';
var Widget = require('web.Widget');
var assetsLoaded = false;
var WysiwygRoot = Widget.extend({
assetLibs: ['web_editor.compiled_assets_wysiwyg'],
publicMethods: ['isDirty', 'save', 'getValue', 'setValue', 'getEditable', 'on', 'trigger'],
/**
* @see 'web_editor.wysiwyg' module
**/
init: function (parent, params) {
this._super.apply(this, arguments);
this._params = params;
this.$editor = null;
},
/**
* Load assets
*
* @override
**/
willStart: function () {
var self = this;
var $target = this.$el;
this.$el = null;
return this._super().then(function () {
if (!assetsLoaded) {
var Wysiwyg = odoo.__DEBUG__.services['web_editor.wysiwyg'];
_.each(['getRange', 'setRange', 'setRangeFromNode'], function (methodName) {
WysiwygRoot[methodName] = Wysiwyg[methodName].bind(Wysiwyg);
});
assetsLoaded = true;
}
var Wysiwyg = self._getWysiwygContructor();
var instance = new Wysiwyg(self, self._params);
self._params = null;
_.each(self.publicMethods, function (methodName) {
self[methodName] = instance[methodName].bind(instance);
});
return instance.attachTo($target).then(function () {
self.$editor = instance.$el;
});
});
},
_getWysiwygContructor: function () {
return odoo.__DEBUG__.services['web_editor.wysiwyg'];
}
});
return WysiwygRoot;
});
@@ -19,7 +19,10 @@ var Wysiwyg = Widget.extend({
wysiwyg_blur: '_onWysiwygBlur',
},
defaultOptions: {
codeview: config.debug
codeview: config.debug,
recordInfo: {
context: {},
},
},
/**
@@ -693,41 +696,6 @@ var Wysiwyg = Widget.extend({
// Public helper
//--------------------------------------------------------------------------
/**
* Load wysiwyg assets if needed.
*
* @see Wysiwyg.createReadyFunction
* @param {Widget} parent
* @returns {$.Promise}
*/
Wysiwyg.prepare = (function () {
var assetsLoaded = false;
var def;
return function prepare(parent) {
if (assetsLoaded) {
return $.when();
}
if (def) {
return def;
}
def = $.Deferred();
var timeout = setTimeout(function () {
throw _t("Can't load assets of the wysiwyg editor");
}, 10000);
var wysiwyg = new Wysiwyg(parent, {
recordInfo: {
context: {},
}
});
wysiwyg.attachTo($('<textarea>')).then(function () {
assetsLoaded = true;
clearTimeout(timeout);
wysiwyg.destroy();
def.resolve();
});
return def;
};
})();
/**
* @param {Node} node (editable or node inside)
* @returns {Object}
@@ -3,7 +3,9 @@ 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 qweb = core.qweb;
var _fnSummernoteMaster = $.fn.summernote;
var _summernoteMaster = $.summernote;
@@ -165,48 +167,14 @@ Wysiwyg.include({
console.warn('Wysiwyg immediate iframe double load detected');
return;
}
var cwindow = this.$iframe[0].contentWindow;
cwindow.document
var iframeContent = qweb.render('wysiwyg.iframeContent', {
asset: asset,
updateIframeId: this._onUpdateIframeId,
avoidDoubleLoad: _avoidDoubleLoad
});
this.$iframe[0].contentWindow.document
.open("text/html", "replace")
.write(
'<head>' +
'<meta charset="utf-8">' +
'<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>\n' +
'<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>\n' +
_.map(asset.cssLibs, function (cssLib) {
return '<link type="text/css" rel="stylesheet" href="' + cssLib + '"/>';
}).join('\n') + '\n' +
_.map(asset.cssContents, function (cssContent) {
return '<style type="text/css">' + cssContent + '</style>';
}).join('\n') + '\n' +
_.map(asset.jsContents, function (jsContent) {
if (jsContent.indexOf('<inline asset>') !== -1) {
return '<script type="text/javascript">' + jsContent + '</script>';
}
}).join('\n') + '\n' +
'</head>\n' +
'<body class="o_in_iframe">\n' +
'<div id="iframe_target" style="height: calc(100vh - 6px);"></div>\n' +
'<script type="text/javascript">' +
'window.$ = window.jQuery = window.top.jQuery;' +
'var _summernoteMaster = $.summernote;' +
'var _fnSummernoteMaster = $.fn.summernote;' +
'delete $.summernote;' +
'delete $.fn.summernote;' +
'</script>\n' +
'<script type="text/javascript" src="/web_editor/static/lib/summernote/summernote.js"></script>\n' +
'<script type="text/javascript">' +
'window._summernoteSlave = $.summernote;' +
'window._summernoteSlave.iframe = true;' +
'window._summernoteSlave.lang = _summernoteMaster.lang;' +
'window._fnSummenoteSlave = $.fn.summernote;' +
'$.summernote = _summernoteMaster;' +
'$.fn.summernote = _fnSummernoteMaster;' +
'if (window.top.' + this._onUpdateIframeId + ') {' +
'window.top.' + this._onUpdateIframeId + '(' + _avoidDoubleLoad + ')' +
'}' +
'</script>\n' +
'</body>');
.write(iframeContent);
}.bind(this));
}.bind(this));
@@ -15,6 +15,7 @@ Wysiwyg.include({
snippet_cloned: '_onSnippetCloned',
snippet_dropped: '_onSnippetDropped',
snippet_focused: '_onSnippetFocused',
reload_snippet_dropzones: '_onReloadSnippetDropzones',
}),
selectorEditableArea: '.note-editable',
@@ -172,6 +173,14 @@ Wysiwyg.include({
var target = context.invoke('editor.restoreTarget', target);
context.invoke('MediaPlugin.hidePopovers');
},
/**
* trigger reload_snippet_dropzones on snippets
*
* @private
*/
_onReloadSnippetDropzones: function () {
this.snippets.trigger('reload_snippet_dropzones');
},
/**
* Triggered when a snippet is cloned in the editable area
*
@@ -258,4 +267,6 @@ $.fn.extend({
},
});
return Wysiwyg;
});
@@ -1,6 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<templates id="template" xml:space="preserve">
<!--=================-->
<!-- Edition Iframe -->
<!--=================-->
<t t-name="wysiwyg.iframeContent"><head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
<t t-foreach="asset.cssLibs || []" t-as="cssLib">
<link type="text/css" rel="stylesheet" t-att-href="cssLib"/>
</t>
<t t-foreach="asset.cssContents || []" t-as="cssContent">
<style type="text/css" t-raw="cssContent"/>
</t>
<t t-foreach="asset.jsContents || []" t-as="jsContent" t-if="jsContent.indexOf('inline asset') !== -1">
<script type="text/javascript" t-raw="jsContent"/>
</t>
</head>
<body class="o_in_iframe">
<div id="iframe_target" style="height: calc(100vh - 6px);"/>
<script type="text/javascript">
window.$ = window.jQuery = window.top.jQuery;
var _summernoteMaster = $.summernote;
var _fnSummernoteMaster = $.fn.summernote;
delete $.summernote;
delete $.fn.summernote;
</script>
<script type="text/javascript" src="/web_editor/static/lib/summernote/summernote.js"/>
<script type="text/javascript">
window._summernoteSlave = $.summernote;
window._summernoteSlave.iframe = true;
window._summernoteSlave.lang = _summernoteMaster.lang;
window._fnSummenoteSlave = $.fn.summernote;
$.summernote = _summernoteMaster;
$.fn.summernote = _fnSummernoteMaster;
if (window.top.<t t-esc="updateIframeId"/>) {
window.top.<t t-esc="updateIframeId"/>(<t t-esc="avoidDoubleLoad"/>);
}
</script>
</body>
</t>
<!--=================-->
<!-- Edition Dialogs -->
<!--=================-->
@@ -67,7 +67,7 @@ QUnit.module('field html', {
}
if (xmlId === 'template.assets_all_style') {
return $.when({
cssLibs: $('head link[href]:not([type="image/x-icon"])').map(function () {
cssLibs: $('link[href]:not([type="image/x-icon"])').map(function () {
return $(this).attr('href');
}).get(),
cssContents: ['body {background-color: red;}']
@@ -815,7 +815,7 @@ QUnit.test('field html translatable', function (assert) {
this.data['note.note'].fields.body.translate = true;
testUtils.createAsyncView({
return testUtils.createAsyncView({
View: FormView,
model: 'note.note',
data: this.data,
@@ -841,7 +841,6 @@ QUnit.test('field html translatable', function (assert) {
form.destroy();
_t.database.multi_lang = multiLang;
});
});
+1 -1
View File
@@ -101,7 +101,7 @@ function patch() {
}
if (xmlId === 'template.assets_all_style') {
return $.when({
cssLibs: $('head link[href]:not([type="image/x-icon"])').map(function () {
cssLibs: $('link[href]:not([type="image/x-icon"])').map(function () {
return $(this).attr('href');
}).get(),
cssContents: ['body {background-color: red;}']
+42 -26
View File
@@ -3039,8 +3039,10 @@ QUnit.test('CodeView', function (assert) {
var defMediaDialogInit;
var defMediaDialogSave;
var defMediaDialogClose;
var defCropDialogInit;
var defCropDialogSave;
var defCropDialogClose;
var defAltDialogInit;
var defAltDialogSave;
var imgWidth = 10;
@@ -3051,26 +3053,34 @@ QUnit.module('Media', {
testUtils.mock.patch(MediaDialog, {
init: function () {
this._super.apply(this, arguments);
this.uid = _.uniqueId();
defMediaDialogInit = $.Deferred();
defMediaDialogSave = $.Deferred();
defMediaDialogClose = $.Deferred();
this.opened(defMediaDialogInit.resolve.bind(defMediaDialogInit));
},
save: function () {
$.when(this._super.apply(this, arguments)).then(function () {
var def = defMediaDialogSave;
this.on('closed', this, function () {
var def = defMediaDialogClose;
defMediaDialogInit = null;
defMediaDialogSave = null;
defMediaDialogClose = null;
def.resolve();
});
},
save: function () {
var def = defMediaDialogSave;
$.when(this._super.apply(this, arguments))
.then(def.resolve.bind(def));
},
});
testUtils.mock.patch(CropDialog, {
init: function () {
$(arguments[2]).attr('src', $(arguments[2]).data('src'));
this._super.apply(this, arguments);
var self = this;
this.uid = _.uniqueId();
defCropDialogInit = $.Deferred();
defCropDialogSave = $.Deferred();
defCropDialogClose = $.Deferred();
this.opened(function () {
var cropper = self.$cropperImage.data('cropper');
cropper.clone();
@@ -3084,15 +3094,19 @@ QUnit.module('Media', {
cropper.render();
defCropDialogInit.resolve();
});
},
save: function () {
$.when(this._super.apply(this, arguments)).then(function () {
var def = defCropDialogSave;
this.on('closed', this, function () {
var def = defCropDialogClose;
defCropDialogInit = null;
defCropDialogSave = null;
defCropDialogClose = null;
def.resolve();
});
},
save: function () {
var def = defCropDialogSave;
$.when(this._super.apply(this, arguments))
.then(def.resolve.bind(def));
},
});
testUtils.mock.patch(AltDialog, {
init: function () {
@@ -3166,24 +3180,23 @@ QUnit.module('Media', {
var _clickMedia = function (wysiwyg, assert, callbackInit, test) {
wysiwyg.$('.note-insert .fa-file-image-o').mousedown().click();
defMediaDialogSave.then(function () {
if (test.check) {
test.check();
}
if (test.content) {
assert.deepEqual(wysiwyg.getValue(), test.content, testName);
}
if (test.start) {
var range = weTestUtils.select(test.start, test.end, $editable);
assert.deepEqual(Wysiwyg.getRange($editable[0]), range, testName + carretTestSuffix);
}
defMediaDialogInit.then(function () {
return callbackInit();
});
return defMediaDialogInit.then(function () {
callbackInit();
var def = $.Deferred();
setTimeout(function () {
def.resolve();
}, 0);
return $.when(defMediaDialogSave, defMediaDialogClose).then(function () {
var def = $.when();
if (test.check) {
def = $.when(test.check());
}
def.then(function () {
if (test.content) {
assert.deepEqual(wysiwyg.getValue(), test.content, testName);
}
if (test.start) {
var range = weTestUtils.select(test.start, test.end, $editable);
assert.deepEqual(Wysiwyg.getRange($editable[0]), range, testName + carretTestSuffix);
}
});
return def;
});
};
@@ -3494,6 +3507,7 @@ QUnit.test('Image crop', function (assert) {
$zoomBtn.mousedown().click();
$('.modal-dialog .modal-footer .btn.btn-primary:contains("Save")').mousedown().click();
});
return $.when(defCropDialogClose, defCropDialogSave);
},
},
},
@@ -3519,6 +3533,7 @@ QUnit.test('Image crop', function (assert) {
$('.o_crop_image_dialog .o_crop_options .btn:has(.fa-arrows-h)').mousedown().click();
$('.modal-dialog .modal-footer .btn.btn-primary:contains("Save")').mousedown().click();
});
return $.when(defCropDialogClose, defCropDialogSave);
},
},
},
@@ -3554,6 +3569,7 @@ QUnit.test('Image crop', function (assert) {
$pointW.trigger('pointerup');
$('.modal-dialog .modal-footer .btn.btn-primary:contains("Save")').mousedown().click();
});
return $.when(defCropDialogClose, defCropDialogSave);
},
},
},
@@ -3659,7 +3675,7 @@ QUnit.test('Pictogram (fontawesome)', function (assert) {
},
test: {
check: function () {
_clickMedia(wysiwyg, assert, function () {
return _clickMedia(wysiwyg, assert, function () {
_insertPictogram('fa-heart');
}, {
content: '<p>\u200B<span class="fa fa-heart"></span>\u200B</p>',
+25 -4
View File
@@ -6,7 +6,11 @@
<t t-call-assets="web.assets_backend" t-js="false"/>
</template>
<template id="wysiwyg" name="Wysiwyg Editor">
<template id="compiled_assets_wysiwyg" name="Wysiwyg Editor">
<t t-call-assets="web_editor.assets_wysiwyg"/>
</template>
<template id="assets_wysiwyg" name="Wysiwyg Editor Assets">
<!-- lib -->
<link rel="stylesheet" type="text/css" href="/web_editor/static/lib/summernote/summernote.css"/>
@@ -16,9 +20,15 @@
<script type="text/javascript" src="/web_editor/static/lib/cropper/js/cropper.js"/>
<script type="text/javascript" src="/web_editor/static/lib/jQuery.transfo.js"/>
<!-- odoo utils -->
<t t-call="web._assets_helpers">
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/bootstrap_overridden.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
</t>
<!-- integration -->
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_iframe.scss"/>
@@ -64,7 +74,7 @@
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/plugin/help_dialog.js"/>
</template>
<template id="wysiwyg_snippets" inherit_id="web_editor.wysiwyg" name="Wysiwyg Editor additional snippets">
<template id="wysiwyg_snippets" inherit_id="web_editor.assets_wysiwyg" name="Wysiwyg Editor additional snippets">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_snippets.scss"/>
@@ -93,7 +103,7 @@
<xpath expr="script[last()]" position="after">
<script type="text/javascript" src="/web_editor/static/lib/vkbeautify/vkbeautify.0.99.00.beta.js"/>
<script type="text/javascript" src="/web_editor/static/src/js/common/ace.js"/>
<t t-call="web_editor.wysiwyg"/>
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/root.js"/>
</xpath>
</template>
@@ -132,6 +142,17 @@
<template id="qunit_suite" inherit_id="web.qunit_suite">
<xpath expr="." position="inside">
<script type="text/javascript">
odoo.define('web_editor.wysiwyg.root.test', function (require) {
'use strict';
var WysiwygRoot = require('web_editor.wysiwyg.root');
WysiwygRoot.include({
assetLibs: null // We need to add the asset because tests performed overwrites (Dialog, Unbreakable...)
});
});
</script>
<t t-call="web_editor.compiled_assets_wysiwyg"/>
<script type="text/javascript" src="/web_editor/static/tests/test_utils.js"/>
<script type="text/javascript" src="/web_editor/static/tests/field_html_tests.js"/>
<script type="text/javascript" src="/web_editor/static/tests/wysiwyg_tests.js"/>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="web_unsplash_assets" inherit_id="web_editor.wysiwyg" name="Unsplash Images Editor Assets">
<template id="web_unsplash_assets" inherit_id="web_editor.assets_wysiwyg" name="Unsplash Images Editor Assets">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/web_unsplash/static/src/scss/unsplash.scss"/>
<script type="text/javascript" src="/web_unsplash/static/src/js/unsplashapi.js"></script>
@@ -4,10 +4,17 @@ odoo.define('website.editor.menu', function (require) {
var Dialog = require('web.Dialog');
var Widget = require('web.Widget');
var core = require('web.core');
var WysiwygMultizone = require('web_editor.wysiwyg.multizone');
var Wysiwyg = require('web_editor.wysiwyg.root');
var _t = core._t;
var WysiwygMultizone = Wysiwyg.extend({
assetLibs: Wysiwyg.prototype.assetLibs.concat(['website.compiled_assets_wysiwyg']),
_getWysiwygContructor: function () {
return odoo.__DEBUG__.services['web_editor.wysiwyg.multizone'];
}
});
var EditorMenu = Widget.extend({
template: 'website.editorbar',
xmlDependencies: ['/website/static/src/xml/website.editor.xml'],
@@ -5,7 +5,7 @@ require('web.dom_ready');
var core = require('web.core');
var Dialog = require('web.Dialog');
var localStorage = require('web.local_storage');
var WysiwygTranslate = require('web_editor.wysiwyg.multizone.translate');
var Wysiwyg = require('web_editor.wysiwyg.root');
var EditorMenu = require('website.editor.menu');
var _t = core._t;
@@ -46,6 +46,13 @@ var TranslatorInfoDialog = Dialog.extend({
},
});
var WysiwygTranslate = Wysiwyg.extend({
assetLibs: Wysiwyg.prototype.assetLibs.concat(['website.compiled_assets_wysiwyg']),
_getWysiwygContructor: function () {
return odoo.__DEBUG__.services['web_editor.wysiwyg.multizone.translate'];
}
});
var TranslatorMenu = EditorMenu.extend({
LOCATION_SEARCH: 'edit_translations',
@@ -6,7 +6,7 @@ var DropzonePlugin = require('web_editor.wysiwyg.plugin.dropzone');
var HelperPlugin = require('web_editor.wysiwyg.plugin.helper');
var TextPlugin = require('web_editor.wysiwyg.plugin.text');
var HistoryPlugin = require('web_editor.wysiwyg.plugin.history');
var Wysiwyg = require('web_editor.wysiwyg');
var Wysiwyg = require('web_editor.wysiwyg.snippets');
var _t = core._t;
@@ -70,8 +70,6 @@ DropzonePlugin.include({
/**
* HtmlEditor
* Intended to edit HTML content. This widget uses the Wysiwyg editor
@@ -412,7 +412,6 @@ var MenuEntryDialog = weWidgets.LinkDialog.extend({
}
return this._super.apply(this, arguments);
},
});
var SelectEditMenuDialog = weWidgets.Dialog.extend({
@@ -11,6 +11,8 @@ var _t = core._t;
* Adds the behavior when clicking on the 'edit' button (+ editor interaction)
*/
var EditPageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
assetLibs: ['web_editor.compiled_assets_wysiwyg', 'website.compiled_assets_wysiwyg'],
xmlDependencies: ['/website/static/src/xml/website.editor.xml'],
actions: _.extend({}, websiteNavbarData.WebsiteNavbarActionWidget.prototype.actions, {
edit: '_startEditMode',
@@ -6,6 +6,8 @@ var TranslatorMenu = require('website.editor.menu.translate');
var websiteNavbarData = require('website.navbar');
var TranslatePageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
assetLibs: ['web_editor.compiled_assets_wysiwyg', 'website.compiled_assets_wysiwyg'],
actions: _.extend({}, websiteNavbarData.WebsiteNavbar.prototype.actions || {}, {
edit_master: '_goToMasterPage',
translate: '_startTranslateMode',
+1 -1
View File
@@ -4,7 +4,7 @@ odoo.define('website.tour.rte', function (require) {
var ajax = require('web.ajax');
var session = require('web.session');
var tour = require('web_tour.tour');
var Wysiwyg = require('web_editor.wysiwyg');
var Wysiwyg = require('web_editor.wysiwyg.root');
var domReady = $.Deferred();
$(domReady.resolve.bind(domReady));
@@ -1,359 +1,3 @@
// TOP BAR (EDIT)
#web_editor-top-edit {
height: $o-navbar-height;
background-color: $o-we-color-dark;
z-index: $zindex-modal - 9;
position: fixed;
top: 0px;
right: 0px;
width: auto;
white-space: nowrap;
background-color: rgba(0, 0, 0, 0);
transition: background-color 400ms $o-we-md-ease 0s;
font-family: $o-we-font-family;
form.navbar-form {
height: $o-navbar-height;
z-index: 1060;
margin: 0;
padding: 0;
@include o-position-absolute($top: -1px, $right: -$o-we-sidebar-width);
transition: right 0.4s $o-we-md-ease 0s;
border-left: 1px solid $o-we-color-divider;
background-color: inherit;
.btn-group {
height: 100%;
}
.btn {
height: 100%;
margin: 0;
padding: 10px;
line-height: 1.2;
font-size: 13px;
font-family: $o-we-font-family;
transition: all 0.3s ease 0s;
border: none;
border-radius: 0;
.fa {
margin-right: $grid-gutter-width/4;
&.fa-times {
color: $o-we-color-danger;
}
}
&.btn-primary {
@include button-variant($o-brand-odoo, $o-brand-odoo);
}
&.btn-secondary {
@include button-variant($o-we-color-dark, $o-we-color-dark);
&:hover {
background: rgba(black, 0.5);
}
}
&:focus,
&:active,
&:focus:active {
outline: none;
}
}
.dropdown-menu {
left: auto;
right: 0;
}
}
}
// Translations
.oe_translate_examples li {
margin: 10px;
padding: 4px;
}
html[lang]>body.editor_enable [data-oe-translation-state] {
background: rgba($o-we-content-to-translate-color, 0.5) !important;
&[data-oe-translation-state="translated"] {
background: rgba($o-we-translated-content-color, 0.5) !important;
}
&.o_dirty {
background: rgba($o-we-translated-content-color, 0.25) !important;
}
}
// NOTE EDITOR
// SNIPPET PANEL
#oe_snippets {
@include o-w-preserve-btn;
@include o-position-absolute(0, auto, 0, -$o-we-sidebar-width);
width: $o-we-sidebar-width;
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 {
color: $o-we-color-text-light;
}
}
.o_colorpicker_section {
&:after {
content: "";
display: table;
clear: both;
}
>button {
&:hover,
&.selected {
box-shadow: 0px 0px 2px 2px $o-we-color-light;
}
&[data-event="foreColor"] {
background-color: $o-we-color-normal;
&:before {
background-color: rgba(white, 0.3);
}
}
}
}
.note-palette-title {
color: $o-we-color-text-light;
}
.palette-reset {
.note-color-reset {
color: desaturate(rgba($o-we-color-danger, 0.6), 40%);
&:hover {
color: $o-we-color-danger;
}
}
}
}
// 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 {
width: $o-we-overlay-option-size;
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);
}
}
@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;
}
}
// INPUTS
.o_switch {
display: flex;
@@ -369,11 +13,10 @@ html[lang]>body.editor_enable [data-oe-translation-state] {
box-shadow: inset 0 0 0px 1px darken($o-we-switch-inactive-color, 10%);
border-radius: 100rem;
height: $o-we-switch-size;
width: $o-we-switch-size * 1.81;
margin-right: 0.51em;
width: $o-we-switch-size * 1.8;
margin-right: 0.5em;
display: inline-block;
transition: all 0.3s $o-we-md-ease;
font-size: 15px;
&:after {
content: "";
@@ -517,297 +160,3 @@ html[lang]>body.editor_enable [data-oe-translation-state] {
}
}
}
// MODALS
body .modal {
// BACKGROUND IMAGE OPTIONS
.o_bg_img_opt_modal .o_bg_img_opt {
margin: 15px 0;
.help-control {
@include o-position-absolute(15px, 15px);
}
.help {
margin: 15px 0;
.simulator {
position: relative;
float: left;
margin-right: 15px;
width: 120px;
height: 100px;
.bg {
@include o-position-absolute(0, 0, 0, 0);
border: 1px dotted #888787;
background-image: url(/web/image);
background-position: center center;
background-size: cover;
}
.el {
@include o-position-absolute(10px, 0, 10px, 0);
border: 1px solid #222;
}
&.contain_bg {
.bg {
@include o-position-absolute(0, 12px, 20px, 12px);
}
.el {
@include o-position-absolute(0, 0, 20px, 0);
}
}
}
+* {
clear: left;
}
}
.o_bg_img_opt_cover_edition {
@include o-we-preview-box;
padding: 0 25px 25px 25px;
h6 {
color: white;
font-weight: bold;
}
.o_bg_img_opt_object {
position: relative;
background: white;
min-height: 10px;
@include o-we-preview-content;
>img {
cursor: crosshair;
border-top: 1px solid #5A5A5A;
border-bottom: 1px solid #111;
}
&:hover .o_focus_point:before {
opacity: 0.5;
}
}
.o_bg_img_opt_ui_info {
animation: fadeInOut 2s ease forwards;
@include o-position-absolute($bottom: 1px, $right: 0);
display: block;
padding: 3px 13px;
background-color: rgba(255, 255, 255, 0.8);
color: #333;
text-align: center;
font-weight: bold;
pointer-events: none;
span {
font-weight: normal;
}
.o_x {
margin-right: 10px
}
}
.grid {
@include o-position-absolute($top: 33.33%, $left: 0);
display: block;
width: 100%;
height: 1px;
background: fade-out(lighten($o-brand-primary, 30%), 0.5);
pointer-events: none;
&.grid-2 {
top: 66.66%
}
&.grid-3 {
top: 0;
left: 33.33%;
width: 1px;
height: 100%
}
&.grid-4 {
top: 0;
left: 66.66%;
width: 1px;
height: 100%
}
}
.o_focus_point {
@include o-position-absolute($top: 0, $left: 0);
width: 30px;
height: 30px;
border: 2px solid white;
border-radius: 100%;
margin-top: -15px;
margin-left: -15px;
box-shadow: 0 0 1px #333;
pointer-events: none;
&.o_with_transition {
transition: all 0.2s ease 0s;
}
&:before {
pointer-events: none;
content: "";
display: block;
width: 100px;
height: 100px;
margin-top: -37px;
margin-left: -37px;
border: 1px solid #EAEAEA;
background: rgba(247, 76, 76, 0);
border-radius: 100em;
opacity: 1;
box-shadow: 0 0 0 100em rgba(0, 0, 0, 0.33);
transition: opacity 0.2s ease 0s;
}
}
}
}
}
// editor_enable
body.editor_enable {
overflow: hidden;
padding-top: 0 !important;
#web_editor-top-edit {
background-color: $o-we-color-dark;
form.navbar-form {
right: 0;
}
}
#wrapwrap {
height: calc(100vh - #{$o-navbar-height});
padding-top: 0px;
.btn {
-webkit-user-select: none;
}
}
}
.wysiwyg_multizone.note-editor {
&>.note-toolbar-wrapper .note-toolbar {
height: $o-navbar-height;
.btn {
height: $o-navbar-height;
}
}
&>.note-statusbar {
display: none;
}
&>.note-editing-area {
overflow: visible;
}
}
.wysiwyg_multizone.note-popover.popover {
border-width: 0 1px;
.popover-content .btn {
height: $o-navbar-height;
}
}
.wysiwyg_multizone.note-popover,
.wysiwyg_multizone.note-editor>.note-toolbar-wrapper .note-toolbar {
background-color: $o-we-color-dark;
.btn {
background-color: $o-we-color-dark;
color: $o-we-color-text-normal;
border: none;
padding: 0.0625rem 0.3125rem !important; // force this because of themes
>.fa {
color: $o-we-color-text-normal;
}
&:hover {
color: $o-we-color-text-light;
>.fa {
color: $o-we-color-text-light;
}
}
&.active {
background-color: $o-we-color-dark;
color: $o-we-color-text-light;
>.fa {
color: $o-we-color-text-light;
}
}
}
>.btn-group {
margin-top: 0;
&.show,
.btn-group.show {
.dropdown-toggle {
border-top: 2px solid white;
background-color: $o-we-color-darker;
color: white;
box-shadow: none;
>.fa,
>span {
color: white;
}
}
}
}
.dropdown-menu {
margin: 0;
border-radius: 0;
background-color: $o-we-color-darker;
color: $o-we-color-text-normal;
white-space: normal;
.dropdown-item {
width: 100%;
color: $o-we-color-text-light;
>.fa {
color: $o-we-color-text-light;
}
&:hover {
background-color: $o-we-tab-active-bg;
color: white;
>.fa {
color: white;
}
}
}
}
.note-para .dropdown-menu {
min-width: 147px;
}
.note-style .dropdown-item * {
color: $o-we-color-text-light;
}
}
@@ -0,0 +1,640 @@
body.editor_enable {
overflow: hidden;
padding-top: 0 !important;
// TOP BAR (EDIT)
#web_editor-top-edit {
height: $o-navbar-height;
background-color: $o-we-color-dark;
z-index: $zindex-modal - 9;
position: fixed;
top: 0px;
right: 0px;
width: auto;
white-space: nowrap;
background-color: rgba(0, 0, 0, 0);
transition: background-color 400ms $o-we-md-ease 0s;
font-family: $o-we-font-family;
form.navbar-form {
height: $o-navbar-height;
z-index: 1060;
margin: 0;
padding: 0;
position: absolute;
top: -1px;
right: 0;
transition: right 0.4s $o-we-md-ease 0s;
border-left: 1px solid $o-we-color-divider;
background-color: inherit;
.btn-group {
height: 100%;
}
.btn {
height: 100%;
margin: 0;
padding: 10px;
line-height: 1.2;
font-size: 13px;
font-family: $o-we-font-family;
transition: all 0.3s ease 0s;
border: none;
border-radius: 0;
.fa {
margin-right: $grid-gutter-width/4;
&.fa-times {
color: $o-we-color-danger;
}
}
&.btn-primary {
@include button-variant($o-brand-odoo, $o-brand-odoo);
}
&.btn-secondary {
@include button-variant($o-we-color-dark, $o-we-color-dark);
&:hover {
background: rgba(black, 0.5);
}
}
&:focus,
&:active,
&:focus:active {
outline: none;
}
}
.dropdown-menu {
left: auto;
right: 0;
}
}
}
#wrapwrap {
height: calc(100vh - #{$o-navbar-height});
padding-top: 0px;
.btn {
-webkit-user-select: none;
}
}
// Translations
.oe_translate_examples li {
margin: 10px;
padding: 4px;
}
html[lang]>body.editor_enable [data-oe-translation-state] {
background: rgba($o-we-content-to-translate-color, 0.5) !important;
&[data-oe-translation-state="translated"] {
background: rgba($o-we-translated-content-color, 0.5) !important;
}
&.o_dirty {
background: rgba($o-we-translated-content-color, 0.25) !important;
}
}
// NOTE EDITOR
// SNIPPET PANEL
#oe_snippets {
@include o-w-preserve-btn;
@include o-position-absolute(0, auto, 0, -$o-we-sidebar-width);
width: $o-we-sidebar-width;
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 {
color: $o-we-color-text-light;
}
}
.o_colorpicker_section {
&:after {
content: "";
display: table;
clear: both;
}
>button {
&:hover,
&.selected {
box-shadow: 0px 0px 2px 2px $o-we-color-light;
}
&[data-event="foreColor"] {
background-color: $o-we-color-normal;
&:before {
background-color: rgba(white, 0.3);
}
}
}
}
.note-palette-title {
color: $o-we-color-text-light;
}
.palette-reset {
.note-color-reset {
color: desaturate(rgba($o-we-color-danger, 0.6), 40%);
&:hover {
color: $o-we-color-danger;
}
}
}
}
// 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);
}
}
@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 {
// BACKGROUND IMAGE OPTIONS
.o_bg_img_opt_modal .o_bg_img_opt {
margin: 15px 0;
.help-control {
@include o-position-absolute(15px, 15px);
}
.help {
margin: 15px 0;
.simulator {
position: relative;
float: left;
margin-right: 15px;
width: 120px;
height: 100px;
.bg {
@include o-position-absolute(0, 0, 0, 0);
border: 1px dotted #888787;
background-image: url(/web/image);
background-position: center center;
background-size: cover;
}
.el {
@include o-position-absolute(10px, 0, 10px, 0);
border: 1px solid #222;
}
&.contain_bg {
.bg {
@include o-position-absolute(0, 12px, 20px, 12px);
}
.el {
@include o-position-absolute(0, 0, 20px, 0);
}
}
}
+* {
clear: left;
}
}
.o_bg_img_opt_cover_edition {
@include o-we-preview-box;
padding: 0 25px 25px 25px;
h6 {
color: white;
font-weight: bold;
}
.o_bg_img_opt_object {
position: relative;
background: white;
min-height: 10px;
@include o-we-preview-content;
>img {
cursor: crosshair;
border-top: 1px solid #5A5A5A;
border-bottom: 1px solid #111;
}
&:hover .o_focus_point:before {
opacity: 0.5;
}
}
.o_bg_img_opt_ui_info {
animation: fadeInOut 2s ease forwards;
@include o-position-absolute($bottom: 1px, $right: 0);
display: block;
padding: 3px 13px;
background-color: rgba(255, 255, 255, 0.8);
color: #333;
text-align: center;
font-weight: bold;
pointer-events: none;
span {
font-weight: normal;
}
.o_x {
margin-right: 10px
}
}
.grid {
@include o-position-absolute($top: 33.33%, $left: 0);
display: block;
width: 100%;
height: 1px;
background: fade-out(lighten($o-brand-primary, 30%), 0.5);
pointer-events: none;
&.grid-2 {
top: 66.66%
}
&.grid-3 {
top: 0;
left: 33.33%;
width: 1px;
height: 100%
}
&.grid-4 {
top: 0;
left: 66.66%;
width: 1px;
height: 100%
}
}
.o_focus_point {
@include o-position-absolute($top: 0, $left: 0);
width: 30px;
height: 30px;
border: 2px solid white;
border-radius: 100%;
margin-top: -15px;
margin-left: -15px;
box-shadow: 0 0 1px #333;
pointer-events: none;
&.o_with_transition {
transition: all 0.2s ease 0s;
}
&:before {
pointer-events: none;
content: "";
display: block;
width: 100px;
height: 100px;
margin-top: -37px;
margin-left: -37px;
border: 1px solid #EAEAEA;
background: rgba(247, 76, 76, 0);
border-radius: 100em;
opacity: 1;
box-shadow: 0 0 0 100em rgba(0, 0, 0, 0.33);
transition: opacity 0.2s ease 0s;
}
}
}
}
}
.wysiwyg_multizone.note-editor {
&>.note-toolbar-wrapper .note-toolbar {
height: $o-navbar-height;
.btn {
height: $o-navbar-height;
}
}
&>.note-statusbar {
display: none;
}
&>.note-editing-area {
overflow: visible;
}
}
.wysiwyg_multizone.note-popover.popover {
border-width: 0 1px;
.popover-content .btn {
height: $o-navbar-height;
}
}
.wysiwyg_multizone.note-popover,
.wysiwyg_multizone.note-editor>.note-toolbar-wrapper .note-toolbar {
background-color: $o-we-color-dark;
.btn {
background-color: $o-we-color-dark;
color: $o-we-color-text-normal;
border: none;
padding: 0.0625rem 0.3125rem !important; // force this because of themes
>.fa {
color: $o-we-color-text-normal;
}
&:hover {
color: $o-we-color-text-light;
>.fa {
color: $o-we-color-text-light;
}
}
&.active {
background-color: $o-we-color-dark;
color: $o-we-color-text-light;
>.fa {
color: $o-we-color-text-light;
}
}
}
>.btn-group {
margin-top: 0;
&.show,
.btn-group.show {
.dropdown-toggle {
border-top: 2px solid white;
background-color: $o-we-color-darker;
color: white;
box-shadow: none;
>.fa,
>span {
color: white;
}
}
}
}
.dropdown-menu {
margin: 0;
border-radius: 0;
background-color: $o-we-color-darker;
color: $o-we-color-text-normal;
white-space: normal;
.dropdown-item {
width: 100%;
color: $o-we-color-text-light;
>.fa {
color: $o-we-color-text-light;
}
&:hover {
background-color: $o-we-tab-active-bg;
color: white;
>.fa {
color: white;
}
}
}
}
.note-para .dropdown-menu {
min-width: 147px;
}
.note-style .dropdown-item * {
color: $o-we-color-text-light;
}
}
}
+17 -5
View File
@@ -80,6 +80,23 @@
</xpath>
</template>
<template id="website.compiled_assets_wysiwyg" name="Website Editor Assets (used in website editor)">
<t t-call-assets="website.assets_wysiwyg"/>
</template>
<template id="website.assets_wysiwyg" name="Website Editor Assets (used in website editor)">
<t t-call="web._assets_helpers">
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/bootstrap_overridden.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
</t>
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/website.wysiwyg.scss"/>
<script type="text/javascript" src="/website/static/src/js/editor/snippets.options.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/wysiwyg_multizone.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/wysiwyg_multizone_translate.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/widget_link.js"/>
</template>
<template id="website.assets_editor" name="Website Editor Assets (used in website editor)">
<t t-call="web._assets_helpers"/>
@@ -88,10 +105,6 @@
<script type="text/javascript" src="/website/static/src/js/editor/editor_menu.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/editor_menu_translate.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/widget_link.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/snippets.options.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/wysiwyg_multizone.js"/>
<script type="text/javascript" src="/website/static/src/js/editor/wysiwyg_multizone_translate.js"/>
<script type="text/javascript" src="/website/static/src/js/menu/content.js"/>
<script type="text/javascript" src="/website/static/src/js/menu/customize.js"/>
@@ -107,7 +120,6 @@
<script type="text/javascript" src="/website/static/src/js/widgets/ace.js"/>
<script type="text/javascript" src="/website/static/src/js/widgets/theme.js"/>
</template>
<!-- Layout -->
@@ -3,7 +3,6 @@ odoo.define('website_forum.editor', function (require) {
var core = require('web.core');
var Widget = require('web.Widget');
var Wysiwyg = require('web_editor.wysiwyg');
var WebsiteNewMenu = require('website.newMenu');
var wUtils = require('website.utils');
var websiteRootData = require('website.WebsiteRoot');
@@ -2,7 +2,7 @@ odoo.define('website_forum.website_forum', function (require) {
'use strict';
var core = require('web.core');
var Wysiwyg = require('web_editor.wysiwyg');
var Wysiwyg = require('web_editor.wysiwyg.root');
var sAnimations = require('website.content.snippets.animation');
var session = require('web.session');
var qweb = core.qweb;