4ab6b6374222cd801c566e4fdc159e94aa153bd8
[odoo/odoo.git] / addons / web_graph / static / src / js / pivot.js
1
2 var PivotTable = openerp.web.Class.extend({
3         init: function (options) {
4                 this.rows = [];
5                 this.cols = [];
6                 this.cells = [];
7                 this.row_groupby = options.row_groupby;
8                 this.col_groupby = [];
9                 this.model = options.model;
10                 this.measure = options.measure;
11                 this.measure_label = options.measure_label;
12                 this.domain = options.domain;
13                 this.id_seed = 0;
14         },
15
16         // Load initial data into the rows, cols and cells array.
17         // This function needs to be called after init and before
18         // drawing the table (otherwise the data returned will be empty...)
19         start: function () {
20                 var self = this;
21                 this.rows.push({
22                         id: this.generate_id(),
23                         path: [],
24                         name: "Total",
25                         is_expanded: false,
26                         parent: null,
27                         children: [],
28                         domain: this.domain,
29                 });
30
31                 this.cols.push({
32                         id: this.generate_id(),
33                         path: [],
34                         name: this.measure_label,
35                         is_expanded: false,
36                         parent: null,
37                         children: [],
38                         domain: this.domain,
39                 });
40
41                 // get total and create first cell
42                 var tot = query_groups (this.model, this.measure, this.domain, [])
43                         .then(function (total) {
44                                 var val = total[0].attributes.aggregates[self.measure];
45                                 self.set_value(self.rows[0].id, self.cols[0].id, val);
46                         });
47
48                 var grp = query_groups (this.model, this.visible_fields(), this.domain, this.row_groupby)
49                         .then(function (groups) {
50                                 _.each(groups, function (group) {
51                                         var new_id = self.generate_id(),
52                                                 new_row = {
53                                                 id: new_id,
54                                                 path: [group.attributes.value[1]],
55                                                 name: group.attributes.value[1],
56                                                 is_expanded: false,
57                                                 parent: self.rows[0],
58                                                 children: [],
59                                                 domain: group.model._domain,
60                                         };
61
62                                         self.rows[0].children.push(new_row);
63                                         self.rows.push(new_row);
64                                         self.set_value(new_id, self.cols[0].id, 
65                                                                    group.attributes.aggregates[self.measure]);
66                                 });
67                                 self.rows[0].is_expanded = true;
68                         });
69
70                 return $.when(tot, grp);
71         },
72
73         generate_id: function () {
74                 this.id_seed += 1;
75                 return this.id_seed;
76         },
77
78         visible_fields: function () {
79                 return this.row_groupby.concat(this.col_groupby, this.measure);
80         },
81
82         set_value: function (row, col, value) {
83                 var cell = _.find(this.cells, function (c) {
84                         return ((c.row_id == row) && (c.col_id == col));
85                 });
86                 if (cell) {
87                         cell.value = value;
88                 } else {
89                         this.cells.push({row_id: row, col_id: col, value: value});
90                 }
91         },
92
93         get_value: function (row, col) {
94                 var cell = _.find(this.cells, function (c) {
95                         return ((c.row_id == row) && (c.col_id == col));
96                 });
97                 return (cell) ? cell.value : '';
98         },
99
100         get_col: function (id) {
101                 return _.find(this.cols, function (col) { return col.id == id;});
102         },
103
104         get_row: function (id) {
105                 return _.find(this.rows, function (row) { return row.id == id;});
106         },
107
108         fold_row: function (row) {
109                 var list = [];
110                 function tree_traversal(tree) {
111                         list.push(tree);
112                         _.each(tree.children, tree_traversal);
113                 }
114                 tree_traversal(row);
115                 this.rows = _.difference(this.rows, _.rest(list));
116                 row.is_expanded = false;
117         var fold_lvls = _.map(this.rows, function(g) {return g.path.length;});
118         var new_groupby_length = _.max(fold_lvls); 
119         this.row_groupby.splice(new_groupby_length);
120         row.children = [];
121         },
122
123         fold_col: function (col) {
124                 var list = [];
125                 function tree_traversal(tree) {
126                         list.push(tree);
127                         _.each(tree.children, tree_traversal);
128                 }
129                 tree_traversal(col);
130                 this.cols = _.difference(this.cols, _.rest(list));
131                 col.is_expanded = false;
132         var fold_lvls = _.map(this.cols, function(g) {return g.path.length;});
133         var new_groupby_length = _.max(fold_lvls); 
134         this.col_groupby.splice(new_groupby_length);
135         col.children = [];
136         },
137
138         expand_row: function (row_id, field_id) {
139         var self = this,
140                 row = this.get_row(row_id);
141
142         if (row.path.length == this.row_groupby.length) {
143             this.row_groupby.push(field_id);
144         }
145         return query_groups_data(this.model, this.visible_fields(), row.domain, this.col_groupby, field_id)
146             .then(function (groups) {
147                 _.each(groups, function (group) {
148                         var new_row_id = self.make_row(group, row);
149                     _.each(group, function (data) {
150                         var col = _.find(self.cols, function (c) {
151                                 return _.isEqual(_.rest(data.path), c.path);
152                         });
153                         if (col) {
154                                 self.set_value(new_row_id, col.id, data.attributes.aggregates[self.measure]);
155                         }
156                     });
157                 });
158                 row.is_expanded = true;
159         });
160         },
161
162         make_row: function (groups, parent) {
163                 var new_row = {
164                         id: this.generate_id(),
165                         path: parent.path.concat(groups[0].attributes.value[1]),
166                         name: groups[0].attributes.value[1],
167                         is_expanded: false,
168                         parent: parent.id,
169                         children: [],
170                         domain: groups[0].model._domain,
171                 };
172                 parent.children.push(new_row);
173                 insertAfter(this.rows, parent, new_row);
174                 return new_row.id;
175         },
176
177         expand_col: function (col_id, field_id) {
178         var self = this,
179                 col = this.get_col(col_id);
180
181         if (col.path.length == this.col_groupby.length) {
182             this.col_groupby.push(field_id);
183         }
184
185         return query_groups_data(this.model, this.visible_fields(), col.domain, this.row_groupby, field_id)
186             .then(function (groups) {
187                 _.each(groups, function (group) {
188                         var new_col_id = self.make_col(group, col);
189                     _.each(group, function (data) {
190                         var row = _.find(self.rows, function (c) {
191                                 return _.isEqual(data.path.slice(1), c.path);
192                         });
193                         if (row) {
194                                 self.set_value(row.id, new_col_id, data.attributes.aggregates[self.measure]);
195                         }
196                     });
197                 });
198                 col.is_expanded = true;
199         });
200         },
201
202         make_col: function (groups, parent) {
203                 var new_col = {
204                         id: this.generate_id(),
205                         path: parent.path.concat(groups[0].attributes.value[1]),
206                         name: groups[0].attributes.value[1],
207                         is_expanded: false,
208                         parent: parent.id,
209                         children: [],
210                         domain: groups[0].model._domain,
211                 };
212                 parent.children.push(new_col);
213                 insertAfter(this.cols, parent, new_col);
214                 return new_col.id;
215         },
216
217         get_chart_data: function () {
218                 var self = this;
219                 var values = _.map(this.rows[0].children, function (pt) {
220                         var val = self.get_value(pt.id, 2);
221                         return {x: pt.name, y: val};
222                 });
223                 return [{key: 'Bar chart', values: values}];
224
225         },
226
227 });
228