nm-time-series-chart
src/app/shared/widgets/charts/time-series-chart/time-series-chart.component.ts
selector | nm-time-series-chart |
styleUrls | time-series-chart.component.scss |
templateUrl | ./time-series-chart.component.html |
Widget inputs |
Widget outputs |
Properties |
|
Methods |
constructor(widgetframeService: WidgetframeService, translateService: TranslateService, currentLocaleService: CurrentLocaleService)
|
||||||||||||
Parameters :
|
Protected configureWidget | ||||||
configureWidget(configuration: WidgetConfig)
|
||||||
Decorators : WidgetConfigure
|
||||||
Parameters :
Returns :
void
|
formatNumber | ||||
formatNumber(number: )
|
||||
Parameters :
Returns :
any
|
handleException | ||||||
handleException(message: string)
|
||||||
Parameters :
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
populateChart | ||||
populateChart(data: )
|
||||
Parameters :
Returns :
void
|
setCustomColors | ||||||
setCustomColors(results: any[])
|
||||||
Parameters :
Returns :
void
|
setMultipleSeriesChartTicks | ||||
setMultipleSeriesChartTicks(values: )
|
||||
Parameters :
Returns :
void
|
setSingleSeriesChartTicks | ||||
setSingleSeriesChartTicks(values: )
|
||||
Parameters :
Returns :
void
|
Public chartBody |
chartBody:
|
Default value : new Subject<any>()
|
Decorators : WidgetInput
|
Public chartInterval |
chartInterval:
|
Type : number
|
Public chartType |
chartType:
|
Type : string
|
Public chartUri |
chartUri:
|
Default value : new Subject<string>()
|
Decorators : WidgetInput
|
colorScheme |
colorScheme:
|
Type : object
|
Default value : {
domain: ["#8093c7", "#abc378", "#e57e99", "#ffc699", "#A1B4BC"],
}
|
Public configuration |
configuration:
|
Type : WidgetConfig<TimeSeriesChartConfiguration>
|
Decorators : WidgetConfiguration
|
Private configurationColors |
configurationColors:
|
Type : customColor[]
|
Public cssClass |
cssClass:
|
Type : string
|
Public currentLocale |
currentLocale:
|
Type : string
|
Public customColors |
customColors:
|
Type : customColor[]
|
Public customXLabel |
customXLabel:
|
Default value : new Subject<string>()
|
Decorators : WidgetInput
|
Public errorHandler |
errorHandler:
|
Default value : new Subject<string>()
|
Decorators : WidgetOutput
|
Public handleError |
handleError:
|
Type : boolean
|
Public header |
header:
|
Type : string
|
Public infotext |
infotext:
|
Type : string
|
Public legendTitle |
legendTitle:
|
Type : string
|
Default value : ""
|
Public measurementUnit |
measurementUnit:
|
Default value : new Subject<any>()
|
Decorators : WidgetInput
|
Public resetChart |
resetChart:
|
Default value : new Subject<boolean>()
|
Decorators : WidgetInput
|
Public results |
results:
|
Type : any[]
|
Public selectedUiLocale |
selectedUiLocale:
|
Default value : new Subject<any>()
|
Decorators : WidgetInput
|
Public showDataLabel |
showDataLabel:
|
Type : boolean
|
Public showLegend |
showLegend:
|
Type : boolean
|
Public showXAxis |
showXAxis:
|
Type : boolean
|
Public showXAxisLabel |
showXAxisLabel:
|
Type : boolean
|
Public showYAxis |
showYAxis:
|
Type : boolean
|
Public showYAxisLabel |
showYAxisLabel:
|
Type : boolean
|
Public title |
title:
|
Type : string
|
Public tooltipShowX |
tooltipShowX:
|
Type : boolean
|
Public tooltipShowY |
tooltipShowY:
|
Type : boolean
|
Public translateService |
translateService:
|
Type : TranslateService
|
Public unitOfMeasurement |
unitOfMeasurement:
|
Type : string
|
Private unsubscribe |
unsubscribe:
|
Default value : NgUnsubscribe.create()
|
Public widgetId |
widgetId:
|
Type : string
|
Decorators : WidgetId
|
Public wikiLink |
wikiLink:
|
Type : string
|
Public xAxisInterval |
xAxisInterval:
|
Type : number
|
Public xAxisLabel |
xAxisLabel:
|
Type : string
|
Public xAxisTicks |
xAxisTicks:
|
Type : any[]
|
Public yAxisLabel |
yAxisLabel:
|
Type : string
|
Public yAxisLabelsFormat |
yAxisLabelsFormat:
|
Default value : this.formatNumber.bind(this)
|
import {
timer,
empty,
combineLatest,
of,
Subject,
Observable,
Subscription,
} from "rxjs";
import {
takeUntil,
debounceTime,
mergeMap,
concatMap,
distinctUntilChanged,
catchError,
} from "rxjs/operators";
import { Component, OnDestroy } from "@angular/core";
import { getOrDefault, WidgetConfig } from "../../widget.configuration";
import {
WidgetComponent,
WidgetId,
WidgetConfiguration,
WidgetConfigure,
WidgetInput,
WidgetOutput,
} from "../../widget.metadata";
import { WidgetframeService } from "../../widgetframe/widgetframe.service";
import { TranslateService } from "@ngx-translate/core";
import { NgUnsubscribe } from "../../../ng-unsubscribe";
import * as uriTemplates_ from "uri-templates";
import { CurrentLocaleService } from "../../../components/i18n/currentLocale.service";
const uriTemplates = uriTemplates_;
export interface TimeSeriesChartConfiguration {
header?: string;
title?: string;
cssClass?: string;
showDataLabel?: boolean;
showXAxis?: boolean;
showYAxis?: boolean;
showXAxisLabel?: boolean;
showYAxisLabel?: boolean;
showLegend?: boolean;
colorScheme?: customColor[];
xAxisInterval?: number;
infoText?: string;
infoWidth?: string;
infoHeight?: string;
wikiLink?: string;
legendTitle?: boolean;
yAxisLabel?: string;
configurationColors?: customColor[];
handleError?: boolean;
chartInterval?: number;
}
@WidgetComponent("nm-time-series-chart")
@Component({
selector: "nm-time-series-chart",
templateUrl: "./time-series-chart.component.html",
styleUrls: ["./time-series-chart.component.scss"],
})
export class TimeSeriesChartWidgetComponent implements OnDestroy {
public results: any[];
public header: string;
public title: string;
public cssClass: string;
public showDataLabel: boolean;
public showXAxis: boolean;
public showYAxis: boolean;
public showXAxisLabel: boolean;
public showYAxisLabel: boolean;
public showLegend: boolean;
public xAxisTicks: any[];
public chartType: string;
public xAxisInterval: number;
public xAxisLabel: string;
public yAxisLabel: string;
public wikiLink: string;
public infotext: string;
public legendTitle: string = "";
public currentLocale: string;
public handleError: boolean;
public customColors: customColor[];
private configurationColors: customColor[];
public unitOfMeasurement: string;
public yAxisLabelsFormat = this.formatNumber.bind(this);
public chartInterval: number;
public tooltipShowX: boolean;
public tooltipShowY: boolean;
colorScheme = {
domain: ["#8093c7", "#abc378", "#e57e99", "#ffc699", "#A1B4BC"],
};
@WidgetConfiguration()
public configuration: WidgetConfig<TimeSeriesChartConfiguration>;
@WidgetInput()
public chartUri = new Subject<string>();
@WidgetInput()
public chartBody = new Subject<any>();
@WidgetInput()
public resetChart = new Subject<boolean>();
@WidgetInput()
public measurementUnit = new Subject<any>();
@WidgetInput()
public customXLabel = new Subject<string>();
@WidgetInput()
public selectedUiLocale = new Subject<any>();
@WidgetOutput()
public errorHandler = new Subject<string>();
@WidgetId()
public widgetId: string;
private unsubscribe = NgUnsubscribe.create();
constructor(
private widgetframeService: WidgetframeService,
public translateService: TranslateService,
private currentLocaleService: CurrentLocaleService
) {}
@WidgetConfigure()
protected configureWidget(configuration: WidgetConfig) {
this.header = configuration.configuration.header;
this.title = configuration.configuration.title;
this.cssClass = configuration.configuration.cssClass || "";
this.showDataLabel = configuration.configuration.showDataLabel;
this.showXAxis = configuration.configuration.showXAxis;
this.showYAxis = configuration.configuration.showYAxis;
this.showXAxisLabel = configuration.configuration.showXAxisLabel;
this.showYAxisLabel = configuration.configuration.showYAxisLabel;
this.showLegend = configuration.configuration.showLegend;
this.colorScheme = configuration.configuration.customColors
? configuration.configuration.customColors
: this.colorScheme;
this.xAxisInterval = configuration.configuration.xAxisInterval;
this.infotext = configuration.configuration.infoText;
this.wikiLink = configuration.configuration.wikiLink;
this.legendTitle = configuration.configuration.legendTitle || "";
this.yAxisLabel = configuration.configuration.yAxisLabel || "";
this.configurationColors = configuration.configuration.customColorScheme;
this.handleError = configuration.configuration.handleError;
this.chartInterval = configuration.configuration.chartInterval || 1000;
this.tooltipShowX = getOrDefault(
configuration.configuration.tooltipShowX,
true
);
this.tooltipShowY = getOrDefault(
configuration.configuration.tooltipShowY,
false
);
this.resetChart
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((resetChart) => {
if (resetChart) {
this.results = [];
this.xAxisTicks = [];
}
});
combineLatest(
timer(this.chartInterval),
this.chartUri.asObservable(),
this.chartBody.asObservable(),
(interval, uri, body) => [uri, body]
)
.pipe(takeUntil(this.unsubscribe))
.pipe(
debounceTime(5),
mergeMap((input) => {
let url = input[0];
let body = input[1];
return this.widgetframeService.putData(url, body);
}),
catchError((error) => {
this.handleException(error);
return empty();
})
)
.subscribe((data) => {
if (data.message) {
this.handleException(data.message);
} else {
this.populateChart(data);
}
});
combineLatest(
this.measurementUnit.asObservable(),
this.currentLocaleService.getCurrentLocale()
)
.pipe(takeUntil(this.unsubscribe))
.subscribe(([data, locale]) => {
this.currentLocale = locale.toString();
if (data) {
this.yAxisLabel = data.unit;
this.unitOfMeasurement = this.yAxisLabel;
}
});
combineLatest(
this.customXLabel.asObservable(),
this.selectedUiLocale.asObservable()
)
.pipe(takeUntil(this.unsubscribe))
.pipe(
debounceTime(5),
mergeMap(([customXLabel, selectedUiLocale]) =>
this.translateService.get(customXLabel)
)
)
.subscribe((label) => {
this.xAxisLabel = label;
});
}
populateChart(data) {
this.unitOfMeasurement = data.unit;
this.yAxisLabel = data.unit;
this.chartType = data.chartType;
if (this.configurationColors) {
this.setCustomColors(data.values);
}
if (this.xAxisInterval) {
this.xAxisTicks = [];
if (data.values[0].hasOwnProperty("series")) {
this.setMultipleSeriesChartTicks(data.values);
} else {
this.setSingleSeriesChartTicks(data.values);
}
} else {
this.results = data.values;
this.xAxisTicks = data.xAxisTicks;
}
}
setSingleSeriesChartTicks(values) {
let resultsLength = values.length;
let breakpoint = Math.floor(resultsLength / this.xAxisInterval);
for (let x = 0; x < resultsLength; x += breakpoint) {
this.xAxisTicks.push(values[x].name);
}
this.results = values;
}
setMultipleSeriesChartTicks(values) {
let maxSeriesLength = 0;
let maxSeriesIndex = 0;
let breakpoint;
values.forEach((lineSeries, index) => {
let resultsLength = lineSeries.series.length;
if (resultsLength > maxSeriesLength) {
maxSeriesLength = resultsLength;
maxSeriesIndex = index;
}
});
breakpoint = Math.floor(maxSeriesLength / this.xAxisInterval);
this.xAxisTicks = [];
for (let x = 0; x < maxSeriesLength; x += breakpoint) {
this.xAxisTicks.push(values[maxSeriesIndex].series[x].name);
}
this.results = values;
}
setCustomColors(results: any[]) {
this.customColors = [];
results.forEach((value) => {
let customColor = this.configurationColors.find(
(color) => color.name === value.seriesColorIdentifier
);
if (customColor) {
this.customColors.push({
name: value.name,
value: customColor.value,
});
}
});
}
formatNumber(number) {
return number.toLocaleString(this.currentLocale);
}
handleException(message: string) {
this.results = [];
if (this.handleError) {
this.errorHandler.next(message);
}
}
ngOnDestroy(): void {
if (this.unsubscribe) {
this.unsubscribe.destroy();
}
}
}
export interface customColor {
name: string;
value: string;
}
<nm-widgetframe
[header]="configuration.configuration.header"
[widgetId]="widgetId"
[configuration]="configuration"
[infoText]="infotext"
[infoTitle]="configuration.configuration.title"
[infoWidth]="configuration.configuration.infoWidth"
[infoHeight]="configuration.configuration.infoHeight"
[infoPlacement]="'bottom'"
[wikiLink]="wikiLink"
>
<ng-container slot="title">
<div class="nm-widgetframe__title">
{{ configuration.configuration.title | translate }}
</div>
</ng-container>
<ng-container slot="content">
<div class="nm-widgetframe__content {{ cssClass }}">
<div style="text-align: center" *ngIf="results?.length === 0">
{{ "table.emptytext.product" | translate }}
</div>
<ngx-charts-bar-vertical
*ngIf="chartType === 'VERTICAL_BAR_CHART' && results?.length != 0"
[style.height]="'100%'"
[results]="results"
[xAxis]="showXAxis"
[yAxis]="showXAxis"
[legend]="showLegend"
[legendTitle]="legendTitle"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[xAxisLabel]="xAxisLabel"
[yAxisLabel]="yAxisLabel"
[xAxisTicks]="xAxisTicks"
[scheme]="colorScheme"
>
<ng-template #tooltipTemplate let-model="model">
<div class="tooltip-padding">
{{ tooltipShowX ? model.name : "" }}
{{ tooltipShowX && tooltipShowY ? ": " : "" }}
{{ tooltipShowY ? model.value : "" }}
</div>
</ng-template>
</ngx-charts-bar-vertical>
<ngx-charts-line-chart
*ngIf="chartType === 'LINE_CHART' && results?.length != 0"
[style.height]="'100%'"
[results]="results"
[xAxis]="showXAxis"
[yAxis]="showXAxis"
[legend]="showLegend"
[legendTitle]="legendTitle"
[xAxisTicks]="xAxisTicks"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[yAxisTickFormatting]="yAxisLabelsFormat"
[xAxisLabel]="xAxisLabel"
[yAxisLabel]="yAxisLabel"
[scheme]="colorScheme"
[customColors]="customColors"
>
<ng-template #tooltipTemplate let-model="model">
<div class="tooltip-padding">
{{ model.series }} . {{ model.name }} <br />
{{ model.value | number: "1.2-5":currentLocale }}
{{ unitOfMeasurement }}
</div>
</ng-template>
<ng-template #seriesTooltipTemplate let-model="model">
<div class="tooltip-padding">
<div *ngFor="let mod of model; let i = index" class="textAlignment">
<div class="tooltip-content-container">
<span
class="tooltip-label-color"
[style.backgroundColor]="mod.color"
></span>
</div>
<div class="tooltip-content-container tooltip-text-width">
<span style="vertical-align: top">
{{ mod.series }} :
{{ mod.value | number: "1.2-5":currentLocale }}
{{ unitOfMeasurement }}
</span>
</div>
</div>
</div>
</ng-template>
</ngx-charts-line-chart>
</div>
</ng-container>
</nm-widgetframe>