Merge pull request #3140 from ChantsovaEkaterina/feature/flot-attributes-usage-in-labels

[3.0] Flot: attributes usage in labels
This commit is contained in:
Igor Kulikov 2020-07-22 13:55:02 +03:00 committed by GitHub
commit 31aca73e39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 168 additions and 6 deletions

View File

@ -19,6 +19,7 @@
import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models';
import * as moment_ from 'moment';
import { DataKeyType } from "@shared/models/telemetry/telemetry.models";
export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph';
@ -149,13 +150,23 @@ export interface TbFlotThresholdsSettings {
thresholdsLineWidth: number;
}
export interface TbFlotGraphSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings {
export interface TbFlotCustomLegendSettings {
customLegendEnabled: boolean;
dataKeysListForLabels: Array<TbFlotLabelPatternSettings>;
}
export interface TbFlotLabelPatternSettings {
name: string;
type: DataKeyType;
}
export interface TbFlotGraphSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
smoothLines: boolean;
}
export declare type BarAlignment = 'left' | 'right' | 'center';
export interface TbFlotBarSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings {
export interface TbFlotBarSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
defaultBarWidth: number;
barAlignment: BarAlignment;
}
@ -503,13 +514,17 @@ export function flotSettingsSchema(chartType: ChartType): JsonSettingsSchema {
GroupTitle: 'Common Settings'
}];
schema.form = [schema.form];
schema.schema.properties = {...schema.schema.properties, ...chartSettingsSchemaForComparison.schema.properties};
schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required);
schema.form.push(chartSettingsSchemaForComparison.form);
schema.schema.properties = {...schema.schema.properties, ...chartSettingsSchemaForComparison.schema.properties, ...chartSettingsSchemaForCustomLegend.schema.properties};
schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required, chartSettingsSchemaForCustomLegend.schema.required);
schema.form.push(chartSettingsSchemaForComparison.form, chartSettingsSchemaForCustomLegend.form);
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle:'Comparison Settings'
});
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle:'Custom Legend Settings'
});
}
return schema;
}
@ -603,6 +618,67 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = {
]
};
const chartSettingsSchemaForCustomLegend: JsonSettingsSchema = {
schema: {
title: 'Custom Legend Settings',
type: 'object',
properties: {
customLegendEnabled: {
title: 'Enable custom legend (this will allow you to use attribute/timeseries values in key labels)',
type: 'boolean',
default: false
},
dataKeysListForLabels: {
title: 'Datakeys list to use in labels',
type: 'array',
items: {
type: 'object',
properties: {
name: {
title: 'Key name',
type: 'string'
},
type: {
title: 'Key type',
type: 'string',
default: 'attribute'
}
},
required: [
'name'
]
}
}
},
required: []
},
form: [
'customLegendEnabled',
{
key: 'dataKeysListForLabels',
condition: 'model.customLegendEnabled === true',
items: [
{
key: 'dataKeysListForLabels[].type',
type: 'rc-select',
multiple: false,
items: [
{
value: 'attribute',
label: 'Attribute'
},
{
value: 'timeseries',
label: 'Timeseries'
}
]
},
'dataKeysListForLabels[].name'
]
}
]
};
export const flotPieSettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',

View File

@ -16,7 +16,15 @@
import { WidgetContext } from '@home/models/widget-component.models';
import { deepClone, isDefined, isEqual, isNumber, isUndefined } from '@app/core/utils';
import {
createLabelFromDatasource,
deepClone,
insertVariable,
isDefined,
isEqual,
isNumber,
isUndefined
} from '@app/core/utils';
import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import {
DataKey,
@ -88,6 +96,9 @@ export class TbFlot {
private thresholdsSourcesSubscription: IWidgetSubscription;
private predefinedThresholds: TbFlotThresholdMarking[];
private labelPatternsSourcesSubscription: IWidgetSubscription;
private labelPatternsSourcesData: DatasourceData[];
private plotInited = false;
private plot: JQueryPlot;
@ -369,6 +380,20 @@ export class TbFlot {
const yaxesMap: {[units: string]: TbFlotAxisOptions} = {};
const predefinedThresholds: TbFlotThresholdMarking[] = [];
const thresholdsDatasources: Datasource[] = [];
if (this.settings.customLegendEnabled) {
this.labelPatternsSourcesData = [];
const labelPatternsDatasources: Datasource[] = [];
subscription.datasources.forEach((item) => {
let datasource: Datasource = {
type: item.type,
entityType: item.entityType,
entityId: item.entityId,
dataKeys: this.settings.dataKeysListForLabels
};
labelPatternsDatasources.push(datasource);
});
this.subscribeForLabelPatternsSources(labelPatternsDatasources);
}
let tooltipValueFormatFunction: TooltipValueFormatFunction = null;
if (this.settings.tooltipValueFormatter && this.settings.tooltipValueFormatter.length) {
@ -506,6 +531,9 @@ export class TbFlot {
}
}
}
if (this.labelPatternsSourcesData?.length) {
this.substituteLabelPatterns(series, i);
}
}
this.subscribeForThresholdsAttributes(thresholdsDatasources);
@ -569,6 +597,10 @@ export class TbFlot {
this.yaxes[yaxisIndex].keysInfo[i].hidden = series.dataKey.hidden;
axisVisibilityChanged = true;
}
if (this.labelPatternsSourcesData?.length) {
this.substituteLabelPatterns(series, i);
}
}
if (axisVisibilityChanged) {
this.options.yaxes.length = 0;
@ -849,6 +881,60 @@ export class TbFlot {
}
}
private subscribeForLabelPatternsSources(datasources: Datasource[]) {
const labelPatternsSourcesSubscriptionOptions: WidgetSubscriptionOptions = {
datasources,
useDashboardTimewindow: false,
type: widgetType.latest,
callbacks: {
onDataUpdated: (subscription) => {
this.labelPatternsParamsDataUpdated(subscription.data)
}
}
};
this.ctx.subscriptionApi.createSubscription(labelPatternsSourcesSubscriptionOptions, true).subscribe(
(subscription) => {
this.labelPatternsSourcesSubscription = subscription;
}
);
}
private labelPatternsParamsDataUpdated(data: DatasourceData[]) {
this.labelPatternsSourcesData = data;
for (let i = 0; i < this.subscription.data.length; i++) {
const series = this.subscription.data[i] as TbFlotSeries;
this.substituteLabelPatterns(series, i);
}
this.updateData();
this.ctx.detectChanges();
}
private substituteLabelPatterns(series: TbFlotSeries, seriesIndex: number) {
let seriesLabelPatternsSourcesData = this.labelPatternsSourcesData.filter((item) => {
return item.datasource.entityId === series.datasource.entityId;
});
let label = createLabelFromDatasource(series.datasource, series.dataKey.pattern);
for (let i = 0; i < seriesLabelPatternsSourcesData.length; i++) {
let keyData = seriesLabelPatternsSourcesData[i];
if (keyData && keyData.data && keyData.data[0]) {
let attrValue = keyData.data[0][1];
let attrName = keyData.dataKey.name;
if (isDefined(attrValue) && (attrValue !== null)) {
label = insertVariable(label, attrName, attrValue);
}
}
}
if (isDefined(this.subscription.legendData)) {
let targetLegendKeyIndex = this.subscription.legendData.keys.findIndex((key) => {
return key.dataIndex === seriesIndex;
});
if (targetLegendKeyIndex !== -1) {
this.subscription.legendData.keys[targetLegendKeyIndex].dataKey.label = label;
}
}
series.dataKey.label = label;
}
private seriesInfoDiv(label: string, color: string, value: any,
units: string, trackDecimals: number, active: boolean,
percent: number, valueFormatFunction: TooltipValueFormatFunction): JQuery<HTMLElement> {