diff --git a/ui-ngx/src/app/core/api/entity-data-subscription.ts b/ui-ngx/src/app/core/api/entity-data-subscription.ts index 0d6c534e4c..8032a32973 100644 --- a/ui-ngx/src/app/core/api/entity-data-subscription.ts +++ b/ui-ngx/src/app/core/api/entity-data-subscription.ts @@ -457,7 +457,7 @@ export class EntityDataSubscription { } this.prepareSubscriptionTimewindow(); - this.prepareData(); + this.prepareData(true); if (this.datasourceType === DatasourceType.entity) { this.subsCommand = new EntityDataCmd(); @@ -567,7 +567,7 @@ export class EntityDataSubscription { this.generateData(true); } - private prepareData() { + private prepareData(isUpdate: boolean) { if (this.timeseriesTimer) { clearTimeout(this.timeseriesTimer); this.timeseriesTimer = null; @@ -641,11 +641,14 @@ export class EntityDataSubscription { for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { this.onAggData(aggSubscriptionData, DataKeyType.timeseries, dataIndex, true, this.entityDataSubscriptionOptions.type === widgetType.timeseries, true, - (data1, dataIndex1, dataKeyIndex) => { + (data, dataIndex1, dataKeyIndex, detectChanges, isLatest) => { if (!this.data[dataIndex1]) { this.data[dataIndex1] = []; } - this.data[dataIndex1][dataKeyIndex] = data1; + this.data[dataIndex1][dataKeyIndex] = data; + if (isUpdate) { + this.notifyListener(data, dataIndex1, dataKeyIndex, detectChanges, isLatest); + } }); } } @@ -706,7 +709,7 @@ export class EntityDataSubscription { this.pageData = pageData; if (this.entityDataSubscriptionOptions.isPaginatedDataSubscription) { - this.prepareData(); + this.prepareData(false); } else if (isInitialData) { this.resetData(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts index 595384abaf..78c9245614 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts @@ -17,7 +17,7 @@ // tslint:disable-next-line:no-reference /// -import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models'; +import { DataKey, Datasource, DatasourceData, FormattedData, JsonSettingsSchema } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { ComparisonDuration } from '@shared/models/time/time.models'; @@ -25,7 +25,7 @@ export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph'; export declare type TbFlotSettings = TbFlotBaseSettings & TbFlotGraphSettings & TbFlotBarSettings & TbFlotPieSettings; -export declare type TooltipValueFormatFunction = (value: any) => string; +export declare type TooltipValueFormatFunction = (value: any, latestData: FormattedData) => string; export declare type TbFlotTicksFormatterFunction = (t: number, a?: TbFlotPlotAxis) => string; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts index bf59e36804..c601df72d4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts @@ -18,7 +18,7 @@ import { WidgetContext } from '@home/models/widget-component.models'; import { createLabelFromDatasource, - deepClone, + deepClone, formattedDataFormDatasourceData, insertVariable, isDefined, isDefinedAndNotNull, @@ -28,7 +28,14 @@ import { isUndefined } from '@app/core/utils'; import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; -import { DataKey, Datasource, DatasourceData, DatasourceType, widgetType } from '@app/shared/models/widget.models'; +import { + DataKey, + Datasource, + DatasourceData, + DatasourceType, + FormattedData, + widgetType +} from '@app/shared/models/widget.models'; import { ChartType, TbFlotAxisOptions, @@ -88,6 +95,8 @@ export class TbFlot { private latestDataThresholds: TbFlotThresholdMarking[]; private attributesThresholds: TbFlotThresholdMarking[]; + private latestData: FormattedData[]; + private labelPatternsSourcesSubscription: IWidgetSubscription; private labelPatternsSourcesData: DatasourceData[]; @@ -379,7 +388,7 @@ export class TbFlot { let tooltipValueFormatFunction: TooltipValueFormatFunction = null; if (this.settings.tooltipValueFormatter && this.settings.tooltipValueFormatter.length) { try { - tooltipValueFormatFunction = new Function('value', this.settings.tooltipValueFormatter) as TooltipValueFormatFunction; + tooltipValueFormatFunction = new Function('value', 'latestData', this.settings.tooltipValueFormatter) as TooltipValueFormatFunction; } catch (e) { tooltipValueFormatFunction = null; } @@ -392,7 +401,7 @@ export class TbFlot { series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction; if (keySettings.tooltipValueFormatter && keySettings.tooltipValueFormatter.length) { try { - series.dataKey.tooltipValueFormatFunction = new Function('value', + series.dataKey.tooltipValueFormatFunction = new Function('value', 'latestData', keySettings.tooltipValueFormatter) as TooltipValueFormatFunction; } catch (e) { series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction; @@ -546,6 +555,13 @@ export class TbFlot { } this.latestDataThresholds = this.thresholdsSourcesDataUpdated(allThresholds, this.subscription.latestData, true); this.options.grid.markings = allThresholds.concat(this.latestDataThresholds); + if (this.subscription.latestData) { + this.latestData = formattedDataFormDatasourceData(this.subscription.latestData); + } else { + this.latestData = []; + } + } else if (this.chartType === 'pie') { + this.latestData = formattedDataFormDatasourceData(this.subscription.data); } this.checkMouseEvents(); @@ -653,6 +669,7 @@ export class TbFlot { this.updateData(); } } else if (this.chartType === 'pie') { + this.latestData = formattedDataFormDatasourceData(this.subscription.data); if (this.animatedPie) { this.nextPieDataAnimation(true); } else { @@ -683,6 +700,11 @@ export class TbFlot { this.plot.getOptions().grid.markings = this.options.grid.markings; this.updateData(); } + if (this.subscription.latestData) { + this.latestData = formattedDataFormDatasourceData(this.subscription.latestData); + } else { + this.latestData = []; + } } } else if (this.isMouseInteraction && this.plot) { this.latestUpdateTimeoutHandle = setTimeout(this.latestDataUpdate.bind(this), 30); @@ -690,6 +712,14 @@ export class TbFlot { } } + private latestDataByDataIndex(index: number): FormattedData { + if (this.latestData[index]) { + return this.latestData[index]; + } else { + return {} as FormattedData; + } + } + private scalingPieRadius() { let scalingLine; this.ctx.width > this.ctx.height ? scalingLine = this.ctx.height : scalingLine = this.ctx.width; @@ -1004,7 +1034,8 @@ export class TbFlot { private seriesInfoDiv(label: string, color: string, value: any, units: string, trackDecimals: number, active: boolean, - percent: number, valueFormatFunction: TooltipValueFormatFunction): JQuery { + percent: number, seriesIndex: number, + valueFormatFunction: TooltipValueFormatFunction): JQuery { const divElement = $('
'); divElement.css({ display: 'flex', @@ -1034,7 +1065,7 @@ export class TbFlot { divElement.append(labelSpan); let valueContent: string; if (valueFormatFunction) { - valueContent = valueFormatFunction(value); + valueContent = valueFormatFunction(value, this.latestDataByDataIndex(seriesIndex)); } else { valueContent = this.ctx.utils.formatValue(value, trackDecimals, units); } @@ -1059,7 +1090,8 @@ export class TbFlot { const units = seriesHoverInfo.units && seriesHoverInfo.units.length ? seriesHoverInfo.units : this.trackUnits; const decimals = isDefinedAndNotNull(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : this.trackDecimals; const divElement = this.seriesInfoDiv(seriesHoverInfo.label, seriesHoverInfo.color, - seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex, null, seriesHoverInfo.tooltipValueFormatFunction); + seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex, null, seriesHoverInfo.index, + seriesHoverInfo.tooltipValueFormatFunction); return divElement.prop('outerHTML'); } @@ -1086,7 +1118,8 @@ export class TbFlot { const units = item.series.dataKey.units && item.series.dataKey.units.length ? item.series.dataKey.units : this.trackUnits; const decimals = isDefinedAndNotNull(item.series.dataKey.decimals) ? item.series.dataKey.decimals : this.trackDecimals; const divElement = this.seriesInfoDiv(item.series.dataKey.label, item.series.dataKey.color, - item.datapoint[1][0][1], units, decimals, true, item.series.percent, item.series.dataKey.tooltipValueFormatFunction); + item.datapoint[1][0][1], units, decimals, true, item.series.percent, 0, + item.series.dataKey.tooltipValueFormatFunction); return divElement.prop('outerHTML'); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html index 05879cb124..5741bfae9f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html @@ -123,7 +123,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html index beebf38268..06b9bc5f86 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html @@ -96,7 +96,7 @@