// vim: set tw=80 ts=4 sw=4 sts=4: /* This file is part of Accountant. Accountant is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Accountant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Accountant. If not, see . */ /* jshint node: true */ 'use strict'; import * as moment from 'moment'; import * as c3 from 'c3'; import { Component, ElementRef, Inject, Input, Output, EventEmitter, OnInit, OnChanges } from '@angular/core'; import { Logger } from '@nsalaun/ng-logger'; import { Account } from '../accounts/account'; import { DailyBalanceService } from '../accounts/dailyBalance.service'; class DateRange { minDate: Date; maxDate: Date; } class xAxis { balances: Date[]; expenses: Date[]; revenues: Date[]; } @Component({ selector: 'balance-chart', template: '
' }) export class BalanceChartComponent implements OnInit, OnChanges { @Input() account: Account; @Output() onUpdate: EventEmitter = new EventEmitter(); private chart: c3.ChartAPI; private balances: number[]; constructor( private elementRef: ElementRef, private logger: Logger, private dailyBalanceService: DailyBalanceService, @Inject('accountIdService') private accountIdService, ) { this.logger.log("Constructor BalanceChartComponent") } loadData() { this.dailyBalanceService.query( this.accountIdService.get() ).subscribe((results) => { var headers: any[][] = [['date', 'balances', 'expenses', 'revenues']]; var rows = results.map(function(result) { return [ result.operation_date, result.balance, result.expenses, result.revenues ]; }); this.chart.unload(); this.chart.load({ rows: headers.concat(rows) }); var x: any; x = this.chart.x(); this.logger.log("x", x); var balances = x.balances; this.onUpdate.emit({ minDate: balances[0], maxDate: balances[balances.length - 1] }); }); }; $onInit() { this.ngOnInit(); } ngOnInit() { var tomorrow = moment().endOf('day').valueOf(); this.chart = c3.generate({ bindto: this.elementRef.nativeElement.children[0], size: { height: 450, }, data: { x: 'date', rows: [], axes: { expenses: 'y2', revenues: 'y2' }, type: 'bar', types: { balances: 'area' }, groups: [ ['expenses', 'revenues'] ], // Disable for the moment because there is an issue when // using subchart line is not refreshed after subset // selection. //regions: { // balances: [{ // start: tomorrow, // style: 'dashed' // }] //} }, regions: [{ start: tomorrow, }], axis: { x: { type: 'timeseries', tick: { format: '%Y-%m-%d', rotate: 50, } }, y: { label: { text: 'Amount', position: 'outer-middle' } }, y2: { show: true, label: { text: 'Amount', position: 'outer-middle' } } }, grid: { x: { show: true, }, y: { show: true, } }, tooltip: { format: { value: function(value, ratio, id, index) { return value + '€'; } } }, subchart: { show: true, onbrush: function(domain) { this.onUpdate.emit({minDate: domain[0], maxDate: domain[1]}); } } }); this.loadData(); }; setLines(account: Account) { if(this.chart) { this.chart.ygrids([ { value: 0, axis: 'y2' }, { value: 0, axis: 'y', class: 'zeroline'}, ]); if(account) { this.chart.ygrids.add({ value: account.authorized_overdraft, axis: 'y', class: 'overdraft' }); } } }; $onChanges(changes) { this.ngOnChanges(changes); } ngOnChanges(changes) { if('account' in changes) { this.setLines(changes.account.currentValue); } else { this.setLines(this.account); } }; }