summaryrefslogtreecommitdiff
path: root/addons/web/static
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-07-13 14:32:05 +0200
committerChristophe Simonis <chs@odoo.com>2018-07-13 14:32:05 +0200
commitf3929aa0f75c2d3ac039bfc5bd41194516ae5571 (patch)
tree6ef909a475e4e99d1e9eb9c3d2e6c891fc7ad892 /addons/web/static
parente8fc62ec74f94fd1bfea105a15082dfede4dc987 (diff)
parent87dadc5bc83714cb0e748824f57e4cd35d02bbbf (diff)
[MERGE] forward port branch saas-11.2 up to 87dadc5bc83
Diffstat (limited to 'addons/web/static')
-rw-r--r--addons/web/static/src/js/chrome/control_panel.js14
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js12
-rw-r--r--addons/web/static/tests/chrome/action_manager_tests.js56
-rw-r--r--addons/web/static/tests/views/form_tests.js36
4 files changed, 114 insertions, 4 deletions
diff --git a/addons/web/static/src/js/chrome/control_panel.js b/addons/web/static/src/js/chrome/control_panel.js
index 4104f37bd3e..0913b574a3d 100644
--- a/addons/web/static/src/js/chrome/control_panel.js
+++ b/addons/web/static/src/js/chrome/control_panel.js
@@ -148,15 +148,25 @@ var ControlPanel = Widget.extend({
}
// Detach control_panel old content and attach new elements
+ var toDetach = this.nodes;
+ if (status.searchview && this.searchview === status.searchview) {
+ // If the searchview is the same as before, don't detach it s.t.
+ // we don't loose any floating content, nor the focus
+ toDetach = _.omit(toDetach, '$searchview');
+ new_cp_content = _.omit(new_cp_content, '$searchview');
+ }
if (options.clear) {
- this._detach_content(this.nodes);
+ this._detach_content(toDetach);
// Show the searchview buttons area, which might have been hidden by
// the searchview, as client actions may insert elements into it
this.nodes.$searchview_buttons.show();
} else {
- this._detach_content(_.pick(this.nodes, _.keys(new_cp_content)));
+ this._detach_content(_.pick(toDetach, _.keys(new_cp_content)));
}
this._attach_content(new_cp_content);
+ if (options.clear || status.searchview) {
+ this.searchview = status.searchview;
+ }
// Update the searchview and switch buttons
if (status.searchview || options.clear) {
diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js
index a12b85abdd0..a0ce8d31af4 100644
--- a/addons/web/static/src/js/views/list/list_editable_renderer.js
+++ b/addons/web/static/src/js/views/list/list_editable_renderer.js
@@ -861,8 +861,16 @@ ListRenderer.include({
*/
_onRemoveIconClick: function (event) {
event.stopPropagation();
- var id = $(event.target).closest('tr').data('id');
- this.trigger_up('list_record_remove', {id: id});
+ var $row = $(event.target).closest('tr');
+ var id = $row.data('id');
+ if ($row.hasClass('o_selected_row')) {
+ this.trigger_up('list_record_remove', {id: id});
+ } else {
+ var self = this;
+ this.unselectRow().then(function () {
+ self.trigger_up('list_record_remove', {id: id});
+ });
+ }
},
/**
* If the list view editable, just let the event bubble. We don't want to
diff --git a/addons/web/static/tests/chrome/action_manager_tests.js b/addons/web/static/tests/chrome/action_manager_tests.js
index dee1b0dbb3f..95e5742e95f 100644
--- a/addons/web/static/tests/chrome/action_manager_tests.js
+++ b/addons/web/static/tests/chrome/action_manager_tests.js
@@ -3431,6 +3431,62 @@ QUnit.module('ActionManager', {
actionManager.destroy();
});
+
+ QUnit.module('Search View Action');
+
+ QUnit.test('search view should keep focus during do_search', function (assert) {
+ assert.expect(5);
+
+ /* One should be able to type something in the search view, press on enter to
+ * make the facet and trigger the search, then do this process
+ * over and over again seamlessly.
+ * Verifying the input's value is a lot trickier than verifying the search_read
+ * because of how native events are handled in tests
+ */
+
+ var searchDeferred = $.Deferred();
+
+ var actionManager = createActionManager({
+ actions: this.actions,
+ archs: this.archs,
+ data: this.data,
+ mockRPC: function (route, args) {
+ if (route === '/web/dataset/search_read') {
+ assert.step('search_read ' + args.domain);
+ if ( _.isEqual(args.domain, [['foo', 'ilike', 'm']])) {
+ return searchDeferred.then(this._super.bind(this, route, args));
+ }
+ }
+ return this._super.apply(this, arguments);
+ }
+ });
+
+ actionManager.doAction(3);
+
+ var $searchInput = $('.o_searchview input');
+ $searchInput.trigger($.Event('keypress', {key: 'm', which: 109, keyCode: 109}));
+ $searchInput.trigger($.Event('keydown', {key: 'Enter', which: 13, keyCode: 13}));
+
+ assert.verifySteps(["search_read ",
+ "search_read foo,ilike,m"]);
+
+ // Triggering the do_search above will kill the current searchview Input
+ $searchInput = $('.o_searchview input');
+ $searchInput.trigger($.Event('keypress', {key: 'o', which: 111, keyCode: 111}));
+
+ // We have something in the input of the search view. Making the search_read
+ // return at this point will trigger the redraw of the view.
+ // However we want to hold on to what we just typed
+ searchDeferred.resolve();
+
+ $searchInput.trigger($.Event('keydown', {key: 'Enter', which: 13, keyCode: 13}));
+
+ assert.verifySteps(["search_read ",
+ "search_read foo,ilike,m",
+ "search_read |,foo,ilike,m,foo,ilike,o"]);
+
+ actionManager.destroy();
+ });
});
});
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index f53bac54e3a..a6176ab4328 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -3117,6 +3117,42 @@ QUnit.module('Views', {
form.destroy();
});
+ QUnit.test('delete a line in a one2many while editing another line triggers a warning', function (assert) {
+ assert.expect(3);
+
+ this.data.partner.records[0].p = [1, 2];
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form>' +
+ '<field name="p">' +
+ '<tree editable="bottom">' +
+ '<field name="display_name" required="True"/>' +
+ '</tree>' +
+ '</field>' +
+ '</form>',
+ res_id: 1,
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+ form.$('.o_data_cell').first().click(); // edit first row
+ form.$('input').val('').trigger('input');
+ form.$('.fa-trash-o').eq(1).click(); // delete second row
+
+ assert.strictEqual($('.modal').find('.modal-title').first().text(), "Warning",
+ "Clicking out of a dirty line while editing should trigger a warning modal.");
+
+ $('.modal').find('.btn-primary').click(); // discard changes
+
+ assert.strictEqual(form.$('.o_data_cell').first().text(), "first record",
+ "Value should have been reset to what it was before editing began.");
+ assert.strictEqual(form.$('.o_data_row').length, 1,
+ "The other line should have been deleted.");
+ form.destroy();
+ });
+
QUnit.test('properly apply onchange on many2many fields', function (assert) {
assert.expect(14);