From ea3b118eae8259ec31e0cc55b5bcbae24aa8c8ce Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Mon, 29 Jun 2015 15:40:46 +0200 Subject: [PATCH] [IMP] account: improve account_contract_dashboard Mainly style and js improvements for graphs --- .../models/account_journal_dashboard.py | 8 +- .../js/account_journal_dashboard_widget.js | 150 +++++++++++------- .../src/less/account_journal_dashboard.less | 81 +++++++++- .../views/account_journal_dashboard_view.xml | 14 +- 4 files changed, 178 insertions(+), 75 deletions(-) diff --git a/addons/account/models/account_journal_dashboard.py b/addons/account/models/account_journal_dashboard.py index 0f4d3f0eeb5..5326d9e3a02 100644 --- a/addons/account/models/account_journal_dashboard.py +++ b/addons/account/models/account_journal_dashboard.py @@ -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}] diff --git a/addons/account/static/src/js/account_journal_dashboard_widget.js b/addons/account/static/src/js/account_journal_dashboard_widget.js index c152a90442d..6716ab79b37 100644 --- a/addons/account/static/src/js/account_journal_dashboard_widget.js +++ b/addons/account/static/src/js/account_journal_dashboard_widget.js @@ -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(''); - var type = self.graph_type - switch(type) { + self.$svg = self.$el.append(''); + + 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 '

' + header + '

Balance ' + y + '

'}, - }); - 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 = $('
').addClass('o_tooltip'); + + $('') + .addClass('o_tooltip_title') + .html(header) + .appendTo($tooltip) + $('
') + .addClass('o_tooltip_content') + .html('Balance ' + y) + .appendTo($tooltip) + return $tooltip[0].outerHTML; + }, + + destroy: function(){ + nv.utils.offWindowResize(this.on_resize); + this._super(); + }, + }); diff --git a/addons/account/static/src/less/account_journal_dashboard.less b/addons/account/static/src/less/account_journal_dashboard.less index 0ded24f5d64..20ab33eaf09 100644 --- a/addons/account/static/src/less/account_journal_dashboard.less +++ b/addons/account/static/src/less/account_journal_dashboard.less @@ -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; + } + } + } + } + } + } } } diff --git a/addons/account/views/account_journal_dashboard_view.xml b/addons/account/views/account_journal_dashboard_view.xml index d673b3253cb..4404803bfd4 100644 --- a/addons/account/views/account_journal_dashboard_view.xml +++ b/addons/account/views/account_journal_dashboard_view.xml @@ -260,14 +260,12 @@
-
- - - - -
- -
+
+ + +
+
+