Skip to content

Commit

Permalink
[FIX] web_editor: send the html editor writes one after another
Browse files Browse the repository at this point in the history
With the following view hierarchy:
   A
   |
   B' (oe_structure_ID view)

Before this fix, when saving multiple templates at once from the same hierarchy
the COW views (website) would not be saved correctly as the first call to
`write` would COW the parent view, then the second concurent call to `write`
would create the child specific view under the generic parent view.
Instead, the generic parent should have been cloned to a specific parent view
and then the child view should be COW under the specific parent.

  A    A'
  |    |
  B'   B*' (This one is the old B', without B' changes in the html editor)

Instead of

  A   A'
      |
      B'

Calling the `write` one after another will do the trick. Indeed, when the
second call is fired, the first call has already triggered the COW behavior.
Thus, the second call correctly retrieves the COW view.

Another issue might still appear, if the parent view write is sent first.
Indeed, the parent view will be COW, thus the specific child view (second write
waiting to be fired) will be deleted to be added on the new specific hierarchy.
Thus, that write will then raise an error since the view does not exist anymore.

task-1934279
Fix odoo#30447
  • Loading branch information
rdeodoo committed Jan 29, 2019
1 parent e59a9d1 commit 6bd579b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
11 changes: 10 additions & 1 deletion addons/web_editor/static/src/js/widgets/ace.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ odoo.define('web_editor.ace', function (require) {
'use strict';

var ajax = require('web.ajax');
var concurrency = require('web.concurrency');
var core = require('web.core');
var Dialog = require('web.Dialog');
var Widget = require('web.Widget');
Expand Down Expand Up @@ -536,6 +537,7 @@ var ViewEditor = Widget.extend({
* error occured.
*/
_saveResources: function () {
var self = this;
var toSave = {};
var errorFound = false;
_.each(this.editingSessions, (function (editingSessions, type) {
Expand Down Expand Up @@ -563,8 +565,15 @@ var ViewEditor = Widget.extend({
if (errorFound) return $.Deferred().reject(errorFound);

var defs = [];
var mutex = new concurrency.Mutex();
_.each(toSave, (function (_toSave, type) {
defs = defs.concat(_.map(_toSave, (type === 'xml' ? this._saveView : this._saveSCSS).bind(this)));
// Child views first as COW on a parent would delete them
_toSave = _.sortBy(_toSave, 'id').reverse();
_.each(_toSave, function (session) {
defs.push(mutex.exec(function () {
return (type === 'xml' ? self._saveView(session) : self._saveSCSS(session));
}));
});
}).bind(this));

return $.when.apply($, defs).fail((function (session, error) {
Expand Down
75 changes: 75 additions & 0 deletions addons/website/static/src/js/html_editor.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
odoo.define('website.test.html_editor', function (require) {
'use strict';

var tour = require('web_tour.tour');
var base = require('web_editor.base');

tour.register('html_editor_multiple_templates', {
test: true,
url: '/aboutus',
wait_for: base.ready(),
},
[
// 1. Edit the page through Edit Mode, it will COW the view
{
content: "enter edit mode",
trigger: 'a[data-action=edit]',
},
{
content: "drop a snippet",
trigger: '#oe_snippets .oe_snippet:has(.s_cover) .oe_snippet_thumbnail',
// id starting by 'oe_structure..' will actually create an inherited view
run: "drag_and_drop #oe_structure_test_ui",
},
{
content: "save the page",
extra_trigger: '#wrapwrap .s_cover',
trigger: "#web_editor-top-edit button[data-action=save]",
},
// 2. Edit generic aboutus view
{
content: "open customize menu",
extra_trigger: "body:not(.editor_enable)",
trigger: '#customize-menu > a',
},
{
content: "open html editor",
trigger: '#html_editor',
},
{
content: "add something in the aboutus view",
trigger: 'div.ace_line .ace_xml:contains("aboutus")',
run: function () {
ace.edit('ace-view-editor').getSession().insert({row: 3, column: 1}, '<p>somenewcontent</p>\n');
},
},
// 3. Edit oe_structure specific view
{
content: "select oe_structure specific view",
trigger: 'div.ace_line .ace_xml:contains("somenewcontent")',
run: function () {
var viewId = $('#ace-view-list option:contains("oe_structure")').val();
$('#ace-view-list').val(viewId).trigger('change');
},
},
{
content: "add something in the oe_structure specific view",
trigger: 'div.ace_line .ace_xml:contains("s_cover")',
run: function () {
ace.edit('ace-view-editor').getSession().insert({row: 2, column: 1}, '<p>anothernewcontent</p>\n');
},
},
{
content: "save the html editor",
extra_trigger: 'div.ace_line .ace_xml:contains("anothernewcontent")',
trigger: ".o_ace_view_editor button[data-action=save]",
},
{
content: "check that the page has both modification",
extra_trigger: '#wrapwrap:contains("anothernewcontent")',
trigger: '#wrapwrap:contains("somenewcontent")',
run: function () {}, // it's a check
},
]
);
});
26 changes: 26 additions & 0 deletions addons/website/tests/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@
import odoo
import odoo.tests


@odoo.tests.tagged('-at_install', 'post_install')
class TestUiHtmlEditor(odoo.tests.HttpCase):
def test_html_editor_multiple_templates(self):
Website = self.env['website']
View = self.env['ir.ui.view']
generic_aboutus = Website.viewref('website.aboutus')
# Use an empty page layout with oe_structure id for this test
oe_structure_layout = '''
<t name="About us" t-name="website.aboutus">
<t t-call="website.layout">
<p>aboutus</p>
<div id="oe_structure_test_ui" class="oe_structure oe_empty"/>
</t>
</t>
'''
generic_aboutus.arch = oe_structure_layout
self.phantom_js("/", "odoo.__DEBUG__.services['web_tour.tour'].run('html_editor_multiple_templates')", "odoo.__DEBUG__.services['web_tour.tour'].tours.html_editor_multiple_templates.ready", login='admin')
self.assertEqual(View.search_count([('key', '=', 'website.aboutus')]), 2, "Aboutus view should have been COW'd")
self.assertTrue(generic_aboutus.arch == oe_structure_layout, "Generic Aboutus view should be untouched")
self.assertEqual(len(generic_aboutus.inherit_children_ids.filtered(lambda v: 'oe_structure' in v.name)), 0, "oe_structure view should have been deleted when aboutus was COW")
specific_aboutus = Website.with_context(website_id=1).viewref('website.aboutus')
self.assertTrue(specific_aboutus.arch != oe_structure_layout, "Specific Aboutus view should have been changed")
self.assertEqual(len(specific_aboutus.inherit_children_ids.filtered(lambda v: 'oe_structure' in v.name)), 1, "oe_structure view should have been created on the specific tree")


class TestUiTranslate(odoo.tests.HttpCase):
def test_admin_tour_rte_translator(self):
self.phantom_js("/", "odoo.__DEBUG__.services['web_tour.tour'].run('rte_translator')", "odoo.__DEBUG__.services['web_tour.tour'].tours.rte_translator.ready", login='admin', timeout=120)
Expand Down
2 changes: 2 additions & 0 deletions addons/website/views/website_templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
<script type="text/javascript" src="/website/static/src/js/content/zoomodoo.js"/>

<script type="text/javascript" src="/website/static/src/js/menu/navbar.js"/>

<script type="text/javascript" src="/website/static/src/js/html_editor.test.js"/>
</xpath>
</template>

Expand Down

0 comments on commit 6bd579b

Please sign in to comment.