[IMP] Break list views completely, change DataGroup API to work better, improve columns management to handle groupby-reordering

bzr revid: xmo@openerp.com-20110517140358-vtank237dh5hso8i
This commit is contained in:
Xavier Morel 2011-05-17 16:03:58 +02:00
parent 196a7ab46e
commit ccf8031e6b
2 changed files with 116 additions and 140 deletions

View File

@ -24,14 +24,39 @@ openerp.base.DataGroup = openerp.base.Controller.extend( /** @lends openerp.bas
* @param {Array} group_by sequence of fields by which to group
*/
init: function(session, model, domain, context, group_by) {
if (group_by) {
if (group_by.length) {
return new openerp.base.ContainerDataGroup(
session, model, domain, context, group_by);
} else {
return new openerp.base.GrouplessDataGroup(
session, model, domain, context);
}
}
this._super(session, null);
this.model = model;
this.context = context;
this.domain = domain;
}
});
openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend(
/** @lends openerp.base.ContainerDataGroup# */ {
/**
*
* @constructs
* @extends openerp.base.DataGroup
*
* @param session
* @param model
* @param domain
* @param context
* @param group_by
*/
init: function (session, model, domain, context, group_by) {
this._super(session, model, domain, context);
this.group_by = group_by;
this.groups = null;
},
/**
* The format returned by ``read_group`` is absolutely dreadful:
@ -107,53 +132,6 @@ openerp.base.DataGroup = openerp.base.Controller.extend( /** @lends openerp.bas
return d.promise();
},
/**
* Retrieves the content of an item in the DataGroup, which results in
* either a DataSet or new DataGroup instance.
*
* Calling :js:func:`~openerp.base.DataGroup.get` without having called
* :js:func:`~openerp.base.DataGroup.list` beforehand will likely result
* in an error.
*
* The resulting :js:class:`~openerp.base.DataGroup` or
* :js:class:`~openerp.base.DataSet` will be provided through the relevant
* callback function. In both functions, the current DataGroup will be
* provided as context (``this``)
*
* @param {Number} index the index of the group to open in the datagroup's collection
* @param {Function} ifDataSet executed if the item results in a DataSet, provided with the new dataset as parameter
* @param {Function} ifDataGroup executed if the item results in a DataSet, provided with the new datagroup as parameter
*/
get: function (index, ifDataSet, ifDataGroup) {
var group = this.groups[index];
if (!group) {
throw new Error("No group at index " + index);
}
var child_context = _.extend({}, this.context, group.__context);
if (group.__context.group_by.length) {
var datagroup = new openerp.base.DataGroup(
this.session, this.model, group.__domain, child_context,
group.__context.group_by);
ifDataGroup.call(this, datagroup);
} else {
var dataset = new openerp.base.DataSetSearch(this.session, this.model);
dataset.domain = group.__domain;
dataset.context = child_context;
ifDataSet.call(this, dataset);
}
},
/**
* Gathers the content of the current data group (the current grouping
* level), and provides it via a promise object to which callbacks should
* be added::
*
* datagroup.list().then(function (list) {
* // manipulate list here
* });
*
* The argument to the callback is the list of elements fetched, the
* context (``this``) is the datagroup itself.
*
* The items of a list have the following properties:
*
* ``length``
@ -171,11 +149,40 @@ openerp.base.DataGroup = openerp.base.Controller.extend( /** @lends openerp.bas
* records have for the current ``grouped_on`` field name).
* ``aggregates``
* a mapping of other aggregation fields provided by ``read_group``
*
* @returns {$.Deferred}
*/
list: function () {
return this.fetch();
list: function (ifGroups, ifRecords) {
var self = this;
this.fetch().then(function (group_records) {
ifGroups(_(group_records).map(function (group) {
var child_context = _.extend({}, self.context, group.__context);
return _.extend(
new openerp.base.DataGroup(
self.session, self.model, group.__domain,
child_context, child_context.group_by),
group);
}));
});
}
});
openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend(
/** @lends openerp.base.GrouplessDataGroup# */ {
/**
*
* @constructs
* @extends openerp.base.DataGroup
*
* @param session
* @param model
* @param domain
* @param context
*/
init: function (session, model, domain, context) {
this._super(session, model, domain, context);
},
list: function (ifGroups, ifRecords) {
ifRecords(_.extend(
new openerp.base.DataSetSearch(this.session, this.model),
{domain: this.domain, context: this.context}));
}
});

View File

@ -52,20 +52,14 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
this.view_id = view_id;
this.columns = [];
this.rows = [];
this.options = _.extend({}, this.defaults, options || {});
this.list = new openerp.base.ListView.List({
options: this.options,
columns: this.columns,
rows: this.rows
});
this.groups = new openerp.base.ListView.Groups({
options: this.options,
columns: this.columns
});
$([this.list, this.groups]).bind({
$(this.groups).bind({
'selected': function (e, selection) {
self.$element.find('#oe-list-delete')
.toggle(!!selection.length);
@ -124,41 +118,15 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
* @param {Object} data.fields_view fields_view_get result (processed)
* @param {Object} data.fields_view.fields mapping of fields for the current model
* @param {Object} data.fields_view.arch current list view descriptor
* @param {Array} columns columns to move to the front (and make visible)
*/
on_loaded: function(data) {
on_loaded: function(data, columns) {
var self = this;
this.fields_view = data.fields_view;
//this.log(this.fields_view);
this.name = "" + this.fields_view.arch.attrs.string;
var fields = this.fields_view.fields;
var domain_computer = openerp.base.form.compute_domain;
this.columns.splice(0, this.columns.length);
this.columns.push.apply(this.columns, _(this.fields_view.arch.children).chain()
.map(function (field) {
var name = field.attrs.name;
var column = _.extend({id: name, tag: field.tag},
field.attrs, fields[name]);
// attrs computer
if (column.attrs) {
var attrs = eval('(' + column.attrs + ')');
column.attrs_for = function (fields) {
var result = {};
for (var attr in attrs) {
result[attr] = domain_computer(attrs[attr], fields);
}
return result;
};
} else {
column.attrs_for = function () { return {}; };
}
return column;
}).value());
this.visible_columns = _.filter(this.columns, function (column) {
return column.invisible !== '1';
});
this.setup_columns(this.fields_view.fields, columns);
if (!this.fields_view.sorted) { this.fields_view.sorted = {}; }
@ -178,49 +146,51 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
self.do_reload();
});
var $table = this.$element.find('table');
this.list.move_to($table);
// sidebar stuff
if (this.view_manager && this.view_manager.sidebar) {
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
}
},
/**
* Fills the table with the provided records after emptying it
*
* TODO: should also re-load the table itself, as e.g. columns may have changed
*
* @param {Object} result filling result
* @param {Array} [result.view] the new view (wrapped fields_view_get result)
* @param {Array} result.records records the records to fill the list view with
*/
do_fill_table: function(result) {
if (result.view) {
this.on_loaded({fields_view: result.view});
}
var records = result.records;
setup_columns: function (fields, groupby_columns) {
var self = this;
var domain_computer = openerp.base.form.compute_domain;
this.rows.splice(0, this.rows.length);
this.rows.push.apply(this.rows, records);
// Keep current selected record, if it's still in our new search
var current_record_id = this.dataset.ids[this.dataset.index];
this.dataset.ids = _(records).chain().map(function (record) {
return record.data.id.value;
}).value();
this.dataset.index = _.indexOf(this.dataset.ids, current_record_id);
if (this.dataset.index < 0) {
this.dataset.index = 0;
}
var field_to_column = function (field) {
var name = field.attrs.name;
var column = _.extend({id: name, tag: field.tag},
field.attrs, fields[name]);
// attrs computer
if (column.attrs) {
var attrs = eval('(' + column.attrs + ')');
column.attrs_for = function (fields) {
var result = {};
for (var attr in attrs) {
result[attr] = domain_computer(attrs[attr], fields);
}
return result;
};
} else {
column.attrs_for = function () { return {}; };
}
return column;
};
this.dataset.count = this.dataset.ids.length;
var results = this.rows.length;
this.$element.find('table')
.find('.oe-pager-last').text(results).end()
.find('.oe-pager-total').text(results);
this.columns.splice(0, this.columns.length);
this.columns.push.apply(
this.columns,
_(this.fields_view.arch.children).map(field_to_column));
this.list.refresh();
_(groupby_columns).each(function (column_id, index) {
var column_index = _(self.columns).chain()
.pluck('id').indexOf(column_id).value();
var column = self.columns.splice(column_index, 1)[0];
delete column.invisible;
self.columns.splice(index, 0, column);
});
this.visible_columns = _.filter(this.columns, function (column) {
return column.invisible !== '1';
});
},
/**
* Used to handle a click on a table row, if no other handler caught the
@ -259,12 +229,16 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
},
/**
* Reloads the search view based on the current settings (dataset & al)
*
* @param {Array} [primary_columns] columns to bring to the front of the
* sequence
*/
do_reload: function () {
do_reload: function (primary_columns) {
// TODO: need to do 5 billion tons of pre-processing, bypass
// DataSet for now
//self.dataset.read_slice(self.dataset.fields, 0, self.limit,
// self.do_fill_table);
var self = this;
this.dataset.offset = 0;
this.dataset.limit = false;
return this.rpc('/base/listview/fill', {
@ -273,7 +247,11 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
'context': this.dataset.context,
'domain': this.dataset.domain,
'sort': this.dataset.sort && this.dataset.sort()
}, this.do_fill_table);
}, function (result) {
if (result.view) {
self.on_loaded({fields_view: result.view}, primary_columns);
}
});
},
/**
* Event handler for a search, asks for the computation/folding of domains
@ -291,24 +269,15 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
contexts: contexts,
group_by_seq: groupbys
}, function (results) {
// TODO: handle non-empty results.group_by with read_group
self.dataset.context = results.context;
self.dataset.domain = results.domain;
if (results.group_by.length) {
self.groups.datagroup = new openerp.base.DataGroup(
self.session, self.dataset.model,
results.domain, results.context,
results.group_by);
self.$element.html(self.groups.render());
return;
}
return self.do_reload();
self.groups.datagroup = new openerp.base.DataGroup(
self.session, self.dataset.model,
results.domain, results.context,
results.group_by);
self.do_reload(results.group_by);
});
},
do_update: function () {
var self = this;
//self.dataset.read_ids(self.dataset.ids, self.dataset.fields, self.do_fill_table);
},
/**
* Handles the signal to delete a line from the DOM
*