From 21c1b1acd34406d1c568a66976c69511a656861e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 25 Jan 2018 15:25:30 +0100 Subject: [FIX] web: add target=_blank to url field widgets Url in the web client are supposed to open in a new tab. This was the way it worked in v10.0 and was lost with the refactoring of the new views. We just reintroduce that behaviour with this commit. Closes github issue #22389 --- addons/web/static/src/js/fields/basic_fields.js | 1 + addons/web/static/tests/fields/basic_fields_tests.js | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'addons/web/static') diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 09406b43711..26e7d86fabc 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1068,6 +1068,7 @@ var UrlWidget = InputField.extend({ _renderReadonly: function () { this.$el.text(this.attrs.text || this.value) .addClass('o_form_uri o_text_overflow') + .attr('target', '_blank') .attr('href', this.value); } }); diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 9ea423250e4..fdc8c530af8 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1073,7 +1073,7 @@ QUnit.module('basic_fields', { QUnit.module('UrlWidget'); QUnit.test('url widget in form view', function (assert) { - assert.expect(8); + assert.expect(9); var form = createView({ View: FormView, @@ -1093,6 +1093,8 @@ QUnit.module('basic_fields', { "should have a anchor with correct classes"); assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').attr('href'), 'yop', "should have proper href link"); + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').attr('target'), '_blank', + "should have target attribute set to _blank"); assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').text(), 'yop', "the value should be displayed properly"); -- cgit v1.2.3 From 5b230c34cb960f3f729d6612735dd9c3c896b785 Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Mon, 29 Jan 2018 10:29:12 +0100 Subject: [FIX] web: noshow list view aggregates w/ currency In df69b5bb the aggregates of a column with currency was shown only if records were of the same currency when a grouping was closed. But when the list view is grouped, this would cause a number of issue: - error if with first grouping is opened, another one is closed - if the first grouping was closed aggregates were always shown - the code only acts when closing a grouping - aggregates could be shown when they should not - aggregates could be not shown when they should So this commit change things so this feature is ignored when the list view is grouped. There is also a fix so `currency_field` of the column is used instead of just using `currency_id` that may be wrong. note: only for saas-14 and saas-15 (feature is not present in saas-16) opw-810835 closes #22598 --- addons/web/static/src/js/views/list_view.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'addons/web/static') diff --git a/addons/web/static/src/js/views/list_view.js b/addons/web/static/src/js/views/list_view.js index 83e1b7bf900..d28ac5e0774 100644 --- a/addons/web/static/src/js/views/list_view.js +++ b/addons/web/static/src/js/views/list_view.js @@ -713,6 +713,7 @@ var ListView = View.extend({ * @param {Array} [records] */ compute_aggregates: function (records) { + var self = this; var columns = _(this.aggregate_columns).filter(function (column) { return column['function']; }); if (_.isEmpty(columns)) { return; } @@ -763,8 +764,12 @@ var ListView = View.extend({ var aggregates = {}; _.each(_.filter(columns, function (column) { - if (column.currency_field && records.length > 0 && records[0].values['currency_id']) { - var currency_ids = _.map(records, function(record) {return record.values['currency_id'][0]}); + if (!self.grouped && column.currency_field) { + var currency_ids = _.map(records, function(record) { + if (record.values[column.currency_field]) { + return record.values[column.currency_field][0]; + } + }); if (_.every(currency_ids, function (currency_id){return currency_id === currency_ids[0]})) { return column; } -- cgit v1.2.3 From a4c7481f249a7e3d999189cfac907dadcd847a6a Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 31 Jan 2018 08:58:06 +0100 Subject: [FIX] web: auto-refresh of time When a TZ mismatch is detected, the datetime value is displayed in the widget. However, on MacOS, this forces the dropdown list to close at each refresh of the value, which occurs every second. The refresh interval is set to 1 minute in case of MacOS. opw-804035 --- addons/web/static/src/js/fields/special_fields.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'addons/web/static') diff --git a/addons/web/static/src/js/fields/special_fields.js b/addons/web/static/src/js/fields/special_fields.js index 19db97fe985..6bd5d03ac69 100644 --- a/addons/web/static/src/js/fields/special_fields.js +++ b/addons/web/static/src/js/fields/special_fields.js @@ -20,7 +20,8 @@ var FieldTimezoneMismatch = FieldSelection.extend({ * @override */ start: function () { - this._datetime = setInterval(this._renderDateTimeTimezone.bind(this), 1000); + var interval = navigator.platform.toUpperCase().indexOf('MAC') >= 0 ? 60000 : 1000; + this._datetime = setInterval(this._renderDateTimeTimezone.bind(this), interval); return this._super.apply(this, arguments); }, /** -- cgit v1.2.3 From e6cccbf441eddf48feaa0ff1e99ecf40f9f973ed Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Tue, 30 Jan 2018 11:04:57 +0100 Subject: [FIX] web: less boolean_toogle Before this commit, the boolean_toggle widget was rendered but the less contained errors that prevented it from displaying correctly This was due to commit 9dead7e3d33ee0ddafb55060b3f95027e9330e55 After this commit, the widget displays correctly There might be an issue in the future because of field_utils.formatBoolean, when this function decides to pass the full options dict OPW 80782 --- addons/web/static/src/less/webclient.less | 50 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'addons/web/static') diff --git a/addons/web/static/src/less/webclient.less b/addons/web/static/src/less/webclient.less index dfc26b11f5a..215b86cef83 100644 --- a/addons/web/static/src/less/webclient.less +++ b/addons/web/static/src/less/webclient.less @@ -86,39 +86,37 @@ div.o_boolean_toggle { width: 32px !important; height: 18px; - & > label { - & > input { + > input { display: none; } - & > .slider { + .slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #a0a0a0; + border-radius: 24px; + + &:before { position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: #a0a0a0; - border-radius: 24px; - - &:before { - position: absolute; - content: ""; - height: 12px; - width: 12px; - left: 3px; - bottom: 3px; - background-color: white; - border-radius: 50%; - } + content: ""; + height: 12px; + width: 12px; + left: 3px; + bottom: 3px; + background-color: white; + border-radius: 50%; } + } - & > input:checked + .slider { - background-color: @odoo-brand-optional; + > input:checked + .slider { + background-color: @odoo-brand-optional; - &:before { - .translate(14px; 0px); - } + &:before { + .translate(14px; 0px); } } } -- cgit v1.2.3 From eeebd4ad857fec39c14abc0a0e387c13adcfa30b Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Tue, 30 Jan 2018 10:41:11 +0100 Subject: [FIX] web: kanban containment Set up the following kanban columns: | Col 1 | Col 2 | Col 3 | Col 4 | Col 5 | Col 6 | F | | | | | | | Card | | <------- Screen width ----------> Col x are unfolded columns. F is a folded colum. Moving the Card from Col 6 to F is impossible: the card won't go 'out of the screen' on the right, which prevents its center to reach F. Commit 5ba6d93810ba44 deactivates the drag & drop on read-only fields. In order to restrict the kanban cards displacements, the `containment` attribute is used to either restrict the displacement: - in `o_kanban_view` if draggable - in the parent if not (to allow the resequence) The class `o_kanban_view` is too restrictive: when movind the card to the folded column F, the card must go out of `o_kanban_view`. opw-803929 --- addons/web/static/src/js/views/kanban/kanban_column.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static') diff --git a/addons/web/static/src/js/views/kanban/kanban_column.js b/addons/web/static/src/js/views/kanban/kanban_column.js index 82fc5d168ff..acb4a7bc412 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column.js +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -93,7 +93,7 @@ var KanbanColumn = Widget.extend({ // should find a way to use the touch events to make sortable work. this.$el.sortable({ connectWith: '.o_kanban_group', - containment: this.draggable ? '.o_kanban_view' : 'parent', + containment: this.draggable ? false : 'parent', revert: 0, delay: 0, items: '> .o_kanban_record:not(.o_updating)', -- cgit v1.2.3 From 695bd75a1383e88099a79de89db9ee1042c83d5e Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Wed, 31 Jan 2018 15:45:48 +0100 Subject: [FIX] web: invalid domain in DomainSelector Backport of this commit: c13c9e0b5c6ff8a8ae030ff2467d4675fb6197b8 Steps to reproduce the bug: - install application MRP Maintenance - open maintenance request form view, and from top right corner click Studio icon - click on Equipment field while you are still in studio interface - It will show left side studio panel, click Domain box and it will throw an error opw:813594 --- .../web/static/src/js/widgets/domain_selector.js | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'addons/web/static') diff --git a/addons/web/static/src/js/widgets/domain_selector.js b/addons/web/static/src/js/widgets/domain_selector.js index eccbd9d7491..5fd517ebc6f 100644 --- a/addons/web/static/src/js/widgets/domain_selector.js +++ b/addons/web/static/src/js/widgets/domain_selector.js @@ -110,7 +110,16 @@ var DomainTree = DomainNode.extend({ /// @see DomainTree._addFlattenedChildren init: function (parent, model, domain, options) { this._super.apply(this, arguments); - this._initialize(domainUtils.stringToDomain(domain)); + try { + domain = domainUtils.stringToDomain(domain); + } catch (err) { + // TODO: domain could contain `parent` for example, which is + // currently not handled by the DomainSelector + this.invalidDomain = true; + this.children = []; + return; + } + this._initialize(domain); }, /// @see DomainTree.init _initialize: function (domain) { @@ -279,6 +288,18 @@ var DomainSelector = DomainTree.extend({ } }, }), + + start: function () { + var self = this; + return this._super.apply(this, arguments).then(function () { + if (self.invalidDomain) { + var msg = _t("This domain is not supported."); + self.$el.html(msg); + } + }); + }, + + _initialize: function (domain) { // Check if the domain starts with implicit "&" operators and make them // explicit. As the DomainSelector is a specialization of a DomainTree, -- cgit v1.2.3 From 9fa597c7ec46c5fe446ab8cf6344ae31a079b044 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Mon, 29 Jan 2018 16:41:26 +0100 Subject: [FIX] web: sequence handlers on modal's one2many list From a form view (say Bill of materials) Edit the form Click on a bom line Click on the external button that makes the product form pop up change the order of suppliers on that product Before this commit, a JS traceback was raised This was because the changing object was not present in the localData that the Model object holds or more accurately, it was not the **right** model object that was targetted and this was due to the propagation of the resequence event After this commit, no error is thrown, and the resequencing works as expected OPW 807196 --- .../web/static/src/js/fields/relational_fields.js | 1 + .../static/tests/fields/relational_fields_tests.js | 87 ++++++++++++++++++++++ 2 files changed, 88 insertions(+) (limited to 'addons/web/static') diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index c399ffebe88..ee5b8c7726c 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -1104,6 +1104,7 @@ var FieldX2Many = AbstractField.extend({ * @param {OdooEvent} event */ _onResequence: function (event) { + event.stopPropagation(); var self = this; this.trigger_up('freeze_order', {id: this.value.id}); var rowIDs = event.data.rowIDs.slice(); diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index be922d3fa1a..31bd9183f58 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -1321,6 +1321,93 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('X2Many sequence list in modal', function (assert) { + assert.expect(5); + + this.data.partner.fields.sequence = {string: 'Sequence', type: 'integer'}; + this.data.partner.records[0].sequence = 1; + this.data.partner.records[1].sequence = 2; + this.data.partner.onchanges = { + sequence: function (obj) { + if (obj.id === 2) { + obj.sequence = 1; + assert.step('onchange sequence'); + } + }, + }; + + this.data.product.fields.turtle_ids = {string: 'Turtles', type: 'one2many', relation: 'turtle'}; + this.data.product.records[0].turtle_ids = [1]; + + this.data.turtle.fields.partner_types_ids = {string: "Partner", type: "one2many", relation: 'partner'}; + this.data.turtle.fields.type_id = {string: "Partner Type", type: "many2one", relation: 'partner_type'}; + + this.data.partner_type.fields.partner_ids = {string: "Partner", type: "one2many", relation: 'partner'}; + this.data.partner_type.records[0].partner_ids = [1,2]; + + testUtils.createAsyncView({ + View: FormView, + model: 'product', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '', + archs: { + 'partner_type,false,form': '
', + 'partner,false,list': '' + + '' + + '' + + '', + }, + res_id: 37, + mockRPC: function (route, args) { + if (route === '/web/dataset/call_kw/product/read') { + return $.when([{id: 37, name: 'xphone', display_name: 'leonardo', turtle_ids: [1]}]); + } + if (route === '/web/dataset/call_kw/turtle/read') { + return $.when([{id: 1, type_id: [12, 'gold']}]); + } + if (route === '/web/dataset/call_kw/partner_type/get_formview_id') { + return $.when(false) + } + if (route === '/web/dataset/call_kw/partner_type/read') { + return $.when([{id: 12, partner_ids: [1,2], display_name: 'gold'}]) + } + if (route === '/web/dataset/call_kw/partner_type/write') { + assert.step('partner_type write'); + } + return this._super.apply(this, arguments); + }, + }).then(function(form) { + form.$buttons.find('.o_form_button_edit').click(); + form.$('.o_data_cell').click(); + form.$('.o_external_button').click(); + + var $modal = $('.modal-dialog'); + assert.equal($modal.length, 1, + 'There should be 1 modal opened'); + + var $handles = $modal.find('.ui-sortable-handle'); + assert.equal($handles.length, 2, + 'There should be 2 sequence handlers'); + + testUtils.dragAndDrop($handles.eq(1), $modal.find('tbody tr').first()); + + // Saving the modal and then the original model + $modal.find('.modal-footer .btn-primary').click(); + form.$buttons.find('.o_form_button_save').click(); + + assert.verifySteps(['onchange sequence', 'partner_type write']); + + form.destroy(); + }); + }); + QUnit.test('autocompletion in a many2one, in form view with a domain', function (assert) { assert.expect(1); -- cgit v1.2.3