Merge pull request #9484 from ArtemDzhereleiko/AD/imp/color-range-setting
Color range setting
This commit is contained in:
		
						commit
						410f67a55c
					
				@ -0,0 +1,50 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2023 The Thingsboard Authors
 | 
			
		||||
 | 
			
		||||
    Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
    you may not use this file except in compliance with the License.
 | 
			
		||||
    You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
        http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
    distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
    See the License for the specific language governing permissions and
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<div *ngIf="panelTitle" class="tb-form-panel-title">{{ panelTitle }}</div>
 | 
			
		||||
<div class="tb-color-ranges"  [formGroup]="colorRangeListFormGroup">
 | 
			
		||||
  <div class="tb-form-row no-padding no-border" [formGroup]="rangeFormGroup" *ngFor="let rangeFormGroup of rangeListFormGroups; trackBy: trackByRange; let $index = index;">
 | 
			
		||||
    <div fxFlex fxLayout="row" fxLayoutGap="24px">
 | 
			
		||||
      <div fxFlex fxLayout="row" fxLayoutGap="12px" fxLayoutAlign="start center">
 | 
			
		||||
        <div class="tb-value-range-text" translate>widgets.color.from</div>
 | 
			
		||||
        <mat-form-field fxFlex appearance="outline" class="center number" subscriptSizing="dynamic">
 | 
			
		||||
          <input matInput type="number" formControlName="from" placeholder="{{ 'widget-config.set' | translate }}">
 | 
			
		||||
        </mat-form-field>
 | 
			
		||||
        <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">
 | 
			
		||||
          <input matInput type="number" formControlName="to" placeholder="{{ 'widget-config.set' | translate }}">
 | 
			
		||||
        </mat-form-field>
 | 
			
		||||
        <tb-color-input asBoxInput
 | 
			
		||||
                        formControlName="color">
 | 
			
		||||
        </tb-color-input>
 | 
			
		||||
      </div>
 | 
			
		||||
      <button type="button"
 | 
			
		||||
              mat-icon-button
 | 
			
		||||
              class="tb-box-button"
 | 
			
		||||
              (click)="removeRange($index)"
 | 
			
		||||
              matTooltip="{{ 'action.remove' | translate }}"
 | 
			
		||||
              matTooltipPosition="above">
 | 
			
		||||
        <mat-icon>delete</mat-icon>
 | 
			
		||||
      </button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
<button class="tb-add-color-range"
 | 
			
		||||
        mat-stroked-button
 | 
			
		||||
        (click)="addRange()">
 | 
			
		||||
  <mat-icon>add</mat-icon>
 | 
			
		||||
</button>
 | 
			
		||||
@ -0,0 +1,136 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2023 The Thingsboard Authors
 | 
			
		||||
///
 | 
			
		||||
/// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
/// you may not use this file except in compliance with the License.
 | 
			
		||||
/// You may obtain a copy of the License at
 | 
			
		||||
///
 | 
			
		||||
///     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
///
 | 
			
		||||
/// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
/// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
/// See the License for the specific language governing permissions and
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
 | 
			
		||||
import {
 | 
			
		||||
  AbstractControl,
 | 
			
		||||
  ControlValueAccessor,
 | 
			
		||||
  FormGroup,
 | 
			
		||||
  NG_VALUE_ACCESSOR,
 | 
			
		||||
  UntypedFormArray,
 | 
			
		||||
  UntypedFormBuilder,
 | 
			
		||||
  UntypedFormGroup
 | 
			
		||||
} from '@angular/forms';
 | 
			
		||||
import { ColorRange } from '@shared/models/widget-settings.models';
 | 
			
		||||
import { TbPopoverComponent } from '@shared/components/popover.component';
 | 
			
		||||
import { Subject } from 'rxjs';
 | 
			
		||||
import { takeUntil } from 'rxjs/operators';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-color-range-list',
 | 
			
		||||
  templateUrl: './color-range-list.component.html',
 | 
			
		||||
  styleUrls: ['color-settings-panel.component.scss'],
 | 
			
		||||
  providers: [
 | 
			
		||||
    {
 | 
			
		||||
      provide: NG_VALUE_ACCESSOR,
 | 
			
		||||
      useExisting: forwardRef(() => ColorRangeListComponent),
 | 
			
		||||
      multi: true
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class ColorRangeListComponent implements OnInit, ControlValueAccessor, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  disabled: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  popover: TbPopoverComponent;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  panelTitle: string;
 | 
			
		||||
 | 
			
		||||
  modelValue: any;
 | 
			
		||||
 | 
			
		||||
  colorRangeListFormGroup: UntypedFormGroup;
 | 
			
		||||
 | 
			
		||||
  private destroy$ = new Subject<void>();
 | 
			
		||||
 | 
			
		||||
  private propagateChange = null;
 | 
			
		||||
 | 
			
		||||
  constructor(private fb: UntypedFormBuilder) {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.colorRangeListFormGroup = this.fb.group({
 | 
			
		||||
        rangeList: this.fb.array([])
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.colorRangeListFormGroup.valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.destroy$)
 | 
			
		||||
    ).subscribe(() => this.updateModel());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    this.destroy$.next();
 | 
			
		||||
    this.destroy$.complete();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerOnChange(fn: any): void {
 | 
			
		||||
    this.propagateChange = fn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerOnTouched(fn: any): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setDisabledState(isDisabled: boolean): void {
 | 
			
		||||
    this.disabled = isDisabled;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  writeValue(value: any): void {
 | 
			
		||||
    if (value && value?.length) {
 | 
			
		||||
      value.forEach((r) => this.rangeListFormArray.push(this.colorRangeControl(r), {emitEvent: false}));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private colorRangeControl(range: ColorRange): UntypedFormGroup {
 | 
			
		||||
    return this.fb.group({
 | 
			
		||||
      from: [range?.from, []],
 | 
			
		||||
      to: [range?.to, []],
 | 
			
		||||
      color: [range?.color, []]
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get rangeListFormArray(): UntypedFormArray {
 | 
			
		||||
    return this.colorRangeListFormGroup.get('rangeList') as UntypedFormArray;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get rangeListFormGroups(): FormGroup[] {
 | 
			
		||||
    return this.rangeListFormArray.controls as FormGroup[];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  trackByRange(index: number, rangeControl: AbstractControl): any {
 | 
			
		||||
    return rangeControl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  removeRange(index: number) {
 | 
			
		||||
    this.rangeListFormArray.removeAt(index);
 | 
			
		||||
    this.colorRangeListFormGroup.markAsDirty();
 | 
			
		||||
    setTimeout(() => {this.popover?.updatePosition();}, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addRange() {
 | 
			
		||||
    const newRange: ColorRange = {
 | 
			
		||||
      color: 'rgba(0,0,0,0.87)'
 | 
			
		||||
    };
 | 
			
		||||
    this.rangeListFormArray.push(this.colorRangeControl(newRange));
 | 
			
		||||
    this.colorRangeListFormGroup.markAsDirty();
 | 
			
		||||
    setTimeout(() => {this.popover?.updatePosition();}, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateModel() {
 | 
			
		||||
    this.propagateChange(this.colorRangeListFormGroup.get('rangeList').value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,57 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2023 The Thingsboard Authors
 | 
			
		||||
 | 
			
		||||
    Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
    you may not use this file except in compliance with the License.
 | 
			
		||||
    You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
        http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
    distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
    See the License for the specific language governing permissions and
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<div class="tb-color-settings-panel" [formGroup]="colorRangeFormGroup">
 | 
			
		||||
  <div class="tb-color-settings-title" translate>widgets.color.color-settings</div>
 | 
			
		||||
  <div class="tb-color-settings-panel-body">
 | 
			
		||||
    <tb-color-range-list fxFlex class="tb-color-ranges-panel"
 | 
			
		||||
                         formControlName="rangeList"
 | 
			
		||||
                         [popover]="popover">
 | 
			
		||||
    </tb-color-range-list>
 | 
			
		||||
  </div>
 | 
			
		||||
  <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
 | 
			
		||||
              color="primary"
 | 
			
		||||
              type="button"
 | 
			
		||||
              (click)="cancel()">
 | 
			
		||||
        {{ 'action.cancel' | translate }}
 | 
			
		||||
      </button>
 | 
			
		||||
      <button mat-raised-button
 | 
			
		||||
              color="primary"
 | 
			
		||||
              type="button"
 | 
			
		||||
              (click)="applyColorRangeSettings()"
 | 
			
		||||
              [disabled]="colorRangeFormGroup.invalid || !colorRangeFormGroup.dirty">
 | 
			
		||||
        {{ 'action.apply' | translate }}
 | 
			
		||||
      </button>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
@ -0,0 +1,78 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2023 The Thingsboard Authors
 | 
			
		||||
///
 | 
			
		||||
/// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
/// you may not use this file except in compliance with the License.
 | 
			
		||||
/// You may obtain a copy of the License at
 | 
			
		||||
///
 | 
			
		||||
///     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
///
 | 
			
		||||
/// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
/// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
/// See the License for the specific language governing permissions and
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
 | 
			
		||||
import { PageComponent } from '@shared/components/page.component';
 | 
			
		||||
import { ColorRange } from '@shared/models/widget-settings.models';
 | 
			
		||||
import { TbPopoverComponent } from '@shared/components/popover.component';
 | 
			
		||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { deepClone } from '@core/utils';
 | 
			
		||||
import {
 | 
			
		||||
  ColorRangeSettingsComponent
 | 
			
		||||
} from '@home/components/widget/lib/settings/common/color-range-settings.component';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-color-range-panel',
 | 
			
		||||
  templateUrl: './color-range-panel.component.html',
 | 
			
		||||
  providers: [],
 | 
			
		||||
  styleUrls: ['./color-settings-panel.component.scss'],
 | 
			
		||||
  encapsulation: ViewEncapsulation.None
 | 
			
		||||
})
 | 
			
		||||
export class ColorRangePanelComponent extends PageComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  colorRangeSettings: Array<ColorRange>;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  popover: TbPopoverComponent<ColorRangePanelComponent>;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  settingsComponents: ColorRangeSettingsComponent[];
 | 
			
		||||
 | 
			
		||||
  @Output()
 | 
			
		||||
  colorRangeApplied = new EventEmitter<Array<ColorRange>>();
 | 
			
		||||
 | 
			
		||||
  colorRangeFormGroup: UntypedFormGroup;
 | 
			
		||||
 | 
			
		||||
  constructor(private fb: UntypedFormBuilder,
 | 
			
		||||
              protected store: Store<AppState>) {
 | 
			
		||||
    super(store);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.colorRangeFormGroup = this.fb.group({
 | 
			
		||||
        rangeList: [this.colorRangeSettings, []]
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  copyColorSettings(comp: ColorRangeSettingsComponent) {
 | 
			
		||||
    this.colorRangeSettings = deepClone(comp.modelValue);
 | 
			
		||||
    this.colorRangeFormGroup.get('rangeList').patchValue(this.colorRangeSettings || [], {emitEvent: false});
 | 
			
		||||
    this.colorRangeFormGroup.markAsDirty();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cancel() {
 | 
			
		||||
    this.popover?.hide();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  applyColorRangeSettings() {
 | 
			
		||||
    const colorRangeSettings = this.colorRangeFormGroup.get('rangeList').value;
 | 
			
		||||
    this.colorRangeApplied.emit(colorRangeSettings);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2023 The Thingsboard Authors
 | 
			
		||||
 | 
			
		||||
    Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
    you may not use this file except in compliance with the License.
 | 
			
		||||
    You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
        http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
    distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
    See the License for the specific language governing permissions and
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<button type="button"
 | 
			
		||||
        mat-stroked-button
 | 
			
		||||
        class="tb-box-button"
 | 
			
		||||
        [disabled]="disabled"
 | 
			
		||||
        #matButton
 | 
			
		||||
        (click)="openColorRangeSettingsPopup($event, matButton)">
 | 
			
		||||
  <div class="tb-color-preview box" [ngClass]="{'disabled': disabled}">
 | 
			
		||||
    <div class="tb-color-result" [style]="colorStyle"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
</button>
 | 
			
		||||
@ -0,0 +1,166 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2023 The Thingsboard Authors
 | 
			
		||||
///
 | 
			
		||||
/// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
/// you may not use this file except in compliance with the License.
 | 
			
		||||
/// You may obtain a copy of the License at
 | 
			
		||||
///
 | 
			
		||||
///     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
///
 | 
			
		||||
/// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
/// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
/// See the License for the specific language governing permissions and
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  Component,
 | 
			
		||||
  forwardRef,
 | 
			
		||||
  Injectable,
 | 
			
		||||
  Input,
 | 
			
		||||
  OnDestroy,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  Renderer2,
 | 
			
		||||
  ViewContainerRef
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
 | 
			
		||||
import { ColorRange, ComponentStyle } from '@shared/models/widget-settings.models';
 | 
			
		||||
import { MatButton } from '@angular/material/button';
 | 
			
		||||
import { TbPopoverService } from '@shared/components/popover.service';
 | 
			
		||||
import { ColorRangePanelComponent } from '@home/components/widget/lib/settings/common/color-range-panel.component';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class ColorRangeSettingsComponentService {
 | 
			
		||||
 | 
			
		||||
  private colorSettingsComponents = new Set<ColorRangeSettingsComponent>();
 | 
			
		||||
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  public registerColorSettingsComponent(comp: ColorRangeSettingsComponent) {
 | 
			
		||||
    this.colorSettingsComponents.add(comp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public unregisterColorSettingsComponent(comp: ColorRangeSettingsComponent) {
 | 
			
		||||
    this.colorSettingsComponents.delete(comp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getOtherColorSettingsComponents(comp: ColorRangeSettingsComponent): ColorRangeSettingsComponent[] {
 | 
			
		||||
    const result: ColorRangeSettingsComponent[] = [];
 | 
			
		||||
    for (const component of this.colorSettingsComponents.values()) {
 | 
			
		||||
      if (component.settingsKey && component.modelValue && component !== comp) {
 | 
			
		||||
        result.push(component);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-color-range-settings',
 | 
			
		||||
  templateUrl: './color-range-settings.component.html',
 | 
			
		||||
  styleUrls: [],
 | 
			
		||||
  providers: [
 | 
			
		||||
    {
 | 
			
		||||
      provide: NG_VALUE_ACCESSOR,
 | 
			
		||||
      useExisting: forwardRef(() => ColorRangeSettingsComponent),
 | 
			
		||||
      multi: true
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class ColorRangeSettingsComponent implements OnInit, ControlValueAccessor, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  disabled: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  settingsKey: string;
 | 
			
		||||
 | 
			
		||||
  modelValue: Array<ColorRange>;
 | 
			
		||||
 | 
			
		||||
  colorStyle: ComponentStyle = {};
 | 
			
		||||
 | 
			
		||||
  private propagateChange = null;
 | 
			
		||||
 | 
			
		||||
  constructor(private popoverService: TbPopoverService,
 | 
			
		||||
              private renderer: Renderer2,
 | 
			
		||||
              private viewContainerRef: ViewContainerRef,
 | 
			
		||||
              private colorSettingsComponentService: ColorRangeSettingsComponentService) {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.colorSettingsComponentService.registerColorSettingsComponent(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    this.colorSettingsComponentService.unregisterColorSettingsComponent(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerOnChange(fn: any): void {
 | 
			
		||||
    this.propagateChange = fn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerOnTouched(fn: any): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setDisabledState(isDisabled: boolean): void {
 | 
			
		||||
    this.disabled = isDisabled;
 | 
			
		||||
    this.updateColorStyle();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  writeValue(value: Array<ColorRange>): void {
 | 
			
		||||
    this.modelValue = value;
 | 
			
		||||
    this.updateColorStyle();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  openColorRangeSettingsPopup($event: Event, matButton: MatButton) {
 | 
			
		||||
    if ($event) {
 | 
			
		||||
      $event.stopPropagation();
 | 
			
		||||
    }
 | 
			
		||||
    const trigger = matButton._elementRef.nativeElement;
 | 
			
		||||
    if (this.popoverService.hasPopover(trigger)) {
 | 
			
		||||
      this.popoverService.hidePopover(trigger);
 | 
			
		||||
    } else {
 | 
			
		||||
      const ctx: any = {
 | 
			
		||||
        colorRangeSettings: this.modelValue,
 | 
			
		||||
        settingsComponents: this.colorSettingsComponentService.getOtherColorSettingsComponents(this)
 | 
			
		||||
      };
 | 
			
		||||
      const colorRangeSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer,
 | 
			
		||||
        this.viewContainerRef, ColorRangePanelComponent, 'left', true, null,
 | 
			
		||||
        ctx,
 | 
			
		||||
        {},
 | 
			
		||||
        {}, {}, true);
 | 
			
		||||
      colorRangeSettingsPanelPopover.tbComponentRef.instance.popover = colorRangeSettingsPanelPopover;
 | 
			
		||||
      colorRangeSettingsPanelPopover.tbComponentRef.instance.colorRangeApplied.subscribe((colorRangeSettings) => {
 | 
			
		||||
        colorRangeSettingsPanelPopover.hide();
 | 
			
		||||
        this.modelValue = colorRangeSettings;
 | 
			
		||||
        this.updateColorStyle();
 | 
			
		||||
        this.propagateChange(this.modelValue);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private updateColorStyle() {
 | 
			
		||||
    if (!this.disabled && this.modelValue) {
 | 
			
		||||
      let colors: string[] = [];
 | 
			
		||||
      if (this.modelValue.length) {
 | 
			
		||||
        const rangeColors = this.modelValue.slice(0, Math.min(3, this.modelValue.length)).map(r => r.color);
 | 
			
		||||
        colors = colors.concat(rangeColors);
 | 
			
		||||
      }
 | 
			
		||||
      if (colors.length === 1) {
 | 
			
		||||
        this.colorStyle = {backgroundColor: colors[0]};
 | 
			
		||||
      } else {
 | 
			
		||||
        const gradientValues: string[] = [];
 | 
			
		||||
        const step = 100 / colors.length;
 | 
			
		||||
        for (let i = 0; i < colors.length; i++) {
 | 
			
		||||
          gradientValues.push(`${colors[i]} ${step*i}%`);
 | 
			
		||||
          gradientValues.push(`${colors[i]} ${step*(i+1)}%`);
 | 
			
		||||
        }
 | 
			
		||||
        this.colorStyle = {background: `linear-gradient(90deg, ${gradientValues.join(', ')})`};
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      this.colorStyle = {};
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -34,7 +34,11 @@
 | 
			
		||||
  <div class="tb-color-settings-panel-body" [fxShow]="colorSettingsFormGroup.get('type').value === colorType.constant">
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-color-settings-panel-body" [fxShow]="colorSettingsFormGroup.get('type').value === colorType.range">
 | 
			
		||||
    <ng-container *ngTemplateOutlet="range"></ng-container>
 | 
			
		||||
    <tb-color-range-list fxFlex class="tb-color-ranges-panel"
 | 
			
		||||
                         formControlName="rangeList"
 | 
			
		||||
                         panelTitle="{{ 'widgets.color.value-range' | translate }}"
 | 
			
		||||
                         [popover]="popover">
 | 
			
		||||
    </tb-color-range-list>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-color-settings-panel-body" [fxShow]="colorSettingsFormGroup.get('type').value === colorType.function">
 | 
			
		||||
    <ng-container *ngTemplateOutlet="function"></ng-container>
 | 
			
		||||
@ -72,43 +76,6 @@
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<ng-template #range>
 | 
			
		||||
  <div fxFlex class="tb-color-ranges-panel">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>widgets.color.value-range</div>
 | 
			
		||||
    <div class="tb-color-ranges" [formGroup]="colorSettingsFormGroup">
 | 
			
		||||
      <div class="tb-form-row no-padding no-border" [formGroup]="rangeFormGroup" *ngFor="let rangeFormGroup of rangeListFormGroups; trackBy: trackByRange; let $index = index;">
 | 
			
		||||
        <div fxFlex fxLayout="row" fxLayoutGap="24px">
 | 
			
		||||
          <div fxFlex fxLayout="row" fxLayoutGap="12px" fxLayoutAlign="start center">
 | 
			
		||||
            <div class="tb-value-range-text" translate>widgets.color.from</div>
 | 
			
		||||
            <mat-form-field fxFlex appearance="outline" class="center number" subscriptSizing="dynamic">
 | 
			
		||||
              <input matInput type="number" formControlName="from" placeholder="{{ 'widget-config.set' | translate }}">
 | 
			
		||||
            </mat-form-field>
 | 
			
		||||
            <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">
 | 
			
		||||
              <input matInput type="number" formControlName="to" placeholder="{{ 'widget-config.set' | translate }}">
 | 
			
		||||
            </mat-form-field>
 | 
			
		||||
            <tb-color-input asBoxInput
 | 
			
		||||
                            formControlName="color">
 | 
			
		||||
            </tb-color-input>
 | 
			
		||||
          </div>
 | 
			
		||||
          <button type="button"
 | 
			
		||||
                  mat-icon-button
 | 
			
		||||
                  class="tb-box-button"
 | 
			
		||||
                  (click)="removeRange($index)"
 | 
			
		||||
                  matTooltip="{{ 'action.remove' | translate }}"
 | 
			
		||||
                  matTooltipPosition="above">
 | 
			
		||||
            <mat-icon>delete</mat-icon>
 | 
			
		||||
          </button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <button class="tb-add-color-range"
 | 
			
		||||
            mat-stroked-button
 | 
			
		||||
            (click)="addRange()">
 | 
			
		||||
      <mat-icon>add</mat-icon>
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
</ng-template>
 | 
			
		||||
<ng-template #function>
 | 
			
		||||
  <div class="tb-form-panel no-padding no-border" [formGroup]="colorSettingsFormGroup">
 | 
			
		||||
    <tb-js-func formControlName="colorFunction"
 | 
			
		||||
 | 
			
		||||
@ -16,9 +16,9 @@
 | 
			
		||||
 | 
			
		||||
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
 | 
			
		||||
import { PageComponent } from '@shared/components/page.component';
 | 
			
		||||
import { ColorRange, ColorSettings, ColorType, colorTypeTranslations } from '@shared/models/widget-settings.models';
 | 
			
		||||
import { ColorSettings, ColorType, colorTypeTranslations } from '@shared/models/widget-settings.models';
 | 
			
		||||
import { TbPopoverComponent } from '@shared/components/popover.component';
 | 
			
		||||
import { AbstractControl, FormGroup, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { deepClone } from '@core/utils';
 | 
			
		||||
@ -67,7 +67,7 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit
 | 
			
		||||
      {
 | 
			
		||||
        type: [this.colorSettings?.type, []],
 | 
			
		||||
        color: [this.colorSettings?.color, []],
 | 
			
		||||
        rangeList: this.fb.array((this.colorSettings?.rangeList || []).map(r => this.colorRangeControl(r))),
 | 
			
		||||
        rangeList: [this.colorSettings?.rangeList, []],
 | 
			
		||||
        colorFunction: [this.colorSettings?.colorFunction, []]
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
@ -76,51 +76,15 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private colorRangeControl(range: ColorRange): AbstractControl {
 | 
			
		||||
    return this.fb.group({
 | 
			
		||||
      from: [range?.from, []],
 | 
			
		||||
      to: [range?.to, []],
 | 
			
		||||
      color: [range?.color, []]
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get rangeListFormArray(): UntypedFormArray {
 | 
			
		||||
    return this.colorSettingsFormGroup.get('rangeList') as UntypedFormArray;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get rangeListFormGroups(): FormGroup[] {
 | 
			
		||||
    return this.rangeListFormArray.controls as FormGroup[];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  trackByRange(index: number, rangeControl: AbstractControl): any {
 | 
			
		||||
    return rangeControl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  removeRange(index: number) {
 | 
			
		||||
    this.rangeListFormArray.removeAt(index);
 | 
			
		||||
    this.colorSettingsFormGroup.markAsDirty();
 | 
			
		||||
    setTimeout(() => {this.popover?.updatePosition();}, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addRange() {
 | 
			
		||||
    const newRange: ColorRange = {
 | 
			
		||||
      color: 'rgba(0,0,0,0.87)'
 | 
			
		||||
    };
 | 
			
		||||
    this.rangeListFormArray.push(this.colorRangeControl(newRange));
 | 
			
		||||
    this.colorSettingsFormGroup.markAsDirty();
 | 
			
		||||
    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
 | 
			
		||||
      colorFunction: this.colorSettings.colorFunction,
 | 
			
		||||
      rangeList: this.colorSettings.rangeList || []
 | 
			
		||||
    }, {emitEvent: false});
 | 
			
		||||
    this.colorSettingsFormGroup.setControl('rangeList',
 | 
			
		||||
      this.fb.array((this.colorSettings.rangeList || []).map(r => this.colorRangeControl(r))), {emitEvent: false});
 | 
			
		||||
    this.colorSettingsFormGroup.markAsDirty();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,12 @@ import {
 | 
			
		||||
} from '@home/components/widget/lib/settings/common/background-settings-panel.component';
 | 
			
		||||
import {
 | 
			
		||||
  CountWidgetSettingsComponent
 | 
			
		||||
} from "@home/components/widget/lib/settings/common/count-widget-settings.component";
 | 
			
		||||
} from '@home/components/widget/lib/settings/common/count-widget-settings.component';
 | 
			
		||||
import { ColorRangeListComponent } from '@home/components/widget/lib/settings/common/color-range-list.component';
 | 
			
		||||
import { ColorRangePanelComponent } from '@home/components/widget/lib/settings/common/color-range-panel.component';
 | 
			
		||||
import {
 | 
			
		||||
  ColorRangeSettingsComponent, ColorRangeSettingsComponentService
 | 
			
		||||
} from '@home/components/widget/lib/settings/common/color-range-settings.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@ -63,7 +68,10 @@ import {
 | 
			
		||||
    ValueSourceComponent,
 | 
			
		||||
    LegendConfigComponent,
 | 
			
		||||
    WidgetFontComponent,
 | 
			
		||||
    CountWidgetSettingsComponent
 | 
			
		||||
    CountWidgetSettingsComponent,
 | 
			
		||||
    ColorRangeListComponent,
 | 
			
		||||
    ColorRangePanelComponent,
 | 
			
		||||
    ColorRangeSettingsComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
@ -85,10 +93,14 @@ import {
 | 
			
		||||
    ValueSourceComponent,
 | 
			
		||||
    LegendConfigComponent,
 | 
			
		||||
    WidgetFontComponent,
 | 
			
		||||
    CountWidgetSettingsComponent
 | 
			
		||||
    CountWidgetSettingsComponent,
 | 
			
		||||
    ColorRangeListComponent,
 | 
			
		||||
    ColorRangePanelComponent,
 | 
			
		||||
    ColorRangeSettingsComponent
 | 
			
		||||
  ],
 | 
			
		||||
  providers: [
 | 
			
		||||
    ColorSettingsComponentService
 | 
			
		||||
    ColorSettingsComponentService,
 | 
			
		||||
    ColorRangeSettingsComponentService
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class WidgetSettingsCommonModule {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user