[REF] moves more code to dataLoader class to simplify pivot class (clean separation between pivot code and loading code) (addon web_graph)

bzr revid: ged@openerp.com-20131217111501-wu0nbid36bncy4wz
This commit is contained in:
Gery Debongnie 2013-12-17 12:15:01 +01:00
parent 65642c8c06
commit de51e3c35a
2 changed files with 142 additions and 122 deletions

View File

@ -163,7 +163,7 @@ instance.web_graph.GraphView = instance.web.View.extend({
display_data: function () {
var pivot = this.pivot_table;
if (pivot.stale_data) {
pivot.load_data().done(this.proxy('display_data'));
pivot.update_data().done(this.proxy('display_data'));
} else {
this.$('.graph_main_content svg').remove();
this.table.empty();

View File

@ -117,15 +117,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
// return all non expanded rows
get_rows_leaves: function () {
return _.filter(this.rows.headers, function (hdr) {
return !hdr.is_expanded;
return _.filter(this.rows.headers, function (hdr) {
return !hdr.is_expanded;
});
},
// return all non expanded cols
get_cols_leaves: function () {
return _.filter(this.cols.headers, function (hdr) {
return !hdr.is_expanded;
return _.filter(this.cols.headers, function (hdr) {
return !hdr.is_expanded;
});
},
@ -232,54 +232,25 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
this.stale_data = true;
},
// To obtain all the values required to draw the full table, we have to do
// at least 2 + min(row.groupby.length, col.groupby.length)
// calls to readgroup. For example, if row.groupby = [r1, r2, r3] and
// col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done
// with the following groupby:
// [], [c1, c2, c3, c4], r1, c1, c2, c3, c4], [r1, r2, c1, c2, c3, c4],
// [r1, r2, r3, c1, c2, c3, c4]
// To simplify the code, we will always do 2 + row.groupby.length calls,
// unless col.groupby.length = 0, in which case we do 2 calls ([] and
// row_groupbys), but this can be optimized later.
load_data: function () {
update_data: function () {
var self = this,
cols = this.cols.groupby,
rows = this.rows.groupby,
def_array,
groupbys;
options = {
col_groupby: this.cols.groupby,
row_groupby: this.rows.groupby,
measure: this.measure,
domain: this.domain,
};
if (cols.length > 0) {
groupbys = _.map(_.range(rows.length + 1), function (i) {
return rows.slice(0, i).concat(cols);
});
groupbys.push([]);
} else {
groupbys = [rows, []];
}
def_array = _.map(groupbys, function (groupby) {
return self.data_loader.get_groups(self.visible_fields(), self.domain, groupby);
});
return $.when.apply(null, def_array).then(function () {
var args = Array.prototype.slice.call(arguments),
col_data = _.first(args),
total = _.last(args)[0],
row_data = _.last(_.initial(args)),
cell_data = args;
return (total === undefined) ? undefined
: self.format_data(total, col_data, row_data, cell_data);
}).then(function (result) {
return this.data_loader.load_data(options).then (function (result) {
self.stale_data = false;
if (result) {
self.no_data = false;
if (self.cols.headers) {
self.update_headers(self.cols, result.col_headers);
self.update_headers(self.rows, result.row_headers);
self.update_headers(self.rows, result.row_headers);
} else {
self.expand_headers(self.cols, result.col_headers);
self.expand_headers(self.rows, result.row_headers);
self.expand_headers(self.rows, result.row_headers);
}
self.cells = result.cells;
} else {
@ -325,10 +296,127 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
root.main = root.headers[0];
},
format_data: function (total, col_data, row_data, cell_data) {
});
openerp.web_graph.DataLoader = openerp.web.Class.extend({
init: function (model) {
this.model = model;
},
get_groups: function (fields, domain, groupbys, options) {
var self = this,
dim_row = this.rows.groupby.length,
dim_col = this.cols.groupby.length,
options = (options) ? options : {},
groupings = (options.first_groupby) ? [options.first_groupby].concat(groupbys) : groupbys;
return this.query_db(fields, domain, groupings).then(function (groups) {
return _.map(groups, function (group) {
return (options.add_path) ?self.add_path(group, []) : group;
});
});
},
query_db: function (fields, domain, groupbys) {
var self = this;
return this.model.query(fields)
.filter(domain)
.group_by(groupbys)
.then(function (results) {
var non_empty_results = _.filter(results, function (group) {
return group.attributes.length > 0;
});
_.each(non_empty_results, self.sanitize_value);
if (groupbys.length <= 1) {
return non_empty_results;
} else {
var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) {
var new_domain = result.model._domain;
var new_groupings = groupbys.slice(1);
return self.query_db(fields,new_domain, new_groupings).then(function (subgroups) {
result.subgroups_data = subgroups;
});
}));
return get_subgroups.then(function () {
return non_empty_results;
});
}
});
},
sanitize_value: function (group) {
var value = group.attributes.value;
if (value === false) {
group.attributes.value = 'undefined';
} else if (value instanceof Array) {
group.attributes.value = value[1];
} else {
group.attributes.value = value;
}
},
add_path: function (group, current_path) {
var self = this;
group.path = current_path.concat(group.attributes.value);
var result = [group];
_.each(group.subgroups_data, function (subgroup) {
result = result.concat(self.add_path(subgroup, group.path));
});
return result;
},
// To obtain all the values required to draw the full table, we have to do
// at least 2 + min(row.groupby.length, col.groupby.length)
// calls to readgroup. For example, if row.groupby = [r1, r2, r3] and
// col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done
// with the following groupby:
// [], [c1, c2, c3, c4], r1, c1, c2, c3, c4], [r1, r2, c1, c2, c3, c4],
// [r1, r2, r3, c1, c2, c3, c4]
// To simplify the code, we will always do 2 + row.groupby.length calls,
// unless col.groupby.length = 0, in which case we do 2 calls ([] and
// row_groupbys), but this can be optimized later.
load_data: function (options) {
var self = this,
cols = options.col_groupby,
rows = options.row_groupby,
measure = options.measure,
domain = options.domain,
visible_fields = rows.concat(cols),
def_array,
groupbys;
if (measure) { visible_fields = visible_fields.concat(measure); }
if (cols.length > 0) {
groupbys = _.map(_.range(rows.length + 1), function (i) {
return rows.slice(0, i).concat(cols);
});
groupbys.push([]);
} else {
groupbys = [rows, []];
}
def_array = _.map(groupbys, function (groupby) {
return self.get_groups(visible_fields, domain, groupby);
});
return $.when.apply(null, def_array).then(function () {
var args = Array.prototype.slice.call(arguments),
col_data = _.first(args),
total = _.last(args)[0],
row_data = _.last(_.initial(args)),
cell_data = args;
return (total === undefined) ? undefined
: self.format_data(total, col_data, row_data, cell_data, options);
});
},
format_data: function (total, col_data, row_data, cell_data, options) {
var self = this,
dim_row = options.row_groupby.length,
dim_col = options.col_groupby.length,
measure = options.measure,
col_headers = make_headers(col_data, dim_col),
row_headers = make_headers(row_data, dim_row),
cells = [];
@ -353,10 +441,10 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
parent: null,
children: [],
title: '',
domain: self.domain,
domain: options.domain,
};
if (self.measure) {
main.total = total.attributes.aggregates[self.measure];
if (measure) {
main.total = total.attributes.aggregates[measure];
} else {
main.total = total.attributes.length;
}
@ -387,8 +475,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
parent: parent,
children: [],
};
if (self.measure) {
node.total = data_pt.attributes.aggregates[self.measure];
if (measure) {
node.total = data_pt.attributes.aggregates[measure];
} else {
node.total = data_pt.attributes.length;
}
@ -412,8 +500,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
group_val = undefined;
}
if (self.measure) {
value = attr.aggregates[self.measure];
if (measure) {
value = attr.aggregates[measure];
} else {
value = attr.length;
}
@ -446,74 +534,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
}
},
});
openerp.web_graph.DataLoader = openerp.web.Class.extend({
init: function (model) {
this.model = model;
},
get_groups: function (fields, domain, groupbys, options) {
var self = this,
options = (options) ? options : {},
groupings = (options.first_groupby) ? [options.first_groupby].concat(groupbys) : groupbys;
return this._query_db(fields, domain, groupings).then(function (groups) {
return _.map(groups, function (group) {
return (options.add_path) ?self._add_path(group, []) : group;
});
});
},
_query_db: function (fields, domain, groupbys) {
var self = this;
return this.model.query(fields)
.filter(domain)
.group_by(groupbys)
.then(function (results) {
var non_empty_results = _.filter(results, function (group) {
return group.attributes.length > 0;
});
_.each(non_empty_results, self._sanitize_value);
if (groupbys.length <= 1) {
return non_empty_results;
} else {
var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) {
var new_domain = result.model._domain;
var new_groupings = groupbys.slice(1);
return self._query_db(fields,new_domain, new_groupings).then(function (subgroups) {
result.subgroups_data = subgroups;
});
}));
return get_subgroups.then(function () {
return non_empty_results;
});
}
});
},
_sanitize_value: function (group) {
var value = group.attributes.value;
if (value === false) {
group.attributes.value = 'undefined';
} else if (value instanceof Array) {
group.attributes.value = value[1];
} else {
group.attributes.value = value;
}
},
_add_path: function (group, current_path) {
var self = this;
group.path = current_path.concat(group.attributes.value);
var result = [group];
_.each(group.subgroups_data, function (subgroup) {
result = result.concat(self._add_path(subgroup, group.path));
});
return result;
},
});