From 5387f545d60377540ec31aade2a6c35f8fe2a0eb Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 8 Sep 2023 16:47:44 +0300 Subject: [PATCH 1/9] edge downlink table - fixed error in case unknown entity type or action. added missing types/actions --- .../components/edge/edge-downlink-table-config.ts | 10 ++++++++-- ui-ngx/src/app/shared/models/edge.models.ts | 14 ++++++++++++-- .../src/assets/locale/locale.constant-en_US.json | 5 +++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts index 5889ebcdf2..f970ad80f4 100644 --- a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts @@ -107,9 +107,15 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig('createdTime', 'event.event-time', this.datePipe, '120px'), new EntityTableColumn('type', 'event.type', '25%', - entity => this.translate.instant(edgeEventTypeTranslations.get(entity.type)), entity => ({}), false), + entity => { + let key = edgeEventTypeTranslations.get(entity.type); + return key ? this.translate.instant(key) : entity.type; + }, entity => ({}), false), new EntityTableColumn('action', 'edge.event-action', '25%', - entity => this.translate.instant(edgeEventActionTypeTranslations.get(entity.action)), entity => ({}), false), + entity => { + let key = edgeEventActionTypeTranslations.get(entity.action); + return key ? this.translate.instant(key) : entity.action; + }, entity => ({}), false), new EntityTableColumn('entityId', 'edge.entity-id', '40%', (entity) => entity.entityId ? entity.entityId : '', () => ({}), false), new EntityTableColumn('status', 'event.status', '10%', diff --git a/ui-ngx/src/app/shared/models/edge.models.ts b/ui-ngx/src/app/shared/models/edge.models.ts index 372a910402..1acfa2ca28 100644 --- a/ui-ngx/src/app/shared/models/edge.models.ts +++ b/ui-ngx/src/app/shared/models/edge.models.ts @@ -59,9 +59,12 @@ export enum EdgeEventType { CUSTOMER = 'CUSTOMER', RELATION = 'RELATION', TENANT = 'TENANT', + TENANT_PROFILE = 'TENANT_PROFILE', WIDGETS_BUNDLE = 'WIDGETS_BUNDLE', WIDGET_TYPE = 'WIDGET_TYPE', - ADMIN_SETTINGS = 'ADMIN_SETTINGS' + ADMIN_SETTINGS = 'ADMIN_SETTINGS', + OTA_PACKAGE = 'OTA_PACKAGE', + QUEUE = 'QUEUE' } export enum EdgeEventActionType { @@ -80,6 +83,8 @@ export enum EdgeEventActionType { RPC_CALL = 'RPC_CALL', ALARM_ACK = 'ALARM_ACK', ALARM_CLEAR = 'ALARM_CLEAR', + ALARM_ASSIGNED = 'ALARM_ASSIGNED', + ALARM_UNASSIGNED = 'ALARM_UNASSIGNED', ASSIGNED_TO_EDGE = 'ASSIGNED_TO_EDGE', UNASSIGNED_FROM_EDGE = 'UNASSIGNED_FROM_EDGE', CREDENTIALS_REQUEST = 'CREDENTIALS_REQUEST', @@ -107,9 +112,12 @@ export const edgeEventTypeTranslations = new Map( [EdgeEventType.CUSTOMER, 'edge-event.type-customer'], [EdgeEventType.RELATION, 'edge-event.type-relation'], [EdgeEventType.TENANT, 'edge-event.type-tenant'], + [EdgeEventType.TENANT_PROFILE, 'edge-event.type-tenant-profile'], [EdgeEventType.WIDGETS_BUNDLE, 'edge-event.type-widgets-bundle'], [EdgeEventType.WIDGET_TYPE, 'edge-event.type-widgets-type'], - [EdgeEventType.ADMIN_SETTINGS, 'edge-event.type-admin-settings'] + [EdgeEventType.ADMIN_SETTINGS, 'edge-event.type-admin-settings'], + [EdgeEventType.OTA_PACKAGE, 'edge-event.type-ota-package'], + [EdgeEventType.QUEUE, 'edge-event.type-queue'] ] ); @@ -130,6 +138,8 @@ export const edgeEventActionTypeTranslations = new Map Date: Fri, 8 Sep 2023 16:53:33 +0300 Subject: [PATCH 2/9] UI: changed validation hints of add telemetry dialog to more precise --- .../attribute/add-attribute-dialog.component.html | 6 +++--- .../components/attribute/add-attribute-dialog.component.ts | 5 ++--- ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 ++ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.html b/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.html index 17e31854cc..af2a959424 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.html @@ -17,7 +17,7 @@ -->
-

{{ title | translate }}

+

{{ (isTelemetry ? 'attribute.add-telemetry' : 'attribute.add') | translate }}

diff --git a/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts b/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts index aadb96c142..dc13dac0df 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts @@ -72,6 +72,11 @@ export class AddAttributeDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts b/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts index 539c9930db..4ce038a4ed 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts @@ -62,6 +62,11 @@ export class EditAttributeValuePanelComponent extends PageComponent implements O return originalErrorState || customErrorState; } + invalid(): boolean { + const value = this.attributeFormGroup.get('value').value; + return !Array.isArray(value) && this.attributeFormGroup.invalid; + } + cancel(): void { this.overlayRef.dispose(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html index 6e4178fccd..f3aefedbce 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html @@ -179,7 +179,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.ts index 9840db6efe..0314120995 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.ts @@ -286,6 +286,7 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { jsonValue: config, + required: true, title: this.translate.instant('gateway.title-connectors-json', {typeName: type}) } }).afterClosed().subscribe( diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts index dbda5f4db2..941731f7e0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts @@ -31,6 +31,7 @@ import { JsonObjectEditDialogComponent, JsonObjectEditDialogData } from '@shared/components/dialog/json-object-edit-dialog.component'; +import { jsonRequired } from '@shared/components/json-object-edit.component'; @Component({ @@ -77,7 +78,7 @@ export class GatewayServiceRPCComponent extends PageComponent implements AfterVi this.commandForm = this.fb.group({ command: [null,[Validators.required]], time: [60, [Validators.required, Validators.min(1)]], - params: ["{}", [Validators.required]], + params: [{}, [jsonRequired]], result: [null] }) @@ -114,7 +115,8 @@ export class GatewayServiceRPCComponent extends PageComponent implements AfterVi disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { - jsonValue: JSON.parse(this.commandForm.get('params').value) + jsonValue: JSON.parse(this.commandForm.get('params').value), + required: true } }).afterClosed().subscribe( (res) => { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html index 24fe07d92b..40636a9d1b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html @@ -26,14 +26,14 @@ -
+
- - + {{ getErrorMessageText(key.settings,'required') }} @@ -193,7 +193,7 @@
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts index d4c0ad2630..eb3b0c9abf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts @@ -604,7 +604,8 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni } public inputChanged(source: MultipleInputWidgetSource, key: MultipleInputWidgetDataKey) { - if (!this.settings.showActionButtons && !this.isSavingInProgress && this.multipleInputFormGroup.get(key.formId).valid) { + const control = this.multipleInputFormGroup.get(key.formId); + if (!this.settings.showActionButtons && !this.isSavingInProgress && (Array.isArray(control.value) || control.valid)) { this.isSavingInProgress = true; const dataToSave: MultipleInputWidgetSource = { datasource: source.datasource, @@ -775,6 +776,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { jsonValue: formControl.value, + required: key.settings.required, title: key.settings.dialogTitle, saveLabel: key.settings.saveButtonLabel, cancelLabel: key.settings.cancelButtonLabel @@ -791,4 +793,16 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni } ); } + + invalid(): boolean { + for (const source of this.sources) { + for (const key of this.visibleKeys(source)) { + const control = this.multipleInputFormGroup.get(key.formId); + if (!Array.isArray(control.value) && control.invalid) { + return true; + } + } + } + return false; + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html index 732d6e3119..cdd1d8e2da 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html @@ -89,7 +89,6 @@ diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.html index 97f2214f2e..6d059fddec 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.html @@ -22,7 +22,7 @@ class="tb-rule-node-configuration-json" formControlName="configuration" [label]="'rulenode.configuration' | translate" - [required]="required" + [jsonRequired]="required" [fillHeight]="true">
diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html index 141979d8ff..3b216bda71 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html @@ -33,8 +33,7 @@ diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts index e55431a327..4aeed2a360 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts @@ -26,6 +26,7 @@ import { isNotEmptyStr } from '@core/utils'; export interface JsonObjectEditDialogData { jsonValue: object; + required?: boolean; title?: string; saveLabel?: string; cancelLabel?: string; @@ -43,6 +44,8 @@ export class JsonObjectEditDialogComponent extends DialogComponent, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: JsonObjectEditDialogData, diff --git a/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts b/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts index 8da5fb1396..c70de1ab48 100644 --- a/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts +++ b/ui-ngx/src/app/shared/components/directives/tb-json-to-string.directive.ts @@ -17,19 +17,23 @@ import { Directive, ElementRef, forwardRef, HostListener, Renderer2, SkipSelf } from '@angular/core'; import { ControlValueAccessor, - UntypedFormControl, FormGroupDirective, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgForm, + UntypedFormControl, ValidationErrors, Validator } from '@angular/forms'; import { ErrorStateMatcher } from '@angular/material/core'; -import { isObject } from "@core/utils"; +import { isObject } from '@core/utils'; @Directive({ selector: '[tb-json-to-string]', + // eslint-disable-next-line @angular-eslint/no-host-metadata-property + host: { + '(blur)': 'onTouched()' + }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TbJsonToStringDirective), @@ -48,18 +52,26 @@ import { isObject } from "@core/utils"; export class TbJsonToStringDirective implements ControlValueAccessor, Validator, ErrorStateMatcher { private propagateChange = null; + public onTouched = () => {}; private parseError: boolean; private data: any; @HostListener('input', ['$event.target.value']) input(newValue: any): void { try { - this.data = JSON.parse(newValue); - if (isObject(this.data)) { - this.parseError = false; + if (newValue) { + this.data = JSON.parse(newValue); + if (isObject(this.data)) { + this.parseError = false; + } else { + this.data = null; + this.parseError = true; + } } else { - this.parseError = true; + this.data = null; + this.parseError = false; } } catch (e) { + this.data = null; this.parseError = true; } @@ -73,9 +85,7 @@ export class TbJsonToStringDirective implements ControlValueAccessor, Validator, } isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean { - const originalErrorState = this.errorStateMatcher.isErrorState(control, form); - const customErrorState = !!(control && control.invalid && this.parseError); - return originalErrorState || customErrorState; + return !!(control && control.invalid && !Array.isArray(control.value) && control.touched); } validate(c: UntypedFormControl): ValidationErrors { @@ -87,11 +97,9 @@ export class TbJsonToStringDirective implements ControlValueAccessor, Validator, } writeValue(obj: any): void { - if (obj) { - this.data = obj; - this.parseError = false; - this.render.setProperty(this.element.nativeElement, 'value', JSON.stringify(obj)); - } + this.data = obj; + this.parseError = false; + this.render.setProperty(this.element.nativeElement, 'value', obj ? JSON.stringify(obj) : ''); } registerOnChange(fn: any): void { @@ -99,5 +107,6 @@ export class TbJsonToStringDirective implements ControlValueAccessor, Validator, } registerOnTouched(fn: any): void { + this.onTouched = fn; } } diff --git a/ui-ngx/src/app/shared/components/json-object-edit.component.html b/ui-ngx/src/app/shared/components/json-object-edit.component.html index c0024da9dd..3ed828e6cf 100644 --- a/ui-ngx/src/app/shared/components/json-object-edit.component.html +++ b/ui-ngx/src/app/shared/components/json-object-edit.component.html @@ -20,7 +20,7 @@ [fullscreen]="fullscreen" (fullscreenChanged)="onFullscreen()" fxLayout="column">
diff --git a/ui-ngx/src/app/shared/components/json-object-edit.component.ts b/ui-ngx/src/app/shared/components/json-object-edit.component.ts index f7e3116b0f..f89430f98b 100644 --- a/ui-ngx/src/app/shared/components/json-object-edit.component.ts +++ b/ui-ngx/src/app/shared/components/json-object-edit.component.ts @@ -24,7 +24,14 @@ import { OnInit, ViewChild } from '@angular/core'; -import { ControlValueAccessor, UntypedFormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms'; +import { + ControlValueAccessor, + UntypedFormControl, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + Validator, + AbstractControl, ValidationErrors +} from '@angular/forms'; import { Ace } from 'ace-builds'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions'; @@ -34,6 +41,9 @@ import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { guid, isDefinedAndNotNull, isObject, isUndefined } from '@core/utils'; import { ResizeObserver } from '@juggle/resize-observer'; import { getAce } from '@shared/models/ace/ace.models'; +import { coerceBoolean } from '@shared/decorators/coercion'; + +export const jsonRequired = (control: AbstractControl): ValidationErrors | null => !control.value ? {required: true} : null; @Component({ selector: 'tb-json-object-edit', @@ -73,27 +83,13 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va @Input() sort: (key: string, value: any) => any; - private requiredValue: boolean; - - get required(): boolean { - return this.requiredValue; - } - + @coerceBoolean() @Input() - set required(value: boolean) { - this.requiredValue = coerceBooleanProperty(value); - } - - private readonlyValue: boolean; - - get readonly(): boolean { - return this.readonlyValue; - } + jsonRequired: boolean; + @coerceBoolean() @Input() - set readonly(value: boolean) { - this.readonlyValue = coerceBooleanProperty(value); - } + readonly: boolean; fullscreen = false; @@ -245,12 +241,10 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va try { if (isDefinedAndNotNull(this.modelValue)) { this.contentValue = JSON.stringify(this.modelValue, isUndefined(this.sort) ? undefined : - (key, objectValue) => { - return this.sort(key, objectValue); - }, 2); + (key, objectValue) => this.sort(key, objectValue), 2); this.objectValid = true; } else { - this.objectValid = !this.required; + this.objectValid = !this.jsonRequired; this.validationError = 'Json object is required.'; } } catch (e) { @@ -288,8 +282,8 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va this.validationError = errorInfo; } } else { - this.objectValid = !this.required; - this.validationError = this.required ? 'Json object is required.' : ''; + this.objectValid = !this.jsonRequired; + this.validationError = this.jsonRequired ? 'Json object is required.' : ''; } this.modelValue = data; this.propagateChange(data); diff --git a/ui-ngx/src/app/shared/components/value-input.component.html b/ui-ngx/src/app/shared/components/value-input.component.html index 57d6954699..9f7f9d0ffc 100644 --- a/ui-ngx/src/app/shared/components/value-input.component.html +++ b/ui-ngx/src/app/shared/components/value-input.component.html @@ -67,7 +67,7 @@ - + {{ (requiredText ? requiredText : 'value.json-value-required') | translate }} diff --git a/ui-ngx/src/app/shared/components/value-input.component.ts b/ui-ngx/src/app/shared/components/value-input.component.ts index 4ba7abf157..52828cec35 100644 --- a/ui-ngx/src/app/shared/components/value-input.component.ts +++ b/ui-ngx/src/app/shared/components/value-input.component.ts @@ -15,7 +15,7 @@ /// import { Component, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm } from '@angular/forms'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm, NgModel } from '@angular/forms'; import { ValueType, valueTypesMap } from '@shared/models/constants'; import { isObject } from '@core/utils'; import { MatDialog } from '@angular/material/dialog'; @@ -23,6 +23,7 @@ import { JsonObjectEditDialogComponent, JsonObjectEditDialogData } from '@shared/components/dialog/json-object-edit-dialog.component'; +import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ selector: 'tb-value-input', @@ -73,7 +74,8 @@ export class ValueInputComponent implements OnInit, ControlValueAccessor { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { - jsonValue: this.modelValue + jsonValue: this.modelValue, + required: true } }).afterClosed().subscribe( (res) => { @@ -115,7 +117,8 @@ export class ValueInputComponent implements OnInit, ControlValueAccessor { } updateView() { - if (this.inputForm.valid || this.valueType === ValueType.BOOLEAN) { + if (this.inputForm.valid || this.valueType === ValueType.BOOLEAN || + (this.valueType === ValueType.JSON && Array.isArray(this.modelValue))) { this.propagateChange(this.modelValue); } else { this.propagateChange(null); From b3a8ce17be81fd97608eb993e413c680e1806603 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 12 Sep 2023 13:08:59 +0300 Subject: [PATCH 9/9] UI: Code cleanup --- ui-ngx/src/app/shared/components/value-input.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui-ngx/src/app/shared/components/value-input.component.ts b/ui-ngx/src/app/shared/components/value-input.component.ts index 52828cec35..6d57b1ddd2 100644 --- a/ui-ngx/src/app/shared/components/value-input.component.ts +++ b/ui-ngx/src/app/shared/components/value-input.component.ts @@ -15,7 +15,7 @@ /// import { Component, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm, NgModel } from '@angular/forms'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm } from '@angular/forms'; import { ValueType, valueTypesMap } from '@shared/models/constants'; import { isObject } from '@core/utils'; import { MatDialog } from '@angular/material/dialog'; @@ -23,7 +23,6 @@ import { JsonObjectEditDialogComponent, JsonObjectEditDialogData } from '@shared/components/dialog/json-object-edit-dialog.component'; -import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ selector: 'tb-value-input',