summaryrefslogtreecommitdiff
path: root/addons/web_editor
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-02-26 16:39:30 +0100
committerChristophe Simonis <chs@odoo.com>2019-02-26 16:39:30 +0100
commitff9c9341d6ed4e9ab18a0aa02e79441999d658f1 (patch)
tree47ffd01e071d3783cff6013cfc4b6c3d8e47a841 /addons/web_editor
parentbc84fdf71b15ad419f8693861aea682ee751f85c (diff)
parentfcb972db9dc778eeaf7d6b6ba3638c78d93998ad (diff)
[MERGE] forward port branch saas-12.2 up to fcb972db9dc
Diffstat (limited to 'addons/web_editor')
-rw-r--r--addons/web_editor/models/ir_ui_view.py15
-rw-r--r--addons/web_editor/static/src/js/wysiwyg/plugin/keyboard.js30
-rw-r--r--addons/web_editor/static/src/js/wysiwyg/plugin/media.js3
-rw-r--r--addons/web_editor/static/src/scss/web_editor.variables.scss38
-rw-r--r--addons/web_editor/static/src/xml/editor.xml8
-rw-r--r--addons/web_editor/static/tests/wysiwyg_keyboard_tests.js49
6 files changed, 98 insertions, 45 deletions
diff --git a/addons/web_editor/models/ir_ui_view.py b/addons/web_editor/models/ir_ui_view.py
index e281d9f9ecc..41de79b3c24 100644
--- a/addons/web_editor/models/ir_ui_view.py
+++ b/addons/web_editor/models/ir_ui_view.py
@@ -159,6 +159,10 @@ class IrUiView(models.Model):
out.tail = el.tail
return out
+ @api.model
+ def _set_noupdate(self):
+ self.sudo().mapped('model_data_id').write({'noupdate': True})
+
@api.multi
def save(self, value, xpath=None):
""" Update a view section. The view section may embed fields to write
@@ -195,16 +199,12 @@ class IrUiView(models.Model):
new_arch = self.replace_arch_section(xpath, arch_section)
old_arch = etree.fromstring(self.arch.encode('utf-8'))
if not self._are_archs_equal(old_arch, new_arch):
- self.sudo().model_data_id.write({'noupdate': True}) # TODO check if we remove this
+ self._set_noupdate()
self.write({'arch': self._pretty_arch(new_arch)})
@api.model
def _view_get_inherited_children(self, view, options):
- extensions = view.inherit_children_ids
- if not options:
- # only active children
- extensions = extensions.filtered(lambda view: view.active)
- return extensions
+ return view.inherit_children_ids
@api.model
def _view_obj(self, view_id):
@@ -252,6 +252,9 @@ class IrUiView(models.Model):
views_to_return += self._views_get(called_view, options=options, bundles=bundles)
extensions = self._view_get_inherited_children(view, options)
+ if not options:
+ # only active children
+ extensions = extensions.filtered(lambda view: view.active)
# Keep options in a deterministic order regardless of their applicability
for extension in extensions.sorted(key=lambda v: v.id):
diff --git a/addons/web_editor/static/src/js/wysiwyg/plugin/keyboard.js b/addons/web_editor/static/src/js/wysiwyg/plugin/keyboard.js
index 3db30752277..0cb451c100d 100644
--- a/addons/web_editor/static/src/js/wysiwyg/plugin/keyboard.js
+++ b/addons/web_editor/static/src/js/wysiwyg/plugin/keyboard.js
@@ -42,7 +42,6 @@ var KeyboardPlugin = AbstractPlugin.extend({
range = direction === 'prev' ? this._insertInvisibleCharAfterSingleBR(range) : range;
range = this._rerangeOutOfBR(range, direction);
range = this._cleanRangeAfterDeletion(range);
- range = this._replaceEmptyParentWithEmptyP(range);
return range;
},
/**
@@ -219,8 +218,15 @@ var KeyboardPlugin = AbstractPlugin.extend({
* @returns {Boolean} true if case handled
*/
_handleDeletion: function (direction) {
- var didDeleteNodes = this.context.invoke('HelperPlugin.deleteSelection')
var range = this.context.invoke('editor.createRange');
+ range = direction === 'prev' && this._replaceEmptyParentWithEmptyP(range);
+ if (range) {
+ range = this._afterDeletion(range, direction);
+ range.select();
+ return true;
+ }
+ var didDeleteNodes = this.context.invoke('HelperPlugin.deleteSelection');
+ range = this.context.invoke('editor.createRange');
var wasOnStartOfBR = direction === 'prev' && !range.so && range.sc.tagName === 'BR';
this._removeNextEmptyUnbreakable(range.sc);
@@ -837,23 +843,27 @@ var KeyboardPlugin = AbstractPlugin.extend({
*
* @private
* @param {Object} range
- * @returns {Object} range
+ * @returns {Object|undefined} range
*/
_replaceEmptyParentWithEmptyP: function (range) {
- if (range.sc === this.editable || range.sc.parentNode === this.editable) {
- return range;
+ var node = range.sc.childElementCount === 1 && range.sc.firstChild.tagName === 'BR' ? range.sc.firstChild : range.sc;
+ if (node === this.editable || !node.parentNode || node.parentNode === this.editable) {
+ return;
}
- var node = dom.isVoid(range.sc) && range.sc.parentNode ? range.sc.parentNode : range.sc;
- var parentOnlyHasNode = node.parentNode && this.context.invoke('HelperPlugin.onlyContains', node.parentNode, node);
- if (dom.isEmpty(node) && node.tagName !== 'LI' && parentOnlyHasNode) {
+ if (
+ dom.isEmpty(node) &&
+ this.context.invoke('HelperPlugin.onlyContains', node.parentNode, node) &&
+ ['LI', 'P'].indexOf(node.parentNode.tagName) === -1
+ ) {
var emptyP = this.document.createElement('p');
var br = this.document.createElement('br');
$(emptyP).append(br);
- $(node).before(emptyP).remove();
+ $(node.parentNode).before(emptyP).remove();
range.sc = range.ec = br;
range.so = range.eo = 0;
+ return range.collapse(true);
}
- return range;
+ return;
},
/**
* Replace all leading space from a text node with one non-breakable space.
diff --git a/addons/web_editor/static/src/js/wysiwyg/plugin/media.js b/addons/web_editor/static/src/js/wysiwyg/plugin/media.js
index b4d484af805..e60cfbe8039 100644
--- a/addons/web_editor/static/src/js/wysiwyg/plugin/media.js
+++ b/addons/web_editor/static/src/js/wysiwyg/plugin/media.js
@@ -151,6 +151,9 @@ var MediaPlugin = AbstractPlugin.extend({
* @param {Object} data contains the media to insert
*/
insertMedia: function (previous, data) {
+ if (!data.media) {
+ return;
+ }
var newMedia = data.media;
this._wrapCommand(function () {
this.$editable.focus();
diff --git a/addons/web_editor/static/src/scss/web_editor.variables.scss b/addons/web_editor/static/src/scss/web_editor.variables.scss
index a66e3516c77..e317fe7616b 100644
--- a/addons/web_editor/static/src/scss/web_editor.variables.scss
+++ b/addons/web_editor/static/src/scss/web_editor.variables.scss
@@ -117,10 +117,17 @@ $o-checklist-before-size: 13px;
color: #555;
background-color: #fff;
border-radius: 0;
+
&.is-invalid {
border-color: $danger;
}
}
+ .input-group .form-control {
+ height: auto;
+ }
+ .input-group-text {
+ background-color: #e9ecef;
+ }
.was-validated {
.form-control:invalid {
@@ -143,10 +150,14 @@ $o-checklist-before-size: 13px;
border-radius: 0;
background-color: $o-we-color-paper;
+ .modal-header {
+ border-bottom-color: #e9ecef;
+ }
.modal-body {
background-color: white;
}
.modal-footer {
+ border-top-color: #e9ecef;
text-align: left;
}
}
@@ -154,23 +165,23 @@ $o-checklist-before-size: 13px;
@mixin o-w-preserve-tabs {
.nav-tabs {
- border-bottom: 1px solid gray('200');
+ border-bottom: 1px solid #e9ecef;
> li {
> a {
line-height: 1.5;
color: $o-we-color-light;
+
&:hover {
- border-color: gray('200');
+ border-color: #dee2e6;
}
- }
- &.active > a {
- &, &:hover, &:focus {
- color: $o-we-color-normal;
- background-color: $o-we-color-paper;
- border-color: gray('200');
- border-bottom-color: transparent;
+ &.active {
+ &, &:hover, &:focus {
+ color: $o-we-color-normal;
+ background-color: $o-we-color-paper;
+ border-color: #dee2e6 #dee2e6 #FFFFFF;
+ }
}
}
}
@@ -182,7 +193,7 @@ $o-checklist-before-size: 13px;
border-radius: 0;
font-weight: normal;
text-transform: none;
- @include button-size(.375rem, .75rem, 1rem, 1.5, 0);
+ @include button-size(.375rem, .75rem, 0.875rem, 1.5, 0);
&.btn-primary {
@include button-variant($o-brand-primary, $o-brand-primary);
@@ -207,13 +218,6 @@ $o-checklist-before-size: 13px;
&.btn-danger {
@include button-variant($o-we-color-danger, $o-we-color-danger);
}
-
- &.btn-lg {
- @include button-size(.5rem, 1rem, 1.25rem, 1.5, 0);
- }
- &.btn-sm {
- @include button-size(.25rem, .5rem, .875rem, 1.5, 0);
- }
}
}
diff --git a/addons/web_editor/static/src/xml/editor.xml b/addons/web_editor/static/src/xml/editor.xml
index 51c3d5412ff..aa8b5a2f094 100644
--- a/addons/web_editor/static/src/xml/editor.xml
+++ b/addons/web_editor/static/src/xml/editor.xml
@@ -45,7 +45,7 @@
<label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_size_x">Background width</label>
<div class="col-md-5">
<div class="input-group">
- <input type="number" min="0" max="100" class="form-control form-control-sm" id="o_bg_img_opt_custom_size_x" placeholder="auto"/>
+ <input type="number" min="0" max="100" class="form-control" id="o_bg_img_opt_custom_size_x" placeholder="auto"/>
<div class="input-group-append">
<div class="input-group-text">%</div>
</div>
@@ -56,7 +56,7 @@
<label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_size_y">Background height</label>
<div class="col-md-5">
<div class="input-group">
- <input type="number" min="0" max="100" class="form-control form-control-sm" id="o_bg_img_opt_custom_size_y" placeholder="auto"/>
+ <input type="number" min="0" max="100" class="form-control" id="o_bg_img_opt_custom_size_y" placeholder="auto"/>
<div class="input-group-append">
<div class="input-group-text">%</div>
</div>
@@ -71,7 +71,7 @@
<label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_pos_x">Horizontal</label>
<div class="col-md-5">
<div class="input-group">
- <input type="number" min="0" max="100" class="form-control form-control-sm" id="o_bg_img_opt_custom_pos_x" placeholder="auto"/>
+ <input type="number" min="0" max="100" class="form-control " id="o_bg_img_opt_custom_pos_x" placeholder="auto"/>
<div class="input-group-append">
<div class="input-group-text">%</div>
</div>
@@ -82,7 +82,7 @@
<label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_pos_y">Vertical</label>
<div class="col-md-5">
<div class="input-group">
- <input type="number" min="0" max="100" class="form-control form-control-sm" id="o_bg_img_opt_custom_pos_y" placeholder="auto"/>
+ <input type="number" min="0" max="100" class="form-control" id="o_bg_img_opt_custom_pos_y" placeholder="auto"/>
<div class="input-group-append">
<div class="input-group-text">%</div>
</div>
diff --git a/addons/web_editor/static/tests/wysiwyg_keyboard_tests.js b/addons/web_editor/static/tests/wysiwyg_keyboard_tests.js
index 14f06ec2e9d..56ceb27a025 100644
--- a/addons/web_editor/static/tests/wysiwyg_keyboard_tests.js
+++ b/addons/web_editor/static/tests/wysiwyg_keyboard_tests.js
@@ -3093,7 +3093,7 @@ var keyboardTestsBackspace = [{
},
},
{
- name: "in complex-dom (empty-td (td before) -> 2x SHIFT-ENTER): 3x BACKSPACE",
+ name: "in complex-dom (empty-td (td before) -> 2x SHIFT-ENTER): 3x BACKSPACE -> 'a'",
content: '<table class="table table-bordered"><tbody><tr><td><p>dom not to edit</p></td><td><p><br><br><br></p></td></tr></tbody></table>',
steps: [{
start: 'p:eq(1)->3',
@@ -3102,19 +3102,35 @@ var keyboardTestsBackspace = [{
key: 'BACKSPACE',
}, {
key: 'BACKSPACE',
+ }, {
+ key: 'a',
}],
test: {
- content: '<table class="table table-bordered"><tbody><tr><td><p>dom not to edit</p></td><td><p><br></p></td></tr></tbody></table>',
- start: "p:eq(1):contents()[0]->0",
+ content: '<table class="table table-bordered"><tbody><tr><td><p>dom not to edit</p></td><td><p>a</p></td></tr></tbody></table>',
+ start: "p:eq(1):contents()[0]->1",
},
},
{
- name: "in complex-dom (empty-td (td before) -> 2x SHIFT-ENTER): 3x BACKSPACE -> 'a'",
- content: '<table class="table table-bordered"><tbody><tr><td><p>dom not to edit</p></td><td><p><br><br><br></p></td></tr></tbody></table>',
+ name: "in h1: BACKSPACE on full selection -> 'a'",
+ content: '<h1>dom to delete</h1>',
steps: [{
- start: 'p:eq(1)->3',
+ start: 'h1:contents()[0]->0',
+ end: 'h1:contents()[0]->13',
key: 'BACKSPACE',
}, {
+ key: 'a',
+ }],
+ test: {
+ content: '<h1>a</h1>',
+ start: "h1:contents()[0]->1",
+ },
+ },
+ {
+ name: "in h1: BACKSPACE on full selection -> BACKSPACE -> 'a'",
+ content: '<h1>dom to delete</h1>',
+ steps: [{
+ start: 'h1:contents()[0]->0',
+ end: 'h1:contents()[0]->13',
key: 'BACKSPACE',
}, {
key: 'BACKSPACE',
@@ -3122,8 +3138,25 @@ var keyboardTestsBackspace = [{
key: 'a',
}],
test: {
- content: '<table class="table table-bordered"><tbody><tr><td><p>dom not to edit</p></td><td><p>a</p></td></tr></tbody></table>',
- start: "p:eq(1):contents()[0]->1",
+ content: '<p>a</p>',
+ start: "p:contents()[0]->1",
+ },
+ },
+ {
+ name: "in h1: BACKSPACE on full selection -> DELETE -> 'a'",
+ content: '<h1>dom to delete</h1>',
+ steps: [{
+ start: 'h1:contents()[0]->0',
+ end: 'h1:contents()[0]->13',
+ key: 'BACKSPACE',
+ }, {
+ key: 'DELETE',
+ }, {
+ key: 'a',
+ }],
+ test: {
+ content: '<h1>a</h1>',
+ start: "h1:contents()[0]->1",
},
},