diff --git a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m-server.component.scss b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m-server.component.scss deleted file mode 100644 index 1c55a86d8b..0000000000 --- a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m-server.component.scss +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright © 2016-2021 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. - */ -:host ::ng-deep { - textarea.mat-input-element.cdk-textarea-autosize { - box-sizing: content-box; - } -} diff --git a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m-server.component.ts b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m-server.component.ts index d599927834..09b7014212 100644 --- a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m-server.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m-server.component.ts @@ -41,7 +41,7 @@ import { Subject } from 'rxjs'; @Component({ selector: 'tb-security-config-lwm2m-server', templateUrl: './security-config-lwm2m-server.component.html', - styleUrls: ['./security-config-lwm2m-server.component.scss'], + styleUrls: [], providers: [ { provide: NG_VALUE_ACCESSOR, diff --git a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.scss b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.scss index 0188fcd559..393d2a9ef8 100644 --- a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.scss +++ b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.scss @@ -27,8 +27,4 @@ .mat-tab-body { padding: 16px 0; } - - textarea.mat-input-element.cdk-textarea-autosize { - box-sizing: content-box; - } } diff --git a/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts index dc1da3d973..996e79d6bc 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { Store } from '@ngrx/store'; import { AppState } from '@app/core/core.state'; @@ -33,6 +33,8 @@ import { transportPayloadTypeTranslationMap, } from '@shared/models/device.models'; import { isDefinedAndNotNull } from '@core/utils'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'tb-coap-device-profile-transport-configuration', @@ -44,7 +46,7 @@ import { isDefinedAndNotNull } from '@core/utils'; multi: true }] }) -export class CoapDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit { +export class CoapDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { coapTransportDeviceTypes = Object.keys(CoapTransportDeviceType); @@ -56,6 +58,7 @@ export class CoapDeviceProfileTransportConfigurationComponent implements Control coapDeviceProfileTransportConfigurationFormGroup: FormGroup; + private destroy$ = new Subject(); private requiredValue: boolean; private transportPayloadTypeConfiguration = this.fb.group({ @@ -99,15 +102,23 @@ export class CoapDeviceProfileTransportConfigurationComponent implements Control }) } ); - this.coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType') - .valueChanges.subscribe(coapDeviceType => { + this.coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(coapDeviceType => { this.updateCoapDeviceTypeBasedControls(coapDeviceType, true); }); - this.coapDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { + this.coapDeviceProfileTransportConfigurationFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(() => { this.updateModel(); }); } + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + get coapDeviceTypeDefault(): boolean { const coapDeviceType = this.coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType').value; return coapDeviceType === CoapTransportDeviceType.DEFAULT; diff --git a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts index b95433d096..27dda6dc91 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts @@ -14,13 +14,15 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { Store } from '@ngrx/store'; import { AppState } from '@app/core/core.state'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { DeviceProfileConfiguration, DeviceProfileType } from '@shared/models/device.models'; import { deepClone } from '@core/utils'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'tb-device-profile-configuration', @@ -32,12 +34,14 @@ import { deepClone } from '@core/utils'; multi: true }] }) -export class DeviceProfileConfigurationComponent implements ControlValueAccessor, OnInit { +export class DeviceProfileConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { deviceProfileType = DeviceProfileType; deviceProfileConfigurationFormGroup: FormGroup; + private destroy$ = new Subject(); + private requiredValue: boolean; get required(): boolean { return this.requiredValue; @@ -69,11 +73,18 @@ export class DeviceProfileConfigurationComponent implements ControlValueAccessor this.deviceProfileConfigurationFormGroup = this.fb.group({ configuration: [null, Validators.required] }); - this.deviceProfileConfigurationFormGroup.valueChanges.subscribe(() => { + this.deviceProfileConfigurationFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(() => { this.updateModel(); }); } + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; if (this.disabled) { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html index fdc02f910a..711b72d615 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html @@ -15,112 +15,107 @@ limitations under the License. --> -
-
-
-
- - {{ 'device-profile.lwm2m.mode' | translate }} - - - {{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityMode]) }} - - - - - {{ 'device-profile.lwm2m.server-host' | translate }} - - - {{ 'device-profile.lwm2m.server-host' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - - - {{ 'device-profile.lwm2m.server-port' | translate }} - - - {{ 'device-profile.lwm2m.server-port' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - - - {{ 'device-profile.lwm2m.short-id' | translate }} - - - {{ 'device-profile.lwm2m.short-id' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - -
-
-
-
- - {{ 'device-profile.lwm2m.client-hold-off-time' | translate }} - - - {{ 'device-profile.lwm2m.client-hold-off-time' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - - - {{ 'device-profile.lwm2m.bootstrap-server-account-timeout' | translate }} - - - {{ 'device-profile.lwm2m.bootstrap-server-account-timeout' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - - - {{ 'device-profile.lwm2m.bootstrap-server' | translate }} - -
-
- - {{ 'device-profile.lwm2m.server-public-key' | translate }} - - {{serverPublicKey.value?.length || 0}}/{{lenMaxServerPublicKey}} - - {{ 'device-profile.lwm2m.server-public-key' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - - {{ 'device-profile.lwm2m.server-public-key' | translate }} - {{ 'device-profile.lwm2m.pattern_hex_dec' | translate: { - count: 0} }} - - - {{ 'device-profile.lwm2m.server-public-key' | translate }} - {{ 'device-profile.lwm2m.pattern_hex_dec' | translate: { - count: lenMaxServerPublicKey } }} - - -
-
+
+
+ + {{ 'device-profile.lwm2m.mode' | translate }} + + + {{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityMode]) }} + + + + + {{ 'device-profile.lwm2m.server-host' | translate }} + + + {{ 'device-profile.lwm2m.server-host' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + + + {{ 'device-profile.lwm2m.server-port' | translate }} + + + {{ 'device-profile.lwm2m.server-port' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + + + {{ 'device-profile.lwm2m.short-id' | translate }} + + + {{ 'device-profile.lwm2m.short-id' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + +
+
+ + {{ 'device-profile.lwm2m.client-hold-off-time' | translate }} + + + {{ 'device-profile.lwm2m.client-hold-off-time' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + + + {{ 'device-profile.lwm2m.bootstrap-server-account-timeout' | translate }} + + + {{ 'device-profile.lwm2m.bootstrap-server-account-timeout' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + + + {{ 'device-profile.lwm2m.bootstrap-server' | translate }} + +
+
+
+ + {{ 'device-profile.lwm2m.server-public-key' | translate }} + + {{serverPublicKey.value?.length || 0}}/{{lenMaxServerPublicKey}} + + {{ 'device-profile.lwm2m.server-public-key' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + + {{ 'device-profile.lwm2m.server-public-key' | translate }} + {{ 'device-profile.lwm2m.pattern_hex_dec' | translate: { + count: 0} }} + + + {{ 'device-profile.lwm2m.server-public-key' | translate }} + {{ 'device-profile.lwm2m.pattern_hex_dec' | translate: { + count: lenMaxServerPublicKey } }} + +
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html index a29605a527..1a783aa4f5 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html @@ -15,12 +15,12 @@ limitations under the License. --> -
+
-
+
{{ 'device-profile.lwm2m.client-only-observe-after-connect-label' | translate }}
-
- - -
-
- - -
+ + + +
@@ -58,94 +54,73 @@ - -
{{ 'device-profile.lwm2m.servers' | translate | uppercase }}
-
+ {{ 'device-profile.lwm2m.servers' | translate }}
-
-
- - {{ 'device-profile.lwm2m.short-id' | translate }} - - - {{ 'device-profile.lwm2m.short-id' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - - - {{ 'device-profile.lwm2m.lifetime' | translate }} - - - {{ 'device-profile.lwm2m.lifetime' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - - - {{ 'device-profile.lwm2m.default-min-period' | translate }} - - - {{ 'device-profile.lwm2m.default-min-period' | translate }} - {{ 'device-profile.lwm2m.required' | translate }} - - -
-
- - {{ 'device-profile.lwm2m.binding' | translate }} - - - {{ bindingModeTypeNamesMap.get(bindingModeType[bindingMode]) }} - - - -
-
- - {{ 'device-profile.lwm2m.notif-if-disabled' | translate }} - -
+
+ + {{ 'device-profile.lwm2m.short-id' | translate }} + + + {{ 'device-profile.lwm2m.short-id' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + + + {{ 'device-profile.lwm2m.lifetime' | translate }} + + + {{ 'device-profile.lwm2m.lifetime' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + + + + {{ 'device-profile.lwm2m.default-min-period' | translate }} + + + {{ 'device-profile.lwm2m.default-min-period' | translate }} + {{ 'device-profile.lwm2m.required' | translate }} + +
+ + {{ 'device-profile.lwm2m.binding' | translate }} + + + {{ bindingModeTypeNamesMap.get(bindingModeType[bindingMode]) }} + + + + + {{ 'device-profile.lwm2m.notif-if-disabled' | translate }} + - - - -
{{ 'device-profile.lwm2m.bootstrap-server' | translate | uppercase }}
-
+ {{ 'device-profile.lwm2m.bootstrap-server' | translate }}
-
- - -
+ +
-
- - -
{{ 'device-profile.lwm2m.lwm2m-server' | translate | uppercase }}
-
+ {{ 'device-profile.lwm2m.lwm2m-server' | translate }}
-
- - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts index 0a943ab5af..eda01c0584 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts @@ -15,7 +15,7 @@ /// import { DeviceProfileTransportConfiguration } from '@shared/models/device.models'; -import { Component, forwardRef, Input } from '@angular/core'; +import { Component, forwardRef, Input, OnDestroy } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { @@ -39,6 +39,8 @@ import { deepClone, isDefinedAndNotNull, isEmpty, isUndefined } from '@core/util import { JsonArray, JsonObject } from '@angular/compiler-cli/ngcc/src/packages/entry_point'; import { Direction } from '@shared/models/page/sort-order'; import _ from 'lodash'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'tb-profile-lwm2m-device-transport-configuration', @@ -49,11 +51,12 @@ import _ from 'lodash'; multi: true }] }) -export class Lwm2mDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, Validators { +export class Lwm2mDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, Validators, OnDestroy { private configurationValue: Lwm2mProfileConfigModels; private requiredValue: boolean; private disabled = false; + private destroy$ = new Subject(); bindingModeType = BINDING_MODE; bindingModeTypes = Object.keys(BINDING_MODE); @@ -87,17 +90,21 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro lifetime: [null, Validators.required], defaultMinPeriod: [null, Validators.required], notifIfDisabled: [true, []], - binding:[], + binding: [], bootstrapServer: [null, Validators.required], lwm2mServer: [null, Validators.required], }); this.lwm2mDeviceConfigFormGroup = this.fb.group({ configurationJson: [null, Validators.required] }); - this.lwm2mDeviceProfileFormGroup.valueChanges.subscribe((value) => { + this.lwm2mDeviceProfileFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { this.updateDeviceProfileValue(value); }); - this.lwm2mDeviceConfigFormGroup.valueChanges.subscribe(() => { + this.lwm2mDeviceConfigFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(() => { this.updateModel(); }); this.sortFunction = this.sortObjectKeyPathJson; @@ -110,6 +117,11 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro registerOnTouched(fn: any): void { } + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; if (isDisabled) { @@ -122,11 +134,17 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro } writeValue(value: Lwm2mProfileConfigModels | null): void { - this.configurationValue = (Object.keys(value).length === 0) ? getDefaultProfileConfig() : value; - this.lwm2mDeviceConfigFormGroup.patchValue({ - configurationJson: this.configurationValue - }, {emitEvent: false}); - this.initWriteValue(); + if (isDefinedAndNotNull(value)) { + if (Object.keys(value).length !== 0 && (value?.clientLwM2mSettings || value?.observeAttr || value?.bootstrap)) { + this.configurationValue = value; + } else { + this.configurationValue = getDefaultProfileConfig(); + } + this.lwm2mDeviceConfigFormGroup.patchValue({ + configurationJson: this.configurationValue + }, {emitEvent: false}); + this.initWriteValue(); + } } private initWriteValue = (): void => { @@ -252,7 +270,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro instanceUpdate.id = instanceId; instanceUpdate.resources.forEach(resource => { resource.keyName = _.camelCase(resource.name + instanceUpdate.id); - }) + }); return instanceUpdate; } diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts index 8f1f676769..ae7c3ccdc6 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts @@ -15,10 +15,19 @@ /// import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core'; -import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; +import { + ControlValueAccessor, + FormBuilder, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + Validator, + Validators +} from '@angular/forms'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { Observable } from 'rxjs'; -import { filter, map, mergeMap, publishReplay, refCount, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, mergeMap, share, tap } from 'rxjs/operators'; import { ModelValue, ObjectLwM2M, PAGE_SIZE_LIMIT } from './lwm2m-profile-config.models'; import { DeviceProfileService } from '@core/http/device-profile.service'; import { Direction } from '@shared/models/page/sort-order'; @@ -33,13 +42,18 @@ import { PageLink } from '@shared/models/page/page-link'; provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Lwm2mObjectListComponent), multi: true - }] + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mObjectListComponent), + multi: true + } + ] }) -export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, Validators { +export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, Validator { private requiredValue: boolean; private dirty = false; - private lw2mModels: Observable>; private modelValue: Array = []; lwm2mListFormGroup: FormGroup; @@ -78,8 +92,8 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V } private updateValidators = (): void => { - this.lwm2mListFormGroup.get('objectLwm2m').setValidators(this.required ? [Validators.required] : []); - this.lwm2mListFormGroup.get('objectLwm2m').updateValueAndValidity(); + this.lwm2mListFormGroup.get('objectsList').setValidators(this.required ? [Validators.required] : []); + this.lwm2mListFormGroup.get('objectsList').updateValueAndValidity(); } registerOnChange(fn: any): void { @@ -92,6 +106,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V ngOnInit() { this.filteredObjectsList = this.lwm2mListFormGroup.get('objectLwm2m').valueChanges .pipe( + distinctUntilChanged(), tap((value) => { if (value && typeof value !== 'string') { this.add(value); @@ -100,7 +115,8 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V } }), filter(searchText => isString(searchText)), - mergeMap(searchText => this.fetchListObjects(searchText)) + mergeMap(searchText => this.fetchListObjects(searchText)), + share() ); } @@ -131,6 +147,12 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V } } + validate(): ValidationErrors | null { + return this.lwm2mListFormGroup.valid ? null : { + lwm2mListObj: false + }; + } + private add(object: ObjectLwM2M): void { if (isDefinedAndNotNull(this.modelValue) && this.modelValue.indexOf(object.keyId) === -1) { this.modelValue.push(object.keyId); @@ -157,23 +179,13 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V return object ? object.name : undefined; } - private fetchListObjects = (searchText?: string): Observable> => { + private fetchListObjects = (searchText: string): Observable> => { this.searchText = searchText; - return this.getLwM2mModelsPage().pipe( - map(objectLwM2Ms => objectLwM2Ms) - ); - } - - private getLwM2mModelsPage(): Observable> { const pageLink = new PageLink(PAGE_SIZE_LIMIT, 0, this.searchText, { property: 'id', direction: Direction.ASC }); - this.lw2mModels = this.deviceProfileService.getLwm2mObjectsPage(pageLink).pipe( - publishReplay(1), - refCount() - ); - return this.lw2mModels; + return this.deviceProfileService.getLwm2mObjectsPage(pageLink); } onFocus = (): void => { @@ -183,10 +195,9 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V } } - private clear = (value: string = ''): void => { - this.objectInput.nativeElement.value = value; + private clear = (): void => { this.searchText = ''; - this.lwm2mListFormGroup.get('objectLwm2m').patchValue(value); + this.lwm2mListFormGroup.get('objectLwm2m').patchValue(null); setTimeout(() => { this.objectInput.nativeElement.blur(); this.objectInput.nativeElement.focus(); diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.html index e58861c1eb..3ee9bffa27 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
@@ -46,14 +46,14 @@
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.html index 759e880ffa..02d594905d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.html @@ -16,7 +16,7 @@ -->
- + diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.scss b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.scss index 2de6fe17d6..afed0db1ff 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.scss +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.scss @@ -24,6 +24,9 @@ } :host{ + section { + padding: 2px; + } .instance-list { mat-expansion-panel-header { color: inherit; diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts index acea41394a..b719ca9ad6 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts @@ -64,7 +64,7 @@ export const BINDING_MODE_NAMES = new Map( [BINDING_MODE.UQ, 'UQ: UDP connection in queue mode'], [BINDING_MODE.US, 'US: both UDP and SMS connections active, both in standard mode'], [BINDING_MODE.UQS, 'UQS: both UDP and SMS connections active; UDP in queue mode, SMS in standard mode'], - [BINDING_MODE.T,'T: TCP connection in standard mode'], + [BINDING_MODE.T, 'T: TCP connection in standard mode'], [BINDING_MODE.TQ, 'TQ: TCP connection in queue mode'], [BINDING_MODE.TS, 'TS: both TCP and SMS connections active, both in standard mode'], [BINDING_MODE.TQS, 'TQS: both TCP and SMS connections active; TCP in queue mode, SMS in standard mode'], @@ -162,7 +162,6 @@ export interface Lwm2mProfileConfigModels { clientLwM2mSettings: ClientLwM2mSettings; observeAttr: ObservableAttributes; bootstrap: BootstrapSecurityConfig; - } export interface ClientLwM2mSettings { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts index 381e2f9e8d..0cbb50ed8e 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, @@ -39,6 +39,8 @@ import { transportPayloadTypeTranslationMap } from '@shared/models/device.models'; import { isDefinedAndNotNull } from '@core/utils'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'tb-mqtt-device-profile-transport-configuration', @@ -50,7 +52,7 @@ import { isDefinedAndNotNull } from '@core/utils'; multi: true }] }) -export class MqttDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit { +export class MqttDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { transportPayloadTypes = Object.keys(TransportPayloadType); @@ -58,6 +60,7 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control mqttDeviceProfileTransportConfigurationFormGroup: FormGroup; + private destroy$ = new Subject(); private requiredValue: boolean; get required(): boolean { @@ -98,15 +101,23 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control }) }, {validator: this.uniqueDeviceTopicValidator} ); - this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType') - .valueChanges.subscribe(payloadType => { + this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(payloadType => { this.updateTransportPayloadBasedControls(payloadType, true); }); - this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { + this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(() => { this.updateModel(); }); } + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; if (this.disabled) { @@ -192,8 +203,8 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control } private uniqueDeviceTopicValidator(control: FormGroup): { [key: string]: boolean } | null { - if (control.value) { - const formValue = control.value as MqttDeviceProfileTransportConfiguration; + if (control.getRawValue()) { + const formValue = control.getRawValue() as MqttDeviceProfileTransportConfiguration; if (formValue.deviceAttributesTopic === formValue.deviceTelemetryTopic) { return {unique: true}; } diff --git a/ui-ngx/src/app/modules/home/components/profile/device/snmp-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/snmp-device-profile-transport-configuration.component.ts index 96f7454cba..e6749a9219 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/snmp-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/snmp-device-profile-transport-configuration.component.ts @@ -14,17 +14,19 @@ /// limitations under the License. /// -import {Component, forwardRef, Input, OnInit} from '@angular/core'; -import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators} from '@angular/forms'; -import {Store} from '@ngrx/store'; -import {AppState} from '@app/core/core.state'; -import {coerceBooleanProperty} from '@angular/cdk/coercion'; +import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@app/core/core.state'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { DeviceProfileTransportConfiguration, DeviceTransportType, SnmpDeviceProfileTransportConfiguration } from '@shared/models/device.models'; -import {isDefinedAndNotNull} from "@core/utils"; +import { isDefinedAndNotNull } from '@core/utils'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; export interface OidMappingConfiguration { isAttribute: boolean; @@ -44,8 +46,11 @@ export interface OidMappingConfiguration { multi: true }] }) -export class SnmpDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit { +export class SnmpDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { + snmpDeviceProfileTransportConfigurationFormGroup: FormGroup; + + private destroy$ = new Subject(); private requiredValue: boolean; private configuration = []; @@ -71,11 +76,18 @@ export class SnmpDeviceProfileTransportConfigurationComponent implements Control this.snmpDeviceProfileTransportConfigurationFormGroup = this.fb.group({ configuration: [null, Validators.required] }); - this.snmpDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { + this.snmpDeviceProfileTransportConfigurationFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(() => { this.updateModel(); }); } + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + registerOnChange(fn: any): void { this.propagateChange = fn; } diff --git a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts index 804b349cff..2c53f04986 100644 --- a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts @@ -32,7 +32,7 @@ import { }) export class DeviceProfileTabsComponent extends EntityTabsComponent { - deviceTransportTypes = Object.keys(DeviceTransportType); + deviceTransportTypes = Object.values(DeviceTransportType); deviceTransportTypeTranslations = deviceTransportTypeTranslationMap;