diff options
| author | Vandan Shah <vas@odoo.com> | 2018-10-25 06:53:00 +0000 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2019-04-23 13:45:15 +0000 |
| commit | 9b90d8727da9df6eb7ce756c4f9ffb0973e6ea65 (patch) | |
| tree | 0617989834e0d6915314b39d1c07d5b50690b1b2 /addons/web/static/src/js/views/basic | |
| parent | 8c931ffc2e6f31caac4c15050403a84ca92b8c82 (diff) | |
[IMP] web: enable drag&drop in ungrouped kanban views
With this rev., the resequencing feature (with drag and drop) that
was already available in list views is now available also in kanban
views having a field with widget="handle". This works for main as
well as x2many kanban views.
Some code handling the resequencing has been moved from the list
components (controller and renderer) to the basic ones, so that the
logic is shared between list and kanban.
Task 1902808
closes odoo/odoo#28581
Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
Co-authored-by: Mohammed Shekha <msh@openerp.com>
Co-authored-by: Aaron Bohy <aab@odoo.com>
Diffstat (limited to 'addons/web/static/src/js/views/basic')
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_controller.js | 32 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_renderer.js | 58 |
2 files changed, 90 insertions, 0 deletions
diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index 064f7b84a52..610e7e6dc6b 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -19,6 +19,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { custom_events: _.extend({}, AbstractController.prototype.custom_events, FieldManagerMixin.custom_events, { discard_changes: '_onDiscardChanges', reload: '_onReload', + resequence_records: '_onResequenceRecords', set_dirty: '_onSetDirty', sidebar_data_asked: '_onSidebarDataAsked', translate: '_onTranslate', @@ -642,6 +643,37 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { } }, /** + * Resequence records in the given order. + * + * @private + * @param {OdooEvent} ev + * @param {string[]} ev.data.recordIds + * @param {integer} ev.data.offset + * @param {string} ev.data.handleField + */ + _onResequenceRecords: function (ev) { + var self = this; + + this.trigger_up('mutexify', { + action: function () { + var state = self.model.get(self.handle); + var resIDs = _.map(ev.data.recordIds, function (recordID) { + return _.findWhere(state.data, {id: recordID}).res_id; + }); + var options = { + offset: ev.data.offset, + field: ev.data.handleField, + }; + return self.model.resequence(self.modelName, resIDs, self.handle, options) + .then(function () { + self._updateEnv(); + state = self.model.get(self.handle); + return self.renderer.updateState(state, {noRender: true}); + }); + }, + }); + }, + /** * @private * @param {OdooEvent} ev */ diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js index 4c03d9b77a1..4ee2ef8fbb3 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -31,6 +31,9 @@ var BasicRenderer = AbstractRenderer.extend({ this.viewType = params.viewType; this.mode = params.mode || 'readonly'; this.widgets = []; + // This attribute lets us know if there is a handle widget on a field, + // and on which field it is set. + this.handleField = null; }, /** * This method has two responsabilities: find every invalid fields in the @@ -389,6 +392,61 @@ var BasicRenderer = AbstractRenderer.extend({ return this.state.count !== 0; }, /** + * Force the resequencing of the records after moving one of them to a given + * index. + * + * @private + * @param {string} recordId datapoint id of the moved record + * @param {integer} toIndex new index of the moved record + */ + _moveRecord: function (recordId, toIndex) { + var self = this; + var records = this.state.data; + var record = _.findWhere(records, {id: recordId}); + var fromIndex = records.indexOf(record); + var lowerIndex = Math.min(fromIndex, toIndex); + var upperIndex = Math.max(fromIndex, toIndex) + 1; + var order = _.findWhere(this.state.orderedBy, {name: this.handleField}); + var asc = !order || order.asc; + var reorderAll = false; + var sequence = (asc ? -1 : 1) * Infinity; + + // determine if we need to reorder all records + _.each(records, function (record, index) { + if ((index < lowerIndex || index >= upperIndex) && + ((asc && sequence >= record.data[self.handleField]) || + (!asc && sequence <= record.data[self.handleField]))) { + reorderAll = true; + } + sequence = record.data[self.handleField]; + }); + + if (reorderAll) { + records = _.without(records, record); + records.splice(toIndex, 0, record); + } else { + records = records.slice(lowerIndex, upperIndex); + records = _.without(records, record); + if (fromIndex > toIndex) { + records.unshift(record); + } else { + records.push(record); + } + } + + var sequences = _.pluck(_.pluck(records, 'data'), this.handleField); + var recordIds = _.pluck(records, 'id'); + if (!asc) { + recordIds.reverse(); + } + + this.trigger_up('resequence_records', { + handleField: this.handleField, + offset: _.min(sequences), + recordIds: recordIds, + }); + }, + /** * This function is called each time a field widget is created, when it is * ready (after its willStart and Start methods are complete). This is the * place where work having to do with $el should be done. |
