Commit 77477f69ee1e98e8461454aa5cc47902692cedee

Authored by Chantsova Ekaterina
1 parent 4bea89a6

Flot: add ability to use attributes in datakeys labels

... ... @@ -19,6 +19,7 @@
19 19
20 20 import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models';
21 21 import * as moment_ from 'moment';
  22 +import { DataKeyType } from "@shared/models/telemetry/telemetry.models";
22 23
23 24 export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph';
24 25
... ... @@ -149,13 +150,24 @@ export interface TbFlotThresholdsSettings {
149 150 thresholdsLineWidth: number;
150 151 }
151 152
152   -export interface TbFlotGraphSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings {
  153 +export interface TbFlotCustomLegendSettings {
  154 + customLegendEnabled: boolean;
  155 + dataKeysListForLabels: Array<TbFlotLabelPatternSettings>;
  156 +}
  157 +
  158 +export interface TbFlotLabelPatternSettings {
  159 + name: string;
  160 + type: DataKeyType;
  161 + settings?: object
  162 +}
  163 +
  164 +export interface TbFlotGraphSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
153 165 smoothLines: boolean;
154 166 }
155 167
156 168 export declare type BarAlignment = 'left' | 'right' | 'center';
157 169
158   -export interface TbFlotBarSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings {
  170 +export interface TbFlotBarSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
159 171 defaultBarWidth: number;
160 172 barAlignment: BarAlignment;
161 173 }
... ... @@ -503,13 +515,17 @@ export function flotSettingsSchema(chartType: ChartType): JsonSettingsSchema {
503 515 GroupTitle: 'Common Settings'
504 516 }];
505 517 schema.form = [schema.form];
506   - schema.schema.properties = {...schema.schema.properties, ...chartSettingsSchemaForComparison.schema.properties};
507   - schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required);
508   - schema.form.push(chartSettingsSchemaForComparison.form);
  518 + schema.schema.properties = {...schema.schema.properties, ...chartSettingsSchemaForComparison.schema.properties, ...chartSettingsSchemaForCustomLegend.schema.properties};
  519 + schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required, chartSettingsSchemaForCustomLegend.schema.required);
  520 + schema.form.push(chartSettingsSchemaForComparison.form, chartSettingsSchemaForCustomLegend.form);
509 521 schema.groupInfoes.push({
510 522 formIndex: schema.groupInfoes.length,
511 523 GroupTitle:'Comparison Settings'
512 524 });
  525 + schema.groupInfoes.push({
  526 + formIndex: schema.groupInfoes.length,
  527 + GroupTitle:'Custom Legend Settings'
  528 + });
513 529 }
514 530 return schema;
515 531 }
... ... @@ -603,6 +619,67 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = {
603 619 ]
604 620 };
605 621
  622 +const chartSettingsSchemaForCustomLegend: JsonSettingsSchema = {
  623 + schema: {
  624 + title: 'Custom Legend Settings',
  625 + type: 'object',
  626 + properties: {
  627 + customLegendEnabled: {
  628 + title: 'Enable custom legend (this will allow you to use attribute/timeseries values in key labels)',
  629 + type: 'boolean',
  630 + default: false
  631 + },
  632 + dataKeysListForLabels: {
  633 + title: 'Datakeys list to use in labels',
  634 + type: 'array',
  635 + items: {
  636 + type: 'object',
  637 + properties: {
  638 + name: {
  639 + title: 'Key name',
  640 + type: 'string'
  641 + },
  642 + type: {
  643 + title: 'Key type',
  644 + type: 'string',
  645 + default: 'attribute'
  646 + }
  647 + },
  648 + required: [
  649 + 'name'
  650 + ]
  651 + }
  652 + }
  653 + },
  654 + required: []
  655 + },
  656 + form: [
  657 + 'customLegendEnabled',
  658 + {
  659 + key: 'dataKeysListForLabels',
  660 + condition: 'model.customLegendEnabled === true',
  661 + items: [
  662 + {
  663 + key: 'dataKeysListForLabels[].type',
  664 + type: 'rc-select',
  665 + multiple: false,
  666 + items: [
  667 + {
  668 + value: 'attribute',
  669 + label: 'Attribute'
  670 + },
  671 + {
  672 + value: 'timeseries',
  673 + label: 'Timeseries'
  674 + }
  675 + ]
  676 + },
  677 + 'dataKeysListForLabels[].name'
  678 + ]
  679 + }
  680 + ]
  681 +};
  682 +
606 683 export const flotPieSettingsSchema: JsonSettingsSchema = {
607 684 schema: {
608 685 type: 'object',
... ...
... ... @@ -16,7 +16,15 @@
16 16
17 17
18 18 import { WidgetContext } from '@home/models/widget-component.models';
19   -import { deepClone, isDefined, isEqual, isNumber, isUndefined } from '@app/core/utils';
  19 +import {
  20 + createLabelFromDatasource,
  21 + deepClone,
  22 + insertVariable,
  23 + isDefined,
  24 + isEqual,
  25 + isNumber,
  26 + isUndefined
  27 +} from '@app/core/utils';
20 28 import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
21 29 import {
22 30 DataKey,
... ... @@ -88,6 +96,9 @@ export class TbFlot {
88 96 private thresholdsSourcesSubscription: IWidgetSubscription;
89 97 private predefinedThresholds: TbFlotThresholdMarking[];
90 98
  99 + private labelPatternsSourcesSubscription: IWidgetSubscription;
  100 + private labelPatternsSourcesData: DatasourceData[];
  101 +
91 102 private plotInited = false;
92 103 private plot: JQueryPlot;
93 104
... ... @@ -369,6 +380,20 @@ export class TbFlot {
369 380 const yaxesMap: {[units: string]: TbFlotAxisOptions} = {};
370 381 const predefinedThresholds: TbFlotThresholdMarking[] = [];
371 382 const thresholdsDatasources: Datasource[] = [];
  383 + if (this.settings.customLegendEnabled) {
  384 + this.labelPatternsSourcesData = [];
  385 + const labelPatternsDatasources: Datasource[] = [];
  386 + subscription.datasources.forEach((item) => {
  387 + let datasource: Datasource = {
  388 + type: item.type,
  389 + entityType: item.entityType,
  390 + entityId: item.entityId,
  391 + dataKeys: this.settings.dataKeysListForLabels
  392 + };
  393 + labelPatternsDatasources.push(datasource);
  394 + });
  395 + this.subscribeForLabelPatternsSources(labelPatternsDatasources);
  396 + }
372 397
373 398 let tooltipValueFormatFunction: TooltipValueFormatFunction = null;
374 399 if (this.settings.tooltipValueFormatter && this.settings.tooltipValueFormatter.length) {
... ... @@ -506,6 +531,9 @@ export class TbFlot {
506 531 }
507 532 }
508 533 }
  534 + if (this.labelPatternsSourcesData?.length) {
  535 + this.substituteLabelPatterns(series, i);
  536 + }
509 537 }
510 538
511 539 this.subscribeForThresholdsAttributes(thresholdsDatasources);
... ... @@ -569,6 +597,10 @@ export class TbFlot {
569 597 this.yaxes[yaxisIndex].keysInfo[i].hidden = series.dataKey.hidden;
570 598 axisVisibilityChanged = true;
571 599 }
  600 +
  601 + if (this.labelPatternsSourcesData?.length) {
  602 + this.substituteLabelPatterns(series, i);
  603 + }
572 604 }
573 605 if (axisVisibilityChanged) {
574 606 this.options.yaxes.length = 0;
... ... @@ -849,6 +881,60 @@ export class TbFlot {
849 881 }
850 882 }
851 883
  884 + private subscribeForLabelPatternsSources(datasources: Datasource[]) {
  885 + const labelPatternsSourcesSubscriptionOptions: WidgetSubscriptionOptions = {
  886 + datasources,
  887 + useDashboardTimewindow: false,
  888 + type: widgetType.latest,
  889 + callbacks: {
  890 + onDataUpdated: (subscription) => {
  891 + this.labelPatternsParamsDataUpdated(subscription.data)
  892 + }
  893 + }
  894 + };
  895 + this.ctx.subscriptionApi.createSubscription(labelPatternsSourcesSubscriptionOptions, true).subscribe(
  896 + (subscription) => {
  897 + this.labelPatternsSourcesSubscription = subscription;
  898 + }
  899 + );
  900 + }
  901 +
  902 + private labelPatternsParamsDataUpdated(data: DatasourceData[]) {
  903 + this.labelPatternsSourcesData = data;
  904 + for (let i = 0; i < this.subscription.data.length; i++) {
  905 + const series = this.subscription.data[i] as TbFlotSeries;
  906 + this.substituteLabelPatterns(series, i);
  907 + }
  908 + this.updateData();
  909 + this.ctx.detectChanges();
  910 + }
  911 +
  912 + private substituteLabelPatterns(series: TbFlotSeries, seriesIndex: number) {
  913 + let seriesLabelPatternsSourcesData = this.labelPatternsSourcesData.filter((item) => {
  914 + return item.datasource.entityId === series.datasource.entityId;
  915 + });
  916 + let label = createLabelFromDatasource(series.datasource, series.dataKey.pattern);
  917 + for (let i = 0; i < seriesLabelPatternsSourcesData.length; i++) {
  918 + let keyData = seriesLabelPatternsSourcesData[i];
  919 + if (keyData && keyData.data && keyData.data[0]) {
  920 + let attrValue = keyData.data[0][1];
  921 + let attrName = keyData.dataKey.name;
  922 + if (isDefined(attrValue) && (attrValue !== null)) {
  923 + label = insertVariable(label, attrName, attrValue);
  924 + }
  925 + }
  926 + }
  927 + if (isDefined(this.subscription.legendData)) {
  928 + let targetLegendKeyIndex = this.subscription.legendData.keys.findIndex((key) => {
  929 + return key.dataIndex === seriesIndex;
  930 + });
  931 + if (targetLegendKeyIndex !== -1) {
  932 + this.subscription.legendData.keys[targetLegendKeyIndex].dataKey.label = label;
  933 + }
  934 + }
  935 + series.dataKey.label = label;
  936 + }
  937 +
852 938 private seriesInfoDiv(label: string, color: string, value: any,
853 939 units: string, trackDecimals: number, active: boolean,
854 940 percent: number, valueFormatFunction: TooltipValueFormatFunction): JQuery<HTMLElement> {
... ...