Merge pull request #10948 from ArtemDzhereleiko/AD/hot-fix/digital-gauge

Hot fix for color settings and digital gauge
This commit is contained in:
Igor Kulikov 2024-06-07 15:30:05 +03:00 committed by GitHub
commit 2c2273d15b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 191 additions and 141 deletions

View File

@ -100,6 +100,8 @@
[previewText]="valuePreviewFn"> [previewText]="valuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="valueColor" <tb-color-settings formControlName="valueColor"
[minValue]="progressBarWidgetConfigForm.get('tickMin').value"
[maxValue]="progressBarWidgetConfigForm.get('tickMax').value"
settingsKey="{{'widgets.progress-bar.value' | translate }}"> settingsKey="{{'widgets.progress-bar.value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
@ -137,6 +139,8 @@
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div>{{ 'widgets.progress-bar.bar-color' | translate }}</div> <div>{{ 'widgets.progress-bar.bar-color' | translate }}</div>
<tb-color-settings formControlName="barColor" <tb-color-settings formControlName="barColor"
[minValue]="progressBarWidgetConfigForm.get('tickMin').value"
[maxValue]="progressBarWidgetConfigForm.get('tickMax').value"
settingsKey="{{'widgets.progress-bar.bar-color' | translate }}"> settingsKey="{{'widgets.progress-bar.bar-color' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>

View File

@ -53,8 +53,21 @@
<div class="tb-form-row space-between column-xs"> <div class="tb-form-row space-between column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showMinMax"> <mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showMinMax">
{{ 'widgets.gauge.min-and-max-value' | translate }} {{ 'widgets.gauge.min-and-max-label' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<tb-font-settings formControlName="minMaxFont"
disabledLineHeight
[previewText]="previewFn">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="minMaxColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row space-between column-xs">
<div class="fixed-title-width">{{ 'widgets.gauge.min-and-max-value' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div class="tb-small-label" translate>widgets.gauge.min-value-short</div> <div class="tb-small-label" translate>widgets.gauge.min-value-short</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
@ -64,14 +77,6 @@
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="maxValue" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="maxValue" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<tb-font-settings formControlName="minMaxFont"
disabledLineHeight
[previewText]="previewFn">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="minMaxColor">
</tb-color-input>
</div> </div>
</div> </div>
@ -117,14 +122,6 @@
</div> </div>
</div> </div>
<div class="tb-form-row space-between">
<div translate>widgets.gauge.default-color</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="defaultColor">
</tb-color-input>
</div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div translate>widgets.gauge.gauge-bar-background</div> <div translate>widgets.gauge.gauge-bar-background</div>
<tb-color-input asBoxInput <tb-color-input asBoxInput
@ -137,6 +134,7 @@
<div class="fixed-title-width">{{ 'widgets.gauge.bar-color' | translate }}</div> <div class="fixed-title-width">{{ 'widgets.gauge.bar-color' | translate }}</div>
<tb-color-settings formControlName="barColor" <tb-color-settings formControlName="barColor"
rangeAdvancedMode rangeAdvancedMode
gradientAdvancedMode
[minValue]="simpleGaugeWidgetConfigForm.get('minValue').value" [minValue]="simpleGaugeWidgetConfigForm.get('minValue').value"
[maxValue]="simpleGaugeWidgetConfigForm.get('maxValue').value" [maxValue]="simpleGaugeWidgetConfigForm.get('maxValue').value"
[aliasController]="aliasController" [aliasController]="aliasController"

View File

@ -98,7 +98,7 @@ export class DigitalSimpleGaugeBasicConfigComponent extends BasicWidgetConfigCom
protected onConfigSet(configData: WidgetConfigComponentData) { protected onConfigSet(configData: WidgetConfigComponentData) {
const settings: DigitalGaugeSettings = {...defaultDigitalSimpleGaugeOptions, ...(configData.config.settings || {})}; const settings: DigitalGaugeSettings = {...defaultDigitalSimpleGaugeOptions, ...(configData.config.settings || {})};
convertLevelColorsSettingsToColorProcessor(settings); convertLevelColorsSettingsToColorProcessor(settings, settings.defaultColor || '#2196f3');
this.simpleGaugeWidgetConfigForm = this.fb.group({ this.simpleGaugeWidgetConfigForm = this.fb.group({
timewindowConfig: [getTimewindowConfig(configData.config), []], timewindowConfig: [getTimewindowConfig(configData.config), []],
@ -124,7 +124,6 @@ export class DigitalSimpleGaugeBasicConfigComponent extends BasicWidgetConfigCom
titleFont: [settings.titleFont, []], titleFont: [settings.titleFont, []],
titleColor: [settings.titleFont?.color, []], titleColor: [settings.titleFont?.color, []],
defaultColor: [settings.defaultColor, []],
gaugeColor: [settings.gaugeColor, []], gaugeColor: [settings.gaugeColor, []],
barColor: [settings.barColor, []], barColor: [settings.barColor, []],
@ -165,7 +164,6 @@ export class DigitalSimpleGaugeBasicConfigComponent extends BasicWidgetConfigCom
this.widgetConfig.config.settings.titleFont = config.titleFont; this.widgetConfig.config.settings.titleFont = config.titleFont;
this.widgetConfig.config.settings.titleFont.color = config.titleColor; this.widgetConfig.config.settings.titleFont.color = config.titleColor;
this.widgetConfig.config.settings.defaultColor = config.defaultColor;
this.widgetConfig.config.settings.gaugeColor = config.gaugeColor; this.widgetConfig.config.settings.gaugeColor = config.gaugeColor;
this.widgetConfig.config.settings.barColor = config.barColor; this.widgetConfig.config.settings.barColor = config.barColor;
const barColor: ColorSettings = config.barColor; const barColor: ColorSettings = config.barColor;

View File

@ -131,7 +131,12 @@ export class ProgressBarWidgetComponent implements OnInit, OnDestroy, AfterViewI
this.showValue = this.settings.showValue; this.showValue = this.settings.showValue;
this.valueStyle = textStyle(this.settings.valueFont); this.valueStyle = textStyle(this.settings.valueFont);
this.valueColor = ColorProcessor.fromSettings(this.settings.valueColor); this.valueColor = ColorProcessor.fromColorProcessorSettings({
settings: this.settings.valueColor,
ctx: this.ctx,
minGradientValue: this.settings.tickMin,
maxGradientValue: this.settings.tickMax
});
this.showTitleValueRow = this.showValue || this.showTitleValueRow = this.showValue ||
(this.layout === ProgressBarLayout.simplified && this.widgetComponent.dashboardWidget.showWidgetTitlePanel); (this.layout === ProgressBarLayout.simplified && this.widgetComponent.dashboardWidget.showWidgetTitlePanel);
@ -142,7 +147,12 @@ export class ProgressBarWidgetComponent implements OnInit, OnDestroy, AfterViewI
this.titleValueRowClass = (this.layout === ProgressBarLayout.simplified && this.titleValueRowClass = (this.layout === ProgressBarLayout.simplified &&
!this.widgetComponent.dashboardWidget.showWidgetTitlePanel) ? 'flex-end' : ''; !this.widgetComponent.dashboardWidget.showWidgetTitlePanel) ? 'flex-end' : '';
this.barColor = ColorProcessor.fromSettings(this.settings.barColor); this.barColor = ColorProcessor.fromColorProcessorSettings({
settings: this.settings.barColor,
ctx: this.ctx,
minGradientValue: this.settings.tickMin,
maxGradientValue: this.settings.tickMax
});;
this.showTicks = this.settings.showTicks && this.layout === ProgressBarLayout.default; this.showTicks = this.settings.showTicks && this.layout === ProgressBarLayout.default;
if (this.showTicks) { if (this.showTicks) {

View File

@ -22,6 +22,7 @@ import {
ColorSettings, ColorSettings,
ColorType, ColorType,
constantColor, constantColor,
defaultGradient,
ValueSourceConfig, ValueSourceConfig,
ValueSourceType ValueSourceType
} from '@shared/models/widget-settings.models'; } from '@shared/models/widget-settings.models';
@ -161,9 +162,19 @@ export const backwardCompatibilityTicks = (ticksValue: AttributeSourceProperty[]
return ticks; return ticks;
}; };
export const convertLevelColorsSettingsToColorProcessor = (settings: DigitalGaugeSettings) => { export const convertLevelColorsSettingsToColorProcessor = (settings: DigitalGaugeSettings, defaultColor?: string) => {
if (!settings.barColor) { if (settings.barColor) {
settings.barColor = constantColor(settings.gaugeColor); if (!settings.barColor.color) {
settings.barColor.color = defaultColor;
}
if (isDefinedAndNotNull(settings.barColor.gradient)) {
settings.barColor.gradient.minValue = settings.minValue;
settings.barColor.gradient.maxValue = settings.maxValue;
} else {
settings.barColor.gradient = defaultGradient(settings.minValue, settings.maxValue);
}
} else {
settings.barColor = constantColor(defaultColor);
if (settings.fixedLevelColors?.length) { if (settings.fixedLevelColors?.length) {
settings.barColor.rangeList = { settings.barColor.rangeList = {
advancedMode: settings.useFixedLevelColor, advancedMode: settings.useFixedLevelColor,
@ -175,7 +186,9 @@ export const convertLevelColorsSettingsToColorProcessor = (settings: DigitalGaug
settings.barColor.gradient = { settings.barColor.gradient = {
advancedMode: false, advancedMode: false,
gradient: settings.levelColors as string[], gradient: settings.levelColors as string[],
gradientAdvanced: null gradientAdvanced: null,
minValue: settings.minValue,
maxValue: settings.maxValue
}; };
} }
if (settings.useFixedLevelColor) { if (settings.useFixedLevelColor) {

View File

@ -60,7 +60,7 @@ export class TbCanvasDigitalGauge {
this.localSettings.gaugeWidthScale = settings.gaugeWidthScale || 0.75; this.localSettings.gaugeWidthScale = settings.gaugeWidthScale || 0.75;
this.localSettings.gaugeColor = settings.gaugeColor || tinycolor(keyColor).setAlpha(0.2).toRgbString(); this.localSettings.gaugeColor = settings.gaugeColor || tinycolor(keyColor).setAlpha(0.2).toRgbString();
convertLevelColorsSettingsToColorProcessor(settings); convertLevelColorsSettingsToColorProcessor(settings, keyColor);
this.localSettings.barColor = settings.barColor; this.localSettings.barColor = settings.barColor;
this.localSettings.showTicks = settings.showTicks || false; this.localSettings.showTicks = settings.showTicks || false;

View File

@ -44,6 +44,8 @@
[previewText]="valuePreviewFn"> [previewText]="valuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="valueColor" <tb-color-settings formControlName="valueColor"
[minValue]="progressBarWidgetSettingsForm.get('tickMin').value"
[maxValue]="progressBarWidgetSettingsForm.get('tickMax').value"
settingsKey="{{'widgets.progress-bar.value' | translate }}"> settingsKey="{{'widgets.progress-bar.value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
@ -78,6 +80,8 @@
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div>{{ 'widgets.progress-bar.bar-color' | translate }}</div> <div>{{ 'widgets.progress-bar.bar-color' | translate }}</div>
<tb-color-settings formControlName="barColor" <tb-color-settings formControlName="barColor"
[minValue]="progressBarWidgetSettingsForm.get('tickMin').value"
[maxValue]="progressBarWidgetSettingsForm.get('tickMax').value"
settingsKey="{{'widgets.progress-bar.bar-color' | translate }}"> settingsKey="{{'widgets.progress-bar.bar-color' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>

View File

@ -38,20 +38,22 @@
<ng-template [ngSwitchCase]="false"> <ng-template [ngSwitchCase]="false">
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical" <div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
(cdkDropListDropped)="rangeDrop($event, 'range')"> (cdkDropListDropped)="rangeDrop($event, 'range')">
<div cdkDrag class="tb-form-row no-padding no-border tb-draggable" <div cdkDrag class="tb-draggable tb-advanced-range-drag"
[formGroup]="rangeFormGroup" [formGroup]="rangeFormGroup"
*ngFor="let rangeFormGroup of rangeListFormGroups; trackBy: trackByRange; let $index = index; last as isLast;" *ngFor="let rangeFormGroup of rangeListFormGroups; trackBy: trackByRange; let $index = index; last as isLast;"
[ngStyle]="!isLast ? {paddingBottom: '8px'} : {}"> [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}">
<div class="range"> <div fxFlex fxLayout="row" fxLayoutAlign="start center">
<div class="range-container"> <div class="tb-form-row range-container">
<div class="tb-value-range-text" translate>widgets.color.from</div> <div class="tb-value-range-text" translate>widgets.color.from</div>
<mat-form-field fxFlex appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" class="center number" subscriptSizing="dynamic">
<input matInput type="number" formControlName="from" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput type="number" formControlName="from" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<div class="tb-value-range-text tb-value-range-text-to" translate>widgets.color.to</div> <div class="tb-value-range-text tb-value-range-text-to" translate>widgets.color.to</div>
<mat-form-field fxFlex appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" class="center number" subscriptSizing="dynamic">
<input matInput type="number" formControlName="to" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput type="number" formControlName="to" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<tb-color-input asBoxInput <tb-color-input asBoxInput
formControlName="color"> formControlName="color">
</tb-color-input> </tb-color-input>
@ -64,15 +66,15 @@
matTooltipPosition="above"> matTooltipPosition="above">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
</button> </button>
<button class="tb-box-button"
mat-icon-button
type="button"
cdkDragHandle
matTooltip="{{ 'action.drag' | translate }}"
matTooltipPosition="above">
<mat-icon>drag_indicator</mat-icon>
</button>
</div> </div>
<button class="tb-box-button"
mat-icon-button
type="button"
cdkDragHandle
matTooltip="{{ 'action.drag' | translate }}"
matTooltipPosition="above">
<mat-icon>drag_indicator</mat-icon>
</button>
</div> </div>
</div> </div>
</ng-template> </ng-template>
@ -103,9 +105,10 @@
</ng-template> </ng-template>
</div> </div>
<button class="tb-add-color-range" <div class="tb-add-color-range">
mat-stroked-button <button mat-stroked-button
(click)="addRange()"> (click)="addRange()">
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
</button> </button>
</div>
</ng-container> </ng-container>

View File

@ -13,24 +13,32 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import '../../../../../../../../scss/constants';
:host { .range-container {
.range { display: flex;
display: flex; flex: 1;
flex: 1; flex-direction: row;
align-items: center; align-items: center;
flex-direction: row; gap: 12px;
padding: 8px;
&-container { margin-right: 12px;
display: flex; border: 1px solid rgba(0, 0, 0, 0.12);
flex: 1; border-radius: 6px;
flex-direction: row; }
align-items: center; .tb-add-color-range {
gap: 12px; button {
padding: 8px; width: 100%;
margin-right: 12px; }
border: 1px solid rgba(0, 0, 0, 0.12); }
border-radius: 6px; .tb-value-range-text {
} width: 64px;
font-size: 14px;
color: rgba(0, 0, 0, 0.38);
@media #{$mat-xs} {
width: auto;
}
&.tb-value-range-text-to {
text-align: center;
} }
} }

View File

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { import {
AbstractControl, AbstractControl,
ControlValueAccessor, ControlValueAccessor,
@ -62,7 +62,8 @@ export function advancedRangeValidator(control: AbstractControl): ValidationErro
useExisting: forwardRef(() => ColorRangeListComponent), useExisting: forwardRef(() => ColorRangeListComponent),
multi: true multi: true
} }
] ],
encapsulation: ViewEncapsulation.None
}) })
export class ColorRangeListComponent implements OnInit, ControlValueAccessor, OnDestroy { export class ColorRangeListComponent implements OnInit, ControlValueAccessor, OnDestroy {
@ -108,6 +109,9 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
this.colorRangeListFormGroup.valueChanges.pipe( this.colorRangeListFormGroup.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe(() => this.updateModel()); ).subscribe(() => this.updateModel());
this.colorRangeListFormGroup.get('advancedMode').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => Promise.resolve().then(() => this.popover?.updatePosition()));
} }
ngOnDestroy() { ngOnDestroy() {
@ -171,6 +175,7 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
public removeAdvancedRange(index: number) { public removeAdvancedRange(index: number) {
(this.colorRangeListFormGroup.get('rangeAdvanced') as UntypedFormArray).removeAt(index); (this.colorRangeListFormGroup.get('rangeAdvanced') as UntypedFormArray).removeAt(index);
Promise.resolve().then(() => this.popover?.updatePosition());
} }
get advancedRangeFormArray(): UntypedFormArray { get advancedRangeFormArray(): UntypedFormArray {
@ -184,7 +189,7 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
removeRange(index: number) { removeRange(index: number) {
this.rangeListFormArray.removeAt(index); this.rangeListFormArray.removeAt(index);
this.colorRangeListFormGroup.markAsDirty(); this.colorRangeListFormGroup.markAsDirty();
setTimeout(() => {this.popover?.updatePosition();}, 0); Promise.resolve().then(() => this.popover?.updatePosition());
} }
rangeDrop(event: CdkDragDrop<string[]>, range: string) { rangeDrop(event: CdkDragDrop<string[]>, range: string) {
@ -207,6 +212,7 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
const advancedRangeColorsArray = this.colorRangeListFormGroup.get('rangeAdvanced') as UntypedFormArray; const advancedRangeColorsArray = this.colorRangeListFormGroup.get('rangeAdvanced') as UntypedFormArray;
const advancedRangeColorControl = this.fb.control(advancedRange, [advancedRangeValidator]); const advancedRangeColorControl = this.fb.control(advancedRange, [advancedRangeValidator]);
advancedRangeColorsArray.push(advancedRangeColorControl); advancedRangeColorsArray.push(advancedRangeColorControl);
Promise.resolve().then(() => this.popover?.updatePosition());
} }
addRange() { addRange() {
@ -218,7 +224,7 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
}; };
this.rangeListFormArray.push(this.colorRangeControl(newRange)); this.rangeListFormArray.push(this.colorRangeControl(newRange));
this.colorRangeListFormGroup.markAsDirty(); this.colorRangeListFormGroup.markAsDirty();
setTimeout(() => {this.popover?.updatePosition();}, 0); Promise.resolve().then(() => this.popover?.updatePosition());
} }
} }

View File

@ -55,17 +55,6 @@
} }
.tb-form-row { .tb-form-row {
height: auto; height: auto;
.tb-value-range-text {
width: 64px;
font-size: 14px;
color: rgba(0, 0, 0, 0.38);
@media #{$mat-xs} {
width: auto;
}
&.tb-value-range-text-to {
text-align: center;
}
}
} }
button.mat-mdc-button-base.tb-add-color-range { button.mat-mdc-button-base.tb-add-color-range {
&:not(:disabled) { &:not(:disabled) {

View File

@ -20,7 +20,8 @@ import {
ColorSettings, ColorSettings,
ColorType, ColorType,
colorTypeTranslations, colorTypeTranslations,
defaultGradient defaultGradient,
defaultRange
} from '@shared/models/widget-settings.models'; } from '@shared/models/widget-settings.models';
import { TbPopoverComponent } from '@shared/components/popover.component'; import { TbPopoverComponent } from '@shared/components/popover.component';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
@ -102,12 +103,12 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit
type: [this.colorSettings?.type || ColorType.constant, []], type: [this.colorSettings?.type || ColorType.constant, []],
color: [this.colorSettings?.color, []], color: [this.colorSettings?.color, []],
gradient: [this.colorSettings?.gradient || defaultGradient(this.minValue, this.maxValue), []], gradient: [this.colorSettings?.gradient || defaultGradient(this.minValue, this.maxValue), []],
rangeList: [this.colorSettings?.rangeList, []], rangeList: [this.colorSettings?.rangeList || defaultRange(), []],
colorFunction: [this.colorSettings?.colorFunction, []] colorFunction: [this.colorSettings?.colorFunction, []]
} }
); );
this.colorSettingsFormGroup.get('type').valueChanges.subscribe(() => { this.colorSettingsFormGroup.get('type').valueChanges.subscribe(() => {
setTimeout(() => {this.popover?.updatePosition();}, 0); Promise.resolve().then(() => this.popover?.updatePosition());
}); });
} }

View File

@ -103,11 +103,11 @@ export class ColorSettingsComponent implements OnInit, ControlValueAccessor, OnD
@Input() @Input()
@coerceNumber() @coerceNumber()
minValue: number; minValue = 0;
@Input() @Input()
@coerceNumber() @coerceNumber()
maxValue: number; maxValue = 100;
colorType = ColorType; colorType = ColorType;

View File

@ -16,11 +16,36 @@
@import "../../../../../../../../scss/constants"; @import "../../../../../../../../scss/constants";
:host { :host {
overflow: auto; overflow: auto;
height: 100%; height: 100%;
max-height: 420px; max-height: 420px;
.gradient-preview {
width: 100%;
padding: 40px 12px 0;
.gradient-background {
position: relative;
height: 56px;
border-radius: 8px;
}
}
.gradient-settings {
flex: 1;
gap: 16px;
display: flex;
flex-direction: column;
}
.tb-add-gradient {
margin-right: 92px;
@media #{$mat-lt-lg} {
margin-right: 52px;
}
}
}
::ng-deep {
.gradient { .gradient {
display: flex; display: flex;
flex: 1; flex: 1;
@ -67,32 +92,6 @@
} }
} }
} }
.gradient-preview {
width: 100%;
padding: 40px 12px 0;
.gradient-background {
position: relative;
height: 56px;
border-radius: 8px;
}
}
.gradient-settings {
flex: 1;
gap: 16px;
display: flex;
flex-direction: column;
}
.tb-add-gradient {
margin-right: 92px;
@media #{$mat-lt-lg} {
margin-right: 52px;
}
}
}
::ng-deep {
.gradient-background { .gradient-background {
.pointer { .pointer {
position: absolute; position: absolute;

View File

@ -31,7 +31,7 @@ import { takeUntil } from 'rxjs/operators';
import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean, coerceNumber } from '@shared/decorators/coercion';
import { isDefinedAndNotNull } from '@core/utils'; import { isDefinedAndNotNull } from '@core/utils';
import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models';
import { Datasource } from '@shared/models/widget.models'; import { Datasource } from '@shared/models/widget.models';
@ -71,10 +71,12 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro
datasource: Datasource; datasource: Datasource;
@Input() @Input()
minValue: string; @coerceNumber()
minValue: number;
@Input() @Input()
maxValue: string; @coerceNumber()
maxValue: number;
@Input() @Input()
@coerceBoolean() @coerceBoolean()
@ -115,6 +117,9 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro
this.gradientFormGroup.valueChanges.pipe( this.gradientFormGroup.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe(() => this.updateModel()); ).subscribe(() => this.updateModel());
this.gradientFormGroup.get('advancedMode').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => Promise.resolve().then(() => this.popover?.updatePosition()));
} }
ngOnDestroy() { ngOnDestroy() {
@ -228,7 +233,7 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro
this.gradientListFormArray.removeAt(index); this.gradientListFormArray.removeAt(index);
} }
this.gradientFormGroup.markAsDirty(); this.gradientFormGroup.markAsDirty();
setTimeout(() => {this.popover?.updatePosition();}, 0); Promise.resolve().then(() => this.popover?.updatePosition());
} }
gradientDrop(event: CdkDragDrop<string[]>, advanced = false) { gradientDrop(event: CdkDragDrop<string[]>, advanced = false) {
@ -247,7 +252,7 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro
this.gradientListFormArray.push(this.colorGradientControl('rgba(0,0,0,0.87)')); this.gradientListFormArray.push(this.colorGradientControl('rgba(0,0,0,0.87)'));
} }
this.gradientFormGroup.markAsDirty(); this.gradientFormGroup.markAsDirty();
setTimeout(() => {this.popover?.updatePosition();}, 0); Promise.resolve().then(() => this.popover?.updatePosition());
} }
updateModel() { updateModel() {

View File

@ -41,8 +41,22 @@
<div class="tb-form-row space-between column-xs"> <div class="tb-form-row space-between column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showMinMax"> <mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showMinMax">
{{ 'widgets.gauge.min-and-max-value' | translate }} {{ 'widgets.gauge.min-and-max-label' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<tb-font-settings formControlName="minMaxFont"
disabledLineHeight
[previewText]="previewFn">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="minMaxColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row space-between column-xs">
<div class="fixed-title-width">{{ 'widgets.gauge.min-and-max-value' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div class="tb-small-label" translate>widgets.gauge.min-value-short</div> <div class="tb-small-label" translate>widgets.gauge.min-value-short</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
@ -52,14 +66,6 @@
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="maxValue" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="maxValue" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<tb-font-settings formControlName="minMaxFont"
disabledLineHeight
[previewText]="previewFn">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="minMaxColor">
</tb-color-input>
</div> </div>
</div> </div>
@ -160,14 +166,6 @@
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
<div class="tb-form-row space-between">
<div class="fixed-title-width">{{ 'widgets.gauge.default-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="defaultColor">
</tb-color-input>
</div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div class="fixed-title-width">{{ 'widgets.gauge.gauge-bar-background' | translate }}</div> <div class="fixed-title-width">{{ 'widgets.gauge.gauge-bar-background' | translate }}</div>
<tb-color-input asBoxInput <tb-color-input asBoxInput
@ -180,6 +178,7 @@
<div class="fixed-title-width">{{ 'widgets.gauge.bar-color' | translate }}</div> <div class="fixed-title-width">{{ 'widgets.gauge.bar-color' | translate }}</div>
<tb-color-settings formControlName="barColor" <tb-color-settings formControlName="barColor"
rangeAdvancedMode rangeAdvancedMode
gradientAdvancedMode
[minValue]="digitalGaugeWidgetSettingsForm.get('minValue').value" [minValue]="digitalGaugeWidgetSettingsForm.get('minValue').value"
[maxValue]="digitalGaugeWidgetSettingsForm.get('maxValue').value" [maxValue]="digitalGaugeWidgetSettingsForm.get('maxValue').value"
[aliasController]="aliasController" [aliasController]="aliasController"
@ -222,13 +221,23 @@
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical" <div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
(cdkDropListDropped)="tickValueDrop($event)"> (cdkDropListDropped)="tickValueDrop($event)">
<div cdkDrag class="tb-draggable" *ngFor="let tickValueControl of tickValuesFormArray().controls; trackBy: trackByTickValue; <div cdkDrag class="tb-draggable" *ngFor="let tickValueControl of tickValuesFormArray().controls; trackBy: trackByTickValue;
let $index = index; last as isLast;" fxLayout="column" [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}"> let $index = index; last as isLast;" fxLayout="row" [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}">
<tb-tick-value [formControl]="tickValueControl" <tb-tick-value fxFlex
[formControl]="tickValueControl"
[aliasController]="aliasController" [aliasController]="aliasController"
[dataKeyCallbacks]="dataKeyCallbacks" [dataKeyCallbacks]="dataKeyCallbacks"
[datasource]="datasource" [datasource]="datasource"
(removeTickValue)="removeTickValue($index)"> (removeTickValue)="removeTickValue($index)">
</tb-tick-value> </tb-tick-value>
<button class="tb-box-button"
fxHide.lt-lg
mat-icon-button
type="button"
cdkDragHandle
matTooltip="{{ 'action.drag' | translate }}"
matTooltipPosition="above">
<mat-icon>drag_indicator</mat-icon>
</button>
</div> </div>
</div> </div>
<div *ngIf="!tickValuesFormArray().controls.length"> <div *ngIf="!tickValuesFormArray().controls.length">

View File

@ -138,7 +138,7 @@ export class DigitalGaugeWidgetSettingsComponent extends WidgetSettingsComponent
protected onSettingsSet(settings: WidgetSettings) { protected onSettingsSet(settings: WidgetSettings) {
if (!settings.barColor) { if (!settings.barColor) {
settings.barColor = constantColor(settings.gaugeColor); settings.barColor = constantColor(settings.defaultColor || '#2196f3');
if (settings.fixedLevelColors.length) { if (settings.fixedLevelColors.length) {
settings.barColor.rangeList = { settings.barColor.rangeList = {
@ -192,7 +192,6 @@ export class DigitalGaugeWidgetSettingsComponent extends WidgetSettingsComponent
dashThickness: [settings.dashThickness, [Validators.min(0)]], dashThickness: [settings.dashThickness, [Validators.min(0)]],
roundedLineCap: [settings.roundedLineCap, []], roundedLineCap: [settings.roundedLineCap, []],
defaultColor: [settings.defaultColor, []],
gaugeColor: [settings.gaugeColor, []], gaugeColor: [settings.gaugeColor, []],
barColor: [settings.barColor], barColor: [settings.barColor],

View File

@ -63,8 +63,6 @@
<tb-color-settings formControlName="batteryLevelColor" <tb-color-settings formControlName="batteryLevelColor"
rangeAdvancedMode rangeAdvancedMode
gradientAdvancedMode gradientAdvancedMode
minValue="0"
maxValue="100"
[aliasController]="aliasController" [aliasController]="aliasController"
[dataKeyCallbacks]="dataKeyCallbacks" [dataKeyCallbacks]="dataKeyCallbacks"
[datasource]="datasource" [datasource]="datasource"
@ -76,8 +74,6 @@
<tb-color-settings formControlName="batteryShapeColor" <tb-color-settings formControlName="batteryShapeColor"
rangeAdvancedMode rangeAdvancedMode
gradientAdvancedMode gradientAdvancedMode
minValue="0"
maxValue="100"
[aliasController]="aliasController" [aliasController]="aliasController"
[dataKeyCallbacks]="dataKeyCallbacks" [dataKeyCallbacks]="dataKeyCallbacks"
[datasource]="datasource" [datasource]="datasource"

View File

@ -297,6 +297,12 @@ export const defaultGradient = (minValue?: number, maxValue?: number): ColorGrad
maxValue: isDefinedAndNotNull(maxValue) ? maxValue : 100 maxValue: isDefinedAndNotNull(maxValue) ? maxValue : 100
}); });
export const defaultRange = (): ColorRangeSettings => ({
advancedMode: false,
range: [],
rangeAdvanced: []
});
const updateGradientMinMaxValues = (colorSettings: ColorSettings, minValue?: number, maxValue?: number): void => { const updateGradientMinMaxValues = (colorSettings: ColorSettings, minValue?: number, maxValue?: number): void => {
if (isDefinedAndNotNull(colorSettings.gradient)) { if (isDefinedAndNotNull(colorSettings.gradient)) {
if (isDefinedAndNotNull(minValue)) { if (isDefinedAndNotNull(minValue)) {
@ -431,7 +437,7 @@ export abstract class AdvancedModeColorProcessor extends ColorProcessor {
protected constructor(protected settings: ColorSettings, protected constructor(protected settings: ColorSettings,
protected ctx: WidgetContext) { protected ctx: WidgetContext) {
super(settings); super(settings);
this.advancedMode = this.getCurrentConfig().advancedMode; this.advancedMode = this.getCurrentConfig()?.advancedMode;
if (this.advancedMode) { if (this.advancedMode) {
createValueSubscription( createValueSubscription(
this.ctx, this.ctx,
@ -529,7 +535,7 @@ class RangeColorProcessor extends AdvancedModeColorProcessor {
this.settings.rangeList.range as Array<ColorRange>; this.settings.rangeList.range as Array<ColorRange>;
} }
if (rangeList.length && isDefinedAndNotNull(value) && isNumeric(value)) { if (rangeList?.length && isDefinedAndNotNull(value) && isNumeric(value)) {
const num = Number(value); const num = Number(value);
for (const range of rangeList) { for (const range of rangeList) {
if (advancedMode ? if (advancedMode ?
@ -571,7 +577,8 @@ class GradientColorProcessor extends AdvancedModeColorProcessor {
update(value: any): void { update(value: any): void {
const progress = this.calculateProgress(+value, this.minValue, this.maxValue); const progress = this.calculateProgress(+value, this.minValue, this.maxValue);
super.update(progress); super.update(progress);
this.color = this.getGradientColor(progress, this.settings.gradient.gradient); this.color = this.getGradientColor(progress,
this.advancedMode ? this.settings.gradient.gradientAdvanced : this.settings.gradient.gradient);
} }
updatedAdvancedData(data: Array<DatasourceData>) { updatedAdvancedData(data: Array<DatasourceData>) {

View File

@ -6232,6 +6232,7 @@
"gauge-bar-background": "Gauge bar background", "gauge-bar-background": "Gauge bar background",
"bar-color": "Bar color", "bar-color": "Bar color",
"min-and-max-value": "Min and max value", "min-and-max-value": "Min and max value",
"min-and-max-label": "Min and max label",
"font": "Font", "font": "Font",
"tick-width-and-color": "Tick width and color" "tick-width-and-color": "Tick width and color"
}, },