From 3cf97e0a4f811e99240a545c9777b78015a4e96e Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 6 Jul 2021 17:50:20 +0300 Subject: [PATCH 1/4] UI: Init models for transport type switch --- .../device/device-credentials.component.ts | 6 +++- .../device-credentials-dialog.component.html | 1 + .../device-credentials-dialog.component.ts | 32 +++++++++---------- .../device/devices-table-config.resolver.ts | 4 ++- ui-ngx/src/app/shared/models/device.models.ts | 14 ++++++++ 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts index 21c8d40a42..a7d4b8008b 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts @@ -31,7 +31,8 @@ import { credentialTypeNames, DeviceCredentialMQTTBasic, DeviceCredentials, - DeviceCredentialsType + DeviceCredentialsType, + DeviceTransportType } from '@shared/models/device.models'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -58,6 +59,9 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, @Input() disabled: boolean; + @Input() + deviceTransportType = DeviceTransportType.DEFAULT; + private destroy$ = new Subject(); deviceCredentialsFormGroup: FormGroup; diff --git a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html index 75d6beaaed..d246f3e1c6 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html @@ -31,6 +31,7 @@
diff --git a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts index dca62cd081..fe00156800 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts @@ -21,13 +21,16 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms'; import { DeviceService } from '@core/http/device.service'; -import { credentialTypeNames, DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models'; +import { DeviceCredentials, DeviceProfileInfo, DeviceTransportType } from '@shared/models/device.models'; import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; +import { DeviceProfileService } from '@core/http/device-profile.service'; +import { forkJoin } from 'rxjs'; export interface DeviceCredentialsDialogData { isReadOnly: boolean; deviceId: string; + deviceProfileId: string; } @Component({ @@ -47,18 +50,13 @@ export class DeviceCredentialsDialogComponent extends submitted = false; - deviceCredentialsType = DeviceCredentialsType; - - credentialsTypes = Object.keys(DeviceCredentialsType); - - credentialTypeNamesMap = credentialTypeNames; - - hidePassword = true; + deviceTransportType: DeviceTransportType; constructor(protected store: Store, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: DeviceCredentialsDialogData, private deviceService: DeviceService, + private deviceProfileService: DeviceProfileService, @SkipSelf() private errorStateMatcher: ErrorStateMatcher, public dialogRef: MatDialogRef, public fb: FormBuilder) { @@ -84,14 +82,16 @@ export class DeviceCredentialsDialogComponent extends } loadDeviceCredentials() { - this.deviceService.getDeviceCredentials(this.data.deviceId).subscribe( - (deviceCredentials) => { - this.deviceCredentials = deviceCredentials; - this.deviceCredentialsFormGroup.patchValue({ - credential: deviceCredentials - }, {emitEvent: false}); - } - ); + const task = []; + task.push(this.deviceService.getDeviceCredentials(this.data.deviceId)); + task.push(this.deviceProfileService.getDeviceProfileInfo(this.data.deviceProfileId)); + forkJoin(task).subscribe(([deviceCredentials, deviceProfile]: [DeviceCredentials, DeviceProfileInfo]) => { + this.deviceTransportType = deviceProfile.transportType; + this.deviceCredentials = deviceCredentials; + this.deviceCredentialsFormGroup.patchValue({ + credential: deviceCredentials + }, {emitEvent: false}); + }); } cancel(): void { diff --git a/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts index 363117a2a4..516e0efa57 100644 --- a/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts @@ -112,7 +112,8 @@ export class DevicesTableConfigResolver implements Resolve this.onDeviceAction(action); - this.config.detailsReadonly = () => (this.config.componentsData.deviceScope === 'customer_user' || this.config.componentsData.deviceScope === 'edge_customer_user'); + this.config.detailsReadonly = () => + (this.config.componentsData.deviceScope === 'customer_user' || this.config.componentsData.deviceScope === 'edge_customer_user'); this.config.headerComponent = DeviceTableHeaderComponent; @@ -528,6 +529,7 @@ export class DevicesTableConfigResolver implements Resolve { diff --git a/ui-ngx/src/app/shared/models/device.models.ts b/ui-ngx/src/app/shared/models/device.models.ts index 2c09d64113..ba2a7aefd9 100644 --- a/ui-ngx/src/app/shared/models/device.models.ts +++ b/ui-ngx/src/app/shared/models/device.models.ts @@ -680,6 +680,20 @@ export const credentialTypeNames = new Map( ] ); +export const credentialTypesByTransportType = new Map( + [ + [DeviceTransportType.DEFAULT, [ + DeviceCredentialsType.ACCESS_TOKEN, DeviceCredentialsType.X509_CERTIFICATE, DeviceCredentialsType.MQTT_BASIC + ]], + [DeviceTransportType.MQTT, [ + DeviceCredentialsType.ACCESS_TOKEN, DeviceCredentialsType.X509_CERTIFICATE, DeviceCredentialsType.MQTT_BASIC + ]], + [DeviceTransportType.COAP, [DeviceCredentialsType.ACCESS_TOKEN, DeviceCredentialsType.X509_CERTIFICATE]], + [DeviceTransportType.LWM2M, [DeviceCredentialsType.LWM2M_CREDENTIALS]], + [DeviceTransportType.SNMP, [DeviceCredentialsType.ACCESS_TOKEN, DeviceCredentialsType.X509_CERTIFICATE]] + ] +); + export interface DeviceCredentials extends BaseData { deviceId: DeviceId; credentialsType: DeviceCredentialsType; From 34453f26687180ccd1fcd83ca2a0e29e6a54a57b Mon Sep 17 00:00:00 2001 From: Vladyslav Prykhodko Date: Wed, 7 Jul 2021 00:21:34 +0300 Subject: [PATCH 2/4] UI: Device credential add processing deviceTransportType --- .../device/device-credentials.component.html | 2 +- .../device/device-credentials.component.ts | 18 ++++++++++++++++-- .../wizard/device-wizard-dialog.component.html | 4 +++- .../wizard/device-wizard-dialog.component.ts | 16 ++++++++++++++++ .../device-credentials-dialog.component.html | 2 +- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html index 0cf349a074..76c1fa13bb 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html @@ -16,7 +16,7 @@ -->
- + device.credentials-type diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts index a7d4b8008b..d558213ec4 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts @@ -29,6 +29,7 @@ import { } from '@angular/forms'; import { credentialTypeNames, + credentialTypesByTransportType, DeviceCredentialMQTTBasic, DeviceCredentials, DeviceCredentialsType, @@ -59,8 +60,21 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, @Input() disabled: boolean; + private deviceTransportTypeValue = DeviceTransportType.DEFAULT; + get deviceTransportType(): DeviceTransportType { + return this.deviceTransportTypeValue + } @Input() - deviceTransportType = DeviceTransportType.DEFAULT; + set deviceTransportType(type: DeviceTransportType) { + if (type) { + this.deviceTransportTypeValue = type; + this.credentialsTypes = credentialTypesByTransportType.get(type); + const currentType = this.deviceCredentialsFormGroup.get('credentialsType').value; + if (!this.credentialsTypes.includes(currentType)) { + this.deviceCredentialsFormGroup.get('credentialsType').patchValue(this.credentialsTypes[0], {onlySelf: true}); + } + } + } private destroy$ = new Subject(); @@ -68,7 +82,7 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, deviceCredentialsType = DeviceCredentialsType; - credentialsTypes = Object.values(DeviceCredentialsType); + credentialsTypes = credentialTypesByTransportType.get(DeviceTransportType.DEFAULT); credentialTypeNamesMap = credentialTypeNames; diff --git a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html index 54cf110d5b..75c0819527 100644 --- a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html @@ -64,7 +64,8 @@ [ngClass]="{invisible: deviceWizardFormGroup.get('addProfileType').value !== 0}" [addNewProfile]="false" [selectDefaultProfile]="true" - [editProfileEnabled]="false"> + [editProfileEnabled]="false" + (deviceProfileChanged)="deviceProfileChanged($event)"> @@ -154,6 +155,7 @@ {{ 'device.wizard.add-credentials' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts index b9c38d24dd..68e82fc7e1 100644 --- a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts @@ -25,6 +25,7 @@ import { createDeviceProfileConfiguration, createDeviceProfileTransportConfiguration, DeviceProfile, + DeviceProfileInfo, DeviceProfileType, DeviceProvisionConfiguration, DeviceProvisionType, @@ -91,6 +92,7 @@ export class DeviceWizardDialogComponent extends serviceType = ServiceType.TB_RULE_ENGINE; private subscriptions: Subscription[] = []; + private currentDeviceProfileTransportType = DeviceTransportType.DEFAULT; constructor(protected store: Store, protected router: Router, @@ -265,6 +267,20 @@ export class DeviceWizardDialogComponent extends } } + get deviceTransportType(): DeviceTransportType { + if (this.deviceWizardFormGroup.get('addProfileType').value) { + return this.transportConfigFormGroup.get('transportType').value; + } else { + return this.currentDeviceProfileTransportType; + } + } + + deviceProfileChanged(deviceProfile: DeviceProfileInfo) { + if (deviceProfile) { + this.currentDeviceProfileTransportType = deviceProfile.transportType; + } + } + private createDeviceProfile(): Observable { if (this.deviceWizardFormGroup.get('addProfileType').value) { const deviceProvisionConfiguration: DeviceProvisionConfiguration = this.provisionConfigFormGroup.get('provisionConfiguration').value; diff --git a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html index d246f3e1c6..8e1a67a8a9 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html @@ -17,7 +17,7 @@ -->
-

device.device-credentials

+

{{ 'device.device-credentials' | translate }}

+ + +
diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts new file mode 100644 index 0000000000..d4c88431a9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts @@ -0,0 +1,133 @@ +/// +/// 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. +/// + +import { Component, forwardRef, Input, OnDestroy } from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + Validator, + ValidatorFn, + Validators +} from '@angular/forms'; +import { Subject } from 'rxjs'; +import { DeviceCredentialMQTTBasic } from '@shared/models/device.models'; +import { takeUntil } from 'rxjs/operators'; +import { isDefinedAndNotNull, isEmptyStr } from '@core/utils'; + +@Component({ + selector: 'tb-device-credentials-mqtt-basic', + templateUrl: './device-credentials-mqtt-basic.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent), + multi: true, + }], + styleUrls: [] +}) +export class DeviceCredentialsMqttBasicComponent implements ControlValueAccessor, Validator, OnDestroy { + + @Input() + disabled: boolean; + + deviceCredentialsMqttFormGroup: FormGroup; + + hidePassword = true; + + private destroy$ = new Subject(); + private propagateChange = (v: any) => {}; + + constructor(public fb: FormBuilder) { + this.deviceCredentialsMqttFormGroup = this.fb.group({ + clientId: [null, [Validators.pattern(/^[A-Za-z0-9]+$/)]], + userName: [null], + password: [null] + }, {validators: this.atLeastOne(Validators.required, ['clientId', 'userName'])}); + this.deviceCredentialsMqttFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + this.updateView(value); + }); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void {} + + setDisabledState(isDisabled: boolean) { + this.disabled = isDisabled; + if (this.disabled) { + this.deviceCredentialsMqttFormGroup.disable({emitEvent: false}); + } else { + this.deviceCredentialsMqttFormGroup.enable({emitEvent: false}); + } + } + + validate(): ValidationErrors | null { + return this.deviceCredentialsMqttFormGroup.valid ? null : { + deviceCredentialsMqttBasic: false + }; + } + + writeValue(mqttBasic: string) { + if (isDefinedAndNotNull(mqttBasic) && !isEmptyStr(mqttBasic)) { + const value = JSON.parse(mqttBasic); + this.deviceCredentialsMqttFormGroup.patchValue(value, {emitEvent: false}); + } + } + + updateView(value: DeviceCredentialMQTTBasic) { + const formValue = JSON.stringify(value); + this.propagateChange(formValue); + } + + passwordChanged() { + const value = this.deviceCredentialsMqttFormGroup.get('password').value; + if (value !== '') { + this.deviceCredentialsMqttFormGroup.get('userName').setValidators([Validators.required]); + } else { + this.deviceCredentialsMqttFormGroup.get('userName').setValidators([]); + } + this.deviceCredentialsMqttFormGroup.get('userName').updateValueAndValidity({emitEvent: false}); + } + + private atLeastOne(validator: ValidatorFn, controls: string[] = null) { + return (group: FormGroup): ValidationErrors | null => { + if (!controls) { + controls = Object.keys(group.controls); + } + const hasAtLeastOne = group?.controls && controls.some(k => !validator(group.controls[k])); + + return hasAtLeastOne ? null : {atLeastOne: true}; + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html index 76c1fa13bb..76a9935565 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html @@ -24,58 +24,35 @@ - - device.access-token - - - {{ 'device.access-token-required' | translate }} - - - {{ 'device.access-token-invalid' | translate }} - - - - device.rsa-key - - - {{ 'device.rsa-key-required' | translate }} - - -
- - device.client-id - - - {{ 'device.client-id-pattern' | translate }} - - - - device.user-name - - - {{ 'device.user-name-required' | translate }} - - - - device.password - - - - -
-
- - +
+ + + device.access-token + + + {{ 'device.access-token-required' | translate }} + + + {{ 'device.access-token-invalid' | translate }} + + + + + + device.rsa-key + + + {{ 'device.rsa-key-required' | translate }} + + + + + + + + + + +
diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts index d558213ec4..3617ecbcf4 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts @@ -22,15 +22,12 @@ import { FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, - ValidationErrors, Validator, - ValidatorFn, Validators } from '@angular/forms'; import { credentialTypeNames, credentialTypesByTransportType, - DeviceCredentialMQTTBasic, DeviceCredentials, DeviceCredentialsType, DeviceTransportType @@ -62,7 +59,7 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, private deviceTransportTypeValue = DeviceTransportType.DEFAULT; get deviceTransportType(): DeviceTransportType { - return this.deviceTransportTypeValue + return this.deviceTransportTypeValue; } @Input() set deviceTransportType(type: DeviceTransportType) { @@ -86,22 +83,14 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, credentialTypeNamesMap = credentialTypeNames; - hidePassword = true; - private propagateChange = (v: any) => {}; constructor(public fb: FormBuilder) { this.deviceCredentialsFormGroup = this.fb.group({ credentialsType: [DeviceCredentialsType.ACCESS_TOKEN], credentialsId: [null], - credentialsValue: [null], - credentialsBasic: this.fb.group({ - clientId: [null, [Validators.pattern(/^[A-Za-z0-9]+$/)]], - userName: [null], - password: [null] - }, {validators: this.atLeastOne(Validators.required, ['clientId', 'userName'])}) + credentialsValue: [null] }); - this.deviceCredentialsFormGroup.get('credentialsBasic').disable(); this.deviceCredentialsFormGroup.valueChanges.pipe( takeUntil(this.destroy$) ).subscribe(() => { @@ -127,18 +116,11 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, writeValue(value: DeviceCredentials | null): void { if (isDefinedAndNotNull(value)) { - let credentialsBasic = {clientId: null, userName: null, password: null}; - let credentialsValue = null; - if (value.credentialsType === DeviceCredentialsType.MQTT_BASIC) { - credentialsBasic = JSON.parse(value.credentialsValue) as DeviceCredentialMQTTBasic; - } else { - credentialsValue = value.credentialsValue; - } + const credentialsType = this.credentialsTypes.includes(value.credentialsType) ? value.credentialsType : this.credentialsTypes[0]; this.deviceCredentialsFormGroup.patchValue({ - credentialsType: value.credentialsType, + credentialsType, credentialsId: value.credentialsId, - credentialsValue, - credentialsBasic + credentialsValue: value.credentialsValue }, {emitEvent: false}); this.updateValidators(); } @@ -146,10 +128,6 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, updateView() { const deviceCredentialsValue = this.deviceCredentialsFormGroup.value; - if (deviceCredentialsValue.credentialsType === DeviceCredentialsType.MQTT_BASIC) { - deviceCredentialsValue.credentialsValue = JSON.stringify(deviceCredentialsValue.credentialsBasic); - } - delete deviceCredentialsValue.credentialsBasic; this.propagateChange(deviceCredentialsValue); } @@ -181,14 +159,12 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, credentialsTypeChanged(): void { this.deviceCredentialsFormGroup.patchValue({ credentialsId: null, - credentialsValue: null, - credentialsBasic: {clientId: '', userName: '', password: ''} + credentialsValue: null }); this.updateValidators(); } updateValidators(): void { - this.hidePassword = true; const credentialsType = this.deviceCredentialsFormGroup.get('credentialsType').value as DeviceCredentialsType; switch (credentialsType) { case DeviceCredentialsType.ACCESS_TOKEN: @@ -196,48 +172,13 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false}); this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([]); this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false}); - this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false}); break; - case DeviceCredentialsType.X509_CERTIFICATE: - case DeviceCredentialsType.LWM2M_CREDENTIALS: + default: this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([Validators.required]); this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false}); this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]); this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false}); - this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false}); break; - case DeviceCredentialsType.MQTT_BASIC: - this.deviceCredentialsFormGroup.get('credentialsBasic').enable({emitEvent: false}); - this.deviceCredentialsFormGroup.get('credentialsBasic').updateValueAndValidity({emitEvent: false}); - this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]); - this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false}); - this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([]); - this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false}); - break; - } - } - - private atLeastOne(validator: ValidatorFn, controls: string[] = null) { - return (group: FormGroup): ValidationErrors | null => { - if (!controls) { - controls = Object.keys(group.controls); - } - const hasAtLeastOne = group?.controls && controls.some(k => !validator(group.controls[k])); - - return hasAtLeastOne ? null : {atLeastOne: true}; - }; - } - - passwordChanged() { - const value = this.deviceCredentialsFormGroup.get('credentialsBasic.password').value; - if (value !== '') { - this.deviceCredentialsFormGroup.get('credentialsBasic.userName').setValidators([Validators.required]); - } else { - this.deviceCredentialsFormGroup.get('credentialsBasic.userName').setValidators([]); } - this.deviceCredentialsFormGroup.get('credentialsBasic.userName').updateValueAndValidity({ - emitEvent: false, - onlySelf: true - }); } } diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts new file mode 100644 index 0000000000..c3427bba68 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts @@ -0,0 +1,46 @@ +/// +/// 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. +/// + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { CopyDeviceCredentialsComponent } from './copy-device-credentials.component'; +import { DeviceCredentialsComponent } from './device-credentials.component'; +import { SecurityConfigLwm2mComponent } from './security-config-lwm2m.component'; +import { SecurityConfigLwm2mServerComponent } from './security-config-lwm2m-server.component'; +import { DeviceCredentialsMqttBasicComponent } from './device-credentials-mqtt-basic.component'; + +@NgModule({ + declarations: [ + CopyDeviceCredentialsComponent, + DeviceCredentialsComponent, + SecurityConfigLwm2mComponent, + SecurityConfigLwm2mServerComponent, + DeviceCredentialsMqttBasicComponent + ], + imports: [ + CommonModule, + SharedModule + ], + exports: [ + CopyDeviceCredentialsComponent, + DeviceCredentialsComponent, + SecurityConfigLwm2mComponent, + SecurityConfigLwm2mServerComponent, + DeviceCredentialsMqttBasicComponent + ] +}) +export class DeviceCredentialsModule { } diff --git a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html index 77b7601ed5..200cd88f74 100644 --- a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html +++ b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html @@ -15,8 +15,8 @@ limitations under the License. --> - - + + device.lwm2m-security-config.endpoint @@ -79,7 +79,7 @@ - +
@@ -109,15 +109,4 @@
- - - - - -
diff --git a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts index eb920d6190..cbb85e305f 100644 --- a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts @@ -89,6 +89,7 @@ export class SecurityConfigLwm2mComponent implements ControlValueAccessor, Valid this.lwm2mConfigFormGroup.disable({emitEvent: false}); } else { this.lwm2mConfigFormGroup.enable({emitEvent: false}); + this.securityConfigClientUpdateValidators(this.lwm2mConfigFormGroup.get('client.securityConfigClientMode').value); } } @@ -126,21 +127,21 @@ export class SecurityConfigLwm2mComponent implements ControlValueAccessor, Valid switch (mode) { case Lwm2mSecurityType.NO_SEC: this.setValidatorsNoSecX509(); - this.lwm2mConfigFormGroup.get('client.cert').disable(); + this.lwm2mConfigFormGroup.get('client.cert').disable({emitEvent: false}); break; case Lwm2mSecurityType.X509: this.setValidatorsNoSecX509(); - this.lwm2mConfigFormGroup.get('client.cert').enable(); + this.lwm2mConfigFormGroup.get('client.cert').enable({emitEvent: false}); break; case Lwm2mSecurityType.PSK: this.lenMaxKeyClient = LEN_MAX_PSK; this.setValidatorsPskRpk(mode); - this.lwm2mConfigFormGroup.get('client.identity').enable(); + this.lwm2mConfigFormGroup.get('client.identity').enable({emitEvent: false}); break; case Lwm2mSecurityType.RPK: this.lenMaxKeyClient = LEN_MAX_PUBLIC_KEY_RPK; this.setValidatorsPskRpk(mode); - this.lwm2mConfigFormGroup.get('client.identity').disable(); + this.lwm2mConfigFormGroup.get('client.identity').disable({emitEvent: false}); break; } this.lwm2mConfigFormGroup.get('client.identity').updateValueAndValidity({emitEvent: false}); diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index d0ad42b62e..98b50cde33 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -110,7 +110,6 @@ import { RuleChainAutocompleteComponent } from '@home/components/rule-chain/rule import { DeviceProfileProvisionConfigurationComponent } from '@home/components/profile/device-profile-provision-configuration.component'; import { AlarmScheduleComponent } from '@home/components/profile/alarm/alarm-schedule.component'; import { DeviceWizardDialogComponent } from '@home/components/wizard/device-wizard-dialog.component'; -import { DeviceCredentialsComponent } from '@home/components/device/device-credentials.component'; import { AlarmScheduleInfoComponent } from '@home/components/profile/alarm/alarm-schedule-info.component'; import { AlarmScheduleDialogComponent } from '@home/components/profile/alarm/alarm-schedule-dialog.component'; import { EditAlarmDetailsDialogComponent } from '@home/components/profile/alarm/edit-alarm-details-dialog.component'; @@ -120,7 +119,6 @@ import { TenantProfileConfigurationComponent } from '@home/components/profile/te import { SmsProviderConfigurationComponent } from '@home/components/sms/sms-provider-configuration.component'; import { AwsSnsProviderConfigurationComponent } from '@home/components/sms/aws-sns-provider-configuration.component'; import { TwilioSmsProviderConfigurationComponent } from '@home/components/sms/twilio-sms-provider-configuration.component'; -import { CopyDeviceCredentialsComponent } from '@home/components/device/copy-device-credentials.component'; import { Lwm2mProfileComponentsModule } from '@home/components/profile/device/lwm2m/lwm2m-profile-components.module'; import { DashboardPageComponent } from '@home/components/dashboard-page/dashboard-page.component'; import { DashboardToolbarComponent } from '@home/components/dashboard-page/dashboard-toolbar.component'; @@ -138,11 +136,10 @@ import { EMBED_DASHBOARD_DIALOG_TOKEN } from '@home/components/widget/dialog/emb import { EdgeDownlinkTableComponent } from '@home/components/edge/edge-downlink-table.component'; import { EdgeDownlinkTableHeaderComponent } from '@home/components/edge/edge-downlink-table-header.component'; import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-page/widget-types-panel.component'; -import { SecurityConfigLwm2mComponent } from '@home/components/device/security-config-lwm2m.component'; -import { SecurityConfigLwm2mServerComponent } from '@home/components/device/security-config-lwm2m-server.component'; import { DashboardImageDialogComponent } from '@home/components/dashboard-page/dashboard-image-dialog.component'; import { WidgetContainerComponent } from '@home/components/widget/widget-container.component'; import { SnmpDeviceProfileTransportModule } from '@home/components/profile/device/snpm/snmp-device-profile-transport.module'; +import { DeviceCredentialsModule } from '@home/components/device/device-credentials.module'; @NgModule({ declarations: @@ -243,10 +240,6 @@ import { SnmpDeviceProfileTransportModule } from '@home/components/profile/devic DeviceProfileProvisionConfigurationComponent, AlarmScheduleComponent, DeviceWizardDialogComponent, - DeviceCredentialsComponent, - CopyDeviceCredentialsComponent, - SecurityConfigLwm2mComponent, - SecurityConfigLwm2mServerComponent, AlarmScheduleDialogComponent, EditAlarmDetailsDialogComponent, SmsProviderConfigurationComponent, @@ -272,7 +265,8 @@ import { SnmpDeviceProfileTransportModule } from '@home/components/profile/devic SharedHomeComponentsModule, Lwm2mProfileComponentsModule, SnmpDeviceProfileTransportModule, - StatesControllerModule + StatesControllerModule, + DeviceCredentialsModule ], exports: [ EntitiesTableComponent, @@ -351,10 +345,6 @@ import { SnmpDeviceProfileTransportModule } from '@home/components/profile/devic AddDeviceProfileDialogComponent, RuleChainAutocompleteComponent, DeviceWizardDialogComponent, - DeviceCredentialsComponent, - CopyDeviceCredentialsComponent, - SecurityConfigLwm2mComponent, - SecurityConfigLwm2mServerComponent, AlarmScheduleInfoComponent, AlarmScheduleComponent, AlarmScheduleDialogComponent, diff --git a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html index 8e1a67a8a9..c453493a2c 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html @@ -25,16 +25,26 @@ close - + -
+
-
- - -
+
+
+ + +
+
+ +
+ + + {{ 'device.loading-device-credentials' | translate }} + +
+
diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts index c3427bba68..49f1c2c097 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts @@ -19,16 +19,16 @@ import { CommonModule } from '@angular/common'; import { SharedModule } from '@shared/shared.module'; import { CopyDeviceCredentialsComponent } from './copy-device-credentials.component'; import { DeviceCredentialsComponent } from './device-credentials.component'; -import { SecurityConfigLwm2mComponent } from './security-config-lwm2m.component'; -import { SecurityConfigLwm2mServerComponent } from './security-config-lwm2m-server.component'; +import { DeviceCredentialsLwm2mComponent } from './device-credentials-lwm2m.component'; +import { DeviceCredentialsLwm2mServerComponent } from './device-credentials-lwm2m-server.component'; import { DeviceCredentialsMqttBasicComponent } from './device-credentials-mqtt-basic.component'; @NgModule({ declarations: [ CopyDeviceCredentialsComponent, DeviceCredentialsComponent, - SecurityConfigLwm2mComponent, - SecurityConfigLwm2mServerComponent, + DeviceCredentialsLwm2mComponent, + DeviceCredentialsLwm2mServerComponent, DeviceCredentialsMqttBasicComponent ], imports: [ @@ -38,8 +38,8 @@ import { DeviceCredentialsMqttBasicComponent } from './device-credentials-mqtt-b exports: [ CopyDeviceCredentialsComponent, DeviceCredentialsComponent, - SecurityConfigLwm2mComponent, - SecurityConfigLwm2mServerComponent, + DeviceCredentialsLwm2mComponent, + DeviceCredentialsLwm2mServerComponent, DeviceCredentialsMqttBasicComponent ] })