summaryrefslogtreecommitdiff
path: root/addons/web
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
parente8fc62ec74f94fd1bfea105a15082dfede4dc987 (diff)
parent87dadc5bc83714cb0e748824f57e4cd35d02bbbf (diff)
[MERGE] forward port branch saas-11.2 up to 87dadc5bc83
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/controllers/main.py2
-rw-r--r--addons/web/models/ir_http.py4
-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
-rw-r--r--addons/web/views/report_templates.xml3
7 files changed, 118 insertions, 9 deletions
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index f4cddcc1ee2..41d5d229772 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -1496,6 +1496,8 @@ class ExcelExport(ExportFormat, http.Controller):
if isinstance(cell_value, pycompat.string_types):
cell_value = re.sub("\r", " ", pycompat.to_text(cell_value))
+ # Excel supports a maximum of 32767 characters in each cell:
+ cell_value = cell_value[:32767]
elif isinstance(cell_value, datetime.datetime):
cell_style = datetime_style
elif isinstance(cell_value, datetime.date):
diff --git a/addons/web/models/ir_http.py b/addons/web/models/ir_http.py
index bbe793812b9..46bc09a3022 100644
--- a/addons/web/models/ir_http.py
+++ b/addons/web/models/ir_http.py
@@ -26,7 +26,7 @@ class Http(models.AbstractModel):
"session_id": request.session.sid,
"uid": request.session.uid,
"is_system": user._is_system(),
- "is_superuser": user._is_superuser(),
+ "is_superuser": user._is_superuser() if request.session.uid else False,
"user_context": request.session.get_context() if request.session.uid else {},
"db": request.session.db,
"server_version": version_info.get('server_version'),
@@ -37,7 +37,7 @@ class Http(models.AbstractModel):
"company_id": user.company_id.id if request.session.uid else None,
"partner_id": user.partner_id.id if request.session.uid and user.partner_id else None,
"user_companies": {'current_company': (user.company_id.id, user.company_id.name), 'allowed_companies': [(comp.id, comp.name) for comp in user.company_ids]} if display_switch_company_menu else False,
- "currencies": self.get_currencies(),
+ "currencies": self.get_currencies() if request.session.uid else {},
"web.base.url": self.env['ir.config_parameter'].sudo().get_param('web.base.url', default=''),
}
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);
diff --git a/addons/web/views/report_templates.xml b/addons/web/views/report_templates.xml
index c26e1e2bf45..a675bfbd161 100644
--- a/addons/web/views/report_templates.xml
+++ b/addons/web/views/report_templates.xml
@@ -14,9 +14,6 @@
<link href="/portal/static/src/less/portal.less" rel="stylesheet" type="text/less"/>
<link href="/website/static/src/less/website.less" rel="stylesheet" type="text/less"/>
- <!-- TODO: Put in the right report ..? -->
- <link href="https://fonts.googleapis.com/css?family=Work+Sans:thin,light,regular,medium,bold,semi-bold" rel="stylesheet"/>
-
<link href="/web/static/lib/fontawesome/css/font-awesome.css" rel="stylesheet" type="text/css"/>
<link href="/web/static/src/less/report.less" rel="stylesheet" type="text/less"/>