178 lines
3.7 KiB
TypeScript
178 lines
3.7 KiB
TypeScript
// vim: set tw=80 ts=2 sw=2 sts=2:
|
|
|
|
import * as moment from 'moment';
|
|
import * as c3 from 'c3';
|
|
|
|
import {
|
|
Component, ElementRef,
|
|
Inject, Input, Output, EventEmitter,
|
|
OnInit, OnChanges
|
|
} from '@angular/core';
|
|
|
|
import { Account } from '../accounts/account';
|
|
import { DailyBalanceService } from '../accounts/dailyBalance.service';
|
|
|
|
class DateRange {
|
|
minDate: Date;
|
|
maxDate: Date;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'balance-chart',
|
|
template: '<div></div>'
|
|
})
|
|
export class BalanceChartComponent implements OnInit, OnChanges {
|
|
@Input() account: Account;
|
|
@Output() onUpdate: EventEmitter<DateRange> = new EventEmitter<DateRange>();
|
|
|
|
private chart: c3.ChartAPI;
|
|
private balances: number[];
|
|
|
|
constructor(
|
|
private elementRef: ElementRef,
|
|
private dailyBalanceService: DailyBalanceService,
|
|
) {
|
|
}
|
|
|
|
loadData(account: Account) {
|
|
this.dailyBalanceService.query(
|
|
account.id
|
|
).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();
|
|
|
|
var balances = x.balances;
|
|
|
|
this.onUpdate.emit({
|
|
minDate: balances[0],
|
|
maxDate: balances[balances.length - 1]
|
|
});
|
|
});
|
|
};
|
|
|
|
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: (domain) => {
|
|
this.onUpdate.emit({minDate: domain[0], maxDate: domain[1]});
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
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'
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
ngOnChanges(changes) {
|
|
if('account' in changes && changes.account.currentValue) {
|
|
this.loadData(changes.account.currentValue);
|
|
this.setLines(changes.account.currentValue);
|
|
} else {
|
|
this.setLines(this.account);
|
|
}
|
|
};
|
|
}
|