diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/views/field_manager_mixin.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/static/src/js/views/field_manager_mixin.js')
| -rw-r--r-- | addons/web/static/src/js/views/field_manager_mixin.js | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/addons/web/static/src/js/views/field_manager_mixin.js b/addons/web/static/src/js/views/field_manager_mixin.js new file mode 100644 index 00000000..aab8dd14 --- /dev/null +++ b/addons/web/static/src/js/views/field_manager_mixin.js @@ -0,0 +1,166 @@ +odoo.define('web.FieldManagerMixin', function (require) { +"use strict"; + +/** + * The FieldManagerMixin is a mixin, designed to do the plumbing between field + * widgets and a basicmodel. Field widgets can be used outside of a view. In + * that case, someone needs to listen to events bubbling up from the widgets and + * calling the correct methods on the model. This is the field_manager's job. + */ + +var BasicModel = require('web.BasicModel'); +var concurrency = require('web.concurrency'); + +var FieldManagerMixin = { + custom_events: { + field_changed: '_onFieldChanged', + load: '_onLoad', + mutexify: '_onMutexify', + }, + /** + * A FieldManagerMixin can be initialized with an instance of a basicModel. + * If not, it will simply uses its own. + * + * @param {BasicModel} [model] + */ + init: function (model) { + this.model = model || new BasicModel(this); + this.mutex = new concurrency.Mutex(); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Apply changes by notifying the basic model, then saving the data if + * necessary, and finally, confirming the changes to the UI. + * + * @todo find a way to remove ugly 3rd argument... + * + * @param {string} dataPointID + * @param {Object} changes + * @param {OdooEvent} event + * @returns {Promise} resolves when the change has been done, and the UI + * updated + */ + _applyChanges: function (dataPointID, changes, event) { + var self = this; + var options = _.pick(event.data, 'context', 'doNotSetDirty', 'notifyChange', 'viewType', 'allowWarning'); + return this.model.notifyChanges(dataPointID, changes, options) + .then(function (result) { + if (event.data.force_save) { + return self.model.save(dataPointID).then(function () { + return self._confirmSave(dataPointID); + }).guardedCatch(function () { + return self._rejectSave(dataPointID); + }); + } else if (options.notifyChange !== false) { + return self._confirmChange(dataPointID, result, event); + } + }); + }, + /** + * This method will be called whenever a field value has changed (and has + * been confirmed by the model). + * + * @abstract + * @param {string} id basicModel Id for the changed record + * @param {string[]} fields the fields (names) that have been changed + * @param {OdooEvent} event the event that triggered the change + * @returns {Promise} + */ + _confirmChange: function (id, fields, event) { + return Promise.resolve(); + }, + /** + * This method will be called whenever a save has been triggered by a change + * in some controlled field value. For example, when a priority widget is + * being changed in a readonly form. + * + * @see _onFieldChanged + * @abstract + * @param {string} id The basicModel ID for the saved record + * @returns {Promise} + */ + _confirmSave: function (id) { + return Promise.resolve(); + }, + /** + * This method will be called whenever a save has been triggered by a change + * and has failed. For example, when a statusbar button is clicked in a + * readonly form view. + * + * @abstract + * @private + * @param {string} id The basicModel ID for the saved record + * @returns {Deferred} + */ + _rejectSave: function (id) { + return Promise.resolve(); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * This is the main job of the FMM: deciding what to do when a controlled + * field changes. Most of the time, it notifies the model that a change + * just occurred, then confirm the change. + * + * @param {OdooEvent} event + */ + _onFieldChanged: function (event) { + // in case of field changed in relational record (e.g. in the form view + // of a one2many subrecord), the field_changed event must be stopped as + // soon as is it handled by a field_manager (i.e. the one of the + // subrecord's form view), otherwise it bubbles up to the main form view + // but its model doesn't have any data related to the given dataPointID + event.stopPropagation(); + return this._applyChanges(event.data.dataPointID, event.data.changes, event) + .then(event.data.onSuccess || function () {}) + .guardedCatch(event.data.onFailure || function () {}); + }, + /** + * Some widgets need to trigger a reload of their data. For example, a + * one2many with a pager needs to be able to fetch the next page. To do + * that, it can trigger a load event. This will then ask the model to + * actually reload the data, then call the on_success callback. + * + * @param {OdooEvent} event + * @param {number} [event.data.limit] + * @param {number} [event.data.offset] + * @param {function} [event.data.on_success] callback + */ + _onLoad: function (event) { + var self = this; + event.stopPropagation(); // prevent other field managers from handling this request + var data = event.data; + if (!data.on_success) { return; } + var params = {}; + if ('limit' in data) { + params.limit = data.limit; + } + if ('offset' in data) { + params.offset = data.offset; + } + this.mutex.exec(function () { + return self.model.reload(data.id, params).then(function (db_id) { + data.on_success(self.model.get(db_id)); + }); + }); + }, + /** + * @private + * @param {OdooEvent} ev + * @param {function} ev.data.action the function to execute in the mutex + */ + _onMutexify: function (ev) { + ev.stopPropagation(); // prevent other field managers from handling this request + this.mutex.exec(ev.data.action); + }, +}; + +return FieldManagerMixin; +}); |
