diff options
| author | Robot Odoo <xmo+roboto@odoo.com> | 2019-04-02 15:46:39 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-02 15:46:39 +0200 |
| commit | 9aea7ae1627e7af10fb03677142ccfc5333f654e (patch) | |
| tree | 1233647e18260747f3fd315f79f4cae8b06bc0f6 /addons/web/static/src/js/views/basic/basic_model.js | |
| parent | a82dbe4d680149b9bf15b7a122c6f8bd1b3582fa (diff) | |
| parent | 8ea5a40417c2da2e82db66ad36fbf1e8e78bbe11 (diff) | |
[MERGE] web,*: list view improvements
This branch brings several improvements related to the list view:
- grouped list views are now editable
- 'expand' attribute can be used to open by default the first level groups
- if there are a lot of groups, a pager is displayed (instead of having all
groups in the same page)
- when grouped on a many2one field, custom buttons (on the many2one
comodel) can be inserted in each group's header
- we can edit several records in a row in editable list views
- editable lists do not flicker anymore when switching a row to edit mode
- we can navigate through the cells in list views with the arrows (in
readonly)
Co-authored-by: Aaron Bohy aab@odoo.com
Co-authored-by: David Monjoie dmo@odoo.com
Co-authored-by: Martin Geubelle mge@odoo.com
Co-authored-by: Ravi Gadhia rga@odoo.com
Task 1915702
closes odoo/odoo#31756
Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
Diffstat (limited to 'addons/web/static/src/js/views/basic/basic_model.js')
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 100 |
1 files changed, 80 insertions, 20 deletions
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 79fac0f2247..804e6d6d1c9 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -90,6 +90,7 @@ var core = require('web.core'); var Domain = require('web.Domain'); var session = require('web.session'); var utils = require('web.utils'); +var viewUtils = require('web.viewUtils'); var _t = core._t; @@ -178,7 +179,7 @@ var BasicModel = AbstractModel.extend({ addDefaultRecord: function (listID, options) { var self = this; var list = this.localData[listID]; - var context = this._getContext(list); + var context = _.extend({}, this._getDefaultContext(list), this._getContext(list)); var position = (options && options.position) || 'top'; var params = { @@ -637,6 +638,9 @@ var BasicModel = AbstractModel.extend({ getDomain: element.getDomain, getFieldNames: element.getFieldNames, groupedBy: element.groupedBy, + groupsCount: element.groupsCount, + groupsLimit: element.groupsLimit, + groupsOffset: element.groupsOffset, id: element.id, isDirty: element.isDirty, isOpen: element.isOpen, @@ -3333,6 +3337,27 @@ var BasicModel = AbstractModel.extend({ return toFetch; }, /** + * Given a dataPoint of type list (that may be a group), returns an object + * with 'default_' keys to be used to create new records in that group. + * + * @private + * @param {Object} dataPoint + * @returns {Object} + */ + _getDefaultContext: function (dataPoint) { + var defaultContext = {}; + while (dataPoint.parentID) { + var parent = this.localData[dataPoint.parentID]; + var groupByField = parent.groupedBy[0].split(':')[0]; + var value = viewUtils.getGroupValue(dataPoint, groupByField); + if (value) { + defaultContext['default_' + groupByField] = value; + } + dataPoint = parent; + } + return defaultContext; + }, + /** * Some records are associated to a/some domain(s). This method allows to * retrieve them, evaluated. * @@ -3709,6 +3734,9 @@ var BasicModel = AbstractModel.extend({ fields: fields, fieldsInfo: params.fieldsInfo, groupedBy: params.groupedBy || [], + groupsCount: 0, + groupsLimit: type === 'list' && params.groupsLimit || null, + groupsOffset: 0, id: _.uniqueId(params.modelName + '_'), isOpen: params.isOpen, limit: type === 'record' ? 1 : params.limit, @@ -4219,23 +4247,33 @@ var BasicModel = AbstractModel.extend({ */ _readGroup: function (list, options) { var self = this; + options = options || {}; var groupByField = list.groupedBy[0]; var rawGroupBy = groupByField.split(':')[0]; var fields = _.uniq(list.getFieldNames().concat(rawGroupBy)); - var orderedBy = _.filter(list.orderedBy, function(order){ + var orderedBy = _.filter(list.orderedBy, function (order) { return order.name === rawGroupBy || list.fields[order.name].group_operator !== undefined; }); + var openGroupsLimit = list.groupsLimit || self.OPEN_GROUP_LIMIT; + var expand = list.openGroupByDefault && options.fetchRecordsWithGroups; return this._rpc({ model: list.model, - method: 'read_group', + method: 'web_read_group', fields: fields, domain: list.domain, context: list.context, groupBy: list.groupedBy, + limit: list.groupsLimit, + offset: list.groupsOffset, orderBy: orderedBy, lazy: true, + expand: expand, + expand_limit: expand ? list.limit : null, + expand_orderby: expand ? list.orderedBy : null, }) - .then(function (groups) { + .then(function (result) { + var groups = result.groups; + list.groupsCount = result.length; var previousGroups = _.map(list.data, function (groupID) { return self.localData[groupID]; }); @@ -4285,7 +4323,7 @@ var BasicModel = AbstractModel.extend({ delete self.localData[newGroup.id]; // restore the internal state of the group var updatedProps = _.pick(oldGroup, 'isOpen', 'offset', 'id'); - if (options && options.onlyGroups || oldGroup.isOpen && newGroup.groupedBy.length) { + if (options.onlyGroups || oldGroup.isOpen && newGroup.groupedBy.length) { // If the group is opened and contains subgroups, // also keep its data to keep internal state of // sub-groups @@ -4298,20 +4336,28 @@ var BasicModel = AbstractModel.extend({ // form view) are reloaded newGroup.limit = oldGroup.limit + oldGroup.loadMoreOffset; self.localData[newGroup.id] = newGroup; - } else if (!newGroup.openGroupByDefault || openGroupCount >= self.OPEN_GROUP_LIMIT) { + } else if (!newGroup.openGroupByDefault || openGroupCount >= openGroupsLimit) { newGroup.isOpen = false; + } else if ('__fold' in group) { + newGroup.isOpen = !group.__fold; } else { - newGroup.isOpen = '__fold' in group ? !group.__fold : true; + // open the group iff it is a first level group + newGroup.isOpen = !self.localData[newGroup.parentID].parentID; } list.data.push(newGroup.id); list.count += newGroup.count; if (newGroup.isOpen && newGroup.count > 0) { openGroupCount++; + if (group.__data) { + // bypass the search_read when the group's records have been obtained + // by the call to 'web_read_group' (see @_searchReadUngroupedList) + newGroup.__data = group.__data; + } options = _.defaults({enableRelationalFetch: false}, options); defs.push(self._load(newGroup, options)); } }); - if (options && options.keepEmptyGroups) { + if (options.keepEmptyGroups) { // Find the groups that were available in a previous // readGroup but are not there anymore. // Note that these groups are put after existing groups so @@ -4327,7 +4373,7 @@ var BasicModel = AbstractModel.extend({ } return Promise.all(defs).then(function (groups) { - if (!options || !options.onlyGroups) { + if (!options.onlyGroups) { // generate the res_ids of the main list, being the concatenation // of the fetched res_ids in each group list.res_ids = _.flatten(_.map(groups, function (group) { @@ -4460,6 +4506,12 @@ var BasicModel = AbstractModel.extend({ if (options.offset !== undefined) { this._setOffset(element.id, options.offset); } + if (options.groupsLimit !== undefined) { + element.groupsLimit = options.groupsLimit; + } + if (options.groupsOffset !== undefined) { + element.groupsOffset = options.groupsOffset; + } if (options.loadMoreOffset !== undefined) { element.loadMoreOffset = options.loadMoreOffset; } else { @@ -4510,17 +4562,25 @@ var BasicModel = AbstractModel.extend({ _searchReadUngroupedList: function (list) { var self = this; var fieldNames = list.getFieldNames(); - return this._rpc({ - route: '/web/dataset/search_read', - model: list.model, - fields: fieldNames, - context: list.getContext(), - domain: list.domain || [], - limit: list.limit, - offset: list.loadMoreOffset + list.offset, - orderBy: list.orderedBy, - }) - .then(function (result) { + var prom; + if (list.__data) { + // the data have already been fetched (alonside the groups by the + // call to 'web_read_group'), so we can bypass the search_read + prom = Promise.resolve(list.__data); + } else { + prom = this._rpc({ + route: '/web/dataset/search_read', + model: list.model, + fields: fieldNames, + context: list.getContext(), + domain: list.domain || [], + limit: list.limit, + offset: list.loadMoreOffset + list.offset, + orderBy: list.orderedBy, + }); + } + return prom.then(function (result) { + delete list.__data; list.count = result.length; var ids = _.pluck(result.records, 'id'); var data = _.map(result.records, function (record) { |
