From c20098088d0c58d5cf0dc20754a040b5104d1bb1 Mon Sep 17 00:00:00 2001 From: Dmitriymush Date: Fri, 20 Oct 2023 15:09:40 +0300 Subject: [PATCH] UI: Liquid level widget improvements, string autocomplete improvements --- .../app/core/services/resources.service.ts | 4 +- ...uid-level-card-basic-config.component.html | 4 +- .../indicator/liquid-level-widget.models.ts | 3 +- .../lib/indicator/liquid-level-widget.ts | 31 +++++----- ...-level-card-widget-settings.component.html | 3 + .../string-autocomplete.component.html | 22 ++++--- .../string-autocomplete.component.scss | 33 ++++++----- .../string-autocomplete.component.ts | 58 ++++++++++++------- ui-ngx/src/app/shared/shared.module.ts | 3 - 9 files changed, 99 insertions(+), 62 deletions(-) diff --git a/ui-ngx/src/app/core/services/resources.service.ts b/ui-ngx/src/app/core/services/resources.service.ts index 29d86fc2fb..f7a34c9ef5 100644 --- a/ui-ngx/src/app/core/services/resources.service.ts +++ b/ui-ngx/src/app/core/services/resources.service.ts @@ -68,7 +68,9 @@ export class ResourcesService { } const subject = new ReplaySubject(); this.loadedJsonResources[url] = subject; - this.http.get(url).subscribe( + const req$ = (url.endsWith('.raw') || url.endsWith('.svg') ? + this.http.get(url, {responseType: 'text'}) : this.http.get(url)) as Observable; + req$.subscribe( { next: (o) => { if (postProcess) { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/liquid-level-card-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/liquid-level-card-basic-config.component.html index 03cc7894c6..82dcb21c81 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/liquid-level-card-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/liquid-level-card-basic-config.component.html @@ -93,6 +93,7 @@
widgets.liquid-level-card.shape-attribute-name
@@ -151,6 +152,7 @@ @@ -183,6 +185,7 @@
widget-config.show-card-buttons
- {{ 'widget-config.data-export' | translate }} {{ 'fullscreen.fullscreen' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts index fabe986b9f..7602a97dfe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts @@ -16,7 +16,8 @@ import { ColorSettings, - constantColor, cssTextFromInlineStyle, + constantColor, + cssTextFromInlineStyle, DateFormatSettings, Font, lastUpdateAgoDateFormat diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.ts index 7c86989f31..eab8c16bef 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.ts @@ -43,13 +43,11 @@ import { import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance; import { ResourcesService } from '@core/services/resources.service'; import { NULL_UUID } from '@shared/models/id/has-uuid'; -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'tb-liquid-level-widget', - template: '', - styleUrls: [], - encapsulation: ViewEncapsulation.None + template: '' }) export class LiquidLevelWidgetComponent implements OnInit { @@ -98,17 +96,7 @@ export class LiquidLevelWidgetComponent implements OnInit { ngOnInit(): void { this.ctx.$scope.liquidLevelWidget = this; this.settings = {...levelCardDefaultSettings(), ...this.ctx.widgetConfig, ...this.ctx.settings}; - - this.tankColor = ColorProcessor.fromSettings(this.settings.tankColor); - this.volumeColor = ColorProcessor.fromSettings(this.settings.volumeColor); - this.valueColor = ColorProcessor.fromSettings(this.settings.valueColor); - this.liquidColor = ColorProcessor.fromSettings(this.settings.liquidColor); - this.backgroundOverlayColor = ColorProcessor.fromSettings(this.settings.backgroundOverlayColor); - this.tooltipLevelColor = ColorProcessor.fromSettings(this.settings.tooltipLevelColor); - this.tooltipDateColor = ColorProcessor.fromSettings(this.settings.tooltipDateColor); - this.tooltipBackgroundColor = ColorProcessor.fromSettings(this.settings.tooltipBackgroundColor); - - this.tooltipDateFormat = DateFormatProcessor.fromSettings(this.ctx.$injector, this.settings.tooltipDateFormat); + this.declareStyles(); } public onInit() { @@ -140,6 +128,19 @@ export class LiquidLevelWidgetComponent implements OnInit { }); } + private declareStyles():void { + this.tankColor = ColorProcessor.fromSettings(this.settings.tankColor); + this.volumeColor = ColorProcessor.fromSettings(this.settings.volumeColor); + this.valueColor = ColorProcessor.fromSettings(this.settings.valueColor); + this.liquidColor = ColorProcessor.fromSettings(this.settings.liquidColor); + this.backgroundOverlayColor = ColorProcessor.fromSettings(this.settings.backgroundOverlayColor); + this.tooltipLevelColor = ColorProcessor.fromSettings(this.settings.tooltipLevelColor); + this.tooltipDateColor = ColorProcessor.fromSettings(this.settings.tooltipDateColor); + this.tooltipBackgroundColor = ColorProcessor.fromSettings(this.settings.tooltipBackgroundColor); + + this.tooltipDateFormat = DateFormatProcessor.fromSettings(this.ctx.$injector, this.settings.tooltipDateFormat); + } + private getData(): Observable<{ svg: string; volume: number; units: string }> { const entityId: EntityId = { entityType: this.ctx.datasources[0].entityType, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/liquid-level-card-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/liquid-level-card-widget-settings.component.html index 7137226fdc..0f3f943cc4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/liquid-level-card-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/liquid-level-card-widget-settings.component.html @@ -48,6 +48,7 @@
widgets.liquid-level-card.shape-attribute-name
@@ -110,6 +111,7 @@ @@ -143,6 +145,7 @@ [fxShow]="levelCardWidgetSettingsForm.get('volumeSource')?.value === volumeOptions.attribute" [fetchOptionsFn]="fetchOptions.bind(this)" [required]="isRequired('volumeAttributeName')" + [errorText]="'widgets.liquid-level-card.attribute-name-required' | translate" style="flex: 1; width: auto;" asBoxInput colorClearButton class="flex" formControlName="volumeAttributeName"> diff --git a/ui-ngx/src/app/shared/components/string-autocomplete.component.html b/ui-ngx/src/app/shared/components/string-autocomplete.component.html index f021b57618..b2380ba239 100644 --- a/ui-ngx/src/app/shared/components/string-autocomplete.component.html +++ b/ui-ngx/src/app/shared/components/string-autocomplete.component.html @@ -15,30 +15,36 @@ limitations under the License. --> - + + {{label}} - - + [matTooltipClass]="tooltipClass" + class="material-icons tb-suffix-show-always tb-error"> warning + + {{errorText}} + - + diff --git a/ui-ngx/src/app/shared/components/string-autocomplete.component.scss b/ui-ngx/src/app/shared/components/string-autocomplete.component.scss index 950fca110d..d97c3f8987 100644 --- a/ui-ngx/src/app/shared/components/string-autocomplete.component.scss +++ b/ui-ngx/src/app/shared/components/string-autocomplete.component.scss @@ -13,19 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -.tb-autocomplete.tb-option-input-autocomplete { - .mat-mdc-option { - border-bottom: none; - .mdc-list-item__primary-text { - flex: 1; - display: flex; - flex-direction: row; - gap: 8px; - .tb-option { - font-size: 14px; - font-weight: 400; - line-height: 20px; - letter-spacing: 0.2px; +:host { + display: flex; + flex: 1 1 0%; + max-width: 100%; + box-sizing: border-box; + + .tb-autocomplete.tb-option-input-autocomplete { + .mat-mdc-option { + border-bottom: none; + .mdc-list-item__primary-text { + flex: 1; + display: flex; + flex-direction: row; + gap: 8px; + .tb-option { + font-size: 14px; + font-weight: 400; + line-height: 20px; + letter-spacing: 0.2px; + } } } } diff --git a/ui-ngx/src/app/shared/components/string-autocomplete.component.ts b/ui-ngx/src/app/shared/components/string-autocomplete.component.ts index b2e03db797..9f6d238d3e 100644 --- a/ui-ngx/src/app/shared/components/string-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/string-autocomplete.component.ts @@ -19,11 +19,8 @@ import { Input, forwardRef, OnInit, - AfterViewInit, - HostBinding, ViewChild, - ElementRef, - Injector + ElementRef } from '@angular/core'; import { ControlValueAccessor, @@ -33,7 +30,9 @@ import { FormBuilder } from '@angular/forms'; import { Observable, of } from 'rxjs'; -import { tap, map, switchMap } from 'rxjs/operators'; +import { tap, map, switchMap, take } from 'rxjs/operators'; +import { TranslateService } from '@ngx-translate/core'; +import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ selector: 'tb-string-autocomplete', @@ -47,13 +46,12 @@ import { tap, map, switchMap } from 'rxjs/operators'; } ] }) -export class StringAutocompleteComponent implements ControlValueAccessor, OnInit, AfterViewInit { - - @HostBinding('style.display') get hostDisplay() {return 'flex';}; +export class StringAutocompleteComponent implements ControlValueAccessor, OnInit { @Input() disabled: boolean; + @coerceBoolean() @Input() required: boolean; @@ -61,11 +59,36 @@ export class StringAutocompleteComponent implements ControlValueAccessor, OnInit @ViewChild('nameInput', {static: true}) nameInput: ElementRef; + @Input() + placeholderText: string = this.translate.instant('widget-config.set'); + + @Input() + subscriptSizing: string = 'dynamic'; + + @Input() + ngClass: string | string[] | Set | { [klass: string]: any; } = 'tb-inline-field tb-suffix-show-on-hover'; + + @Input() + appearance: string = 'outline'; + + @Input() + label: string; + + @Input() + tooltipClass: string = 'tb-error-tooltip'; + + @Input() + errorText: string; + + @coerceBoolean() + @Input() + showInlineError: boolean = false; + selectionFormControl: FormControl; modelValue: string | null; - filteredOptions: Observable>; + filteredOptions$: Observable>; searchText = ''; @@ -73,13 +96,13 @@ export class StringAutocompleteComponent implements ControlValueAccessor, OnInit private propagateChange = (_val: any) => {}; - constructor(private injector: Injector, - private fb: FormBuilder) { + constructor(private fb: FormBuilder, + private translate: TranslateService) { } ngOnInit() { - this.selectionFormControl = this.fb.control('', []); - this.filteredOptions = this.selectionFormControl.valueChanges + this.selectionFormControl = this.fb.control('', this.required ? [Validators.required] : []); + this.filteredOptions$ = this.selectionFormControl.valueChanges .pipe( tap(value => this.updateView(value)), map(value => value ? value : ''), @@ -87,12 +110,6 @@ export class StringAutocompleteComponent implements ControlValueAccessor, OnInit ); } - ngAfterViewInit() { - if (this.required) { - this.selectionFormControl.setValidators([Validators.required]); - } - } - writeValue(option?: string): void { this.searchText = ''; this.modelValue = option ? option : null; @@ -107,7 +124,8 @@ export class StringAutocompleteComponent implements ControlValueAccessor, OnInit } return option; - }) + }), + take(1) ) .subscribe(result => { this.selectionFormControl.patchValue(result, { emitEvent: false }); diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts index fb6a1a086e..042e453fe1 100644 --- a/ui-ngx/src/app/shared/shared.module.ts +++ b/ui-ngx/src/app/shared/shared.module.ts @@ -200,7 +200,6 @@ import { ColorPickerPanelComponent } from '@shared/components/color-picker/color import { TbIconComponent } from '@shared/components/icon.component'; import { HintTooltipIconComponent } from '@shared/components/hint-tooltip-icon.component'; import { StringAutocompleteComponent } from '@shared/components/string-autocomplete.component'; -import { MatFormFieldModule } from '@angular/material/form-field'; export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) { return markedOptionsService; @@ -401,7 +400,6 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) MatGridListModule, MatDialogModule, MatSelectModule, - MatFormFieldModule, MatTooltipModule, MatTableModule, MatPaginatorModule, @@ -517,7 +515,6 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) MatGridListModule, MatDialogModule, MatSelectModule, - MatFormFieldModule, MatTooltipModule, MatTableModule, MatPaginatorModule,