Commit 77477f69ee1e98e8461454aa5cc47902692cedee
1 parent
4bea89a6
Flot: add ability to use attributes in datakeys labels
Showing
2 changed files
with
169 additions
and
6 deletions
... | ... | @@ -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> { | ... | ... |