@ -24,7 +24,7 @@ import {
Input ,
OnChanges ,
OnDestroy ,
V iewChild
v iewChild
} from '@angular/core' ;
import {
BarController ,
@ -55,20 +55,21 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
templateUrl : './investment-chart.component.html'
} )
export class GfInvestmentChartComponent implements OnChanges , OnDestroy {
@Input ( ) benchmarkDataItems : InvestmentItem [ ] = [ ] ;
@Input ( ) benchmarkDataLabel = '' ;
@Input ( ) colorScheme : ColorScheme ;
@Input ( ) currency : string ;
@Input ( ) groupBy : GroupBy ;
@Input ( ) historicalDataItems : LineChartItem [ ] = [ ] ;
@Input ( ) isInPercentage = false ;
@Input ( ) isLoading = false ;
@Input ( ) locale = getLocale ( ) ;
@Input ( ) savingsRate = 0 ;
@Input ( ) public readonly benchmarkDataItems : InvestmentItem [ ] = [ ] ;
@Input ( ) public readonly benchmarkDataLabel = '' ;
@Input ( ) public readonly colorScheme : ColorScheme ;
@Input ( ) public readonly currency : string ;
@Input ( ) public readonly groupBy : GroupBy ;
@Input ( ) public readonly historicalDataItems : LineChartItem [ ] = [ ] ;
@Input ( ) public readonly isInPercentage = false ;
@Input ( ) public readonly isLoading = false ;
@Input ( ) public readonly locale = getLocale ( ) ;
@Input ( ) public readonly savingsRate = 0 ;
@ViewChild ( 'chartCanvas' ) chartCanvas : ElementRef < HTMLCanvasElement > ;
private readonly chartCanvas =
viewChild . required < ElementRef < HTMLCanvasElement > > ( 'chartCanvas' ) ;
public chart : Chart < 'bar' | 'line' > ;
private chart : Chart < 'bar' | 'line' > ;
private investments : InvestmentItem [ ] ;
private values : LineChartItem [ ] ;
@ -118,7 +119,7 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
borderWidth : this.groupBy ? 0 : 1 ,
data : this.investments.map ( ( { date , investment } ) = > {
return {
x : parseDate ( date ) . getTime ( ) ,
x : parseDate ( date ) ? . getTime ( ) ? ? null ,
y : this.isInPercentage ? investment * 100 : investment
} ;
} ) ,
@ -138,7 +139,7 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
borderWidth : 2 ,
data : this.values.map ( ( { date , value } ) = > {
return {
x : parseDate ( date ) . getTime ( ) ,
x : parseDate ( date ) ? . getTime ( ) ? ? null ,
y : this.isInPercentage ? value * 100 : value
} ;
} ) ,
@ -165,123 +166,126 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
this . getTooltipPluginConfiguration ( ) ;
const annotations = this . chart . options . plugins . annotation
. annotations as Record < string , AnnotationOptions < ' line ' > > ;
? . annotations as Record < string , AnnotationOptions < ' line ' > > ;
if ( this . savingsRate && annotations . savingsRate ) {
annotations . savingsRate . value = this . savingsRate ;
}
this . chart . update ( ) ;
} else {
this . chart = new Chart ( this . chartCanvas . nativeElement , {
data : chartData ,
options : {
animation : false ,
elements : {
line : {
tension : 0
this . chart = new Chart < 'bar' | 'line' > (
this . chartCanvas ( ) . nativeElement ,
{
data : chartData ,
options : {
animation : false ,
elements : {
line : {
tension : 0
} ,
point : {
hoverBackgroundColor : getBackgroundColor ( this . colorScheme ) ,
hoverRadius : 2 ,
radius : 0
}
} ,
point : {
hoverBackgroundColor : getBackgroundColor ( this . colorScheme ) ,
hoverRadius : 2 ,
radius : 0
}
} ,
interaction : { intersect : false , mode : 'index' } ,
maintainAspectRatio : true ,
plugins : {
annotation : {
annotations : {
savingsRate : this.savingsRate
? {
borderColor : ` rgba( ${ primaryColorRgb . r } , ${ primaryColorRgb . g } , ${ primaryColorRgb . b } , 0.75) ` ,
borderWidth : 1 ,
label : {
backgroundColor : ` rgb( ${ primaryColorRgb . r } , ${ primaryColorRgb . g } , ${ primaryColorRgb . b } ) ` ,
borderRadius : 2 ,
color : 'white' ,
content : $localize ` Savings Rate ` ,
display : true ,
font : { size : 10 , weight : 'normal' } ,
padding : {
x : 4 ,
y : 2
interaction : { intersect : false , mode : 'index' } ,
maintainAspectRatio : true ,
plugins : {
annotation : {
annotations : {
savingsRate : this.savingsRate
? {
borderColor : ` rgba( ${ primaryColorRgb . r } , ${ primaryColorRgb . g } , ${ primaryColorRgb . b } , 0.75) ` ,
borderWidth : 1 ,
label : {
backgroundColor : ` rgb( ${ primaryColorRgb . r } , ${ primaryColorRgb . g } , ${ primaryColorRgb . b } ) ` ,
borderRadius : 2 ,
color : 'white' ,
content : $localize ` Savings Rate ` ,
display : true ,
font : { size : 10 , weight : 'normal' } ,
padding : {
x : 4 ,
y : 2
} ,
position : 'start'
} ,
position : 'start'
} ,
scaleID : 'y' ,
type : 'line' ,
value : this.savingsRate
}
: undefined ,
yAxis : {
borderColor : ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) ` ,
borderWidth : 1 ,
scaleID : 'y' ,
type : 'line' ,
value : 0
scaleID : 'y' ,
type : 'line' ,
value : this.savingsRate
}
: undefined ,
yAxis : {
borderColor : ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) ` ,
borderWidth : 1 ,
scaleID : 'y' ,
type : 'line' ,
value : 0
}
}
}
} ,
legend : {
display : false
} ,
tooltip : this.getTooltipPluginConfiguration ( ) ,
verticalHoverLine : {
color : ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) `
}
} ,
responsive : true ,
scales : {
x : {
border : {
color : ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) ` ,
width : this.groupBy ? 0 : 1
} ,
display : true ,
grid : {
legend : {
display : false
} ,
type : 'time' ,
time : {
tooltipFormat : getDateFormatString ( this . locale ) ,
unit : 'year'
tooltip : this.getTooltipPluginConfiguration ( ) ,
verticalHoverLine : {
color : ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) `
}
} ,
y : {
border : {
display : false
} ,
display : ! this . isInPercentage ,
grid : {
color : ( { scale , tick } ) = > {
if (
tick . value === 0 ||
tick . value === scale . max ||
tick . value === scale . min
) {
return ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) ` ;
}
return 'transparent' ;
responsive : true ,
scales : {
x : {
border : {
color : ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) ` ,
width : this.groupBy ? 0 : 1
} ,
display : true ,
grid : {
display : false
} ,
type : 'time' ,
time : {
tooltipFormat : getDateFormatString ( this . locale ) ,
unit : 'year'
}
} ,
position : 'right' ,
ticks : {
callback : ( value : number ) = > {
return transformTickToAbbreviation ( value ) ;
y : {
border : {
display : false
} ,
display : true ,
mirror : true ,
z : 1
display : ! this . isInPercentage ,
grid : {
color : ( { scale , tick } ) = > {
if (
tick . value === 0 ||
tick . value === scale . max ||
tick . value === scale . min
) {
return ` rgba( ${ getTextColor ( this . colorScheme ) } , 0.1) ` ;
}
return 'transparent' ;
}
} ,
position : 'right' ,
ticks : {
callback : ( value : number ) = > {
return transformTickToAbbreviation ( value ) ;
} ,
display : true ,
mirror : true ,
z : 1
}
}
}
}
} ,
plugins : [
getVerticalHoverLinePlugin ( this . chartCanvas , this . colorScheme )
] ,
type : this . groupBy ? 'bar' : 'line'
} ) ;
} ,
plugins : [
getVerticalHoverLinePlugin ( this . chartCanvas ( ) , this . colorScheme )
] ,
type : this . groupBy ? 'bar' : 'line'
}
) ;
}
}
}
@ -305,8 +309,12 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
}
private isInFuture < T > ( aContext : ScriptableLineSegmentContext , aValue : T ) {
return isAfter ( new Date ( aContext ? . p1 ? . parsed ? . x ) , new Date ( ) )
? aValue
: undefined ;
const xValue = aContext ? . p1 ? . parsed ? . x ;
if ( xValue == null ) {
return undefined ;
}
return isAfter ( new Date ( xValue ) , new Date ( ) ) ? aValue : undefined ;
}
}