diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-01-03 14:05:48 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-01-03 14:05:48 +0100 |
| commit | 55b810dc70cccb23144986d54fd28bb5f91f2b1b (patch) | |
| tree | a83dda56dac7f02be26f6821dea5b2f1926ea7b0 /addons/web/static/src/js/fields/relational_fields.js | |
| parent | 8bc7cebd9c19ae8f77378d115a8401d7b7de56b0 (diff) | |
| parent | 726b91b9fbc994c6b2f2cb45e36d4c224497f11b (diff) | |
[MERGE] forward port branch saas-11.1 up to 726b91b9fbc
Diffstat (limited to 'addons/web/static/src/js/fields/relational_fields.js')
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 52654c4ce3a..677663a4967 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -95,6 +95,7 @@ var FieldMany2One = AbstractField.extend({ template: 'FieldMany2One', custom_events: _.extend({}, AbstractField.prototype.custom_events, { 'closed_unset': '_onDialogClosedUnset', + 'field_changed': '_onFieldChanged', 'quick_create': '_onQuickCreate', 'search_create_popup': '_onSearchCreatePopup', }), @@ -124,6 +125,12 @@ var FieldMany2One = AbstractField.extend({ // 'recordParams' is a dict of params used when calling functions // 'getDomain' and 'getContext' on this.record this.recordParams = {fieldName: this.name, viewType: this.viewType}; + // We need to know if the widget is dirty (i.e. if the user has changed + // the value, and those changes haven't been acknowledged yet by the + // environment), to prevent erasing that new value on a reset (e.g. + // coming by an onchange on another field) + this.isDirty = false; + this.lastChangeEvent = undefined; }, start: function () { // booleean indicating that the content of the input isn't synchronized @@ -151,9 +158,31 @@ var FieldMany2One = AbstractField.extend({ * TODO */ reinitialize: function (value) { + this.isDirty = false; this.floating = false; this._setValue(value); }, + /** + * Re-renders the widget if it isn't dirty. The widget is dirty if the user + * changed the value, and that change hasn't been acknowledged yet by the + * environment. For example, another field with an onchange has been updated + * and this field is updated before the onchange returns. Two '_setValue' + * are done (this is sequential), the first one returns and this widget is + * reset. However, it has pending changes, so we don't re-render. + * + * @override + */ + reset: function (record, event) { + this._reset(record, event); + if (!event || event === this.lastChangeEvent) { + this.isDirty = false; + } + if (this.isDirty) { + return $.when(); + } else { + return this._render(); + } + }, //-------------------------------------------------------------------------- // Private @@ -238,6 +267,16 @@ var FieldMany2One = AbstractField.extend({ return value.split('\n')[0]; }, /** + * Listens to events 'field_changed' to keep track of the last event that + * has been trigerred. This allows to detect that all changes have been + * acknowledged by the environment. + * + * @param {OdooEvent} event 'field_changed' event + */ + _onFieldChanged: function (event) { + this.lastChangeEvent = event; + }, + /** * @private * @param {string} name * @returns {Deferred} resolved after the name_create or when the slowcreate @@ -476,6 +515,7 @@ var FieldMany2One = AbstractField.extend({ * @private */ _onDialogClosedUnset: function () { + this.isDirty = false; this.floating = false; this._render(); }, @@ -544,6 +584,7 @@ var FieldMany2One = AbstractField.extend({ // confirmation that the many2one is not properly set. return; } + this.isDirty = true; if (this.$input.val() === "") { this.reinitialize(false); } else if (this._getDisplayName(this.m2o_value) !== this.$input.val()) { @@ -796,7 +837,7 @@ var FieldX2Many = AbstractField.extend({ this.currentColInvisibleFields = this._evalColumnInvisibleFields(); this.renderer = new ListRenderer(this, this.value, { arch: arch, - mode: this.mode, + editable: this.mode === 'edit' && arch.attrs.editable, addCreateLine: !this.isReadonly && this.activeActions.create, addTrashIcon: !this.isReadonly && this.activeActions.delete, isMany2Many: this.isMany2Many, @@ -1337,12 +1378,12 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({ throw _.str.sprintf(msg, this.field.string); } + this.uploadedFiles = {}; this.uploadingFiles = []; this.fileupload_id = _.uniqueId('oe_fileupload_temp'); $(window).on(this.fileupload_id, this._onFileLoaded.bind(this)); this.metadata = {}; - this._generatedMetadata(); }, destroy: function () { @@ -1372,10 +1413,10 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({ _generatedMetadata: function () { var self = this; _.each(this.value.data, function (record) { - // attachments are tagged `allowUnlink` because only new attachments - // will be unlinked after deletion + // tagging `allowUnlink` ascertains if the attachment was user + // uploaded or was an existing or system generated attachment self.metadata[record.id] = { - allowUnlink: false, + allowUnlink: self.uploadedFiles[record.data.id] || false, url: self._getFileUrl(record.data), }; }); @@ -1387,6 +1428,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({ _render: function () { // render the attachments ; as the attachments will changes after each // _setValue, we put the rendering here to ensure they will be updated + this._generatedMetadata(); this.$('.oe_placeholder_files, .oe_attachments') .replaceWith($(qweb.render('FieldBinaryFileUploader.files', { widget: this, @@ -1494,6 +1536,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({ self.do_warn(_t('Uploading Error'), file.error); } else { attachment_ids.push(file.id); + self.uploadedFiles[file.id] = true; } }); |
