UI: Implement 'copy color settings from' for color settings component.

This commit is contained in:
Igor Kulikov 2023-10-09 18:01:39 +03:00
parent 00a09cd80b
commit b45b5827a9
16 changed files with 121 additions and 45 deletions

View File

@ -61,7 +61,7 @@
</tb-font-settings> </tb-font-settings>
</div> </div>
<div class="tb-color-field"> <div class="tb-color-field">
<tb-color-settings formControlName="color"> <tb-color-settings formControlName="color" settingsKey="{{ (index+1) }}. {{ aggregatedValueCardKeyPositionTranslationMap.get(keyRowFormGroup.get('position').value) | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
<div class="tb-arrow-field"> <div class="tb-arrow-field">

View File

@ -87,6 +87,9 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
@Input() @Input()
keyName: string; keyName: string;
@Input()
index: number;
@Output() @Output()
keyRemoved = new EventEmitter(); keyRemoved = new EventEmitter();

View File

@ -32,6 +32,7 @@
<div *ngFor="let keyControl of keysFormArray().controls; trackBy: trackByKey; let $index = index;"> <div *ngFor="let keyControl of keysFormArray().controls; trackBy: trackByKey; let $index = index;">
<tb-aggregated-data-key-row fxFlex <tb-aggregated-data-key-row fxFlex
[formControl]="keyControl" [formControl]="keyControl"
[index]="$index"
[datasourceType]="datasourceType" [datasourceType]="datasourceType"
[keyName]="keyName" [keyName]="keyName"
(keyRemoved)="removeKey($index)"> (keyRemoved)="removeKey($index)">

View File

@ -56,7 +56,7 @@
<tb-font-settings formControlName="labelFont" <tb-font-settings formControlName="labelFont"
[previewText]="valueCardWidgetConfigForm.get('label').value"> [previewText]="valueCardWidgetConfigForm.get('label').value">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="labelColor"> <tb-color-settings formControlName="labelColor" settingsKey="{{'widgets.value-card.label' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -74,7 +74,7 @@
[color]="valueCardWidgetConfigForm.get('iconColor').value?.color" [color]="valueCardWidgetConfigForm.get('iconColor').value?.color"
formControlName="icon"> formControlName="icon">
</tb-material-icon-select> </tb-material-icon-select>
<tb-color-settings formControlName="iconColor"> <tb-color-settings formControlName="iconColor" settingsKey="{{'widgets.value-card.icon' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -89,7 +89,7 @@
<tb-font-settings formControlName="valueFont" <tb-font-settings formControlName="valueFont"
[previewText]="valuePreviewFn"> [previewText]="valuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="valueColor"> <tb-color-settings formControlName="valueColor" settingsKey="{{'widgets.value-card.value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -102,7 +102,7 @@
<tb-font-settings formControlName="dateFont" <tb-font-settings formControlName="dateFont"
[previewText]="datePreviewFn"> [previewText]="datePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="dateColor"> <tb-color-settings formControlName="dateColor" settingsKey="{{'widgets.value-card.date' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>

View File

@ -91,18 +91,18 @@
[autoScale]="batteryLevelWidgetConfigForm.get('autoScaleValueSize').value" [autoScale]="batteryLevelWidgetConfigForm.get('autoScaleValueSize').value"
[previewText]="valuePreviewFn"> [previewText]="valuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="valueColor"> <tb-color-settings formControlName="valueColor" settingsKey="{{'widgets.battery-level.value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div>{{ 'widgets.battery-level.battery-level-color' | translate }}</div> <div>{{ 'widgets.battery-level.battery-level-color' | translate }}</div>
<tb-color-settings formControlName="batteryLevelColor"> <tb-color-settings formControlName="batteryLevelColor" settingsKey="{{'widgets.battery-level.battery-level-color' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div>{{ 'widgets.battery-level.battery-shape-color' | translate }}</div> <div>{{ 'widgets.battery-level.battery-shape-color' | translate }}</div>
<tb-color-settings formControlName="batteryShapeColor"> <tb-color-settings formControlName="batteryShapeColor" settingsKey="{{'widgets.battery-level.battery-shape-color' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">

View File

@ -49,7 +49,7 @@
[previewText]="centerValuePreviewFn"> [previewText]="centerValuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings *ngIf="!windSpeedDirectionWidgetConfigForm.get('centerValueKey').value" <tb-color-settings *ngIf="!windSpeedDirectionWidgetConfigForm.get('centerValueKey').value"
formControlName="centerValueColor"> formControlName="centerValueColor" settingsKey="{{'widgets.wind-speed-direction.wind-direction' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -71,7 +71,7 @@
[previewText]="centerValuePreviewFn"> [previewText]="centerValuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings *ngIf="windSpeedDirectionWidgetConfigForm.get('centerValueKey').value" <tb-color-settings *ngIf="windSpeedDirectionWidgetConfigForm.get('centerValueKey').value"
formControlName="centerValueColor"> formControlName="centerValueColor" settingsKey="{{'widgets.wind-speed-direction.center-value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>

View File

@ -36,7 +36,7 @@
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div>{{ 'widgets.aggregated-value-card.color' | translate }}</div> <div>{{ 'widgets.aggregated-value-card.color' | translate }}</div>
<tb-color-settings formControlName="color"> <tb-color-settings formControlName="color" settingsKey="{{'widgets.aggregated-value-card.color' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
<div class="tb-form-row"> <div class="tb-form-row">

View File

@ -41,7 +41,7 @@
<tb-font-settings formControlName="labelFont" <tb-font-settings formControlName="labelFont"
[previewText]="label"> [previewText]="label">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="labelColor"> <tb-color-settings formControlName="labelColor" settingsKey="{{'widgets.value-card.label' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -59,7 +59,7 @@
[color]="valueCardWidgetSettingsForm.get('iconColor').value?.color" [color]="valueCardWidgetSettingsForm.get('iconColor').value?.color"
formControlName="icon"> formControlName="icon">
</tb-material-icon-select> </tb-material-icon-select>
<tb-color-settings formControlName="iconColor"> <tb-color-settings formControlName="iconColor" settingsKey="{{'widgets.value-card.icon' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -69,7 +69,7 @@
<tb-font-settings formControlName="valueFont" <tb-font-settings formControlName="valueFont"
[previewText]="valuePreviewFn"> [previewText]="valuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="valueColor"> <tb-color-settings formControlName="valueColor" settingsKey="{{'widgets.value-card.value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -82,7 +82,7 @@
<tb-font-settings formControlName="dateFont" <tb-font-settings formControlName="dateFont"
[previewText]="datePreviewFn"> [previewText]="datePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="dateColor"> <tb-color-settings formControlName="dateColor" settingsKey="{{'widgets.value-card.date' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>

View File

@ -40,6 +40,22 @@
<ng-container *ngTemplateOutlet="function"></ng-container> <ng-container *ngTemplateOutlet="function"></ng-container>
</div> </div>
<div class="tb-color-settings-panel-buttons"> <div class="tb-color-settings-panel-buttons">
<button *ngIf="settingsComponents?.length"
#copySettingsButton
mat-stroked-button
color="primary"
type="button"
[matMenuTriggerFor]="settingsSourcesMenu" [matMenuTriggerData]="{menuWidth: copySettingsButton._elementRef.nativeElement.clientWidth}">
{{ 'widgets.color.copy-color-settings-from' | translate }}
</button>
<mat-menu #settingsSourcesMenu="matMenu">
<ng-template matMenuContent let-menuWidth="menuWidth">
<div [style.min-width.px]="menuWidth">
<button mat-menu-item *ngFor="let comp of settingsComponents" (click)="copyColorSettings(comp)">{{ comp.settingsKey }}</button>
</div>
</ng-template>
</mat-menu>
<span fxFlex></span>
<button mat-button <button mat-button
color="primary" color="primary"
type="button" type="button"

View File

@ -16,27 +16,14 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { import { ColorRange, ColorSettings, ColorType, colorTypeTranslations } from '@shared/models/widget-settings.models';
ColorRange,
ColorSettings,
ColorType,
colorTypeTranslations
} from '@shared/models/widget-settings.models';
import { TbPopoverComponent } from '@shared/components/popover.component'; import { TbPopoverComponent } from '@shared/components/popover.component';
import { import { AbstractControl, FormGroup, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
AbstractControl,
FormControl,
FormGroup,
UntypedFormArray,
UntypedFormBuilder,
UntypedFormGroup
} from '@angular/forms';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { Datasource, DatasourceType } from '@shared/models/widget.models';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { ColorSettingsComponent } from '@home/components/widget/lib/settings/common/color-settings.component';
@Component({ @Component({
selector: 'tb-color-settings-panel', selector: 'tb-color-settings-panel',
@ -53,6 +40,9 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit
@Input() @Input()
popover: TbPopoverComponent<ColorSettingsPanelComponent>; popover: TbPopoverComponent<ColorSettingsPanelComponent>;
@Input()
settingsComponents: ColorSettingsComponent[];
@Output() @Output()
colorSettingsApplied = new EventEmitter<ColorSettings>(); colorSettingsApplied = new EventEmitter<ColorSettings>();
@ -121,6 +111,19 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit
setTimeout(() => {this.popover?.updatePosition();}, 0); setTimeout(() => {this.popover?.updatePosition();}, 0);
} }
copyColorSettings(comp: ColorSettingsComponent) {
const sourceSettings = deepClone(comp.modelValue);
this.colorSettings = sourceSettings;
this.colorSettingsFormGroup.patchValue({
type: this.colorSettings.type,
color: this.colorSettings.color,
colorFunction: this.colorSettings.colorFunction
}, {emitEvent: false});
this.colorSettingsFormGroup.setControl('rangeList',
this.fb.array((this.colorSettings.rangeList || []).map(r => this.colorRangeControl(r))), {emitEvent: false});
this.colorSettingsFormGroup.markAsDirty();
}
cancel() { cancel() {
this.popover?.hide(); this.popover?.hide();
} }

View File

@ -14,7 +14,16 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } from '@angular/core'; import {
Component,
forwardRef,
Injectable,
Input,
OnDestroy,
OnInit,
Renderer2,
ViewContainerRef
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { ColorSettings, ColorType, ComponentStyle } from '@shared/models/widget-settings.models'; import { ColorSettings, ColorType, ComponentStyle } from '@shared/models/widget-settings.models';
import { MatButton } from '@angular/material/button'; import { MatButton } from '@angular/material/button';
@ -23,6 +32,33 @@ import {
ColorSettingsPanelComponent ColorSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/color-settings-panel.component'; } from '@home/components/widget/lib/settings/common/color-settings-panel.component';
@Injectable()
export class ColorSettingsComponentService {
private colorSettingsComponents = new Set<ColorSettingsComponent>();
constructor() {}
public registerColorSettingsComponent(comp: ColorSettingsComponent) {
this.colorSettingsComponents.add(comp);
}
public unregisterColorSettingsComponent(comp: ColorSettingsComponent) {
this.colorSettingsComponents.delete(comp);
}
public getOtherColorSettingsComponents(comp: ColorSettingsComponent): ColorSettingsComponent[] {
const result: ColorSettingsComponent[] = [];
for (const component of this.colorSettingsComponents.values()) {
if (component.settingsKey && component.modelValue && component !== comp) {
result.push(component);
}
}
return result;
}
}
@Component({ @Component({
selector: 'tb-color-settings', selector: 'tb-color-settings',
templateUrl: './color-settings.component.html', templateUrl: './color-settings.component.html',
@ -35,11 +71,14 @@ import {
} }
] ]
}) })
export class ColorSettingsComponent implements OnInit, ControlValueAccessor { export class ColorSettingsComponent implements OnInit, ControlValueAccessor, OnDestroy {
@Input() @Input()
disabled: boolean; disabled: boolean;
@Input()
settingsKey: string;
colorType = ColorType; colorType = ColorType;
modelValue: ColorSettings; modelValue: ColorSettings;
@ -50,9 +89,15 @@ export class ColorSettingsComponent implements OnInit, ControlValueAccessor {
constructor(private popoverService: TbPopoverService, constructor(private popoverService: TbPopoverService,
private renderer: Renderer2, private renderer: Renderer2,
private viewContainerRef: ViewContainerRef) {} private viewContainerRef: ViewContainerRef,
private colorSettingsComponentService: ColorSettingsComponentService) {}
ngOnInit(): void { ngOnInit(): void {
this.colorSettingsComponentService.registerColorSettingsComponent(this);
}
ngOnDestroy() {
this.colorSettingsComponentService.unregisterColorSettingsComponent(this);
} }
registerOnChange(fn: any): void { registerOnChange(fn: any): void {
@ -81,7 +126,8 @@ export class ColorSettingsComponent implements OnInit, ControlValueAccessor {
this.popoverService.hidePopover(trigger); this.popoverService.hidePopover(trigger);
} else { } else {
const ctx: any = { const ctx: any = {
colorSettings: this.modelValue colorSettings: this.modelValue,
settingsComponents: this.colorSettingsComponentService.getOtherColorSettingsComponents(this)
}; };
const colorSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, const colorSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, ColorSettingsPanelComponent, 'left', true, null, this.viewContainerRef, ColorSettingsPanelComponent, 'left', true, null,

View File

@ -42,7 +42,7 @@
<tb-font-settings formControlName="labelFont" <tb-font-settings formControlName="labelFont"
[previewText]="countWidgetConfigForm.get('label').value"> [previewText]="countWidgetConfigForm.get('label').value">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="labelColor"> <tb-color-settings formControlName="labelColor" settingsKey="{{'widgets.count.label' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -63,7 +63,7 @@
: ''" : ''"
formControlName="icon"> formControlName="icon">
</tb-material-icon-select> </tb-material-icon-select>
<tb-color-settings formControlName="iconColor"> <tb-color-settings formControlName="iconColor" settingsKey="{{'widgets.count.icon' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -76,7 +76,7 @@
<input matInput type="number" min="0" formControlName="iconBackgroundSize" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput type="number" min="0" formControlName="iconBackgroundSize" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<tb-css-unit-select fxFlex formControlName="iconBackgroundSizeUnit"></tb-css-unit-select> <tb-css-unit-select fxFlex formControlName="iconBackgroundSizeUnit"></tb-css-unit-select>
<tb-color-settings formControlName="iconBackgroundColor"> <tb-color-settings formControlName="iconBackgroundColor" settingsKey="{{'widgets.count.icon-background' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
@ -86,7 +86,7 @@
<tb-font-settings formControlName="valueFont" <tb-font-settings formControlName="valueFont"
previewText="10"> previewText="10">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="valueColor"> <tb-color-settings formControlName="valueColor" settingsKey="{{'widgets.count.value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>

View File

@ -27,7 +27,10 @@ import {
} from '@home/components/widget/lib/settings/common/image-cards-select.component'; } from '@home/components/widget/lib/settings/common/image-cards-select.component';
import { FontSettingsComponent } from '@home/components/widget/lib/settings/common/font-settings.component'; import { FontSettingsComponent } from '@home/components/widget/lib/settings/common/font-settings.component';
import { FontSettingsPanelComponent } from '@home/components/widget/lib/settings/common/font-settings-panel.component'; import { FontSettingsPanelComponent } from '@home/components/widget/lib/settings/common/font-settings-panel.component';
import { ColorSettingsComponent } from '@home/components/widget/lib/settings/common/color-settings.component'; import {
ColorSettingsComponent,
ColorSettingsComponentService
} from '@home/components/widget/lib/settings/common/color-settings.component';
import { import {
ColorSettingsPanelComponent ColorSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/color-settings-panel.component'; } from '@home/components/widget/lib/settings/common/color-settings-panel.component';
@ -83,6 +86,9 @@ import {
LegendConfigComponent, LegendConfigComponent,
WidgetFontComponent, WidgetFontComponent,
CountWidgetSettingsComponent CountWidgetSettingsComponent
],
providers: [
ColorSettingsComponentService
] ]
}) })
export class WidgetSettingsCommonModule { export class WidgetSettingsCommonModule {

View File

@ -40,18 +40,18 @@
[autoScale]="batteryLevelWidgetSettingsForm.get('autoScaleValueSize').value" [autoScale]="batteryLevelWidgetSettingsForm.get('autoScaleValueSize').value"
[previewText]="valuePreviewFn"> [previewText]="valuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="valueColor"> <tb-color-settings formControlName="valueColor" settingsKey="{{'widgets.battery-level.value' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div>{{ 'widgets.battery-level.battery-level-color' | translate }}</div> <div>{{ 'widgets.battery-level.battery-level-color' | translate }}</div>
<tb-color-settings formControlName="batteryLevelColor"> <tb-color-settings formControlName="batteryLevelColor" settingsKey="{{'widgets.battery-level.battery-level-color' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div>{{ 'widgets.battery-level.battery-shape-color' | translate }}</div> <div>{{ 'widgets.battery-level.battery-shape-color' | translate }}</div>
<tb-color-settings formControlName="batteryShapeColor"> <tb-color-settings formControlName="batteryShapeColor" settingsKey="{{'widgets.battery-level.battery-shape-color' | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">

View File

@ -36,7 +36,7 @@
[initialPreviewStyle]="{ color: windSpeedDirectionWidgetSettingsForm.get('centerValueColor').value?.color }" [initialPreviewStyle]="{ color: windSpeedDirectionWidgetSettingsForm.get('centerValueColor').value?.color }"
[previewText]="centerValuePreviewFn"> [previewText]="centerValuePreviewFn">
</tb-font-settings> </tb-font-settings>
<tb-color-settings formControlName="centerValueColor"> <tb-color-settings formControlName="centerValueColor" settingsKey="{{ (hasCenterValue ? 'widgets.wind-speed-direction.center-value' : 'widgets.wind-speed-direction.wind-direction') | translate }}">
</tb-color-settings> </tb-color-settings>
</div> </div>
</div> </div>

View File

@ -5201,7 +5201,8 @@
"value-range": "Value range", "value-range": "Value range",
"from": "From", "from": "From",
"to": "To", "to": "To",
"color-function": "Color function" "color-function": "Color function",
"copy-color-settings-from": "Copy color settings from"
}, },
"dashboard-state": { "dashboard-state": {
"dashboard-state-settings": "Dashboard state settings", "dashboard-state-settings": "Dashboard state settings",