diff --git a/addons/barcodes/static/src/js/form_view_barcode_handler.js b/addons/barcodes/static/src/js/form_view_barcode_handler.js
index ffc6dfc7383..fd0a84166f5 100644
--- a/addons/barcodes/static/src/js/form_view_barcode_handler.js
+++ b/addons/barcodes/static/src/js/form_view_barcode_handler.js
@@ -27,6 +27,8 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
this.__quantity_listener = _.bind(this._set_quantity_listener, this);
BarcodeHandlerMixin.init.apply(this, arguments);
+ this.process_barcode_mutex = new utils.Mutex();
+
return this._super.apply(this, arguments);
},
@@ -136,25 +138,35 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
else if (this.form_view.get('actual_mode') === 'view')
this._display_no_edit_mode_warning();
else {
- // Call hook method possibly implemented by subclass
- this.pre_onchange_hook(barcode).then(function(proceed) {
- if (proceed === true) {
- // Wait for hypothetical ongoing onchange to finish
- self.form_view.onchanges_mutex.exec(function() {
- // A real onchange is triggered when a value actually changes (which can correspond
- // to a widget's blur event per example). Commit the value of fields before
- // programmatically triggering an onchange to be consistent with this.
- var mutex_commit_value = new utils.Mutex();
- _.each(self.form_view.fields, function(field) {
- mutex_commit_value.exec(_.bind(field.commit_value, field));
- });
- return mutex_commit_value.def.then(function(){
- // Trigger the barcode onchange
- self.set_value(barcode);
- });
- });
+ var process_barcode = function () {
+ // this function can be passed to `Mutex.exec` in order to make sure
+ // that every ongoing onchanges in the form view are done
+ var form_onchanges_mutex = function () {
+ return self.form_view.onchanges_mutex.def;
}
- });
+
+ // before setting the barcode field with the received barcode, we commit
+ // every fields of the form view and we wait for their hypothetical ongoing
+ // onchanges to finish
+ var commit_mutex = new utils.Mutex();
+ _.each(self.form_view.fields, function (field) {
+ commit_mutex.exec(function () {
+ return field.commit_value();
+ });
+ commit_mutex.exec(form_onchanges_mutex);
+ });
+
+ return commit_mutex.def.then(function () {
+ return self.pre_onchange_hook(barcode).then(function (proceed) {
+ if (proceed) {
+ self.set_value(barcode); // set the barcode field with the received one
+ return form_onchanges_mutex(); // wait for its onchange to finish
+ }
+ });
+ });
+ };
+
+ this.process_barcode_mutex.exec(process_barcode);
}
},
diff --git a/addons/web/static/src/js/views/list_view_editable.js b/addons/web/static/src/js/views/list_view_editable.js
index 6f8e4b973a4..221383f6890 100644
--- a/addons/web/static/src/js/views/list_view_editable.js
+++ b/addons/web/static/src/js/views/list_view_editable.js
@@ -641,7 +641,8 @@ ListView.include(/** @lends instance.web.ListView# */{
if (saveInfo.created) {
return self.start_edition();
}
- var record = self.records[next_record](saveInfo.record);
+ var options = { wraparound: !self.is_action_enabled('create') };
+ var record = self.records[next_record](saveInfo.record, options);
if (record === undefined) {
return self.start_edition();
}
diff --git a/addons/web_editor/static/src/js/backend.js b/addons/web_editor/static/src/js/backend.js
index 36cd33c60fd..3585ddfdb9a 100644
--- a/addons/web_editor/static/src/js/backend.js
+++ b/addons/web_editor/static/src/js/backend.js
@@ -161,6 +161,11 @@ var FieldTextHtmlSimple = widget.extend({
return !this.get('value') || this.get('value') === "
" || !this.get('value').match(/\S/);
},
commit_value: function () {
+ /* Switch to WYSIWYG mode if currently in code view */
+ if (session.debug) {
+ var layoutInfo = this.$textarea.data('layoutInfo');
+ $.summernote.pluginEvents.codeview(undefined, undefined, layoutInfo, false);
+ }
if (this.options['style-inline']) {
transcoder.class_to_style(this.$content);
transcoder.font_to_img(this.$content);
@@ -374,6 +379,11 @@ var FieldTextHtml = widget.extend({
this._dirty_flag = false;
return this.editor.save();
} else if (this._dirty_flag && this.editor && this.editor.buildingBlock) {
+ /* Switch to WYSIWYG mode if currently in code view */
+ if (session.debug) {
+ var layoutInfo = this.editor.rte.editable().data('layoutInfo');
+ $.summernote.pluginEvents.codeview(undefined, undefined, layoutInfo, false);
+ }
this.editor.buildingBlock.clean_for_save();
this.internal_set_value( this.$content.html() );
}
diff --git a/addons/web_editor/static/src/js/rte.summernote.js b/addons/web_editor/static/src/js/rte.summernote.js
index 73565e19743..97574c0cb86 100644
--- a/addons/web_editor/static/src/js/rte.summernote.js
+++ b/addons/web_editor/static/src/js/rte.summernote.js
@@ -539,12 +539,32 @@ function prettify_html(html) {
}
return result;
}
-$.summernote.pluginEvents.codeview = function (event, editor, layoutInfo) {
+
+/*
+ * This override when clicking on the 'Code View' button has two aims:
+ *
+ * - have our own code view implementation for FieldTextHtml
+ * - add an 'enable' paramater to call the function directly and allow us to
+ * disable (false) or enable (true) the code view mode.
+ */
+$.summernote.pluginEvents.codeview = function (event, editor, layoutInfo, enable) {
+ if (layoutInfo === undefined) {
+ return;
+ }
if (layoutInfo.toolbar) {
+ // if editor inline (FieldTextHtmlSimple)
+ var is_activated = $.summernote.eventHandler.modules.codeview.isActivated(layoutInfo);
+ if (is_activated === enable) {
+ return;
+ }
return eventHandler.modules.codeview.toggle(layoutInfo);
} else {
+ // if editor iframe (FieldTextHtml)
var $editor = layoutInfo.editor();
var $textarea = $editor.prev('textarea');
+ if ($textarea.is('textarea') === enable) {
+ return;
+ }
if (!$textarea.length) {
// init and create texarea
diff --git a/addons/web_editor/static/src/js/tour.rte.js b/addons/web_editor/static/src/js/tour.rte.js
index 2d85600e578..5ca69cd0e13 100644
--- a/addons/web_editor/static/src/js/tour.rte.js
+++ b/addons/web_editor/static/src/js/tour.rte.js
@@ -403,6 +403,51 @@ Tour.register({
});
+Tour.register({
+ id: 'rte_backend_inline',
+ name: "Test RTE in backend view",
+ mode: 'test',
+ steps: [
+ {
+ title: "Beginning test",
+ },
+ {
+ title: "Click on edit button",
+ element: '.o_form_button_edit, .oe_form_button_edit',
+ },
+ {
+ title: "Add text to inline html field and save",
+ element: '.o_form_button_save, .oe_form_button_save',
+ onload: function(){
+ $('.oe_form_field_html_text .note-editable > p').append('world');
+ },
+ },
+ {
+ title: "Verify saved data after edition then click on edit button",
+ waitFor: '.oe_form_field_html_text p > i:last-child:contains(world)',
+ element: '.o_form_button_edit, .oe_form_button_edit',
+ },
+ {
+ title: "Switch to code view mode",
+ element: 'button[data-event="codeview"]',
+ },
+ {
+ title: "Modify code view content and save",
+ element: '.o_form_button_save, .oe_form_button_save',
+ onload: function(){
+ $('.oe_form_field_html_text textarea.note-codable').val(function(_, val){
+ return val.replace('', '!');
+ });
+ },
+ },
+ {
+ title: "Verify saved data after code view edition",
+ waitFor: '.oe_form_field_html_text p > u:last-child:contains(!)',
+ },
+ ]
+});
+
+
});
});
diff --git a/addons/web_editor/tests/__init__.py b/addons/web_editor/tests/__init__.py
index ee3fba301a9..7c583996806 100644
--- a/addons/web_editor/tests/__init__.py
+++ b/addons/web_editor/tests/__init__.py
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import test_ui
import test_converter
+import test_backend_view
diff --git a/addons/web_editor/tests/test_backend_view.py b/addons/web_editor/tests/test_backend_view.py
new file mode 100644
index 00000000000..cceb2af3adf
--- /dev/null
+++ b/addons/web_editor/tests/test_backend_view.py
@@ -0,0 +1,15 @@
+from openerp.api import Environment
+import openerp.tests
+
+@openerp.tests.common.at_install(False)
+@openerp.tests.common.post_install(True)
+class TestBackendView(openerp.tests.HttpCase):
+
+ def test_01_rte_backend_inline(self):
+ """ Test saving inline editor in or out of code view mode. """
+ with self.registry.cursor() as test_cursor:
+ env = Environment(test_cursor, self.uid, {})
+ test_record = env['web_editor.converter.test'].create({'html': 'hello
'})
+ form_url = "/web?debug#id={}&view_type=form&model=web_editor.converter.test".format(test_record.id)
+
+ self.phantom_js(form_url, "odoo.__DEBUG__.services['web.Tour'].run('rte_backend_inline', 'test')", "odoo.__DEBUG__.services['web.Tour'].tours.rte", login="admin")