Merge branch 'feature/latestTsAggregation' of github.com:thingsboard/thingsboard into feature/latestTsAggregation
This commit is contained in:
commit
b38f23fa0f
@ -457,7 +457,7 @@ export class EntityDataSubscription {
|
|||||||
}
|
}
|
||||||
this.prepareSubscriptionTimewindow();
|
this.prepareSubscriptionTimewindow();
|
||||||
|
|
||||||
this.prepareData();
|
this.prepareData(true);
|
||||||
|
|
||||||
if (this.datasourceType === DatasourceType.entity) {
|
if (this.datasourceType === DatasourceType.entity) {
|
||||||
this.subsCommand = new EntityDataCmd();
|
this.subsCommand = new EntityDataCmd();
|
||||||
@ -567,7 +567,7 @@ export class EntityDataSubscription {
|
|||||||
this.generateData(true);
|
this.generateData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private prepareData() {
|
private prepareData(isUpdate: boolean) {
|
||||||
if (this.timeseriesTimer) {
|
if (this.timeseriesTimer) {
|
||||||
clearTimeout(this.timeseriesTimer);
|
clearTimeout(this.timeseriesTimer);
|
||||||
this.timeseriesTimer = null;
|
this.timeseriesTimer = null;
|
||||||
@ -641,11 +641,14 @@ export class EntityDataSubscription {
|
|||||||
for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) {
|
for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) {
|
||||||
this.onAggData(aggSubscriptionData, DataKeyType.timeseries, dataIndex, true,
|
this.onAggData(aggSubscriptionData, DataKeyType.timeseries, dataIndex, true,
|
||||||
this.entityDataSubscriptionOptions.type === widgetType.timeseries, true,
|
this.entityDataSubscriptionOptions.type === widgetType.timeseries, true,
|
||||||
(data1, dataIndex1, dataKeyIndex) => {
|
(data, dataIndex1, dataKeyIndex, detectChanges, isLatest) => {
|
||||||
if (!this.data[dataIndex1]) {
|
if (!this.data[dataIndex1]) {
|
||||||
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;
|
this.pageData = pageData;
|
||||||
|
|
||||||
if (this.entityDataSubscriptionOptions.isPaginatedDataSubscription) {
|
if (this.entityDataSubscriptionOptions.isPaginatedDataSubscription) {
|
||||||
this.prepareData();
|
this.prepareData(false);
|
||||||
} else if (isInitialData) {
|
} else if (isInitialData) {
|
||||||
this.resetData();
|
this.resetData();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
// tslint:disable-next-line:no-reference
|
// tslint:disable-next-line:no-reference
|
||||||
/// <reference path="../../../../../../../src/typings/jquery.flot.typings.d.ts" />
|
/// <reference path="../../../../../../../src/typings/jquery.flot.typings.d.ts" />
|
||||||
|
|
||||||
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 { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
||||||
import { ComparisonDuration } from '@shared/models/time/time.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 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;
|
export declare type TbFlotTicksFormatterFunction = (t: number, a?: TbFlotPlotAxis) => string;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
import { WidgetContext } from '@home/models/widget-component.models';
|
import { WidgetContext } from '@home/models/widget-component.models';
|
||||||
import {
|
import {
|
||||||
createLabelFromDatasource,
|
createLabelFromDatasource,
|
||||||
deepClone,
|
deepClone, formattedDataFormDatasourceData,
|
||||||
insertVariable,
|
insertVariable,
|
||||||
isDefined,
|
isDefined,
|
||||||
isDefinedAndNotNull,
|
isDefinedAndNotNull,
|
||||||
@ -28,7 +28,14 @@ import {
|
|||||||
isUndefined
|
isUndefined
|
||||||
} from '@app/core/utils';
|
} from '@app/core/utils';
|
||||||
import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
|
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 {
|
import {
|
||||||
ChartType,
|
ChartType,
|
||||||
TbFlotAxisOptions,
|
TbFlotAxisOptions,
|
||||||
@ -88,6 +95,8 @@ export class TbFlot {
|
|||||||
private latestDataThresholds: TbFlotThresholdMarking[];
|
private latestDataThresholds: TbFlotThresholdMarking[];
|
||||||
private attributesThresholds: TbFlotThresholdMarking[];
|
private attributesThresholds: TbFlotThresholdMarking[];
|
||||||
|
|
||||||
|
private latestData: FormattedData[];
|
||||||
|
|
||||||
private labelPatternsSourcesSubscription: IWidgetSubscription;
|
private labelPatternsSourcesSubscription: IWidgetSubscription;
|
||||||
private labelPatternsSourcesData: DatasourceData[];
|
private labelPatternsSourcesData: DatasourceData[];
|
||||||
|
|
||||||
@ -379,7 +388,7 @@ export class TbFlot {
|
|||||||
let tooltipValueFormatFunction: TooltipValueFormatFunction = null;
|
let tooltipValueFormatFunction: TooltipValueFormatFunction = null;
|
||||||
if (this.settings.tooltipValueFormatter && this.settings.tooltipValueFormatter.length) {
|
if (this.settings.tooltipValueFormatter && this.settings.tooltipValueFormatter.length) {
|
||||||
try {
|
try {
|
||||||
tooltipValueFormatFunction = new Function('value', this.settings.tooltipValueFormatter) as TooltipValueFormatFunction;
|
tooltipValueFormatFunction = new Function('value', 'latestData', this.settings.tooltipValueFormatter) as TooltipValueFormatFunction;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
tooltipValueFormatFunction = null;
|
tooltipValueFormatFunction = null;
|
||||||
}
|
}
|
||||||
@ -392,7 +401,7 @@ export class TbFlot {
|
|||||||
series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction;
|
series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction;
|
||||||
if (keySettings.tooltipValueFormatter && keySettings.tooltipValueFormatter.length) {
|
if (keySettings.tooltipValueFormatter && keySettings.tooltipValueFormatter.length) {
|
||||||
try {
|
try {
|
||||||
series.dataKey.tooltipValueFormatFunction = new Function('value',
|
series.dataKey.tooltipValueFormatFunction = new Function('value', 'latestData',
|
||||||
keySettings.tooltipValueFormatter) as TooltipValueFormatFunction;
|
keySettings.tooltipValueFormatter) as TooltipValueFormatFunction;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction;
|
series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction;
|
||||||
@ -546,6 +555,13 @@ export class TbFlot {
|
|||||||
}
|
}
|
||||||
this.latestDataThresholds = this.thresholdsSourcesDataUpdated(allThresholds, this.subscription.latestData, true);
|
this.latestDataThresholds = this.thresholdsSourcesDataUpdated(allThresholds, this.subscription.latestData, true);
|
||||||
this.options.grid.markings = allThresholds.concat(this.latestDataThresholds);
|
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();
|
this.checkMouseEvents();
|
||||||
@ -653,6 +669,7 @@ export class TbFlot {
|
|||||||
this.updateData();
|
this.updateData();
|
||||||
}
|
}
|
||||||
} else if (this.chartType === 'pie') {
|
} else if (this.chartType === 'pie') {
|
||||||
|
this.latestData = formattedDataFormDatasourceData(this.subscription.data);
|
||||||
if (this.animatedPie) {
|
if (this.animatedPie) {
|
||||||
this.nextPieDataAnimation(true);
|
this.nextPieDataAnimation(true);
|
||||||
} else {
|
} else {
|
||||||
@ -683,6 +700,11 @@ export class TbFlot {
|
|||||||
this.plot.getOptions().grid.markings = this.options.grid.markings;
|
this.plot.getOptions().grid.markings = this.options.grid.markings;
|
||||||
this.updateData();
|
this.updateData();
|
||||||
}
|
}
|
||||||
|
if (this.subscription.latestData) {
|
||||||
|
this.latestData = formattedDataFormDatasourceData(this.subscription.latestData);
|
||||||
|
} else {
|
||||||
|
this.latestData = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (this.isMouseInteraction && this.plot) {
|
} else if (this.isMouseInteraction && this.plot) {
|
||||||
this.latestUpdateTimeoutHandle = setTimeout(this.latestDataUpdate.bind(this), 30);
|
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() {
|
private scalingPieRadius() {
|
||||||
let scalingLine;
|
let scalingLine;
|
||||||
this.ctx.width > this.ctx.height ? scalingLine = this.ctx.height : scalingLine = this.ctx.width;
|
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,
|
private seriesInfoDiv(label: string, color: string, value: any,
|
||||||
units: string, trackDecimals: number, active: boolean,
|
units: string, trackDecimals: number, active: boolean,
|
||||||
percent: number, valueFormatFunction: TooltipValueFormatFunction): JQuery<HTMLElement> {
|
percent: number, seriesIndex: number,
|
||||||
|
valueFormatFunction: TooltipValueFormatFunction): JQuery<HTMLElement> {
|
||||||
const divElement = $('<div></div>');
|
const divElement = $('<div></div>');
|
||||||
divElement.css({
|
divElement.css({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -1034,7 +1065,7 @@ export class TbFlot {
|
|||||||
divElement.append(labelSpan);
|
divElement.append(labelSpan);
|
||||||
let valueContent: string;
|
let valueContent: string;
|
||||||
if (valueFormatFunction) {
|
if (valueFormatFunction) {
|
||||||
valueContent = valueFormatFunction(value);
|
valueContent = valueFormatFunction(value, this.latestDataByDataIndex(seriesIndex));
|
||||||
} else {
|
} else {
|
||||||
valueContent = this.ctx.utils.formatValue(value, trackDecimals, units);
|
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 units = seriesHoverInfo.units && seriesHoverInfo.units.length ? seriesHoverInfo.units : this.trackUnits;
|
||||||
const decimals = isDefinedAndNotNull(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : this.trackDecimals;
|
const decimals = isDefinedAndNotNull(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : this.trackDecimals;
|
||||||
const divElement = this.seriesInfoDiv(seriesHoverInfo.label, seriesHoverInfo.color,
|
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');
|
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 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 decimals = isDefinedAndNotNull(item.series.dataKey.decimals) ? item.series.dataKey.decimals : this.trackDecimals;
|
||||||
const divElement = this.seriesInfoDiv(item.series.dataKey.label, item.series.dataKey.color,
|
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');
|
return divElement.prop('outerHTML');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -123,7 +123,7 @@
|
|||||||
<tb-js-func
|
<tb-js-func
|
||||||
formControlName="tooltipValueFormatter"
|
formControlName="tooltipValueFormatter"
|
||||||
[globalVariables]="functionScopeVariables"
|
[globalVariables]="functionScopeVariables"
|
||||||
[functionArgs]="['value']"
|
[functionArgs]="['value', 'latestData']"
|
||||||
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}"
|
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}"
|
||||||
helpId="widget/lib/flot/tooltip_value_format_fn">
|
helpId="widget/lib/flot/tooltip_value_format_fn">
|
||||||
</tb-js-func>
|
</tb-js-func>
|
||||||
|
|||||||
@ -96,7 +96,7 @@
|
|||||||
<tb-js-func
|
<tb-js-func
|
||||||
formControlName="tooltipValueFormatter"
|
formControlName="tooltipValueFormatter"
|
||||||
[globalVariables]="functionScopeVariables"
|
[globalVariables]="functionScopeVariables"
|
||||||
[functionArgs]="['value']"
|
[functionArgs]="['value', 'latestData']"
|
||||||
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}"
|
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}"
|
||||||
helpId="widget/lib/flot/tooltip_value_format_fn">
|
helpId="widget/lib/flot/tooltip_value_format_fn">
|
||||||
</tb-js-func>
|
</tb-js-func>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user