From 34e5271d7b05a20ac7609f2bd8a2ca1561326e94 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Thu, 12 Sep 2019 08:31:05 +0000 Subject: [FIX] web: list: multi edit input of date(time) fields The Date(Time)Fields listen to 'input' and 'change' events (like all InputFields) to keep track of changes. However, the datepicker already listens to the 'change' event. As a consequence, in multi edition in a list view, if the user changed the value of a date(time) field by directly editing the input, the fieldChanged event was triggered twice, and there were 2 dialogs asking the user if he wanted to save the change. This rev. makes the Date(Time)Fields stop listening themselves to 'input' and 'change' events, and instead completely rely on the datepicker widget. Task 2068280 --- addons/web/static/src/js/fields/basic_fields.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'addons/web/static/src/js/fields/basic_fields.js') diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index da46488cffa..3dc90ea6afe 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -684,6 +684,9 @@ var FieldDate = InputField.extend({ className: "o_field_date", tagName: "span", supportedFieldTypes: ['date', 'datetime'], + // we don't need to listen on 'input' nor 'change' events because the + // datepicker widget is already listening, and will correctly notify changes + events: AbstractField.prototype.events, /** * @override -- cgit v1.2.3 From 708a5b656618e1bcc8034bd7feddfcb5aac6a998 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 13 Sep 2019 09:28:31 +0000 Subject: [FIX] web: list: multi edit boolean with ENTER This rev. solves the similar issue as 801c603218, but with boolean fields. Scenario: select several records, select a boolean cell, press enter to change the boolean value. Task 2068280 --- addons/web/static/src/js/fields/basic_fields.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'addons/web/static/src/js/fields/basic_fields.js') diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 3dc90ea6afe..a2f4917b699 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1083,6 +1083,8 @@ var FieldBoolean = AbstractField.extend({ _onKeydown: function (ev) { switch (ev.which) { case $.ui.keyCode.ENTER: + // prevent subsequent 'click' event (see _onKeydown of AbstractField) + ev.preventDefault(); this.$input.prop('checked', !this.value); this._setValue(!this.value); return; -- cgit v1.2.3 From fa283d3d4eb73eab34d6ae5c8af5623ab07eea49 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Mon, 2 Sep 2019 13:39:38 +0000 Subject: [FIX] web: progress bar feature The progress bar was pretty broken before this commit. > It was not possible to input the value as text > Moving the progress bar to modify value and saving crashed > modifying the max value crashed > The whole feature was ill-defined With this commit, we fix the crashed. It is now possible to write the field behind the progress bar by moving it in RO mode or by typing the input in RW mode *if it is the value we want to write on* It it is the max value that the field targets, we can do it in RO and RW mode, only with the input as text Note that this works *only if* the editable option on the widget is set to true OPW 2061846 closes odoo/odoo#36928 closes odoo/odoo#36970 Signed-off-by: Lucas Perais (lpe) Signed-off-by: Lucas Perais (lpe) --- addons/web/static/src/js/fields/basic_fields.js | 101 ++++++++++++++++-------- 1 file changed, 66 insertions(+), 35 deletions(-) (limited to 'addons/web/static/src/js/fields/basic_fields.js') diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index b3bf09ab88d..38276373cc2 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -2306,11 +2306,28 @@ var FieldProgressBar = AbstractField.extend({ if (this.recordData[this.nodeOptions.current_value]) { this.value = this.recordData[this.nodeOptions.current_value]; } - this.max_value = this.recordData[this.nodeOptions.max_value] || 100; + + // The few next lines determine if the widget can write on the record or not + this.editable_readonly = !!this.nodeOptions.editable_readonly; + // "hard" readonly this.readonly = this.nodeOptions.readonly || !this.nodeOptions.editable; - this.edit_max_value = this.nodeOptions.edit_max_value || false; + + this.canWrite = !this.readonly && ( + this.mode === 'edit' || + (this.editable_readonly && this.mode === 'readonly') || + (this.viewType === 'kanban') // Keep behavior before commit + ); + + // Boolean to toggle if we edit the numerator (value) or the denominator (max_value) + this.edit_max_value = !!this.nodeOptions.edit_max_value; + this.max_value = this.recordData[this.nodeOptions.max_value] || 100; + this.title = _t(this.attrs.title || this.nodeOptions.title) || ''; - this.edit_on_click = !this.nodeOptions.edit_max_value || false; + + // Ability to edit the field through the bar + // /!\ this feature is disabled + this.enableBarAsInput = false; + this.edit_on_click = this.enableBarAsInput && this.mode === 'readonly' && !this.edit_max_value; this.write_mode = false; }, @@ -2318,19 +2335,19 @@ var FieldProgressBar = AbstractField.extend({ var self = this; this._render_value(); - if (!this.readonly) { + if (this.canWrite) { if (this.edit_on_click) { this.$el.on('click', '.o_progress', function (e) { var $target = $(e.currentTarget); - self.value = Math.floor((e.pageX - $target.offset().left) / $target.outerWidth() * self.max_value); + var numValue = Math.floor((e.pageX - $target.offset().left) / $target.outerWidth() * self.max_value); + self.on_update(numValue); self._render_value(); - self.on_update(self.value); }); } else { this.$el.on('click', function () { if (!self.write_mode) { var $input = $('', {type: 'text', class: 'o_progressbar_value o_input'}); - $input.on('blur', _.bind(self.on_change_input, self)); + $input.on('blur', self.on_change_input.bind(self)); self.$('.o_progressbar_value').replaceWith($input); self.write_mode = true; self._render_value(); @@ -2340,24 +2357,25 @@ var FieldProgressBar = AbstractField.extend({ } return this._super(); }, + /** + * Updates the widget with value + * + * @param {Number} value + */ on_update: function (value) { - if (!isNaN(value)) { - if (this.edit_max_value) { - try { - this.max_value = this._parseValue(value); - this._isValid = true; - } catch (e) { - this._isValid = false; - } - var changes = {}; - changes[this.nodeOptions.max_value] = this.max_value; - this.trigger_up('field_changed', { - dataPointID: this.dataPointID, - changes: changes, - }); - } else { - this._setValue(value); - } + if (this.edit_max_value) { + this.max_value = value; + this._isValid = true; + var changes = {}; + changes[this.nodeOptions.max_value] = this.max_value; + this.trigger_up('field_changed', { + dataPointID: this.dataPointID, + changes: changes, + }); + } else { + // _setValues accepts string and will parse it + var formattedValue = this._formatValue(value); + this._setValue(formattedValue); } }, on_change_input: function (e) { @@ -2365,29 +2383,42 @@ var FieldProgressBar = AbstractField.extend({ if (e.type === 'change' && !$input.is(':focus')) { return; } - if (isNaN($input.val())) { - this.do_warn(_t("Wrong value entered!"), _t("Only Integer Value should be valid.")); - } else { - if (e.type === 'input') { - this._render_value($input.val()); - if (parseFloat($input.val()) === 0) { + + var parsedValue; + try { + // Cover all numbers with parseFloat + parsedValue = field_utils.parse.float($input.val()); + } catch (error) { + this.do_warn(_t("Wrong value entered!"), _t("Only Integer or Float Value should be valid.")); + } + + if (parsedValue !== undefined) { + if (e.type === 'input') { // ensure what has just been typed in the input is a number + // returns NaN if not a number + this._render_value(parsedValue); + if (parsedValue === 0) { $input.select(); } - } else { + } else { // Implicit type === 'blur': we commit the value if (this.edit_max_value) { - this.max_value = $(e.target).val(); - } else { - this.value = $(e.target).val() || 0; + parsedValue = parsedValue || 100; } + var $div = $('
', {class: 'o_progressbar_value'}); this.$('.o_progressbar_value').replaceWith($div); this.write_mode = false; + this.on_update(parsedValue); this._render_value(); - this.on_update(this.edit_max_value ? this.max_value : this.value); } } }, + /** + * Renders the value + * + * @private + * @param {Number} v + */ _render_value: function (v) { var value = this.value; var max_value = this.max_value; -- cgit v1.2.3