[FIX] web_editor, website: fix onFocus/onBlur flow + add test
The flow has been broken multiple times across the years. Let's add a test in all stable versions. For the 14.0 forward-port, the test came with a fix which restores the 13.0 flow which we tried to change in 14.0... but only ended up broking it. Indeed, with [1], the 13.0 was fixed. And, with [2], we tried to simplify the flow... but the explanation given by the commit is just wrong: the flow was just broken and the simplification that was to be done in fact practically never occurs. The more the reason to add a test, proving how the flow is working. The simplification may be done someday but not sure it is really worth it. For the 15.0 forward-port, another fix was needed because of [3] which introduced a bug which makes the onBlur method be called multiple times when hiding a whole editor hierarchy. [1]: https://github.com/odoo/odoo/commit/076992bdf099f3a645c9a1ef6df2cdcccbf1c2b2 [2]: https://github.com/odoo/odoo/commit/5c007305c9998ade32c6677cac5552101c3a96af [3]: https://github.com/odoo/odoo/commit/806a8db35b5e0e6a461422f5bba7c97180c3ef29 closes odoo/odoo#79734 X-original-commit: 0acc5e784b15d9c963660da3781763448503f33e Signed-off-by: Romain Derie (rde) <rde@odoo.com> Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -456,6 +456,10 @@ var SnippetEditor = Widget.extend({
|
||||
// and would thus produce a deadlock. Also, this awaited
|
||||
// 'activate_snippet' call would allow to remove the 'toggleOverlay' and
|
||||
// 'toggleOptions' calls at the start of this function.
|
||||
// TODO also to be checked: this not being awaited, the DOM is removed
|
||||
// first, destroying the related editors and not calling onBlur... to
|
||||
// check if this has always been like this or not and this should be
|
||||
// unit tested.
|
||||
const parent = this.$target[0].parentElement;
|
||||
const nextSibling = this.$target[0].nextElementSibling;
|
||||
const previousSibling = this.$target[0].previousElementSibling;
|
||||
@@ -568,7 +572,7 @@ var SnippetEditor = Widget.extend({
|
||||
}
|
||||
|
||||
if (this.areOptionsShown() === show) {
|
||||
return this._customize$Elements;
|
||||
return null;
|
||||
}
|
||||
|
||||
// All onFocus before all ui updates as the onFocus of an option might
|
||||
@@ -1785,7 +1789,8 @@ var SnippetsMenu = Widget.extend({
|
||||
}
|
||||
resolve(null);
|
||||
}).then(async editorToEnable => {
|
||||
if (ifInactiveOptions && this._enabledEditorHierarchy.includes(editorToEnable)) {
|
||||
if (!previewMode && this._enabledEditorHierarchy[0] === editorToEnable
|
||||
|| ifInactiveOptions && this._enabledEditorHierarchy.includes(editorToEnable)) {
|
||||
return editorToEnable;
|
||||
}
|
||||
|
||||
@@ -1802,8 +1807,14 @@ var SnippetsMenu = Widget.extend({
|
||||
for (let i = this.snippetEditors.length; i--;) {
|
||||
const editor = this.snippetEditors[i];
|
||||
editor.toggleOverlay(false, previewMode);
|
||||
if (!previewMode && !this._enabledEditorHierarchy.includes(editor)) {
|
||||
await editor.toggleOptions(false);
|
||||
if (!previewMode) {
|
||||
const wasShown = !!await editor.toggleOptions(false);
|
||||
if (wasShown) {
|
||||
this._updateRightPanelContent({
|
||||
content: [],
|
||||
tab: this.tabs.BLOCKS,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... then enable the right editor or look if some have been
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
odoo.define('website.tour_focus_blur_snippets_options', function (require) {
|
||||
'use strict';
|
||||
|
||||
const options = require('web_editor.snippets.options');
|
||||
|
||||
const FocusBlur = options.Class.extend({
|
||||
onFocus() {
|
||||
window.focusBlurSnippetsResult.push(`focus ${this.focusBlurName}`);
|
||||
},
|
||||
onBlur() {
|
||||
window.focusBlurSnippetsResult.push(`blur ${this.focusBlurName}`);
|
||||
},
|
||||
});
|
||||
|
||||
options.registry.FocusBlurParent = FocusBlur.extend({focusBlurName: 'parent'});
|
||||
options.registry.FocusBlurChild1 = FocusBlur.extend({focusBlurName: 'child1'});
|
||||
options.registry.FocusBlurChild2 = FocusBlur.extend({focusBlurName: 'child2'});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
odoo.define('website.tour.focus_blur_snippets', function (require) {
|
||||
'use strict';
|
||||
|
||||
const ajax = require('web.ajax');
|
||||
const tour = require('web_tour.tour');
|
||||
|
||||
const blockIDToData = {
|
||||
parent: {
|
||||
selector: '.s_focusblur',
|
||||
name: 'section',
|
||||
overlayIndex: 2,
|
||||
},
|
||||
child1: {
|
||||
selector: '.s_focusblur_child1',
|
||||
name: 'first child',
|
||||
overlayIndex: 1,
|
||||
},
|
||||
child2: {
|
||||
selector: '.s_focusblur_child2',
|
||||
name: 'second child',
|
||||
overlayIndex: 0,
|
||||
},
|
||||
};
|
||||
|
||||
function clickAndCheck(blockID, expected) {
|
||||
const blockData = blockIDToData[blockID] || {};
|
||||
|
||||
return [{
|
||||
content: blockID ? `Enable the ${blockData.name}` : 'Disable all blocks',
|
||||
trigger: blockData.selector || '#wrapwrap',
|
||||
}, {
|
||||
content: 'Once the related overlays are enabled/disabled, check that the focus/blur calls have been correct.',
|
||||
trigger: blockID
|
||||
? `.oe_overlay.ui-draggable:eq(${blockData.overlayIndex}).oe_active`
|
||||
: `#oe_manipulators:not(:has(.oe_active))`,
|
||||
run: function (actions) {
|
||||
const result = window.focusBlurSnippetsResult;
|
||||
window.focusBlurSnippetsResult = [];
|
||||
|
||||
if (expected.length !== result.length
|
||||
|| !expected.every((item, i) => item === result[i])) {
|
||||
console.error(`
|
||||
Expected: ${expected.toString()}
|
||||
Result: ${result.toString()}
|
||||
`);
|
||||
}
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
window.focusBlurSnippetsResult = [];
|
||||
|
||||
tour.register('focus_blur_snippets', {
|
||||
url: '/?enable_editor=1',
|
||||
}, [
|
||||
{
|
||||
content: 'First load our custom JS options',
|
||||
trigger: 'body',
|
||||
run: function () {
|
||||
ajax.loadJS('/website/static/tests/tour_utils/focus_blur_snippets_options.js').then(function () {
|
||||
$('body').addClass('focus_blur_snippets_options_loaded');
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
content: 'Drag the custom block into the page',
|
||||
trigger: '#snippet_structure .oe_snippet:has(.oe_snippet_body.s_focusblur) .oe_snippet_thumbnail',
|
||||
extra_trigger: 'body.focus_blur_snippets_options_loaded',
|
||||
run: 'drag_and_drop #wrap',
|
||||
},
|
||||
...clickAndCheck('parent', ['focus parent']),
|
||||
...clickAndCheck(null, ['blur parent']),
|
||||
...clickAndCheck('child1', ['focus parent', 'focus child1']),
|
||||
...clickAndCheck('child1', []),
|
||||
...clickAndCheck(null, ['blur parent', 'blur child1']),
|
||||
...clickAndCheck('parent', ['focus parent']),
|
||||
...clickAndCheck('child1', ['blur parent', 'focus parent', 'focus child1']),
|
||||
...clickAndCheck('child2', ['blur parent', 'blur child1', 'focus parent', 'focus child2']),
|
||||
...clickAndCheck('parent', ['blur parent', 'blur child2', 'focus parent']),
|
||||
]);
|
||||
});
|
||||
@@ -221,3 +221,54 @@ class TestUi(odoo.tests.HttpCase):
|
||||
lang = self.env['res.lang']._activate_lang('nl_NL')
|
||||
self.env['website'].browse(1).write({'language_ids': [(4, lang.id, 0)]})
|
||||
self.start_tour("/nl/contactus", 'edit_translated_page_redirect', login='admin')
|
||||
|
||||
def test_13_editor_focus_blur_unit_test(self):
|
||||
# TODO this should definitely not be a website python tour test but
|
||||
# while waiting for a proper web_editor qunit JS test suite for the
|
||||
# editor, it is better than no test at all as this was broken multiple
|
||||
# times already.
|
||||
self.env["ir.ui.view"].create([{
|
||||
'name': 's_focusblur',
|
||||
'key': 'website.s_focusblur',
|
||||
'type': 'qweb',
|
||||
'arch': """
|
||||
<section class="s_focusblur bg-success py-5">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 s_focusblur_child1 bg-warning py-5"></div>
|
||||
<div class="col-lg-6 s_focusblur_child2 bg-danger py-5"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
""",
|
||||
}, {
|
||||
'name': 's_focusblur_snippets',
|
||||
'mode': 'extension',
|
||||
'inherit_id': self.env.ref('website.snippets').id,
|
||||
'key': 'website.s_focusblur_snippets',
|
||||
'type': 'qweb',
|
||||
'arch': """
|
||||
<data>
|
||||
<xpath expr="//*[@id='snippet_structure']//t[@t-snippet]" position="before">
|
||||
<t t-snippet="website.s_focusblur"/>
|
||||
</xpath>
|
||||
</data>
|
||||
""",
|
||||
}, {
|
||||
'name': 's_focusblur_options',
|
||||
'mode': 'extension',
|
||||
'inherit_id': self.env.ref('web_editor.snippet_options').id,
|
||||
'key': 'website.s_focusblur_options',
|
||||
'type': 'qweb',
|
||||
'arch': """
|
||||
<data>
|
||||
<xpath expr=".">
|
||||
<div data-js="FocusBlurParent" data-selector=".s_focusblur"/>
|
||||
<div data-js="FocusBlurChild1" data-selector=".s_focusblur_child1"/>
|
||||
<div data-js="FocusBlurChild2" data-selector=".s_focusblur_child2"/>
|
||||
</xpath>
|
||||
</data>
|
||||
""",
|
||||
}])
|
||||
|
||||
self.start_tour("/?enable_editor=1", "focus_blur_snippets", login="admin")
|
||||
|
||||
Reference in New Issue
Block a user