From d8d62979fc50b6f24ac0bc316f1ba2564345f983 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 22 May 2024 19:40:49 +0300 Subject: [PATCH] UI: Implement metadata tags section. --- .../svg/iot-svg-object-settings.component.ts | 23 ++- .../lib/svg/iot-svg-widget.component.html | 4 +- .../lib/svg/iot-svg-widget.component.ts | 4 +- ...scada-symbol-metadata-components.module.ts | 43 +++++ .../scada-symbol-metadata-tag.component.html | 74 ++++++++ .../scada-symbol-metadata-tag.component.scss | 22 +++ .../scada-symbol-metadata-tag.component.ts | 154 ++++++++++++++++ .../scada-symbol-metadata-tags.component.html | 36 ++++ .../scada-symbol-metadata-tags.component.scss | 25 +++ .../scada-symbol-metadata-tags.component.ts | 171 ++++++++++++++++++ .../scada-symbol-metadata.component.html | 6 + .../scada-symbol-metadata.component.scss | 9 +- .../scada-symbol-metadata.component.ts | 27 ++- .../scada-symbol-editor.component.ts | 8 +- .../scada-symbol/scada-symbol.component.html | 47 ++++- .../scada-symbol/scada-symbol.component.scss | 41 +++++ .../scada-symbol/scada-symbol.component.ts | 43 ++++- .../pages/scada-symbol/scada-symbol.models.ts | 22 ++- .../pages/scada-symbol/scada-symbol.module.ts | 12 +- .../assets/locale/locale.constant-en_US.json | 8 +- 20 files changed, 748 insertions(+), 31 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-components.module.ts create mode 100644 ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.html create mode 100644 ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.scss create mode 100644 ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts create mode 100644 ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.html create mode 100644 ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.scss create mode 100644 ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts rename ui-ngx/src/app/modules/home/pages/scada-symbol/{ => metadata-components}/scada-symbol-metadata.component.html (91%) rename ui-ngx/src/app/modules/home/pages/scada-symbol/{ => metadata-components}/scada-symbol-metadata.component.scss (88%) rename ui-ngx/src/app/modules/home/pages/scada-symbol/{ => metadata-components}/scada-symbol-metadata.component.ts (85%) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/svg/iot-svg-object-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/svg/iot-svg-object-settings.component.ts index 1154dad79c..613e8b26f9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/svg/iot-svg-object-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/svg/iot-svg-object-settings.component.ts @@ -44,8 +44,9 @@ import { IotSvgPropertyRow, toPropertyRows } from '@home/components/widget/lib/settings/common/svg/iot-svg-object-settings.models'; -import { merge, Observable, Subscription } from 'rxjs'; +import { merge, Observable, of, Subscription } from 'rxjs'; import { WidgetActionCallbacks } from '@home/components/widget/action/manage-widget-actions.component.models'; +import { ImageService } from '@core/http/image.service'; @Component({ selector: 'tb-iot-svg-object-settings', @@ -74,6 +75,12 @@ export class IotSvgObjectSettingsComponent implements OnInit, OnChanges, Control @Input() svgPath = 'drawing.svg'; + @Input() + svgUrl: string; + + @Input() + svgContent: string; + @Input() aliasController: IAliasController; @@ -101,6 +108,7 @@ export class IotSvgObjectSettingsComponent implements OnInit, OnChanges, Control constructor(protected store: Store, private fb: UntypedFormBuilder, private http: HttpClient, + private imageService: ImageService, private cd: ChangeDetectorRef) { } @@ -116,7 +124,7 @@ export class IotSvgObjectSettingsComponent implements OnInit, OnChanges, Control for (const propName of Object.keys(changes)) { const change = changes[propName]; if (!change.firstChange && change.currentValue !== change.previousValue) { - if (['svgPath'].includes(propName)) { + if (['svgPath', 'svgUrl', 'svgContent'].includes(propName)) { this.loadMetadata(); } } @@ -160,7 +168,16 @@ export class IotSvgObjectSettingsComponent implements OnInit, OnChanges, Control this.validatorSubscription = null; } this.validatorTriggers = []; - this.http.get(this.svgPath, {responseType: 'text'}).subscribe( + + let svgContent$: Observable; + if (this.svgContent) { + svgContent$ = of(this.svgContent); + } else if (this.svgUrl) { + svgContent$ = this.imageService.getImageString(this.svgUrl); + } else { + svgContent$ = this.http.get(this.svgPath, {responseType: 'text'}); + } + svgContent$.subscribe( (svgContent) => { this.metadata = parseIotSvgMetadataFromContent(svgContent); this.propertyRows = toPropertyRows(this.metadata.properties); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.html index ee005b98c0..3a9afa0048 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.html @@ -17,7 +17,9 @@ -->
- + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.ts index 608feee493..2dadb5b48d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.ts @@ -38,6 +38,7 @@ import { import { Observable, of } from 'rxjs'; import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models'; import { ImageService } from '@core/http/image.service'; +import { WidgetComponent } from '@home/components/widget/widget.component'; @Component({ selector: 'tb-iot-svg-widget', @@ -61,7 +62,8 @@ export class IotSvgWidgetComponent extends private shapeResize$: ResizeObserver; - constructor(protected imagePipe: ImagePipe, + constructor(public widgetComponent: WidgetComponent, + protected imagePipe: ImagePipe, protected sanitizer: DomSanitizer, private renderer: Renderer2, private imageService: ImageService, diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-components.module.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-components.module.ts new file mode 100644 index 0000000000..5b86c23f04 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-components.module.ts @@ -0,0 +1,43 @@ +/// +/// Copyright © 2016-2024 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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { + ScadaSymbolMetadataTagComponent +} from '@home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component'; +import { ScadaSymbolMetadataComponent } from '@home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component'; +import { + ScadaSymbolMetadataTagsComponent +} from '@home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component'; + +@NgModule({ + declarations: + [ + ScadaSymbolMetadataComponent, + ScadaSymbolMetadataTagComponent, + ScadaSymbolMetadataTagsComponent + ], + imports: [ + CommonModule, + SharedModule + ], + exports: [ + ScadaSymbolMetadataComponent + ] +}) +export class ScadaSymbolMetadataComponentsModule { } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.html new file mode 100644 index 0000000000..830a629764 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.html @@ -0,0 +1,74 @@ + +
+ + + + + +
+ + + + {{ 'scada.state-render-function' | translate }} + + + + + + + +
+
+ + + + {{ 'scada.on-click-action' | translate }} + + + + + + + +
+
+
+
diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.scss b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.scss new file mode 100644 index 0000000000..1e0bacd858 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.scss @@ -0,0 +1,22 @@ +/** + * Copyright © 2016-2024 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. + */ +.tb-scada-symbol-metadata-tag-header { + flex: 1; + display: flex; + flex-direction: row; + gap: 8px; + padding-right: 8px; +} diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts new file mode 100644 index 0000000000..7ca3c909d4 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts @@ -0,0 +1,154 @@ +/// +/// Copyright © 2016-2024 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 { + ChangeDetectorRef, + Component, EventEmitter, + forwardRef, + Input, + OnChanges, + OnInit, Output, + SimpleChanges, ViewChild, + ViewEncapsulation +} from '@angular/core'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { IotSvgTag } from '@home/components/widget/lib/svg/iot-svg.models'; +import { MatExpansionPanel } from '@angular/material/expansion'; + +@Component({ + selector: 'tb-scada-symbol-metadata-tag', + templateUrl: './scada-symbol-metadata-tag.component.html', + styleUrls: ['./scada-symbol-metadata-tag.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolMetadataTagComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class ScadaSymbolMetadataTagComponent implements ControlValueAccessor, OnInit, OnChanges { + + @ViewChild('expansionPanel') + expansionPanel: MatExpansionPanel; + + @Input() + disabled: boolean; + + @Input() + tags: string[]; + + @Output() + tagRemoved = new EventEmitter(); + + availableTags: string[]; + + tagFormGroup: UntypedFormGroup; + + modelValue: IotSvgTag; + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder, + private cd: ChangeDetectorRef) { + } + + ngOnInit() { + this.availableTags = (this.tags || []).concat(); + this.tagFormGroup = this.fb.group({ + tag: [null, [Validators.required]], + stateRenderFunction: [null, []], + clickAction: [null, []] + }); + this.tagFormGroup.valueChanges.subscribe( + () => this.updateModel() + ); + } + + ngOnChanges(changes: SimpleChanges): void { + for (const propName of Object.keys(changes)) { + const change = changes[propName]; + if (!change.firstChange && change.currentValue !== change.previousValue) { + if (['tags'].includes(propName)) { + this.availableTags = (this.tags || []).concat(); + if (this.modelValue?.tag && !this.availableTags.includes(this.modelValue?.tag)) { + this.availableTags.push(this.modelValue?.tag); + this.availableTags.sort(); + } + } + } + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.tagFormGroup.disable({emitEvent: false}); + } else { + this.tagFormGroup.enable({emitEvent: false}); + } + } + + writeValue(value: IotSvgTag): void { + this.modelValue = value; + if (value?.tag && !(this.tags || []).includes(value?.tag)) { + this.availableTags = (this.tags || []).concat(value.tag).sort(); + } + const clickAction = value?.actions && value?.actions.click ? value.actions.click.actionFunction : null; + this.tagFormGroup.patchValue( + { + tag: value?.tag, + stateRenderFunction: value?.stateRenderFunction, + clickAction + }, {emitEvent: false} + ); + } + + private updateModel() { + const value = this.tagFormGroup.value; + if (value.tag && !this.modelValue?.tag) { + this.expansionPanel.open(); + } + this.modelValue = { + tag: value.tag, + stateRenderFunction: value.stateRenderFunction + }; + if (value.clickAction) { + this.modelValue.actions = { + click: { + actionFunction: value.clickAction + } + }; + } else { + this.modelValue.actions = null; + } + this.propagateChange(this.modelValue); + } +} diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.html new file mode 100644 index 0000000000..fc6a6c5265 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.html @@ -0,0 +1,36 @@ + + + + {{ 'scada.no-tags' | translate }} + diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.scss b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.scss new file mode 100644 index 0000000000..1e2ce80fce --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.scss @@ -0,0 +1,25 @@ +/** + * Copyright © 2016-2024 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. + */ +.tb-scada-symbol-metadata-tags { + .tb-scada-symbol-metadata-tags-list { + display: flex; + flex-direction: column; + gap: 8px; + } + .tb-no-tags { + height: 60px; + } +} diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts new file mode 100644 index 0000000000..d30c33aa0f --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts @@ -0,0 +1,171 @@ +/// +/// Copyright © 2016-2024 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, OnChanges, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + UntypedFormArray, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, + ValidationErrors, + Validator +} from '@angular/forms'; +import { IotSvgTag } from '@home/components/widget/lib/svg/iot-svg.models'; + +const tagValidator = (control: AbstractControl): ValidationErrors | null => { + const tag: IotSvgTag = control.value; + if (!tag.tag) { + return { + tag: true + }; + } + return null; +}; + +@Component({ + selector: 'tb-scada-symbol-metadata-tags', + templateUrl: './scada-symbol-metadata-tags.component.html', + styleUrls: ['./scada-symbol-metadata-tags.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolMetadataTagsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolMetadataTagsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class ScadaSymbolMetadataTagsComponent implements ControlValueAccessor, OnInit, Validator, OnChanges { + + @Input() + disabled: boolean; + + @Input() + tags: string[]; + + availableTags: string[]; + + tagsFormGroup: UntypedFormGroup; + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder) { + } + + ngOnInit() { + this.tagsFormGroup = this.fb.group({ + tags: this.fb.array([]) + }); + this.updateAvailableTags(); + this.tagsFormGroup.valueChanges.subscribe( + () => { + let tags: IotSvgTag[] = this.tagsFormGroup.get('tags').value; + if (tags) { + tags = tags.filter(t => !!t.tag); + } + this.updateAvailableTags(); + this.propagateChange(tags); + } + ); + } + + ngOnChanges(changes: SimpleChanges): void { + for (const propName of Object.keys(changes)) { + const change = changes[propName]; + if (!change.firstChange && change.currentValue !== change.previousValue) { + if (['tags'].includes(propName)) { + this.updateAvailableTags(); + } + } + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.tagsFormGroup.disable({emitEvent: false}); + } else { + this.tagsFormGroup.enable({emitEvent: false}); + } + } + + writeValue(value: IotSvgTag[] | undefined): void { + const tags= value || []; + this.tagsFormGroup.setControl('tags', this.prepareTagsFormArray(tags), {emitEvent: false}); + } + + public validate(c: UntypedFormControl) { + const valid = this.tagsFormGroup.valid; + return valid ? null : { + tags: { + valid: false, + }, + }; + } + + tagsFormArray(): UntypedFormArray { + return this.tagsFormGroup.get('tags') as UntypedFormArray; + } + + trackByTag(index: number, tagControl: AbstractControl): any { + return tagControl; + } + + removeTag(index: number) { + (this.tagsFormGroup.get('tags') as UntypedFormArray).removeAt(index); + } + + addTag() { + const tag: IotSvgTag = { + tag: null + }; + const tagsArray = this.tagsFormGroup.get('tags') as UntypedFormArray; + const tagControl = this.fb.control(tag, [tagValidator]); + tagsArray.push(tagControl); + } + + private prepareTagsFormArray(tags: IotSvgTag[] | undefined): UntypedFormArray { + const tagsControls: Array = []; + if (tags) { + tags.forEach((tag) => { + tagsControls.push(this.fb.control(tag, [tagValidator])); + }); + } + return this.fb.array(tagsControls); + } + + private updateAvailableTags() { + const svgTags: IotSvgTag[] = this.tagsFormGroup.get('tags').value; + const usedTags = (svgTags || []).filter(t => !!t.tag).map(t => t.tag); + this.availableTags = (this.tags || []).filter(t => !usedTags.includes(t)); + } +} diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html similarity index 91% rename from ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.html rename to ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html index f4770bd823..13348302d0 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html @@ -51,5 +51,11 @@
+
+ + +
diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.scss b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.scss similarity index 88% rename from ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.scss rename to ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.scss index 48cc8471b8..bfaf8b0529 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.scss +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.scss @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@import '../../../../../scss/constants'; +@import '../../../../../../scss/constants'; .tb-scada-symbol-metadata { display: flex; @@ -61,5 +61,12 @@ gap: 8px; } } + .tb-form-panel { + .mat-expansion-panel.tb-settings { + & > .mat-expansion-panel-header { + font-weight: 400; + } + } + } } } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts similarity index 85% rename from ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.ts rename to ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts index 56f0a2d16b..966115c44e 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-metadata.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts @@ -14,12 +14,15 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, forwardRef, Input, OnInit, ViewEncapsulation } from '@angular/core'; import { ControlValueAccessor, + NG_VALIDATORS, NG_VALUE_ACCESSOR, UntypedFormBuilder, + UntypedFormControl, UntypedFormGroup, + Validator, Validators } from '@angular/forms'; import { PageComponent } from '@shared/components/page.component'; @@ -39,14 +42,23 @@ import { TranslateService } from '@ngx-translate/core'; provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ScadaSymbolMetadataComponent), multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolMetadataComponent), + multi: true } - ] + ], + encapsulation: ViewEncapsulation.None }) -export class ScadaSymbolMetadataComponent extends PageComponent implements OnInit, ControlValueAccessor { +export class ScadaSymbolMetadataComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { @Input() disabled: boolean; + @Input() + tags: string[]; + private modelValue: IotSvgMetadata; private propagateChange = null; @@ -118,6 +130,15 @@ export class ScadaSymbolMetadataComponent extends PageComponent implements OnIni ); } + public validate(c: UntypedFormControl) { + const valid = this.metadataFormGroup.valid; + return valid ? null : { + metadata: { + valid: false, + }, + }; + } + private updateModel() { const metadata: IotSvgMetadata = this.metadataFormGroup.getRawValue(); this.modelValue = metadata; diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts index 833f96ea67..cd25aa7063 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts @@ -17,11 +17,11 @@ import { AfterViewInit, Component, - ElementRef, + ElementRef, EventEmitter, Input, OnChanges, OnDestroy, - OnInit, + OnInit, Output, SimpleChanges, ViewChild, ViewContainerRef, @@ -47,6 +47,9 @@ export class ScadaSymbolEditorComponent implements OnInit, OnDestroy, AfterViewI @Input() data: ScadaSymbolEditorData; + @Output() + tags = new EventEmitter(); + scadaSymbolEditObject: ScadaSymbolEditObject; constructor(private viewContainerRef: ViewContainerRef) { @@ -58,6 +61,7 @@ export class ScadaSymbolEditorComponent implements OnInit, OnDestroy, AfterViewI ngAfterViewInit() { this.scadaSymbolEditObject = new ScadaSymbolEditObject(this.iotSvgShape.nativeElement, this.viewContainerRef); + this.scadaSymbolEditObject.tagsUpdated.subscribe(tags => this.tags.emit(tags)); if (this.data) { this.scadaSymbolEditObject.setContent(this.data.svgContent); } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html index b04247b916..82b415e570 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html @@ -29,14 +29,43 @@ [showCloseDetails]="false" headerHeightPx="64" headerTitle="{{symbolData?.imageResource?.title}}"> - +
+
+ + + + +
+
+
+ + +
+
+
- +