[IMP] account: improve account_contract_dashboard

Mainly style and js improvements for graphs
This commit is contained in:
Martin Geubelle
2015-07-01 18:04:47 +02:00
parent 6cc695106f
commit ea3b118eae
4 changed files with 178 additions and 75 deletions
@@ -87,7 +87,7 @@ class account_journal(models.Model):
short_name = format_date(show_date, 'd MMM', locale=locale)
data.append({'x': short_name, 'y':last_balance, 'name': name})
return [{'values': data, 'color': '#ff7f0e', 'area': True}]
return [{'values': data, 'area': True}]
@api.multi
def get_bar_graph_datas(self):
@@ -96,7 +96,7 @@ class account_journal(models.Model):
if self.type == 'purchase':
title = _('Bills you need to pay')
today = datetime.strptime(fields.Date.context_today(self), DF)
data.append({'label': _('Past'), 'value':0.0, 'color': '#ff0000'})
data.append({'label': _('Past'), 'value':0.0, 'type': 'past'})
day_of_week = int(format_datetime(today, 'e', locale=self._context.get('lang', 'en_US')))
first_day_of_week = today + timedelta(days=-day_of_week+1)
for i in range(-1,4):
@@ -111,7 +111,7 @@ class account_journal(models.Model):
label = str(start_week.day) + '-' +str(end_week.day)+ ' ' + format_date(end_week, 'MMM', locale=self._context.get('lang', 'en_US'))
else:
label = format_date(start_week, 'd MMM', locale=self._context.get('lang', 'en_US'))+'-'+format_date(end_week, 'd MMM', locale=self._context.get('lang', 'en_US'))
data.append({'label':label,'value':0.0, 'color': '#ff0000' if i<0 else '#ff7f0e'})
data.append({'label':label,'value':0.0, 'type': 'past' if i<0 else 'future'})
# Build SQL query to find amount aggregated by week
select_sql_clause = """SELECT sum(residual_signed) as total, min(date) as aggr_date from account_invoice where journal_id = %(journal_id)s and state = 'open'"""
@@ -132,8 +132,6 @@ class account_journal(models.Model):
for index in range(0, len(query_results)):
if query_results[index].get('aggr_date') != None:
data[index]['value'] = query_results[index].get('total')
else:
data[index]['color'] = '#ffffff'
return [{'values': data, 'title': title}]
@@ -5,84 +5,116 @@ var kanban_widgets = require('web_kanban.widgets');
var JournalDashboardGraph = kanban_widgets.AbstractField.extend({
start: function() {
var self = this;
self.graph_type = self.$node.attr('graph_type')
self.display_graph(JSON.parse(self.field.raw_value));
this.graph_type = this.$node.attr('graph_type');
this.data = JSON.parse(this.field.raw_value);
this.display_graph();
},
display_graph : function(data) {
display_graph : function() {
var self = this;
nv.addGraph(function () {
self.$el.append('<svg style="height:75px; overflow:visible;">');
var type = self.graph_type
switch(type) {
self.$svg = self.$el.append('<svg>');
switch(self.graph_type) {
case "line":
var chart = nv.models.lineChart();
chart.options({
x: function(d,u) { return u},
width: self.$el.find('svg').width(),
height: self.$el.find('svg').height(),
margin: {'left': 15, 'right':10, 'top':10, 'bottom': 20},
self.$svg.addClass('o_graph_linechart');
self.chart = nv.models.lineChart();
self.chart.options({
x: function(d, u) { return u },
margin: {'left': 0, 'right': 0, 'top': 0, 'bottom': 0},
showYAxis: false,
showLegend: false,
tooltips: true,
tooltipContent: function(key, x, y, e, graph) {
var header = "";
$.each(e.series.values, function(k,v){
if (v.x === x){
header = v.name;
return self.create_tooltip(x, y, e);
},
});
self.chart.xAxis
.tickFormat(function(d) {
var label = '';
_.each(self.data, function(v, k){
if (v.values[d] && v.values[d].x){
label = v.values[d].x;
}
});
return '<h3>' + header + '</h3> <p> Balance ' + y + '</p>'},
});
chart.xAxis
.tickFormat(function(d) {
var label = '';
$.each(data, function(el){
if (data[el].values[d] && data[el].values[d].x){
label = data[el].values[d].x;
}
return label;
});
return label;
})
.showMaxMin(false);
chart.yAxis.tickFormat(d3.format(',.2f'));
self.chart.yAxis
.tickFormat(d3.format(',.2f'));
break;
case "bar":
var bar_color = [];
$.each(data[0].values, function(k,v){
bar_color.push(v.color);
})
var chart = nv.models.discreteBarChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.width(self.$el.find('svg').width())
.height(self.$el.find('svg').height())
.showValues(false)
.showYAxis(false)
.color(bar_color)
.margin({'left': 15, 'right':10, 'top':10, 'bottom': 25})
.tooltips(true);
chart.xAxis.axisLabel(data[0].title);
chart.yAxis.tickFormat(d3.format(',.2f'));
self.$svg.addClass('o_graph_barchart');
self.chart = nv.models.discreteBarChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.showValues(false)
.showYAxis(false)
.margin({'left': 0, 'right': 0, 'top': 0, 'bottom': 40})
.tooltips(true)
.tooltipContent(function(key, x, y, e, graph) {
return self.create_tooltip(x, y, e);
});
self.chart.xAxis.axisLabel(self.data[0].title);
self.chart.yAxis.tickFormat(d3.format(',.2f'));
break;
}
self.svg = self.$el.find('svg')[0];
d3.select(self.svg)
.datum(data)
d3.select(self.$el.find('svg')[0])
.datum(self.data)
.transition().duration(1200)
.call(chart);
nv.utils.windowResize(function() { d3.select(self.svg).call(chart.width(self.$el.find('svg').width()).height(self.$el.find('svg').height())); self.postprocess(); });
.call(self.chart);
self.customize_chart(self.data);
nv.utils.windowResize(self.on_resize);
});
//ugly, need to do something else
setTimeout(function(){self.postprocess();},2000);
},
postprocess: function(){
var low_rect = $(this.svg).find('rect').filter(function(){return $(this).attr('height') < 1.0 })
low_rect.attr('height', 1);
on_resize: function(){
this.chart.update();
this.customize_chart(this.data);
},
customize_chart: function(){
if (this.graph_type === 'bar') {
// Add classes related to time on each bar of the bar chart
var bar_classes = _.map(this.data[0].values, function (v, k) {return v.type});
_.each(this.$('.nv-bar'), function(v, k){
v.classList.add(bar_classes[k]);
});
}
},
create_tooltip: function(x, y, e){
var header = _.findWhere(e.series.values, {x: x})
header = header && header.name || x;
var $tooltip = $('<div>').addClass('o_tooltip');
$('<b>')
.addClass('o_tooltip_title')
.html(header)
.appendTo($tooltip)
$('<div>')
.addClass('o_tooltip_content')
.html('Balance ' + y)
.appendTo($tooltip)
return $tooltip[0].outerHTML;
},
destroy: function(){
nv.utils.offWindowResize(this.on_resize);
this._super();
},
});
@@ -10,12 +10,87 @@
border-top-style: solid;
border-top-width: 1px;
}
.o_kanban_graph_section {
padding: 16px;
}
.o_dashboard_star {
font-size: 12px;
margin-left: 5px;
}
.o_kanban_graph_section {
padding-top: 20px;
.nvtooltip {
padding: 0 8px 0 8px;
.o_tooltip_content {
color: @odoo-brand-primary;
font-weight: bold;
}
}
.o_graph_linechart {
svg {
height: 75px;
// X axis
g.nv-x.nv-axis {
transform: translateY(50px);
// Remove max and min labels
g.nv-axisMaxMin {
display: none;
}
g.tick.major {
// Don't know why, but leads to strange bold text
// stroke: @odoo-brand-primary;
line {
display: none;
}
}
}
// !important are needed because nvd3 uses inline style on elements
// Remove strokes
g.nv-linesWrap {
g.nv-group.nv-series-0 {
fill-opacity: 0.3 !important;
fill: @odoo-brand-primary !important;
stroke: @odoo-brand-primary !important;
.nv-point {
visibility: hidden;
r: 3;
stroke: @odoo-brand-primary !important;
fill: white;
stroke-width: 2;
}
.nv-point:nth-child(5n+1) {
visibility: visible;
fill-opacity: .95 !important;
stroke-opacity: .95 !important;
}
}
}
}
}
.o_graph_barchart {
svg {
height: 75px;
overflow: visible;
g.nv-barsWrap {
g.nv-group.nv-series-0 {
g.past {
opacity: 0.5;
fill: @odoo-brand-primary !important;
}
g.future {
opacity: 0.5;
fill: @odoo-brand-optional !important;
}
}
}
}
}
}
}
}
@@ -260,14 +260,12 @@
</t>
<t t-name="JournalBodyGraph">
<div class="row">
<div class="col-xs-12 o_kanban_graph_section">
<t t-if="dashboard.show_import">
<button t-if="journal_type == 'bank'" type="object" name="import_statement" class="btn btn-primary btn-sm">Import Statement</button>
<button t-if="journal_type == 'cash'" type="object" name="create_cash_bank" class="btn btn-primary btn-sm">Register Transactions</button>
</t>
<div t-if="!dashboard.show_import">
<field name="kanban_dashboard_graph" t-att-graph_type="_.contains(['cash','bank'],journal_type) ? 'line' : 'bar'" widget="dashboard_graph"></field>
</div>
<div t-if="dashboard.show_import" class="col-xs-12 o_kanban_primary_left">
<button t-if="journal_type == 'bank'" type="object" name="import_statement" class="btn btn-primary btn-sm">Import Statement</button>
<button t-if="journal_type == 'cash'" type="object" name="create_cash_bank" class="btn btn-primary btn-sm">Register Transactions</button>
</div>
<div t-if="!dashboard.show_import" class="o_kanban_graph_section">
<field name="kanban_dashboard_graph" t-att-graph_type="_.contains(['cash','bank'],journal_type) ? 'line' : 'bar'" widget="dashboard_graph"></field>
</div>
</div>
</t>