Use jqWidgets for balance chart.

This commit is contained in:
Alexis Lahouze 2018-06-10 10:03:45 +02:00
parent a915d33a54
commit f19403f0ea
2 changed files with 75 additions and 129 deletions

View File

@ -1,15 +1,15 @@
// vim: set tw=80 ts=2 sw=2 sts=2: // vim: set tw=80 ts=2 sw=2 sts=2:
import * as moment from 'moment'; import * as moment from 'moment';
import * as c3 from 'c3';
import { import {
Component, ElementRef, Component,
Inject, Input, Output, EventEmitter, Inject, Input, Output, EventEmitter,
OnInit, OnChanges OnChanges
} from '@angular/core'; } from '@angular/core';
import { Account } from '../accounts/account'; import { Account } from '../accounts/account';
import { DailyBalance } from './dailyBalance';
import { DailyBalanceService } from '../accounts/dailyBalance.service'; import { DailyBalanceService } from '../accounts/dailyBalance.service';
class DateRange { class DateRange {
@ -19,152 +19,91 @@ class DateRange {
@Component({ @Component({
selector: 'balance-chart', selector: 'balance-chart',
template: '<div></div>' template: `
<jqxChart #balanceChart
[width]="'100%'"
[height]="'100%'"
[title]="'Balance evolution'"
[description]="''"
[source]="data"
[xAxis]="xAxis"
[seriesGroups]="seriesGroups"
(onRangeSelectionChanged)="select($event)">
</jqxChart>
`
}) })
export class BalanceChartComponent implements OnInit, OnChanges { export class BalanceChartComponent implements OnChanges {
@Input() account: Account; @Input() account: Account;
@Output() onUpdate: EventEmitter<DateRange> = new EventEmitter<DateRange>(); @Output() onUpdate: EventEmitter<DateRange> = new EventEmitter<DateRange>();
private chart: c3.ChartAPI; public data;
private balances: number[];
public xAxis: any = {
dataField: 'operation_date',
type: 'date',
baseUnit: 'day',
//unitInterval: 10,
rangeSelector: {
size: 80,
padding: { /*left: 0, right: 0,*/top: 0, bottom: 0 },
backgroundColor: 'white',
dataField: 'balance',
baseUnit: 'month',
gridLines: { visible: false },
serieType: 'line',
//labels: {
// formatFunction: (value: any): any => {
// return this.months[value.getMonth()] + '\'' + value.getFullYear().toString().substring(2);
// }
//}
}
};
public seriesGroups: any = [{
// type: 'column',
// series: [{
// dataField: 'revenues'
// }, {
// dataField: 'expenses'
// }]
//}, {
type: 'line',
series: [{
dataField: 'balance'
}],
bands: [{
minValue: 0, maxValue: 0, fillColor: 'orange', lineWidth: 2
}, {
minValue: 0, maxValue: 0, fillColor: 'red', lineWidth: 2
}]
}];
constructor( constructor(
private elementRef: ElementRef,
private dailyBalanceService: DailyBalanceService, private dailyBalanceService: DailyBalanceService,
) { ) {
this.data = [];
} }
loadData(account: Account) { loadData(account: Account) {
this.dailyBalanceService.query( this.dailyBalanceService.query(
account.id account.id
).subscribe((results) => { ).subscribe((results) => {
var headers: any[][] = [['date', 'balances', 'expenses', 'revenues']]; this.data = results;
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({ this.onUpdate.emit({
minDate: balances[0], minDate: moment(results[0].operation_date).toDate(),
maxDate: balances[balances.length - 1] maxDate: moment(results[results.length - 1].operation_date).toDate()
}); });
}); });
};
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) { setLines(account: Account) {
if(this.chart) { if (account) {
this.chart.ygrids([ this.seriesGroups[0].bands[1].minValue = account.authorized_overdraft;
{ value: 0, axis: 'y2' }, this.seriesGroups[0].bands[1].maxValue = account.authorized_overdraft;
{ value: 0, axis: 'y', class: 'zeroline'},
]);
if(account) {
this.chart.ygrids.add({
value: account.authorized_overdraft,
axis: 'y',
class: 'overdraft'
});
} }
} }
};
ngOnChanges(changes) { ngOnChanges(changes) {
if('account' in changes && changes.account.currentValue) { if('account' in changes && changes.account.currentValue) {
@ -173,5 +112,10 @@ export class BalanceChartComponent implements OnInit, OnChanges {
} else { } else {
this.setLines(this.account); this.setLines(this.account);
} }
}; }
select(event: any) {
let args = event.args;
this.onUpdate.emit({minDate: args.minValue, maxDate: args.maxValue});
}
} }

View File

@ -11,6 +11,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { NgxChartsModule } from '@swimlane/ngx-charts'; import { NgxChartsModule } from '@swimlane/ngx-charts';
import { ToastrModule } from 'ngx-toastr'; import { ToastrModule } from 'ngx-toastr';
import { TextMaskModule } from 'angular2-text-mask'; import { TextMaskModule } from 'angular2-text-mask';
import { jqxChartComponent } from 'jqwidgets-scripts/jqwidgets-ts/angular_jqxchart';
import { BalanceChartComponent } from './balanceChart.component'; import { BalanceChartComponent } from './balanceChart.component';
import { CategoryChartComponent } from './categoryChart.component'; import { CategoryChartComponent } from './categoryChart.component';
@ -42,6 +43,7 @@ import { OperationListState } from './operation.states';
OperationService, OperationService,
], ],
declarations: [ declarations: [
jqxChartComponent,
BalanceChartComponent, BalanceChartComponent,
CategoryChartComponent, CategoryChartComponent,
OperationRowComponent, OperationRowComponent,