From 178873d4337148e75041c61c9cd1862edaafa37d Mon Sep 17 00:00:00 2001 From: Khoi Nguyen Date: Mon, 14 Aug 2017 14:53:44 +0200 Subject: [FIX] web: fix copy (Ctrl-C) of text field content in Firefox Before this commit, it was not possible to copy the contents of a multiline text field in read-only mode in Firefox without losing all line breaks in the process. This is due to a bug affecting div tags (see https://bugzilla.mozilla.org/show_bug.cgi?id=1390115) in Firefox. This commit ensures that the text in a text field is surrounded by a span (as opposed to div) tag. Note that spans were used in saas-15, so we are in fact simply undoing the change to divs introduced by the new views. --- addons/web/static/src/js/fields/basic_fields.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/web/static/src/js/fields') diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 0cb08b55d02..ec04f67e270 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -791,6 +791,7 @@ var FieldFloatTime = FieldFloat.extend({ var FieldText = InputField.extend(TranslatableFieldMixin, { className: 'o_field_text', supportedFieldTypes: ['text'], + tagName: 'span', /** * @constructor -- cgit v1.2.3 From b9bfec96dd038d23e26cc822560fee452a0a3271 Mon Sep 17 00:00:00 2001 From: Adrien Dieudonne Date: Wed, 16 Aug 2017 13:21:54 +0200 Subject: [FIX] web: don't apply timezone offset for date fields Before this rev., all date fields values were off by one day as soon as the user timezone was negative. With the new views, all dates manipulated by the JS are moment instances in UTC, and when being displayed, they are correctly formatted in the user locale by applying the timezone offset. However, this should obviously not be done for date fields as when no time is specified when creating a moment instance, it defaults to 00:00:00, so applying a negative offset always leads to the day before. Remark: It happens that datetime fields are displayed as a date (e.g. purchase order line form view). In that case, the offset is applied on the displayed date. --- addons/web/static/src/js/fields/field_utils.js | 11 +++++------ addons/web/static/src/js/fields/special_fields.js | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'addons/web/static/src/js/fields') diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js index 0a44a52e315..787f66080dd 100644 --- a/addons/web/static/src/js/fields/field_utils.js +++ b/addons/web/static/src/js/fields/field_utils.js @@ -95,8 +95,10 @@ function formatDate(value, field, options) { if (value === false) { return ""; } - if (!options || !('timezone' in options) || options.timezone) { - value = value.clone().add(session.tzOffset < 0 ? -1 : 0, 'days'); + if (field && field.type === 'datetime') { + if (!options || !('timezone' in options) || options.timezone) { + value = value.clone().add(session.tzOffset, 'minutes'); + } } var l10n = core._t.database.parameters; var date_format = time.strftime_to_moment_format(l10n.date_format); @@ -357,11 +359,8 @@ function parseDate(value, field, options) { date = moment.utc(value); } else { date = moment.utc(value, [datePattern, datePatternWoZero, moment.ISO_8601], true); - if (options && options.timezone) { - date.add(session.tzOffset > 0 ? -1 : 0, 'days'); - } } - if (date.isValid() && date.year() >= 1900) { + if (date.isValid()) { if (date.year() === 0) { date.year(moment.utc().year()); } diff --git a/addons/web/static/src/js/fields/special_fields.js b/addons/web/static/src/js/fields/special_fields.js index 69647902afe..7a0bb9ed092 100644 --- a/addons/web/static/src/js/fields/special_fields.js +++ b/addons/web/static/src/js/fields/special_fields.js @@ -54,7 +54,7 @@ var FieldTimezoneMismatch = FieldSelection.extend({ } var offset = this.recordData.tz_offset.match(/([+-])([0-9]{2})([0-9]{2})/); offset = (offset[1] === '-' ? -1 : 1) * (parseInt(offset[2])*60 + parseInt(offset[3])); - var datetime = field_utils.format.datetime(moment.utc().add(offset, 'minutes'), {timezone: false}); + var datetime = field_utils.format.datetime(moment.utc().add(offset, 'minutes'), this.field, {timezone: false}); var content = this.$option.html().split(' ')[0]; content += ' ('+ datetime + ')'; this.$option.html(content); -- cgit v1.2.3 From f5b7ad80fcfd1638cb7ea019a38871c3b8438e36 Mon Sep 17 00:00:00 2001 From: Adrien Dieudonne Date: Wed, 16 Aug 2017 14:49:08 +0200 Subject: [FIX] web: always use browser timezone With the new views, we stopped using the browser timezone to display the dates in Odoo, and we used the timezone defined on the User profile instead. When loading the webclient, the timezone offset was put into the session and used to display all dates. This wasn't a good idea. The given offset was computed for the current time, meaning that it may be incorrect for specific dates (e.g. with the daylight saving, the UTC offset of today is not the same as 6 months ago). Moreover (but less likely), as the offset was stored in the session, it wasn't recalculated afterwards. So if the offset actually changed during the session (e.g. from or to daylight saving time), the displayed dates were incorrect until the user reloaded the page. With this rev., we don't retrieve the offset from the server anymore and we use the browser timezone again (like before the new views). However, we keep the computation of the offset (on the fly) in the session, so that it can be mocked in the test environment. --- addons/web/static/src/js/fields/basic_fields.js | 6 +++--- addons/web/static/src/js/fields/field_utils.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'addons/web/static/src/js/fields') diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index ec04f67e270..035d24dbdf2 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -450,7 +450,7 @@ var FieldDateTime = FieldDate.extend({ */ _getValue: function () { var value = this.datewidget.getValue(); - return value && value.add(-this.getSession().tzOffset, 'minutes'); + return value && value.add(-this.getSession().getTZOffset(value), 'minutes'); }, /** @@ -460,7 +460,7 @@ var FieldDateTime = FieldDate.extend({ * @private */ _makeDatePicker: function () { - var value = this.value && this.value.clone().add(this.getSession().tzOffset, 'minutes'); + var value = this.value && this.value.clone().add(this.getSession().getTZOffset(this.value), 'minutes'); return new datepicker.DateTimeWidget(this, {defaultDate: value}); }, @@ -471,7 +471,7 @@ var FieldDateTime = FieldDate.extend({ * @private */ _renderEdit: function () { - var value = this.value && this.value.clone().add(this.getSession().tzOffset, 'minutes'); + var value = this.value && this.value.clone().add(this.getSession().getTZOffset(this.value), 'minutes'); this.datewidget.setValue(value); this.$input = this.datewidget.$input; }, diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js index 787f66080dd..db5cd34d8b9 100644 --- a/addons/web/static/src/js/fields/field_utils.js +++ b/addons/web/static/src/js/fields/field_utils.js @@ -97,7 +97,7 @@ function formatDate(value, field, options) { } if (field && field.type === 'datetime') { if (!options || !('timezone' in options) || options.timezone) { - value = value.clone().add(session.tzOffset, 'minutes'); + value = value.clone().add(session.getTZOffset(value), 'minutes'); } } var l10n = core._t.database.parameters; @@ -123,7 +123,7 @@ function formatDateTime(value, field, options) { return ""; } if (!options || !('timezone' in options) || options.timezone) { - value = value.clone().add(session.tzOffset, 'minutes'); + value = value.clone().add(session.getTZOffset(value), 'minutes'); } var l10n = core._t.database.parameters; var date_format = time.strftime_to_moment_format(l10n.date_format); @@ -404,7 +404,7 @@ function parseDateTime(value, field, options) { } else { datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601], true); if (options && options.timezone) { - datetime.add(-session.tzOffset, 'minutes'); + datetime.add(-session.getTZOffset(datetime), 'minutes'); } } if (datetime.isValid()) { -- cgit v1.2.3 From 0966f75b7e874bab69173918cbaf38cf031c21bd Mon Sep 17 00:00:00 2001 From: Richard Mathot Date: Fri, 18 Aug 2017 10:55:09 +0200 Subject: [FIX] web: enforce length-limited char fields In Odoo 10.0, `Char` fields with a maximum `size=` attribute were indeed limited in the web client. --- addons/web/static/src/js/fields/basic_fields.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'addons/web/static/src/js/fields') diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 035d24dbdf2..c69ca8bd2e8 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -341,6 +341,9 @@ var FieldChar = InputField.extend(TranslatableFieldMixin, { */ _renderEdit: function () { var def = this._super.apply(this, arguments); + if (this.field.size && this.field.size > 0) { + this.$el.attr('maxlength', this.field.size); + } this.$el = this.$el.add(this._renderTranslateButton()); return def; }, -- cgit v1.2.3 From dbab6f74171c895ba8196653b2755361ac34a823 Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Fri, 18 Aug 2017 15:35:17 +0200 Subject: [FIX] web: advanced use of widget `reference` The reference widget is also meant to be used on a char field, not only on a reference field. The rev. https://github.com/odoo/odoo/commit/a4e30a1b43d0b9acd76508d9e6c466cd1dbdffab removed the use of `field_utils.format.many2one` and replaced it by `_formatValue` to support this use case. The replacement wasn't complete as some occurences was remaining (in reset), which led to traceback when the widget was reset (impossible to create an External Identifier anymore). Also, the reference `_formatValue` wasn't correct as it was displaying the record `display_name` and not the reference field value ; this only makes sense for the External Identifier as its display name is the reference field value but it doesn't make any sense for other reference field. Last but not least, this commit implements the `onchange` and `default_get` for the reference field. --- .../web/static/src/js/fields/relational_fields.js | 49 ++++++++++++---------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'addons/web/static/src/js/fields') diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 0dce6ec2bb4..7b1aa80a835 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -21,7 +21,6 @@ var dialogs = require('web.view_dialogs'); var core = require('web.core'); var data = require('web.data'); var Dialog = require('web.Dialog'); -var field_utils = require('web.field_utils'); var KanbanRenderer = require('web.KanbanRenderer'); var ListRenderer = require('web.ListRenderer'); var Pager = require('web.Pager'); @@ -290,7 +289,7 @@ var FieldMany2One = AbstractField.extend({ _reset: function () { this._super.apply(this, arguments); this.floating = false; - this.m2o_value = field_utils.format.many2one(this.value); + this.m2o_value = this._formatValue(this.value); }, /** * @private @@ -567,7 +566,7 @@ var KanbanFieldMany2One = AbstractField.extend({ tagName: 'span', init: function () { this._super.apply(this, arguments); - this.m2o_value = field_utils.format.many2one(this.value); + this.m2o_value = this._formatValue(this.value); }, //-------------------------------------------------------------------------- @@ -2023,7 +2022,8 @@ var FieldRadio = FieldSelection.extend({ * `name_get` as data). */ var FieldReference = FieldMany2One.extend({ - supportedFieldTypes: ['reference'], + specialData: "_fetchSpecialReference", + supportedFieldTypes: ['char', 'reference'], template: 'FieldReference', events: _.extend({}, FieldMany2One.prototype.events, { 'change select': '_onSelectionChange', @@ -2036,22 +2036,8 @@ var FieldReference = FieldMany2One.extend({ // needs to be copied as it is an unmutable object this.field = _.extend({}, this.field); - if (this.value) { - var model = null; - // The value of a Reference field can either be a string in the form - // of model,record_id or an object - if (typeof this.value === "string") { - var value = this.value.split(','); - model = value[0]; - this.value = { - res_id: parseInt(value[1]), - }; - } else { - model = this.value.model; - } - this._setRelation(model); - } + this._setState(); }, /** * @override @@ -2071,7 +2057,13 @@ var FieldReference = FieldMany2One.extend({ * @override */ _formatValue: function () { - return this.recordData.display_name; + var value; + if (this.field.type === 'char') { + value = this.record.specialData[this.name]; + } else { + value = this.value; + } + return value && value.data && value.data.display_name || ''; }, /** @@ -2097,8 +2089,10 @@ var FieldReference = FieldMany2One.extend({ * @private */ _reset: function () { + var value = this.$('select').val(); + this._setState(); this._super.apply(this, arguments); - this._setRelation(this.value && this.value.model); + this.$('select').val(this.value && this.value.model || value); }, /** * Set `relation` key in field properties. @@ -2110,6 +2104,19 @@ var FieldReference = FieldMany2One.extend({ // used to generate the search in many2one this.field.relation = model; }, + /** + * @private + */ + _setState: function () { + if (this.field.type === 'char') { + // in this case, the value is stored in specialData instead + this.value = this.record.specialData[this.name]; + } + + if (this.value) { + this._setRelation(this.value.model); + } + }, /** * @override * @private -- cgit v1.2.3 From e0d5a875f02ae0c986d9684b067a62e46f8c5e1f Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Tue, 22 Aug 2017 16:19:58 +0200 Subject: [FIX] web: make "slow" create of m2o fields work There were some coding mistakes since some changes introduced by https://github.com/odoo/odoo/commit/d19671f0d0ff7189055cbe0794afed32f8a387e6 --- addons/web/static/src/js/fields/relational_fields.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/web/static/src/js/fields') diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 7b1aa80a835..e05a53194c3 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -225,7 +225,7 @@ var FieldMany2One = AbstractField.extend({ var self = this; var def = $.Deferred(); var slowCreate = function () { - var dialog = self._searchCreatePopup.bind(self, "form", false, self._createContext(name)); + var dialog = self._searchCreatePopup("form", false, self._createContext(name)); dialog.on('closed', self, def.resolve.bind(def)); }; if (this.nodeOptions.quick_create) { @@ -393,7 +393,7 @@ var FieldMany2One = AbstractField.extend({ */ _searchCreatePopup: function (view, ids, context) { var self = this; - new dialogs.SelectCreateDialog(this, _.extend({}, this.nodeOptions, { + return new dialogs.SelectCreateDialog(this, _.extend({}, this.nodeOptions, { res_model: this.field.relation, domain: this.record.getDomain({fieldName: this.name}), context: _.extend({}, this.record.getContext(this.recordParams), context || {}), -- cgit v1.2.3