diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html index bb64c59302..4bda5fa9b5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html @@ -75,6 +75,21 @@ {{ 'widgets.range-chart.data-zoom' | translate }} + +
+
widgets.range-chart.range-chart-appearance
+
+
widget-config.units-short
+ + +
+
+
widget-config.decimals-short
+ + + +
{{ 'widgets.range-chart.range-colors' | translate }}
@@ -87,24 +102,139 @@ formControlName="outOfRangeColor">
+
+ + {{ 'widgets.range-chart.show-range-thresholds' | translate }} + +
{{ 'widgets.range-chart.fill-area' | translate }}
-
-
widget-config.units-short
- - -
-
-
widget-config.decimals-short
- - +
+
widgets.range-chart.fill-area-opacity
+ + +
+
+
widgets.time-series-chart.series.line.line
+
+ + {{ 'widgets.time-series-chart.series.line.show-line' | translate }} +
+
+ + {{ 'widgets.time-series-chart.series.line.step-line' | translate }} + + + + + {{ lineSeriesStepTypeTranslations.get(stepType) | translate }} + + + +
+
+ + {{ 'widgets.time-series-chart.series.line.smooth-line' | translate }} + +
+
+
widgets.time-series-chart.line-type
+ + + + {{ timeSeriesLineTypeTranslations.get(lineType) | translate }} + + + +
+
+
widgets.time-series-chart.line-width
+ + + +
+
+
+
widgets.time-series-chart.series.point.points
+
+ + {{ 'widgets.time-series-chart.series.point.show-points' | translate }} + +
+
+ +
+ {{ 'widgets.time-series-chart.series.point.point-label' | translate }} +
+
+
+ + + + {{ seriesLabelPositionTranslations.get(position) | translate }} + + + + + + + +
+
+
+
widgets.time-series-chart.series.point.point-shape
+ + + + {{ timeSeriesChartShapeTranslations.get(shape) | translate }} + + + +
+
+
widgets.time-series-chart.series.point.point-size
+ + + +
+
+
+
+
widgets.time-series-chart.axis.y-axis
+ + +
+
+
widgets.time-series-chart.axis.x-axis
+ +
+ +
@@ -204,6 +334,9 @@
+ +
widget-config.card-appearance
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts index 566dd4d86e..fc006d05a3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts @@ -14,13 +14,19 @@ /// limitations under the License. /// -import { ChangeDetectorRef, Component, Injector } from '@angular/core'; +import { Component, Injector } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models'; -import { DataKey, legendPositions, legendPositionTranslationMap, WidgetConfig, } from '@shared/models/widget.models'; +import { + DataKey, + Datasource, + legendPositions, + legendPositionTranslationMap, + WidgetConfig, +} from '@shared/models/widget.models'; import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { @@ -38,6 +44,16 @@ import { rangeChartDefaultSettings, RangeChartWidgetSettings } from '@home/components/widget/lib/chart/range-chart-widget.models'; +import { + lineSeriesStepTypes, + lineSeriesStepTypeTranslations, + seriesLabelPositions, + seriesLabelPositionTranslations, + timeSeriesChartShapes, + timeSeriesChartShapeTranslations, + timeSeriesLineTypes, + timeSeriesLineTypeTranslations +} from '@home/components/widget/lib/chart/time-series-chart.models'; @Component({ selector: 'tb-range-chart-basic-config', @@ -46,12 +62,39 @@ import { }) export class RangeChartBasicConfigComponent extends BasicWidgetConfigComponent { + public get datasource(): Datasource { + const datasources: Datasource[] = this.rangeChartWidgetConfigForm.get('datasources').value; + if (datasources && datasources.length) { + return datasources[0]; + } else { + return null; + } + } + + lineSeriesStepTypes = lineSeriesStepTypes; + + lineSeriesStepTypeTranslations = lineSeriesStepTypeTranslations; + + timeSeriesLineTypes = timeSeriesLineTypes; + + timeSeriesLineTypeTranslations = timeSeriesLineTypeTranslations; + + seriesLabelPositions = seriesLabelPositions; + + seriesLabelPositionTranslations = seriesLabelPositionTranslations; + + timeSeriesChartShapes = timeSeriesChartShapes; + + timeSeriesChartShapeTranslations = timeSeriesChartShapeTranslations; + legendPositions = legendPositions; legendPositionTranslationMap = legendPositionTranslationMap; rangeChartWidgetConfigForm: UntypedFormGroup; + pointLabelPreviewFn = this._pointLabelPreviewFn.bind(this); + tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); tooltipDatePreviewFn = this._tooltipDatePreviewFn.bind(this); @@ -90,11 +133,36 @@ export class RangeChartBasicConfigComponent extends BasicWidgetConfigComponent { iconColor: [configData.config.iconColor, []], dataZoom: [settings.dataZoom, []], + + units: [configData.config.units, []], + decimals: [configData.config.decimals, []], rangeColors: [settings.rangeColors, []], outOfRangeColor: [settings.outOfRangeColor, []], + showRangeThresholds: [settings.showRangeThresholds, []], fillArea: [settings.fillArea, []], - units: [configData.config.units, []], - decimals: [configData.config.decimals, []], + fillAreaOpacity: [settings.fillAreaOpacity, [Validators.min(0), Validators.max(100)]], + + showLine: [settings.showLine, []], + step: [settings.step, []], + stepType: [settings.stepType, []], + smooth: [settings.smooth, []], + lineType: [settings.lineType, []], + lineWidth: [settings.lineWidth, [Validators.min(0)]], + + showPoints: [settings.showPoints, []], + showPointLabel: [settings.showPointLabel, []], + pointLabelPosition: [settings.pointLabelPosition, []], + pointLabelFont: [settings.pointLabelFont, []], + pointLabelColor: [settings.pointLabelColor, []], + pointShape: [settings.pointShape, []], + pointSize: [settings.pointSize, [Validators.min(0)]], + + yAxis: [settings.yAxis, []], + xAxis: [settings.xAxis, []], + + thresholds: [settings.thresholds, []], + + animation: [settings.animation, []], showLegend: [settings.showLegend, []], legendPosition: [settings.legendPosition, []], @@ -139,12 +207,39 @@ export class RangeChartBasicConfigComponent extends BasicWidgetConfigComponent { this.widgetConfig.config.settings = this.widgetConfig.config.settings || {}; + this.widgetConfig.config.settings.dataZoom = config.dataZoom; + + this.widgetConfig.config.units = config.units; + this.widgetConfig.config.decimals = config.decimals; + this.widgetConfig.config.settings.rangeColors = config.rangeColors; this.widgetConfig.config.settings.outOfRangeColor = config.outOfRangeColor; + this.widgetConfig.config.settings.showRangeThresholds = config.showRangeThresholds; this.widgetConfig.config.settings.fillArea = config.fillArea; - this.widgetConfig.config.units = config.units; - this.widgetConfig.config.decimals = config.decimals; + this.widgetConfig.config.settings.fillAreaOpacity = config.fillAreaOpacity; + + this.widgetConfig.config.settings.showLine = config.showLine; + this.widgetConfig.config.settings.step = config.step; + this.widgetConfig.config.settings.stepType = config.stepType; + this.widgetConfig.config.settings.smooth = config.smooth; + this.widgetConfig.config.settings.lineType = config.lineType; + this.widgetConfig.config.settings.lineWidth = config.lineWidth; + + this.widgetConfig.config.settings.showPoints = config.showPoints; + this.widgetConfig.config.settings.showPointLabel = config.showPointLabel; + this.widgetConfig.config.settings.pointLabelPosition = config.pointLabelPosition; + this.widgetConfig.config.settings.pointLabelFont = config.pointLabelFont; + this.widgetConfig.config.settings.pointLabelColor = config.pointLabelColor; + this.widgetConfig.config.settings.pointShape = config.pointShape; + this.widgetConfig.config.settings.pointSize = config.pointSize; + + this.widgetConfig.config.settings.yAxis = config.yAxis; + this.widgetConfig.config.settings.xAxis = config.xAxis; + + this.widgetConfig.config.settings.thresholds = config.thresholds; + + this.widgetConfig.config.settings.animation = config.animation; this.widgetConfig.config.settings.showLegend = config.showLegend; this.widgetConfig.config.settings.legendPosition = config.legendPosition; @@ -173,12 +268,16 @@ export class RangeChartBasicConfigComponent extends BasicWidgetConfigComponent { } protected validatorTriggers(): string[] { - return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate']; + return ['showTitle', 'showIcon', 'fillArea', 'showLine', 'step', 'showPointLabel', 'showLegend', 'showTooltip', 'tooltipShowDate']; } protected updateValidators(emitEvent: boolean, trigger?: string) { const showTitle: boolean = this.rangeChartWidgetConfigForm.get('showTitle').value; const showIcon: boolean = this.rangeChartWidgetConfigForm.get('showIcon').value; + const fillArea: boolean = this.rangeChartWidgetConfigForm.get('fillArea').value; + const showLine: boolean = this.rangeChartWidgetConfigForm.get('showLine').value; + const step: boolean = this.rangeChartWidgetConfigForm.get('step').value; + const showPointLabel: boolean = this.rangeChartWidgetConfigForm.get('showPointLabel').value; const showLegend: boolean = this.rangeChartWidgetConfigForm.get('showLegend').value; const showTooltip: boolean = this.rangeChartWidgetConfigForm.get('showTooltip').value; const tooltipShowDate: boolean = this.rangeChartWidgetConfigForm.get('tooltipShowDate').value; @@ -210,6 +309,40 @@ export class RangeChartBasicConfigComponent extends BasicWidgetConfigComponent { this.rangeChartWidgetConfigForm.get('iconColor').disable(); } + if (fillArea) { + this.rangeChartWidgetConfigForm.get('fillAreaOpacity').enable(); + } else { + this.rangeChartWidgetConfigForm.get('fillAreaOpacity').disable(); + } + + if (showLine) { + this.rangeChartWidgetConfigForm.get('step').enable({emitEvent: false}); + if (step) { + this.rangeChartWidgetConfigForm.get('stepType').enable(); + this.rangeChartWidgetConfigForm.get('smooth').disable(); + } else { + this.rangeChartWidgetConfigForm.get('stepType').disable(); + this.rangeChartWidgetConfigForm.get('smooth').enable(); + } + this.rangeChartWidgetConfigForm.get('lineType').enable(); + this.rangeChartWidgetConfigForm.get('lineWidth').enable(); + } else { + this.rangeChartWidgetConfigForm.get('step').disable({emitEvent: false}); + this.rangeChartWidgetConfigForm.get('stepType').disable(); + this.rangeChartWidgetConfigForm.get('smooth').disable(); + this.rangeChartWidgetConfigForm.get('lineType').disable(); + this.rangeChartWidgetConfigForm.get('lineWidth').disable(); + } + if (showPointLabel) { + this.rangeChartWidgetConfigForm.get('pointLabelPosition').enable(); + this.rangeChartWidgetConfigForm.get('pointLabelFont').enable(); + this.rangeChartWidgetConfigForm.get('pointLabelColor').enable(); + } else { + this.rangeChartWidgetConfigForm.get('pointLabelPosition').disable(); + this.rangeChartWidgetConfigForm.get('pointLabelFont').disable(); + this.rangeChartWidgetConfigForm.get('pointLabelColor').disable(); + } + if (showLegend) { this.rangeChartWidgetConfigForm.get('legendPosition').enable(); this.rangeChartWidgetConfigForm.get('legendLabelFont').enable(); @@ -262,6 +395,12 @@ export class RangeChartBasicConfigComponent extends BasicWidgetConfigComponent { config.enableFullscreen = buttons.includes('fullscreen'); } + private _pointLabelPreviewFn(): string { + const units: string = this.rangeChartWidgetConfigForm.get('units').value; + const decimals: number = this.rangeChartWidgetConfigForm.get('decimals').value; + return formatValue(22, decimals, units, false); + } + private _tooltipValuePreviewFn(): string { const units: string = this.rangeChartWidgetConfigForm.get('units').value; const decimals: number = this.rangeChartWidgetConfigForm.get('decimals').value; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.models.ts index ee7b2835e6..eb6ea4a397 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.models.ts @@ -27,16 +27,25 @@ import { LegendPosition } from '@shared/models/widget.models'; import { EChartsTooltipWidgetSettings } from '@home/components/widget/lib/chart/echarts-widget.models'; import { createTimeSeriesChartVisualMapPiece, + defaultTimeSeriesChartXAxisSettings, + defaultTimeSeriesChartYAxisSettings, + LineSeriesStepType, SeriesFillType, + SeriesLabelPosition, timeSeriesChartAnimationDefaultSettings, + TimeSeriesChartAnimationSettings, + timeSeriesChartColorScheme, TimeSeriesChartKeySettings, + TimeSeriesChartLineType, TimeSeriesChartSeriesType, TimeSeriesChartSettings, TimeSeriesChartShape, TimeSeriesChartThreshold, TimeSeriesChartThresholdType, - TimeSeriesChartVisualMapPiece + TimeSeriesChartVisualMapPiece, + TimeSeriesChartXAxisSettings, + TimeSeriesChartYAxisSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; -import { isNumber } from '@core/utils'; +import { isNumber, mergeDeep } from '@core/utils'; import { DeepPartial } from '@shared/models/common'; export interface RangeItem { @@ -54,7 +63,26 @@ export interface RangeChartWidgetSettings extends EChartsTooltipWidgetSettings { dataZoom: boolean; rangeColors: Array; outOfRangeColor: string; + showRangeThresholds: boolean; fillArea: boolean; + fillAreaOpacity: number; + showLine: boolean; + step: boolean; + stepType: LineSeriesStepType; + smooth: boolean; + lineType: TimeSeriesChartLineType; + lineWidth: number; + showPoints: boolean; + showPointLabel: boolean; + pointLabelPosition: SeriesLabelPosition; + pointLabelFont: Font; + pointLabelColor: string; + pointShape: TimeSeriesChartShape; + pointSize: number; + yAxis: TimeSeriesChartYAxisSettings; + xAxis: TimeSeriesChartXAxisSettings; + animation: TimeSeriesChartAnimationSettings; + thresholds: TimeSeriesChartThreshold[]; showLegend: boolean; legendPosition: LegendPosition; legendLabelFont: Font; @@ -75,7 +103,38 @@ export const rangeChartDefaultSettings: RangeChartWidgetSettings = { {from: 40, color: '#D81838'} ], outOfRangeColor: '#ccc', + showRangeThresholds: true, fillArea: true, + fillAreaOpacity: 0.7, + showLine: true, + step: false, + stepType: LineSeriesStepType.start, + smooth: false, + lineType: TimeSeriesChartLineType.solid, + lineWidth: 2, + showPoints: false, + showPointLabel: false, + pointLabelPosition: SeriesLabelPosition.top, + pointLabelFont: { + family: 'Roboto', + size: 11, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + pointLabelColor: timeSeriesChartColorScheme['series.label'].light, + pointShape: TimeSeriesChartShape.emptyCircle, + pointSize: 4, + yAxis: mergeDeep({} as TimeSeriesChartYAxisSettings, + defaultTimeSeriesChartYAxisSettings, + { id: 'default', order: 0, showLine: false, showTicks: false } as TimeSeriesChartYAxisSettings), + xAxis: mergeDeep({} as TimeSeriesChartXAxisSettings, + defaultTimeSeriesChartXAxisSettings, + {showSplitLines: false} as TimeSeriesChartXAxisSettings), + animation: mergeDeep({} as TimeSeriesChartAnimationSettings, + timeSeriesChartAnimationDefaultSettings), + thresholds: [], showLegend: true, legendPosition: LegendPosition.top, legendLabelFont: { @@ -125,7 +184,7 @@ export const rangeChartDefaultSettings: RangeChartWidgetSettings = { export const rangeChartTimeSeriesSettings = (settings: RangeChartWidgetSettings, rangeItems: RangeItem[], decimals: number, units: string): DeepPartial => { - const thresholds: DeepPartial[] = getMarkPoints(rangeItems).map(item => ({ + let thresholds: DeepPartial[] = settings.showRangeThresholds ? getMarkPoints(rangeItems).map(item => ({ type: TimeSeriesChartThresholdType.constant, yAxisId: 'default', units, @@ -146,28 +205,24 @@ export const rangeChartTimeSeriesSettings = (settings: RangeChartWidgetSettings, borderRadius: 4, }, value: item - } as DeepPartial)); + } as DeepPartial)) : []; + if (settings.thresholds?.length) { + thresholds = thresholds.concat(settings.thresholds); + } return { dataZoom: settings.dataZoom, thresholds, yAxes: { default: { - show: true, - showLine: false, - showTicks: false, - showTickLabels: true, - showSplitLines: true, - decimals, - units + ...settings.yAxis, + ...{ + decimals, + units + } } }, - xAxis: { - show: true, - showLine: true, - showTicks: true, - showTickLabels: true, - showSplitLines: false - }, + xAxis: settings.xAxis, + animation: settings.animation, visualMapSettings: { outOfRangeColor: settings.outOfRangeColor, pieces: rangeItems.map(item => item.piece) @@ -188,12 +243,22 @@ export const rangeChartTimeSeriesSettings = (settings: RangeChartWidgetSettings, export const rangeChartTimeSeriesKeySettings = (settings: RangeChartWidgetSettings): DeepPartial => ({ type: TimeSeriesChartSeriesType.line, lineSettings: { - showLine: true, - smooth: false, - showPoints: false, + showLine: settings.showLine, + step: settings.step, + stepType: settings.stepType, + smooth: settings.smooth, + lineType: settings.lineType, + lineWidth: settings.lineWidth, + showPoints: settings.showPoints, + showPointLabel: settings.showPointLabel, + pointLabelPosition: settings.pointLabelPosition, + pointLabelFont: settings.pointLabelFont, + pointLabelColor: settings.pointLabelColor, + pointShape: settings.pointShape, + pointSize: settings.pointSize, fillAreaSettings: { type: settings.fillArea ? SeriesFillType.opacity : SeriesFillType.none, - opacity: 0.7 + opacity: settings.fillAreaOpacity } } }); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index df47a03692..4dc36b6682 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -81,7 +81,7 @@ export const timeSeriesChartTypeTranslations = new Map { - let result: string; - try { - result = formatFunction(params.value[1]); - } catch (_e) { - } - if (isUndefined(result)) { - result = formatValue(params.value[1], item.decimals, item.units, false); - } - return `{value|${result}}`; - }; - } else { - formatter = (params): string => { - const value = formatValue(params.value[1], item.decimals, item.units, false); - return `{value|${value}}`; - }; - } + if (isFunction(labelFormatter)) { + formatter = labelFormatter as LabelFormatterCallback; + } else if (labelFormatter?.length) { + const formatFunction = parseFunction(labelFormatter, ['value']); + formatter = (params): string => { + let result: string; + try { + result = formatFunction(params.value[1]); + } catch (_e) { + } + if (isUndefined(result)) { + result = formatValue(params.value[1], item.decimals, item.units, false); + } + return `{value|${result}}`; + }; + } else { + formatter = (params): string => { + const value = formatValue(params.value[1], item.decimals, item.units, false); + return `{value|${value}}`; + }; } return { show, diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 43e20a46ce..b2dbc2b29f 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6172,9 +6172,12 @@ "range-chart": { "chart": "Chart", "data-zoom": "Data zoom", + "range-chart-appearance": "Range chart appearance", "range-colors": "Range colors", "out-of-range-color": "Out of range color", + "show-range-thresholds": "Show range thresholds", "fill-area": "Fill area", + "fill-area-opacity": "Fill area opacity", "range-chart-card-style": "Range chart card style" }, "rpc": {