import { AfterViewInit , ChangeDetectionStrategy , ChangeDetectorRef , Component , ElementRef , HostListener , Input , OnDestroy , ViewChild , ViewRef , } from '@angular/core' ; import { ChartDataSets , ChartOptions , ChartTooltipItem } from 'chart.js' ; import { Color , Label } from 'ng2-charts' ; import { fromEvent , Subscription } from 'rxjs' ; import { debounceTime , distinctUntilChanged , map , tap } from 'rxjs/operators' ; import { cdLog } from '../../services/ui-store/app-ui-store.service' ; @ Component ( { selector : 'graph-with-single-value' , styleUrls : [ `../../../css/global/components-global.scss` , `../../../css/component/battlegrounds/graph-with-single-value.component.scss` , ] , template : `
		<div class="container-1">
			<div style="display: flex; position: relative; height: 100%; width: 100%;">
				<canvas
					#chart
					*ngIf="!!data?.length; else emptyState"
					baseChart
					[datasets]="data"
					[labels]="labels"
					[options]="lineChartOptions"
					[colors]="colors"
					[legend]="false"
					[chartType]="'line'"
				></canvas>
				<ng-template #emptyState>
					<battlegrounds-empty-state
						[subtitle]="emptyStateMessage"
						[emptyStateIcon]="emptyStateIcon"
					></battlegrounds-empty-state
				></ng-template>
			</div>
		</div>
	` , changeDetection : ChangeDetectionStrategy . OnPush , } ) export class GraphWithSingleValueComponent implements AfterViewInit , OnDestroy { @ ViewChild ( 'chart' , { static : false } ) chart : ElementRef ; @ Input ( ) data : readonly ChartDataSets [ ] ; @ Input ( ) labels : Label ; @ Input ( ) emptyStateMessage : string ; @ Input ( ) emptyStateIcon = 'assets/svg/ftue/battlegrounds.svg' ; @ Input ( ) set labelFormattingFn ( value ) { this . _labelFormattingFn = value ; this . lineChartOptions = this . buildOptions ( ) ; } @ Input ( ) set reverse ( value ) { this . _reverse = value ; this . lineChartOptions = this . buildOptions ( ) ; } colors : Color [ ] = [ ] ; colors$$ : Subscription ; lineChartOptions : ChartOptions = this . buildOptions ( ) ; private _labelFormattingFn : ( label : string , index : number , labels : string [ ] ) => string ; private _reverse = true ; constructor ( private readonly el , private readonly cdr ) { this . colors$$ = fromEvent ( window , 'resize' ) . pipe ( debounceTime ( 100 ) , distinctUntilChanged ( ) , map ( ( ) => this . getColors ( ) ) , tap ( ( colors ) => cdLog ( 'emitting colors in ' , this . constructor . name , colors ) ) ) . subscribe ( ( colors ) => { this . colors = colors ; if ( ! ( this . cdr as ViewRef ) ?. destroyed ) { this . cdr . detectChanges ( ) ; } } ) ; } @ HostListener ( 'window:beforeunload' ) ngOnDestroy ( ) { this . colors$$ ?. unsubscribe ( ) ; } ngAfterViewInit ( ) { setTimeout ( ( ) => { this . colors = this . getColors ( ) ; if ( ! ( this . cdr as ViewRef ) ?. destroyed ) { this . cdr . detectChanges ( ) ; } } ) ; } private getColors ( label ? ) { return [ { backgroundColor : this . getBackgroundColor ( ) , borderColor : '#CE73B4' , pointBackgroundColor : 'transparent' , pointBorderColor : 'transparent' , pointHoverBackgroundColor : 'transparent' , pointHoverBorderColor : 'transparent' , } , ] ; } private getBackgroundColor ( ) { if ( ! this . chart ?. nativeElement ) { console . debug ( 'no native element, not returning gradient' , this . chart ) ; return ; } const chartContainer = this . el . nativeElement . querySelector ( '.container-1' ) ; const rect = chartContainer ?. getBoundingClientRect ( ) ; const chartHeight = rect . height ; const gradient = this . chart . nativeElement ?. getContext ( '2d' ) ?. createLinearGradient ( 0 , 0 , 0 , Math . round ( chartHeight ) ) ; if ( ! gradient ) { console . debug ( 'no gradient, returning' , chartHeight ) ; return ; } gradient . addColorStop ( 0 , 'rgba(206, 115, 180, 0.8)' ) ; gradient . addColorStop ( 0.4 , 'rgba(206, 115, 180, 0.4)' ) ; gradient . addColorStop ( 1 , 'rgba(206, 115, 180, 0)' ) ; return gradient as any ; } private buildOptions ( ) { return { responsive : true , maintainAspectRatio : false , layout : { padding : 0 , } , plugins : { datalabels : { display : false , } , } , scales : { xAxes : [ { gridLines : { color : '#841063' , } , ticks : { fontColor : '#D9C3AB' , fontFamily : 'Open Sans' , fontStyle : 'normal' , maxTicksLimit : 15 , } , } , ] , yAxes : [ { id : 'delta-stats' , position : 'left' , gridLines : { color : '#40032E' , } , ticks : { fontColor : '#D9C3AB' , fontFamily : 'Open Sans' , fontStyle : 'normal' , beginAtZero : true , reverse : this . _reverse , callback : this . _labelFormattingFn ?? ( ( label , index , labels ) => label ) , } , } , ] , } , tooltips : { mode : 'index' , position : 'nearest' , intersect : false , backgroundColor : '#CE73B4' , titleFontFamily : 'Open Sans' , titleFontColor : '#40032E' , bodyFontFamily : 'Open Sans' , bodyFontColor : '#40032E' , xPadding : 5 , yPadding : 5 , caretSize : 10 , caretPadding : 2 , cornerRadius : 0 , displayColors : false , enabled : true , callbacks : { label : ( tooltipItem , data ) => this . _labelFormattingFn ? this . _labelFormattingFn ( tooltipItem . value , 0 , [ ] ) : tooltipItem . value , } , } , } ; } }