OpenERP Web
diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js
index e590280b933..5de601e0921 100644
--- a/addons/web_calendar/static/src/js/calendar.js
+++ b/addons/web_calendar/static/src/js/calendar.js
@@ -35,6 +35,7 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
},
stop: function() {
scheduler.clearAll();
+ this._super();
},
on_loaded: function(data) {
this.fields_view = data;
diff --git a/addons/web_dashboard/static/src/js/dashboard.js b/addons/web_dashboard/static/src/js/dashboard.js
index 008d03d1548..4672492821d 100644
--- a/addons/web_dashboard/static/src/js/dashboard.js
+++ b/addons/web_dashboard/static/src/js/dashboard.js
@@ -301,7 +301,7 @@ openerp.web_dashboard.ConfigOverview = openerp.web.View.extend({
.then(this.on_records_loaded);
},
on_records_loaded: function (read_response, progress_response) {
- var records = read_response[0].records,
+ var records = read_response,
progress = progress_response[0];
var grouped_todos = _(records).chain()
diff --git a/addons/web_default_home/static/src/js/home.js b/addons/web_default_home/static/src/js/home.js
index ed8561bc44d..67964351873 100644
--- a/addons/web_default_home/static/src/js/home.js
+++ b/addons/web_default_home/static/src/js/home.js
@@ -94,8 +94,10 @@ openerp.web_default_home = function (openerp) {
})
},
install_module: function (module_name) {
+ var self = this;
var Modules = new openerp.web.DataSetSearch(
- this, 'ir.module.module', null, [['name', '=', module_name], ['state', '=', 'uninstalled']]);
+ this, 'ir.module.module', null,
+ [['name', '=', module_name], ['state', '=', 'uninstalled']]);
var Upgrade = new openerp.web.DataSet(this, 'base.module.upgrade');
$.blockUI({message:'

'});
@@ -105,13 +107,21 @@ openerp.web_default_home = function (openerp) {
[_.pluck(records, 'id'), 'to install', ['uninstalled']],
function () {
Upgrade.call('upgrade_module', [[]], function () {
- $.unblockUI();
- // TODO: less brutal reloading
- window.location.reload(true);
+ self.run_configuration_wizards();
});
}
)
});
+ },
+ run_configuration_wizards: function () {
+ var self = this;
+ new openerp.web.DataSet(this, 'res.config').call('start', [[]], function (action) {
+ $.unblockUI();
+ self.do_action(action, function () {
+ // TODO: less brutal reloading
+ window.location.reload(true);
+ });
+ });
}
});
};
diff --git a/addons/web_graph/__init__.py b/addons/web_graph/__init__.py
index 53e20f29429..e69de29bb2d 100644
--- a/addons/web_graph/__init__.py
+++ b/addons/web_graph/__init__.py
@@ -1,2 +0,0 @@
-#!/usr/bin/python
-import controllers
\ No newline at end of file
diff --git a/addons/web_graph/__openerp__.py b/addons/web_graph/__openerp__.py
index 4a1c4a6576f..03839744480 100644
--- a/addons/web_graph/__openerp__.py
+++ b/addons/web_graph/__openerp__.py
@@ -3,7 +3,7 @@
"version": "2.0",
"depends": ['web'],
"js": [
- "static/lib/dhtmlxGraph/codebase/dhtmlxchart.js",
+ "static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.js",
"static/src/js/graph.js"],
"css": ["static/lib/dhtmlxGraph/codebase/dhtmlxchart.css"],
"active": True
diff --git a/addons/web_graph/controllers/__init__.py b/addons/web_graph/controllers/__init__.py
deleted file mode 100644
index 039d9715fab..00000000000
--- a/addons/web_graph/controllers/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-import main
\ No newline at end of file
diff --git a/addons/web_graph/controllers/main.py b/addons/web_graph/controllers/main.py
deleted file mode 100644
index cda868c0809..00000000000
--- a/addons/web_graph/controllers/main.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from web.controllers.main import View
-import web.common as openerpweb
-
-class GraphView(View):
- _cp_path = "/web_graph/graphview"
-
- @openerpweb.jsonrequest
- def load(self, req, model, view_id):
- fields_view = self.fields_view_get(req, model, view_id, 'graph')
- all_fields = req.session.model(model).fields_get()
- return {'fields_view': fields_view, 'all_fields':all_fields}
diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js
index 2a493b89166..08ceeddc2d9 100644
--- a/addons/web_graph/static/src/js/graph.js
+++ b/addons/web_graph/static/src/js/graph.js
@@ -19,11 +19,14 @@ openerp.web_graph.GraphView = openerp.web.View.extend({
init: function(parent, dataset, view_id) {
this._super(parent);
- this.view_manager = parent;
this.dataset = dataset;
- this.dataset_index = 0;
- this.model = this.dataset.model;
this.view_id = view_id;
+
+ this.first_field = null;
+ this.abscissa = null;
+ this.ordinate = null;
+ this.columns = [];
+ this.group_field = null;
},
do_show: function () {
// TODO: re-trigger search
@@ -33,348 +36,265 @@ openerp.web_graph.GraphView = openerp.web.View.extend({
this.$element.hide();
},
start: function() {
+ var self = this;
this._super();
- return this.rpc("/web_graph/graphview/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
+ return $.when(
+ this.dataset.call('fields_get', []),
+ this.rpc('/web/view/load', {
+ model: this.dataset.model,
+ view_id: this.view_id,
+ view_type: 'graph'
+ })).then(function (fields_result, view_result) {
+ self.fields = fields_result[0];
+ self.fields_view = view_result[0];
+ self.on_loaded();
+ });
},
- on_loaded: function(data) {
- this.all_fields = data.all_fields;
- this.fields_view = data.fields_view;
- this.name = this.fields_view.name || this.fields_view.arch.attrs.string;
- this.view_id = this.fields_view.view_id;
+ /**
+ * Returns all object fields involved in the graph view
+ */
+ list_fields: function () {
+ var fs = [this.abscissa];
+ fs.push.apply(fs, _(this.columns).pluck('name'));
+ if (this.group_field) {
+ fs.push(this.group_field);
+ }
+ return fs;
+ },
+ on_loaded: function() {
this.chart = this.fields_view.arch.attrs.type || 'pie';
- this.fields = this.fields_view.fields;
- this.chart_info_fields = [];
- this.operator_field = '';
- this.operator_field_one = '';
- this.operator = [];
- this.group_field = [];
- this.orientation = this.fields_view.arch.attrs.orientation || '';
- this.elem_id = this.$element[0]['id'];
+ this.orientation = this.fields_view.arch.attrs.orientation || 'vertical';
_.each(this.fields_view.arch.children, function (field) {
- if (field.attrs.operator) {
- this.operator.push(field.attrs.name);
- }
- else if (field.attrs.group) {
- this.group_field.push(field.attrs.name);
- }
- else {
- this.chart_info_fields.push(field.attrs.name);
- }
- }, this);
-
- this.operator_field = this.operator[0];
- if(this.operator.length > 1){
- this.operator_field_one = this.operator[1];
- }
- if(this.operator == ''){
- this.operator_field = this.chart_info_fields[1];
- }
- this.chart_info = this.chart_info_fields[0];
- this.x_title = this.fields[this.chart_info_fields[0]]['string'];
- this.y_title = this.fields[this.operator_field]['string'];
- this.load_chart();
- },
-
- load_chart: function(data) {
- var self = this;
- var domain = false;
- if(data){
- this.x_title = this.all_fields[this.chart_info_fields]['string'];
- this.y_title = this.all_fields[this.operator_field]['string'];
- self.schedule_chart(data);
- }else{
- if(! _.isEmpty(this.view_manager.dataset.domain)){
- domain = this.view_manager.dataset.domain;
- }else if(! _.isEmpty(this.view_manager.action.domain)){
- domain = this.view_manager.action.domain;
- }
- this.dataset.domain = domain;
- this.dataset.context = this.view_manager.dataset.context;
- this.dataset.read_slice(_(this.fields).keys(),{}, function(res) {
- self.schedule_chart(res);
- });
- }
- },
-
- schedule_chart: function(results) {
- this.$element.html(QWeb.render("GraphView", {"fields_view": this.fields_view, "chart": this.chart,'elem_id': this.elem_id}));
-
- _.each(results, function (result) {
- _.each(result, function (field_value, field_name) {
- if (typeof field_value == 'object') {
- result[field_name] = field_value[field_value.length - 1];
- }
- if (typeof field_value == 'string') {
- var choices = this.all_fields[field_name]['selection'];
- _.each(choices, function (choice) {
- if (field_value == choice[0]) {
- result[field_name] = choice;
- }
- });
- }
- }, this);
- }, this);
-
- var graph_data = {};
- _.each(results, function (result) {
- var group_key = [];
- if(this.group_field.length){
- _.each(this.group_field, function (res) {
- result[res] = (typeof result[res] == 'object') ? result[res][1] : result[res];
- group_key.push(result[res]);
- });
- }else{
- group_key.push(result[this.group_field]);
- }
- var column_key = result[this.chart_info_fields] + "_" + group_key;
- var column_descriptor = {};
- if (graph_data[column_key] == undefined) {
- column_descriptor[this.operator_field] = result[this.operator_field];
- if (this.operator.length > 1) {
- column_descriptor[this.operator_field_one] = result[this.operator_field_one];
- }
- column_descriptor[this.chart_info_fields] = result[this.chart_info_fields];
- if(this.group_field.length){
- _.each(this.group_field, function (res) {
- column_descriptor[res] = (typeof result[res] == 'object') ? result[res][1] : result[res];
- });
- }
+ var attrs = field.attrs;
+ if (attrs.group) {
+ this.group_field = attrs.name;
+ } else if(!this.abscissa) {
+ this.first_field = this.abscissa = attrs.name;
} else {
- column_descriptor = graph_data[column_key];
- column_descriptor[this.operator_field] += result[this.operator_field];
- if (this.operator.length > 1) {
- column_descriptor[this.operator_field_one] += result[this.operator_field_one];
- }
+ this.columns.push({
+ name: attrs.name,
+ operator: attrs.operator || '+'
+ });
}
- graph_data[column_key] = column_descriptor;
}, this);
+ this.ordinate = this.columns[0].name;
+
+ this.dataset.read_slice(
+ this.list_fields(), {}, $.proxy(this, 'schedule_chart'));
+ },
+ schedule_chart: function(results) {
+ var self = this;
+ this.$element.html(QWeb.render("GraphView", {
+ "fields_view": this.fields_view,
+ "chart": this.chart,
+ 'element_id': this.element_id
+ }));
+
+ var fields = _(this.columns).pluck('name').concat([this.abscissa]);
+ if (this.group_field) { fields.push(this.group_field); }
+ // transform search result into usable records (convert from OpenERP
+ // value shapes to usable atomic types
+ var records = _(results).map(function (result) {
+ var point = {};
+ _(result).each(function (value, field) {
+ if (!_(fields).contains(field)) { return; }
+ if (value === false) { point[field] = false; return; }
+ switch (self.fields[field].type) {
+ case 'selection':
+ point[field] = _(self.fields[field].selection).detect(function (choice) {
+ return choice[0] === value;
+ })[1];
+ break;
+ case 'many2one':
+ point[field] = value[1];
+ break;
+ case 'integer': case 'float': case 'char':
+ case 'date': case 'datetime':
+ point[field] = value;
+ break;
+ default:
+ throw new Error(
+ "Unknown field type " + self.fields[field].type
+ + "for field " + field + " (" + value + ")");
+ }
+ });
+ return point;
+ });
+ // aggregate data, because dhtmlx is crap. Aggregate on abscissa field,
+ // leave split on group field => max m*n records where m is the # of
+ // values for the abscissa and n is the # of values for the group field
+ var graph_data = [];
+ _(records).each(function (record) {
+ var abscissa = record[self.abscissa],
+ group = record[self.group_field];
+ var r = _(graph_data).detect(function (potential) {
+ return potential[self.abscissa] === abscissa
+ && (!self.group_field
+ || potential[self.group_field] === group);
+ });
+ var datapoint = r || {};
+
+ datapoint[self.abscissa] = abscissa;
+ if (self.group_field) { datapoint[self.group_field] = group; }
+ _(self.columns).each(function (column) {
+ var val = record[column.name],
+ aggregate = datapoint[column.name];
+ switch(column.operator) {
+ case '+':
+ datapoint[column.name] = (aggregate || 0) + val;
+ return;
+ case '*':
+ datapoint[column.name] = (aggregate || 1) * val;
+ return;
+ case 'min':
+ datapoint[column.name] = (aggregate || Infinity) > val
+ ? val
+ : aggregate;
+ return;
+ case 'max':
+ datapoint[column.name] = (aggregate || -Infinity) < val
+ ? val
+ : aggregate;
+ }
+ });
+
+ if (!r) { graph_data.push(datapoint); }
+ });
+ graph_data = _(graph_data).sortBy(function (point) {
+ return point[self.abscissa] + '[[--]]' + point[self.group_field];
+ });
if (this.chart == 'bar') {
- return this.schedule_bar(_.values(graph_data));
+ return this.schedule_bar(graph_data);
} else if (this.chart == "pie") {
- return this.schedule_pie(_.values(graph_data));
+ return this.schedule_pie(graph_data);
}
},
schedule_bar: function(results) {
var self = this;
- var view_chart = '';
- var group_list = [];
- var legend_list = [];
- var newkey = '', newkey_one;
- var string_legend = '';
- if((self.group_field.length) && (this.operator.length <= 1)){
- view_chart = self.orientation == 'horizontal'? 'stackedBarH' : 'stackedBar';
- }else{
- view_chart = self.orientation == 'horizontal'? 'barH' : 'bar';
- }
-
- _.each(results, function (result) {
- if ((self.group_field.length) && (this.operator.length <= 1)) {
- var legend_key = '';
- _.each(self.group_field, function (res) {
- result[res] = (typeof result[res] == 'object') ? result[res][1] : result[res];
- legend_key += result[res];
- });
- newkey = legend_key.replace(/\s+/g,'_').replace(/[^a-zA-Z 0-9]+/g,'_');
- string_legend = legend_key;
- } else {
- newkey = string_legend = "val";
- }
-
- if (_.contains(group_list, newkey) && _.contains(legend_list, string_legend)) {
- return;
- }
- group_list.push(newkey);
- legend_list.push(string_legend);
-
- if (this.operator.length > 1) {
- newkey_one = "val1";
- group_list.push(newkey_one);
- legend_list.push(newkey_one);
- }
- }, this);
-
- if (group_list.length <=1){
- group_list = [];
- legend_list = [];
- newkey = string_legend = "val";
- group_list.push(newkey);
- legend_list.push(string_legend);
- }
-
- var abscissa_data = {};
- _.each(results, function (result) {
- var label = result[self.chart_info_fields],
- section = {};
- if ((self.group_field.length) && (group_list.length > 1) && (self.operator.length <= 1)){
- var legend_key_two = '';
- _.each(self.group_field, function (res) {
- result[res] = (typeof result[res] == 'object') ? result[res][1] : result[res];
- legend_key_two += result[res];
- });
- newkey = legend_key_two.replace(/\s+/g,'_').replace(/[^a-zA-Z 0-9]+/g,'_');
- }else{
- newkey = "val";
- }
- if (abscissa_data[label] == undefined){
- section[self.chart_info_fields] = label;
- _.each(group_list, function (group) {
- section[group] = 0;
- });
- } else {
- section = abscissa_data[label];
- }
- section[newkey] = result[self.operator_field];
- if (self.operator.length > 1){
- section[newkey_one] = result[self.operator_field_one];
- }
- abscissa_data[label] = section;
- });
-
- //for legend color
- var grp_color = _.map(legend_list, function (group_legend, index) {
- var legend = {color: COLOR_PALETTE[index]};
- if (group_legend == "val"){
- legend['text'] = self.fields[self.operator_field]['string']
- }else if(group_legend == "val1"){
- legend['text'] = self.fields[self.operator_field_one]['string']
- }else{
- legend['text'] = group_legend;
- }
- return legend;
- });
-
- //for axis's value and title
- var max,min,step;
- var maximum,minimum;
- if(_.isEmpty(abscissa_data)){
- max = 9;
- min = 0;
- step=1;
- }else{
- var max_min = [];
- _.each(abscissa_data, function (abscissa_datas) {
- _.each(group_list, function(res){
- max_min.push(abscissa_datas[res]);
- });
- });
- maximum = Math.max.apply(Math,max_min);
- minimum = Math.min.apply(Math,max_min);
- if (maximum == minimum){
- if (maximum == 0){
- max = 9;
- min = 0;
- step=1;
- }else if(maximum > 0){
- max = maximum + (10 - maximum % 10);
- min = 0;
- step = Math.round(max/10);
- }else{
- max = 0;
- min = minimum - (10 + minimum % 10);
- step = Math.round(Math.abs(min)/10);
+ var group_list, view_chart;
+ if (!this.group_field) {
+ view_chart = (this.orientation === 'horizontal') ? 'barH' : 'bar';
+ group_list = _(this.columns).map(function (column, index) {
+ return {
+ group: column.name,
+ text: self.fields[column.name].string,
+ color: COLOR_PALETTE[index % (COLOR_PALETTE.length)]
}
+ });
+ } else {
+ // dhtmlx handles clustered bar charts (> 1 column per abscissa
+ // value) and stacked bar charts (basically the same but with the
+ // columns on top of one another instead of side by side), but it
+ // does not handle clustered stacked bar charts
+ if (this.columns.length > 1) {
+ this.$element.text(
+ 'OpenERP Web does not support combining grouping and '
+ + 'multiple columns in graph at this time.');
+ throw new Error(
+ 'dhtmlx can not handle columns counts of that magnitude');
}
+ // transform series for clustered charts into series for stacked
+ // charts
+ view_chart = (this.orientation === 'horizontal')
+ ? 'stackedBarH' : 'stackedBar';
+ group_list = _(results).chain()
+ .pluck(this.group_field)
+ .uniq()
+ .map(function (value, index) {
+ return {
+ group: self.ordinate + '_' +
+ value.toLowerCase().replace(/\s/g, '_'),
+ text: value,
+ color: COLOR_PALETTE[index % COLOR_PALETTE.length]
+ };
+ }).value();
+
+ results = _(results).chain()
+ .groupBy(function (record) { return record[self.abscissa]; })
+ .map(function (records) {
+ var r = {};
+ // second argument is coerced to a str, no good for boolean
+ r[self.abscissa] = records[0][self.abscissa];
+ _(records).each(function (record) {
+ var key = _.sprintf('%s_%s',
+ self.ordinate,
+ record[self.group_field].toLowerCase().replace(/\s/g, '_'));
+ r[key] = record[self.ordinate];
+ });
+ return r;
+ })
+ .value();
}
+
var abscissa_description = {
- template: self.chart_info_fields,
- title: "
"+self.x_title+""
+ title: "
" + this.fields[this.abscissa].string + "",
+ template: function (obj) {
+ return obj[self.abscissa] || 'Undefined';
+ }
};
var ordinate_description = {
lines: true,
- title: "
"+self.y_title+"",
- start: min,
- step: step,
- end: max
+ title: "
" + this.fields[this.ordinate].string + ""
};
- var x_axis, y_axis, tooltip;
- if (self.orientation == 'horizontal'){
- x_axis = ordinate_description;
- y_axis = abscissa_description;
- }else{
- x_axis = abscissa_description;
- y_axis = ordinate_description;
+ var x_axis, y_axis;
+ if (self.orientation == 'horizontal') {
+ x_axis = ordinate_description;
+ y_axis = abscissa_description;
+ } else {
+ x_axis = abscissa_description;
+ y_axis = ordinate_description;
}
- tooltip = self.chart_info_fields;
-
+
var bar_chart = new dhtmlXChart({
view: view_chart,
- container: self.elem_id+"-barchart",
- value:"#"+group_list[0]+"#",
+ container: this.element_id+"-barchart",
+ value:"#"+group_list[0].group+"#",
gradient: "3d",
border: false,
width: 1024,
tooltip:{
- template:"#"+tooltip+"#"+","+grp_color[0]['text']+"="+"#"+group_list[0]+"#"
+ template: _.sprintf("#%s#, %s=#%s#",
+ this.abscissa, group_list[0].text, group_list[0].group)
},
radius: 0,
- color:grp_color[0]['color'],
+ color:group_list[0].color,
origin:0,
- xAxis:{
- template:function(obj){
- if(x_axis['template']){
- var val = obj[x_axis['template']];
- val = (typeof val == 'object')?val[1]:(!val?'Undefined':val);
- if(val.length > 12){
- val = val.substring(0,12);
- }
- return val;
- }else{
- return obj;
- }
- },
- title:x_axis['title'],
- lines:x_axis['lines']
- },
- yAxis:{
- template:function(obj){
- if(y_axis['template']){
- var vals = obj[y_axis['template']];
- vals = (typeof vals == 'object')?vals[1]:(!vals?'Undefined':vals);
- if(vals.length > 12){
- vals = vals.substring(0,12);
- }
- return vals;
- }else{
- return obj;
- }
- },
- title:y_axis['title'],
- lines: y_axis['lines'],
- start:y_axis['start'],
- step:y_axis['step'],
- end:y_axis['end']
- },
+ xAxis: x_axis,
+ yAxis: y_axis,
padding: {
left: 75
},
legend: {
- values: grp_color,
+ values: group_list,
align:"left",
valign:"top",
layout: "x",
- marker:{
+ marker: {
type:"round",
width:12
}
}
});
for (var m = 1; m
-
\ No newline at end of file
diff --git a/addons/web_hello/__openerp__.py b/addons/web_hello/__openerp__.py
index 7a80645f3b8..498f5129961 100644
--- a/addons/web_hello/__openerp__.py
+++ b/addons/web_hello/__openerp__.py
@@ -5,4 +5,5 @@
"js": ["static/*/*.js", "static/*/js/*.js"],
"css": [],
'active': False,
+ 'web_preload': False,
}
diff --git a/addons/web_hello/static/openerp/base_hello.js b/addons/web_hello/static/openerp/base_hello.js
index 99c97006eac..91caf263196 100644
--- a/addons/web_hello/static/openerp/base_hello.js
+++ b/addons/web_hello/static/openerp/base_hello.js
@@ -13,6 +13,13 @@ openerp.web.SearchView = openerp.web.SearchView.extend({
// here you may tweak globals object, if any, and play with on_* or do_* callbacks on them
+openerp.web.Login = openerp.web.Login.extend({
+ start: function() {
+ console.log('Hello there');
+ this._super.apply(this,arguments);
+ }
+});
+
};
// vim:et fdc=0 fdl=0:
diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css
index afac6cdef47..f92203589b2 100644
--- a/addons/web_kanban/static/src/css/kanban.css
+++ b/addons/web_kanban/static/src/css/kanban.css
@@ -1,8 +1,21 @@
.openerp .oe_kanban_view .oe_column {
- float: left;
width: 100%;
}
+.openerp .oe_vertical_text {
+ writing-mode:tb-rl;
+ -webkit-transform:rotate(90deg);
+ -moz-transform:rotate(90deg);
+ -o-transform: rotate(90deg);
+ -ms-transform: rotate(90deg);
+ transform: rotate(90deg);
+ display:block;
+ width:30px;
+ height:20px;
+ align:center;
+ font-size:24px;
+}
+
.openerp .oe_kanban_view .ui-sortable-placeholder {
border: 1px dotted black;
visibility: visible !important;
@@ -14,6 +27,10 @@
font-size: 1.5em;
font-weight: bold;
}
+.openerp .oe_kanban_view .fold-columns-icon {
+ float: left;
+ padding: 2px 2px 0 0;
+}
.openerp .oe_kanban_action_button {
height: 22px;
margin: 0;
@@ -200,4 +217,3 @@
.openerp .oe_kanban_color_alert .oe_kanban_color_border {
border-color: #c00 !important;
}
-
diff --git a/addons/web_kanban/static/src/img/minus-icon.png b/addons/web_kanban/static/src/img/minus-icon.png
new file mode 100644
index 00000000000..cb655d1e503
Binary files /dev/null and b/addons/web_kanban/static/src/img/minus-icon.png differ
diff --git a/addons/web_kanban/static/src/img/plus-icon.png b/addons/web_kanban/static/src/img/plus-icon.png
new file mode 100644
index 00000000000..7bb9b1be856
Binary files /dev/null and b/addons/web_kanban/static/src/img/plus-icon.png differ
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index 8d6727facaa..46173341361 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -18,6 +18,8 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
this.all_display_data = false;
this.groups = [];
this.qweb = new QWeb2.Engine();
+ this.aggregates = {};
+ this.NO_OF_COLUMNS = 3;
if (this.options.action_views_ids.form) {
this.form_dialog = new openerp.web.FormDialog(this, {}, this.options.action_views_ids.form, dataset).start();
this.form_dialog.on_form_dialog_saved.add_last(this.on_record_saved);
@@ -36,8 +38,17 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
}
},
add_qweb_template: function() {
+ var group_operator = ["avg", "max", "min", "sum", "count"]
for (var i=0, ii=this.fields_view.arch.children.length; i < ii; i++) {
var child = this.fields_view.arch.children[i];
+ if (child.tag === "field") {
+ for(j=0, jj=group_operator.length; j < jj; j++) {
+ if (child.attrs[group_operator[j]]) {
+ this.aggregates[child.attrs.name] = child.attrs[group_operator[j]];
+ break;
+ }
+ }
+ }
if (child.tag === "templates") {
this.transform_qweb_template(child);
this.qweb.add_template(openerp.web.json_node_to_xml(child));
@@ -118,14 +129,33 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
}
}
},
- on_show_data: function(data) {
+ sort_group: function (first, second) {
+ if (first.header && second.header)
+ {
+ first = first.header.toLowerCase();
+ second = second.header.toLowerCase();
+ if (first > second) return 1;
+ else if (first < second) return -1;
+ else return 0;
+ }
+ else return 0;
+ },
+ on_show_data: function() {
var self = this;
- this.$element.html(QWeb.render("KanbanView", {"data": data}));
+ if (!this.group_by.length) {
+ this.do_record_group();
+ }
+ self.all_display_data.sort(this.sort_group);
+ this.$element.html(QWeb.render("KanbanView", {"data": self.all_display_data}));
this.on_reload_kanban();
+ this.$element.find(".oe_vertical_text").hide();
var drag_handel = false;
if (this.$element.find(".oe_kanban_draghandle").length > 0) {
drag_handel = ".oe_kanban_draghandle";
}
+ if (!this.group_by.length) {
+ drag_handel = true;
+ }
this.$element.find(".oe_column").sortable({
connectWith: ".oe_column",
handle : drag_handel,
@@ -134,36 +164,44 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
self.source_index['column'] = ui.item.parent().attr('id');
},
stop: self.on_receive_record,
+ scroll: false
});
this.$element.find(".oe_column").disableSelection()
this.$element.find('button.oe_kanban_button_new').click(this.do_add_record);
+ this.$element.find(".fold-columns-icon").click(function(event) {
+ self.do_fold_unfold_columns(event, this.id);
+ });
},
- on_button_click: function (button_attrs, record_id) {
- var self = this;
- if (this.groups.length) {
- _.each(this.groups, function (group) {
- group.list([],
- function (groups) {},
- function (dataset) {
- dataset.read_slice([], {}, function(records) {
- var index = parseInt(_.indexOf(dataset.ids, record_id));
- if(index >= 0) {
- self.on_confirm_click(dataset, button_attrs, index, record_id);
- }
- });
- }
- );
- });
- } else {
- var index = parseInt(_.indexOf(self.dataset.ids, record_id));
- if (index >= 0) {
- _.extend(self.dataset, {domain: self.domain, context: self.context});
- self.on_confirm_click(self.dataset, button_attrs, index, record_id);
+ do_fold_unfold_columns: function(event, element_id) {
+ var column_id = "column_" + element_id;
+ var column_element = this.$element.find("#" + column_id + " .oe_fold_column");
+ if (column_element.is(":hidden")) {
+ this.$element.find("#" + column_id).find("img.fold-columns-icon").attr('src', '/web_kanban/static/src/img/minus-icon.png');
+ column_element.show();
+ this.$element.find("#" + column_id + ".oe_table_column").css("width",Math.round(99 / this.all_display_data.length) + "%");
+ this.$element.find("#" + column_id + ".oe_vertical_text").hide();
+ }
+ else{
+ this.$element.find("#" + column_id).find("img.fold-columns-icon").attr('src', '/web_kanban/static/src/img/plus-icon.png');
+ column_element.hide();
+ this.$element.find("#" + column_id + ".oe_table_column").css("width","0.5%");
+ this.$element.find("#" + column_id + ".oe_vertical_text").show();
+ }
+
+ },
+ do_record_group: function() {
+ if (this.NO_OF_COLUMNS && this.all_display_data.length > 0) {
+ var records = this.all_display_data[0].records;
+ var record_per_group = Math.round((records).length / this.NO_OF_COLUMNS);
+ this.all_display_data = [];
+ for (var i=0, ii=this.NO_OF_COLUMNS; i < ii; i++) {
+ this.all_display_data.push({'records': records.slice(0,record_per_group), 'value':i, 'header' : false, 'ids':[]});
+ records.splice(0,record_per_group);
}
}
},
- on_confirm_click: function (dataset, button_attrs, index, record_id) {
- this.on_execute_button_click(dataset, button_attrs, record_id);
+ on_button_click: function (button_attrs, record_id) {
+ this.on_execute_button_click(this.dataset, button_attrs, record_id);
},
do_add_record: function() {
this.dataset.index = null;
@@ -179,8 +217,7 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
},
on_record_saved: function(r) {
var id = this.form_dialog.form.datarecord.id;
- // TODO fme: reload record instead of all. need refactoring
- this.do_actual_search();
+ this.on_reload_record(id);
},
do_change_color: function(record_id, $e) {
var self = this,
@@ -198,12 +235,41 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
var data = {};
data[$e.data('name')] = $(this).data('color');
self.dataset.write(id, data, {}, function() {
- // TODO fme: reload record instead of all. need refactoring
- self.do_actual_search();
+ self.on_reload_record(id);
});
$cpicker.remove();
});
},
+ /**
+ Reload one record in view.
+ record_id : reload record id.
+ */
+ on_reload_record: function (record_id){
+ var self = this;
+ this.dataset.read_ids([record_id], [], function (records) {
+ if (records.length > 0) {
+ for (var i=0, ii=self.all_display_data.length; i < ii; i++) {
+ for(j=0, jj=self.all_display_data[i].records.length; j < jj; j++) {
+ if (self.all_display_data[i].records[j].id == record_id) {
+ _.extend(self.all_display_data[i].records[j], records[0]);
+ self.$element.find("#main_" + record_id).children().remove();
+ self.$element.find("#main_" + record_id).append(self.qweb.render('kanban-box', {
+ record: self.do_transform_record(self.all_display_data[i].records[j]),
+ kanban_color: self.kanban_color,
+ kanban_gravatar: self.kanban_gravatar
+ }));
+ break;
+ }
+ }
+ }
+ self.$element.find("#main_" + record_id + " .oe_kanban_action").click(self.on_action_clicked);
+ self.$element.find("#main_" + record_id + " .oe_kanban_box_show_onclick_trigger").click(function() {
+ $(this).parent("#main_" + record_id + " .oe_kanban_box").find(".oe_kanban_box_show_onclick").toggle();
+ });
+ }
+ });
+
+ },
do_delete: function (id) {
var self = this;
return $.when(this.dataset.unlink([id])).then(function () {
@@ -228,16 +294,7 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
this.do_execute_action(
button_attrs, dataset,
record_id, function () {
- var count = 1;
- _.each(self.all_display_data, function(data, index) {
- self.dataset.read_ids( data.ids, [], function(records){
- self.all_display_data[index].records = records;
- if(self.all_display_data.length == count) {
- self.do_actual_search();
- }
- count++;
- });
- });
+ self.do_actual_search();
}
);
},
@@ -249,9 +306,8 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
if (!ui.item.attr("id")) {
return false;
}
- // TODO fme: check what was this sequence
- if (self.fields_view.fields.sequence && (self.source_index.index >= 0 && self.source_index.index != from) ||
- (self.source_index.column && self.source_index.column != ui.item.parent().attr('id'))) {
+ if (self.fields_view.fields.sequence != undefined && ((self.source_index.index >= 0 && self.source_index.index != from) ||
+ (self.source_index.column && self.source_index.column != ui.item.parent().attr('id')))) {
var child_record = ui.item.parent().children();
var data, sequence = 1, index = to;
child_record.splice(0, to);
@@ -338,9 +394,6 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
kanban_gravatar: self.kanban_gravatar
}));
});
- } else {
- self.$element.find("#column_" + data.value).remove();
- self.all_display_data.splice(index, 1);
}
});
this.$element.find('.oe_kanban_action').click(this.on_action_clicked);
@@ -377,8 +430,8 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
do_search: function (domains, contexts, group_by) {
var self = this;
this.rpc('/web/session/eval_domain_and_context', {
- domains: domains,
- contexts: contexts,
+ domains: [this.dataset.get_domain()].concat(domains),
+ contexts: [this.dataset.get_context()].concat(contexts),
group_by_seq: group_by
}, function (results) {
self.domain = results.domain;
@@ -392,23 +445,27 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
group_by = self.group_by;
if (!group_by.length && this.fields_view.arch.attrs.default_group_by) {
group_by = [this.fields_view.arch.attrs.default_group_by];
+ self.group_by = group_by;
}
self.datagroup = new openerp.web.DataGroup(self, self.model, self.domain, self.context, group_by);
- self.dataset.context = self.context;
- self.dataset.domain = self.domain;
- self.datagroup.list([],
+ self.datagroup.list(_.keys(self.fields_view.fields),
function (groups) {
self.groups = groups;
- self.do_render_group(groups);
+ if (groups.length) {
+ self.do_render_group(groups);
+ }
+ else {
+ self.all_display_data = [];
+ self.on_show_data();
+ }
},
function (dataset) {
- self.domain = dataset.domain;
- self.context = dataset.context;
self.groups = [];
- self.dataset.read_slice([], {}, function(records) {
- self.all_display_data = [{'records': records, 'value':false, 'header' : false, 'ids': self.dataset.ids}];
+ self.dataset.read_slice([], {'domain': self.domain, 'context': self.context}, function(records) {
+ if (records.length) self.all_display_data = [{'records': records, 'value':false, 'header' : false, 'ids': self.dataset.ids}];
+ else self.all_display_data = [];
self.$element.find(".oe_kanban_view").remove();
- self.on_show_data(self.all_display_data);
+ self.on_show_data();
});
}
);
@@ -417,8 +474,6 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
this.all_display_data = [];
var self = this;
_.each(datagroups, function (group) {
- self.dataset.context = group.context;
- self.dataset.domain = group.domain;
var group_name = group.value;
var group_value = group.value;
if (!group.value) {
@@ -428,11 +483,15 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({
group_name = group.value[1];
group_value = group.value[0];
}
- self.dataset.read_slice([], {}, function(records) {
- self.all_display_data.push({"value" : group_value, "records": records, 'header':group_name, 'ids': self.dataset.ids});
+ var group_aggregates = {};
+ _.each(self.aggregates, function(value, key) {
+ group_aggregates[value] = group.aggregates[key];
+ });
+ self.dataset.read_slice([], {'domain': group.domain, 'context': group.context}, function(records) {
+ self.all_display_data.push({"value" : group_value, "records": records, 'header':group_name, 'ids': self.dataset.ids, 'aggregates': group_aggregates});
if (datagroups.length == self.all_display_data.length) {
self.$element.find(".oe_kanban_view").remove();
- self.on_show_data(self.all_display_data);
+ self.on_show_data();
}
});
});
diff --git a/addons/web_kanban/static/src/xml/web_kanban.xml b/addons/web_kanban/static/src/xml/web_kanban.xml
index aa7bc73190d..8f3aaf457e9 100644
--- a/addons/web_kanban/static/src/xml/web_kanban.xml
+++ b/addons/web_kanban/static/src/xml/web_kanban.xml
@@ -9,15 +9,22 @@