Browse Source

UI: Refactoring device credential

pull/4871/head
Vladyslav_Prykhodko 5 years ago
parent
commit
886d61673c
  1. 48
      ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.html
  2. 133
      ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts
  3. 83
      ui-ngx/src/app/modules/home/components/device/device-credentials.component.html
  4. 73
      ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts
  5. 46
      ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts
  6. 17
      ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html
  7. 9
      ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts
  8. 16
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  9. 26
      ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html
  10. 11
      ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts
  11. 2
      ui-ngx/src/app/modules/home/pages/device/device.module.ts
  12. 2
      ui-ngx/src/app/shared/models/device.models.ts
  13. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

48
ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.html

@ -0,0 +1,48 @@
<!--
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.
-->
<section [formGroup]="deviceCredentialsMqttFormGroup">
<mat-form-field class="mat-block">
<mat-label translate>device.client-id</mat-label>
<input matInput formControlName="clientId">
<mat-error *ngIf="deviceCredentialsMqttFormGroup.get('clientId').hasError('pattern')">
{{ 'device.client-id-pattern' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label translate>device.user-name</mat-label>
<input matInput formControlName="userName" [required]="!!deviceCredentialsMqttFormGroup.get('password').value">
<mat-error *ngIf="deviceCredentialsMqttFormGroup.get('userName').hasError('required')">
{{ 'device.user-name-required' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label translate>device.password</mat-label>
<input matInput formControlName="password"
autocomplete="new-password"
(ngModelChange)="passwordChanged()"
[type]="hidePassword ? 'password' : 'text'">
<button mat-icon-button matSuffix type="button"
(click)="hidePassword = !hidePassword"
[attr.aria-pressed]="hidePassword">
<mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
</mat-form-field>
<tb-error style="margin-top: -12px; display: block;"
[error]="deviceCredentialsMqttFormGroup.hasError('atLeastOne') ?
('device.client-id-or-user-name-necessary' | translate) : ''"></tb-error>
</section>

133
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};
};
}
}

83
ui-ngx/src/app/modules/home/components/device/device-credentials.component.html

@ -24,58 +24,35 @@
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="deviceCredentialsFormGroup.get('credentialsType').value === deviceCredentialsType.ACCESS_TOKEN"
class="mat-block">
<mat-label translate>device.access-token</mat-label>
<input matInput formControlName="credentialsId" required>
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsId').hasError('required')">
{{ 'device.access-token-required' | translate }}
</mat-error>
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsId').hasError('pattern')">
{{ 'device.access-token-invalid' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field *ngIf="deviceCredentialsFormGroup.get('credentialsType').value === deviceCredentialsType.X509_CERTIFICATE"
class="mat-block">
<mat-label translate>device.rsa-key</mat-label>
<textarea matInput formControlName="credentialsValue" cols="15" rows="5" required></textarea>
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsValue').hasError('required')">
{{ 'device.rsa-key-required' | translate }}
</mat-error>
</mat-form-field>
<section *ngIf="deviceCredentialsFormGroup.get('credentialsType').value === deviceCredentialsType.MQTT_BASIC" formGroupName="credentialsBasic">
<mat-form-field class="mat-block">
<mat-label translate>device.client-id</mat-label>
<input matInput formControlName="clientId">
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsBasic.clientId').hasError('pattern')">
{{ 'device.client-id-pattern' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label translate>device.user-name</mat-label>
<input matInput formControlName="userName" [required]="!!deviceCredentialsFormGroup.get('credentialsBasic.password').value">
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsBasic.userName').hasError('required')">
{{ 'device.user-name-required' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label translate>device.password</mat-label>
<input matInput formControlName="password"
autocomplete="new-password"
(ngModelChange)="passwordChanged()"
[type]="hidePassword ? 'password' : 'text'">
<button mat-icon-button matSuffix type="button"
(click)="hidePassword = !hidePassword"
[attr.aria-pressed]="hidePassword">
<mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
</mat-form-field>
<tb-error style="margin-top: -12px; display: block;"
[error]="deviceCredentialsFormGroup.get('credentialsBasic').hasError('atLeastOne') ?
('device.client-id-or-user-name-necessary' | translate) : ''"></tb-error>
</section>
<div *ngIf="deviceCredentialsFormGroup.get('credentialsType').value === deviceCredentialsType.LWM2M_CREDENTIALS">
<tb-security-config-lwm2m formControlName="credentialsValue">
</tb-security-config-lwm2m>
<div [ngSwitch]="deviceCredentialsFormGroup.get('credentialsType').value">
<ng-template [ngSwitchCase]="deviceCredentialsType.ACCESS_TOKEN">
<mat-form-field class="mat-block">
<mat-label translate>device.access-token</mat-label>
<input matInput formControlName="credentialsId" required>
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsId').hasError('required')">
{{ 'device.access-token-required' | translate }}
</mat-error>
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsId').hasError('pattern')">
{{ 'device.access-token-invalid' | translate }}
</mat-error>
</mat-form-field>
</ng-template>
<ng-template [ngSwitchCase]="deviceCredentialsType.X509_CERTIFICATE">
<mat-form-field class="mat-block">
<mat-label translate>device.rsa-key</mat-label>
<textarea matInput formControlName="credentialsValue" cols="15" rows="5" required></textarea>
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsValue').hasError('required')">
{{ 'device.rsa-key-required' | translate }}
</mat-error>
</mat-form-field>
</ng-template>
<ng-template [ngSwitchCase]="deviceCredentialsType.MQTT_BASIC">
<tb-device-credentials-mqtt-basic formControlName="credentialsValue">
</tb-device-credentials-mqtt-basic>
</ng-template>
<ng-template [ngSwitchCase]="deviceCredentialsType.LWM2M_CREDENTIALS">
<tb-security-config-lwm2m formControlName="credentialsValue">
</tb-security-config-lwm2m>
</ng-template>
</div>
</section>

73
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
});
}
}

46
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 { }

17
ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html

@ -15,8 +15,8 @@
limitations under the License.
-->
<mat-tab-group>
<mat-tab label="{{ 'device.lwm2m-security-config.client-tab' | translate }}" [formGroup]="lwm2mConfigFormGroup">
<mat-tab-group [formGroup]="lwm2mConfigFormGroup">
<mat-tab label="{{ 'device.lwm2m-security-config.client-tab' | translate }}">
<ng-container formGroupName="client">
<mat-form-field class="mat-block">
<mat-label translate>device.lwm2m-security-config.endpoint</mat-label>
@ -79,7 +79,7 @@
</mat-form-field>
</ng-container>
</mat-tab>
<mat-tab label="{{ 'device.lwm2m-security-config.bootstrap-tab' | translate }}" [formGroup]="lwm2mConfigFormGroup">
<mat-tab label="{{ 'device.lwm2m-security-config.bootstrap-tab' | translate }}">
<div style="padding: 2px;" formGroupName="bootstrap">
<mat-accordion multi="true" class="mat-body-1">
<mat-expansion-panel>
@ -109,15 +109,4 @@
</mat-accordion>
</div>
</mat-tab>
<mat-tab label="{{ 'device.lwm2m-security-config.config-json-tab' | translate }}">
<ng-template matTabContent>
<tb-json-object-edit
[ngModel]="lwm2mConfigFormGroup.value"
label="{{ 'device.lwm2m-value' | translate }}"
readonly
[required]="true"
[fillHeight]="false">
</tb-json-object-edit>
</ng-template>
</mat-tab>
</mat-tab-group>

9
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});

16
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,

26
ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html

@ -25,16 +25,26 @@
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="(isLoading$ | async) && !loadingCredentials">
</mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div style="height: 4px;" *ngIf="!(isLoading$ | async) || loadingCredentials"></div>
<div mat-dialog-content>
<fieldset [disabled]="(isLoading$ | async) || isReadOnly">
<tb-device-credentials
[deviceTransportType]="deviceTransportType"
formControlName="credential">
</tb-device-credentials>
</fieldset>
<section *ngIf="!loadingCredentials; else loadCredentials">
<fieldset [disabled]="(isLoading$ | async) || isReadOnly">
<tb-device-credentials
[deviceTransportType]="deviceTransportType"
formControlName="credential">
</tb-device-credentials>
</fieldset>
</section>
<ng-template #loadCredentials>
<div fxLayout="column" fxLayoutAlign="center center">
<mat-spinner color="accent" diameter="65" strokeWidth="4" style="margin-bottom: 18px"></mat-spinner>
<span class="mat-subheading-2" style="margin-bottom: 0">
{{ 'device.loading-device-credentials' | translate }}
</span>
</div>
</ng-template>
</div>
<div mat-dialog-actions fxLayoutAlign="end center">
<button mat-button color="primary"

11
ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts

@ -43,14 +43,12 @@ export class DeviceCredentialsDialogComponent extends
DialogComponent<DeviceCredentialsDialogComponent, DeviceCredentials> implements OnInit, ErrorStateMatcher {
deviceCredentialsFormGroup: FormGroup;
deviceTransportType: DeviceTransportType;
isReadOnly: boolean;
loadingCredentials = true;
deviceCredentials: DeviceCredentials;
submitted = false;
deviceTransportType: DeviceTransportType;
private deviceCredentials: DeviceCredentials;
private submitted = false;
constructor(protected store: Store<AppState>,
protected router: Router,
@ -91,6 +89,7 @@ export class DeviceCredentialsDialogComponent extends
this.deviceCredentialsFormGroup.patchValue({
credential: deviceCredentials
}, {emitEvent: false});
this.loadingCredentials = false;
});
}

2
ui-ngx/src/app/modules/home/pages/device/device.module.ts

@ -33,6 +33,7 @@ import { MqttDeviceTransportConfigurationComponent } from './data/mqtt-device-tr
import { CoapDeviceTransportConfigurationComponent } from './data/coap-device-transport-configuration.component';
import { Lwm2mDeviceTransportConfigurationComponent } from './data/lwm2m-device-transport-configuration.component';
import { SnmpDeviceTransportConfigurationComponent } from './data/snmp-device-transport-configuration.component';
import { DeviceCredentialsModule } from '@home/components/device/device-credentials.module';
@NgModule({
declarations: [
@ -55,6 +56,7 @@ import { SnmpDeviceTransportConfigurationComponent } from './data/snmp-device-tr
SharedModule,
HomeComponentsModule,
HomeDialogsModule,
DeviceCredentialsModule,
DeviceRoutingModule
]
})

2
ui-ngx/src/app/shared/models/device.models.ts

@ -690,7 +690,7 @@ export const credentialTypesByTransportType = new Map<DeviceTransportType, Devic
]],
[DeviceTransportType.COAP, [DeviceCredentialsType.ACCESS_TOKEN, DeviceCredentialsType.X509_CERTIFICATE]],
[DeviceTransportType.LWM2M, [DeviceCredentialsType.LWM2M_CREDENTIALS]],
[DeviceTransportType.SNMP, [DeviceCredentialsType.ACCESS_TOKEN, DeviceCredentialsType.X509_CERTIFICATE]]
[DeviceTransportType.SNMP, [DeviceCredentialsType.ACCESS_TOKEN]]
]
);

3
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -941,13 +941,13 @@
"unassign-devices-title": "Are you sure you want to unassign { count, plural, 1 {1 device} other {# devices} }?",
"unassign-devices-text": "After the confirmation all selected devices will be unassigned and won't be accessible by the customer.",
"device-credentials": "Device Credentials",
"loading-device-credentials": "Loading device credentials...",
"credentials-type": "Credentials type",
"access-token": "Access token",
"access-token-required": "Access token is required.",
"access-token-invalid": "Access token length must be from 1 to 20 characters.",
"rsa-key": "RSA public key",
"rsa-key-required": "RSA public key is required.",
"lwm2m-value": "LwM2M Security config",
"lwm2m-security-config": {
"identity": "Client Identity",
"identity-required": "Client Identity is required.",
@ -971,7 +971,6 @@
"client-secret-key-required": "Client Secret Key is required.",
"client-secret-key-pattern": "Client Secret Key must be hexadecimal format.",
"client-secret-key-length": "Client Secret Key must be {{ count }} characters.",
"config-json-tab": "Json Client Security Config",
"client-public-key": "Client public key",
"client-public-key-hint": "If client public key is empty, the trusted certificate will be used"
},

Loading…
Cancel
Save