diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts index 429b59774b..c74c357739 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts @@ -28,7 +28,7 @@ import { ViewEncapsulation } from '@angular/core'; import { WidgetContext } from '@home/models/widget-component.models'; -import { formattedDataFormDatasourceData, formatValue, isDefinedAndNotNull, isNumeric } from '@core/utils'; +import { formatValue, isDefinedAndNotNull, isNumeric } from '@core/utils'; import { DatePipe } from '@angular/common'; import { backgroundStyle, @@ -37,7 +37,8 @@ import { getDataKey, getSingleTsValue, overlayStyle, - textStyle + textStyle, + updateGradientMinMaxValues } from '@shared/models/widget-settings.models'; import { WidgetComponent } from '@home/components/widget/widget.component'; import { @@ -46,15 +47,9 @@ import { BatteryLevelWidgetSettings } from '@home/components/widget/lib/indicator/battery-level-widget.models'; import { ResizeObserver } from '@juggle/resize-observer'; -import { forkJoin, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; -import { FormattedData } from '@shared/models/widget.models'; -import { - parseThresholdData, - TimeSeriesChartThresholdType -} from '@home/components/widget/lib/chart/time-series-chart.models'; -import { map } from 'rxjs/operators'; const verticalBatteryDimensions = { shapeAspectRatio: 64 / 113, @@ -197,11 +192,11 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView this.showValue = this.settings.showValue; this.autoScaleValueSize = this.showValue && this.settings.autoScaleValueSize; this.valueStyle = textStyle(this.settings.valueFont); - this.valueColor = ColorProcessor.fromSettings(this.settings.valueColor,this.ctx, this.cd); + this.valueColor = ColorProcessor.fromSettings(updateGradientMinMaxValues(this.settings.valueColor, 0, 100), this.ctx); - this.batteryLevelColor = ColorProcessor.fromSettings(this.settings.batteryLevelColor, this.ctx, this.cd); + this.batteryLevelColor = ColorProcessor.fromSettings(updateGradientMinMaxValues(this.settings.batteryLevelColor, 0, 100), this.ctx); - this.batteryShapeColor = ColorProcessor.fromSettings(this.settings.batteryShapeColor, this.ctx, this.cd); + this.batteryShapeColor = ColorProcessor.fromSettings(updateGradientMinMaxValues(this.settings.batteryShapeColor, 0, 100), this.ctx); this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts index 73b6cacf2e..84d668565f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts @@ -99,7 +99,7 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit { type: [this.colorSettings?.type || ColorType.constant, []], color: [this.colorSettings?.color, []], - gradient: [this.colorSettings?.gradient || defaultGradient(), []], + gradient: [this.colorSettings?.gradient || defaultGradient(+this.minValue, +this.maxValue), []], rangeList: [this.colorSettings?.rangeList, []], colorFunction: [this.colorSettings?.colorFunction, []] } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts index b5dbea5cab..b66e5ed1e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts @@ -92,7 +92,6 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro private sanitizer: DomSanitizer) {} ngOnInit(): void { - console.log(this.minValue, this.maxValue); this.gradientFormGroup = this.fb.group({ advancedMode: [false], gradient: this.fb.group({ diff --git a/ui-ngx/src/app/shared/models/widget-settings.models.ts b/ui-ngx/src/app/shared/models/widget-settings.models.ts index 917ed24feb..f4bb216c3a 100644 --- a/ui-ngx/src/app/shared/models/widget-settings.models.ts +++ b/ui-ngx/src/app/shared/models/widget-settings.models.ts @@ -37,7 +37,7 @@ import { map } from 'rxjs/operators'; import { DomSanitizer } from '@angular/platform-browser'; import { AVG_MONTH, DAY, HOUR, Interval, IntervalMath, MINUTE, SECOND, YEAR } from '@shared/models/time/time.models'; import moment from 'moment'; -import tinycolor from 'tinycolor2'; +import tinycolor, { ColorInput } from 'tinycolor2'; import { WidgetContext } from '@home/models/widget-component.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; @@ -234,6 +234,8 @@ export interface ColorGradientSettings { advancedMode?: boolean; gradient?: Array; gradientAdvanced?: Array; + minValue?: number; + maxValue?: number; } export interface DataKeySettings { @@ -265,7 +267,7 @@ export const constantColor = (color: string): ColorSettings => ({ colorFunction: defaultColorFunction }); -export const defaultGradient = (): ColorGradientSettings => ({ +export const defaultGradient = (minValue?: number, maxValue?: number): ColorGradientSettings => ({ advancedMode: false, gradient: ['rgba(0, 255, 0, 1)', 'rgba(255, 0, 0, 1)'], gradientAdvanced: [ @@ -277,9 +279,21 @@ export const defaultGradient = (): ColorGradientSettings => ({ source: {type: ValueSourceDataKeyType.constant}, color: 'rgba(255, 0, 0, 1)' } - ] + ], + minValue: isDefinedAndNotNull(minValue) ? minValue : 0, + maxValue: isDefinedAndNotNull(maxValue) ? maxValue : 100 }); +export const updateGradientMinMaxValues = (colorSettings: ColorSettings, minValue: number, maxValue: number): ColorSettings => { + if (isDefinedAndNotNull(colorSettings.gradient)) { + colorSettings.gradient.minValue = minValue; + colorSettings.gradient.maxValue = maxValue; + } else { + colorSettings.gradient = defaultGradient(minValue, maxValue); + } + return colorSettings; +}; + export const defaultColorFunction = 'var temperature = value;\n' + 'if (typeof temperature !== undefined) {\n' + ' var percent = (temperature + 60)/120 * 100;\n' + @@ -325,17 +339,17 @@ type ValueColorFunction = (value: any) => string; export abstract class ColorProcessor { - static fromSettings(color: ColorSettings, ctx?: WidgetContext, cd?: ChangeDetectorRef, maxValue = 100): ColorProcessor { + static fromSettings(color: ColorSettings, ctx?: WidgetContext): ColorProcessor { const settings = color || constantColor(null); switch (settings.type) { case ColorType.constant: return new ConstantColorProcessor(settings); case ColorType.range: - return new RangeColorProcessor(settings, ctx, cd); + return new RangeColorProcessor(settings, ctx); case ColorType.function: return new FunctionColorProcessor(settings); case ColorType.gradient: - return new GradientColorProcessor(settings, ctx, cd, maxValue); + return new GradientColorProcessor(settings, ctx); default: return new ConstantColorProcessor(settings); } @@ -437,8 +451,7 @@ class RangeColorProcessor extends ColorProcessor { private progress; constructor(protected settings: ColorSettings, - protected ctx: WidgetContext, - protected cd: ChangeDetectorRef) { + protected ctx: WidgetContext) { super(settings); } @@ -563,10 +576,10 @@ class RangeColorProcessor extends ColorProcessor { return this.settings.color; } - public static constantRange(range): boolean { + public static constantRange(range: ColorRange): boolean { return isNumber(range.from) && isNumber(range.to) && range.from === range.to; } - public static constantAdvancedRange(range): boolean { + public static constantAdvancedRange(range: AdvancedColorRange): boolean { return isNumber(range.from.value) && isNumber(range.to.value) && range.from.value === range.to.value; } } @@ -593,17 +606,20 @@ class GradientColorProcessor extends ColorProcessor { private progress: number; + private minValue: number; + private maxValue: number; + private advancedGradientSourcesSubscription: IWidgetSubscription; constructor(protected settings: ColorSettings, - protected ctx: WidgetContext, - protected cd: ChangeDetectorRef, - protected maxValue: number) { + protected ctx: WidgetContext) { super(settings); + this.minValue = isDefinedAndNotNull(settings.gradient.minValue) ? settings.gradient.minValue : 0; + this.maxValue = isDefinedAndNotNull(settings.gradient.maxValue) ? settings.gradient.maxValue : 100; } update(value: any): void { - this.progress = value / this.maxValue; + this.progress = this.calculateProgress(+value, this.minValue, this.maxValue); if(isDefinedAndNotNull(this.settings.gradient.advancedMode) && this.settings.gradient.advancedMode) { this.advancedRangeSubscribe(this.settings.gradient.gradientAdvanced); } else { @@ -617,23 +633,32 @@ class GradientColorProcessor extends ColorProcessor { } } - getProgressColor(progress: number, levelColors): string { + calculateProgress(current: number, min: number, max: number) { + if (current < min) { + return 0; + } else if (current > max) { + return 1; + } + return (current - min) / (max - min); + } + + getProgressColor(progress: number, levelColors: Array): string { const colorsCount = levelColors.length; const inc = colorsCount > 1 ? (1 / (colorsCount - 1)) : 1; const colorsRange = []; - for (let i = 0; i < levelColors.length; i++) { - const levelColor: any = this.settings.gradient.advancedMode ? levelColors[i].color : levelColors[i]; - if (levelColor !== null) { - const tColor = tinycolor(levelColor); + levelColors.forEach((levelColor, i) => { + const color = typeof levelColor === 'string' ? levelColor : levelColor.color; + if (color !== null) { + const tColor = tinycolor(color); colorsRange.push({ - pct: this.settings.gradient.advancedMode ? levelColors[i].source.value / this.maxValue : inc * i, + pct: typeof levelColor !== 'string' ? + this.calculateProgress(+levelColor.source.value, this.minValue, this.maxValue) : inc * i, color: tColor.toRgb(), alpha: tColor.getAlpha(), rgbString: tColor.toRgbString() }); } - } - + }); if (progress === 0 || colorsRange.length === 1) { return colorsRange[0].rgbString; }