Add Device Wizard improvements
This commit is contained in:
parent
e10696087e
commit
c7b57ca543
@ -85,7 +85,7 @@
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="alarmRulesFormGroup">
|
||||
<form [formGroup]="alarmRulesFormGroup" style="padding-bottom: 16px;">
|
||||
<ng-template matStepLabel>{{'device-profile.alarm-rules' | translate:
|
||||
<ng-template matStepLabel>{{'device-profile.alarm-rules-with-count' | translate:
|
||||
{count: alarmRulesFormGroup.get('alarms').value ?
|
||||
alarmRulesFormGroup.get('alarms').value.length : 0} }}</ng-template>
|
||||
<tb-device-profile-alarms
|
||||
|
||||
@ -20,9 +20,9 @@ import {
|
||||
EventEmitter,
|
||||
forwardRef,
|
||||
Input,
|
||||
NgZone,
|
||||
NgZone, OnChanges,
|
||||
OnInit,
|
||||
Output,
|
||||
Output, SimpleChanges,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
@ -55,7 +55,7 @@ import { AddDeviceProfileDialogComponent, AddDeviceProfileDialogData } from './a
|
||||
multi: true
|
||||
}]
|
||||
})
|
||||
export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, OnInit {
|
||||
export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, OnInit, OnChanges {
|
||||
|
||||
selectDeviceProfileFormGroup: FormGroup;
|
||||
|
||||
@ -168,11 +168,22 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
for (const propName of Object.keys(changes)) {
|
||||
const change = changes[propName];
|
||||
if (!change.firstChange && change.currentValue !== change.previousValue) {
|
||||
if (propName === 'transportType') {
|
||||
this.writeValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectDefaultDeviceProfileIfNeeded(): void {
|
||||
if (this.selectDefaultProfile && !this.modelValue) {
|
||||
this.deviceProfileService.getDefaultDeviceProfileInfo().subscribe(
|
||||
(profile) => {
|
||||
if (profile) {
|
||||
if (profile && !this.transportType || (profile.transportType === this.transportType)) {
|
||||
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(profile, {emitEvent: false});
|
||||
this.updateView(profile);
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
<mat-expansion-panel [expanded]="true">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<div>{{'device-profile.alarm-rules' | translate:
|
||||
<div>{{'device-profile.alarm-rules-with-count' | translate:
|
||||
{count: deviceProfileDataFormGroup.get('alarms').value ?
|
||||
deviceProfileDataFormGroup.get('alarms').value.length : 0} }}</div>
|
||||
</mat-panel-title>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<div style="min-width: 1000px;">
|
||||
<div>
|
||||
<mat-toolbar color="primary">
|
||||
<h2 translate>device.add-device-text</h2>
|
||||
<span fxFlex></span>
|
||||
@ -29,7 +29,7 @@
|
||||
</mat-progress-bar>
|
||||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
|
||||
<div mat-dialog-content>
|
||||
<mat-horizontal-stepper [linear]="true" #addDeviceWizardStepper (selectionChange)="changeStep($event)">
|
||||
<mat-horizontal-stepper [linear]="true" [labelPosition]="labelPosition" #addDeviceWizardStepper (selectionChange)="changeStep($event)">
|
||||
<ng-template matStepperIcon="edit">
|
||||
<mat-icon>check</mat-icon>
|
||||
</ng-template>
|
||||
@ -48,17 +48,49 @@
|
||||
<mat-label translate>device.label</mat-label>
|
||||
<input matInput formControlName="label">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-form-field class="mat-block" style="padding-bottom: 14px;">
|
||||
<mat-label translate>device-profile.transport-type</mat-label>
|
||||
<mat-select formControlName="transportType" required>
|
||||
<mat-option *ngFor="let type of deviceTransportTypes" [value]="type">
|
||||
{{deviceTransportTypeTranslations.get(type) | translate}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-hint *ngIf="deviceWizardFormGroup.get('transportType').value">
|
||||
{{deviceTransportTypeHints.get(deviceWizardFormGroup.get('transportType').value) | translate}}
|
||||
</mat-hint>
|
||||
<mat-error *ngIf="deviceWizardFormGroup.get('transportType').hasError('required')">
|
||||
{{ 'device-profile.transport-type-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<div fxLayout="row" fxLayoutGap="16px">
|
||||
<mat-radio-group fxLayout="column" formControlName="addProfileType" fxLayoutAlign="space-around">
|
||||
<mat-radio-button [value]="0" color="primary">
|
||||
<span translate>device.wizard.existing-device-profile</span>
|
||||
</mat-radio-button>
|
||||
<mat-radio-button [value]="1" color="primary">
|
||||
<span translate>device.wizard.new-device-profile</span>
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
<div fxLayout="column">
|
||||
<tb-device-profile-autocomplete
|
||||
[required]="!createProfile"
|
||||
[transportType]="deviceWizardFormGroup.get('transportType').value"
|
||||
formControlName="deviceProfileId"
|
||||
(deviceProfileChanged)="$event?.transportType ? deviceWizardFormGroup.get('transportType').patchValue($event?.transportType) : {}"
|
||||
[addNewProfile]="false"
|
||||
[selectDefaultProfile]="true"
|
||||
[editProfileEnabled]="false">
|
||||
</tb-device-profile-autocomplete>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>device-profile.new-device-profile-name</mat-label>
|
||||
<input matInput formControlName="newDeviceProfileTitle"
|
||||
[required]="createProfile">
|
||||
<mat-error *ngIf="deviceWizardFormGroup.get('newDeviceProfileTitle').hasError('required')">
|
||||
{{ 'device-profile.new-device-profile-name-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<mat-checkbox formControlName="gateway" style="padding-bottom: 16px;">
|
||||
{{ 'device.is-gateway' | translate }}
|
||||
</mat-checkbox>
|
||||
@ -69,39 +101,7 @@
|
||||
</fieldset>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="profileConfigFormGroup">
|
||||
<form [formGroup]="profileConfigFormGroup" style="padding-bottom: 16px;">
|
||||
<ng-template matStepLabel>{{ 'device.wizard.profile-configuration' | translate}}</ng-template>
|
||||
<mat-radio-group fxLayout="column" fxFlex formControlName="addProfileType">
|
||||
<mat-radio-button [value]="0" color="primary">
|
||||
<section>
|
||||
<span translate>device.wizard.existing-device-profile</span>
|
||||
<tb-device-profile-autocomplete
|
||||
[required]="profileConfigFormGroup.get('addProfileType').value === 0"
|
||||
[transportType]="deviceWizardFormGroup.get('transportType').value"
|
||||
formControlName="deviceProfileId"
|
||||
[addNewProfile]="false"
|
||||
[editProfileEnabled]="false">
|
||||
</tb-device-profile-autocomplete>
|
||||
</section>
|
||||
</mat-radio-button>
|
||||
<mat-radio-button [value]="1" color="primary">
|
||||
<section fxLayout="column">
|
||||
<span translate>device.wizard.new-device-profile</span>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>device-profile.device-profile</mat-label>
|
||||
<input matInput formControlName="newDeviceProfileTitle"
|
||||
[required]="profileConfigFormGroup.get('addProfileType').value === 1">
|
||||
<mat-error *ngIf="profileConfigFormGroup.get('newDeviceProfileTitle').hasError('required')">
|
||||
{{ 'device-profile.device-profile-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="transportConfigFormGroup" *ngIf="createdProfile">
|
||||
<mat-step [stepControl]="transportConfigFormGroup" *ngIf="createTransportConfiguration">
|
||||
<form [formGroup]="transportConfigFormGroup" style="padding-bottom: 16px;">
|
||||
<ng-template matStepLabel>{{ 'device-profile.transport-configuration' | translate }}</ng-template>
|
||||
<tb-device-profile-transport-configuration
|
||||
@ -110,9 +110,9 @@
|
||||
</tb-device-profile-transport-configuration>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="alarmRulesFormGroup" *ngIf="createdProfile">
|
||||
<mat-step [stepControl]="alarmRulesFormGroup" [optional]="true" *ngIf="createProfile">
|
||||
<form [formGroup]="alarmRulesFormGroup" style="padding-bottom: 16px;">
|
||||
<ng-template matStepLabel>{{'device-profile.alarm-rules' | translate:
|
||||
<ng-template matStepLabel>{{'device-profile.alarm-rules-with-count' | translate:
|
||||
{count: alarmRulesFormGroup.get('alarms').value ?
|
||||
alarmRulesFormGroup.get('alarms').value.length : 0} }}</ng-template>
|
||||
<tb-device-profile-alarms
|
||||
@ -120,36 +120,50 @@
|
||||
</tb-device-profile-alarms>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="specificConfigFormGroup">
|
||||
<ng-template matStepLabel>{{ 'device.wizard.specific-configuration' | translate }}</ng-template>
|
||||
<form [formGroup]="specificConfigFormGroup" style="padding-bottom: 16px;">
|
||||
<mat-step [stepControl]="credentialsFormGroup" [optional]="true">
|
||||
<ng-template matStepLabel>{{ 'device.credentials' | translate }}</ng-template>
|
||||
<form [formGroup]="credentialsFormGroup" style="padding-bottom: 16px;">
|
||||
<mat-checkbox style="padding-bottom: 16px;" formControlName="setCredential">{{ 'device.wizard.add-credential' | translate }}</mat-checkbox>
|
||||
<tb-device-credentials
|
||||
[fxShow]="credentialsFormGroup.get('setCredential').value"
|
||||
formControlName="credential">
|
||||
</tb-device-credentials>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="customerFormGroup" [optional]="true">
|
||||
<ng-template matStepLabel>{{ 'customer.customer' | translate }}</ng-template>
|
||||
<form [formGroup]="customerFormGroup" style="padding-bottom: 16px;">
|
||||
<tb-entity-autocomplete
|
||||
formControlName="customerId"
|
||||
labelText="device.wizard.customer-to-assign-device"
|
||||
[entityType]="entityType.CUSTOMER">
|
||||
</tb-entity-autocomplete>
|
||||
<mat-checkbox formControlName="setCredential">{{ 'device.wizard.add-credential' | translate }}</mat-checkbox>
|
||||
<tb-device-credentials
|
||||
[fxShow]="specificConfigFormGroup.get('setCredential').value"
|
||||
formControlName="credential">
|
||||
</tb-device-credentials>
|
||||
</form>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
||||
</div>
|
||||
<div mat-dialog-actions fxLayout="row wrap" fxLayoutAlign="space-between center">
|
||||
<button mat-button *ngIf="selectedIndex > 0"
|
||||
[disabled]="(isLoading$ | async)"
|
||||
(click)="previousStep()">{{ 'action.back' | translate }}</button>
|
||||
<span *ngIf="selectedIndex == 0"></span>
|
||||
<div fxLayout="row wrap" fxLayoutGap="20px">
|
||||
<div mat-dialog-actions fxLayout="column" fxLayoutAlign="start wrap" fxLayoutGap="8px" style="height: 100px;">
|
||||
<div fxFlex fxLayout="row" fxLayoutAlign="end">
|
||||
<button mat-raised-button
|
||||
*ngIf="showNext"
|
||||
[disabled]="(isLoading$ | async)"
|
||||
(click)="nextStep()">{{ 'action.next-with-label' | translate:{label: (getFormLabel(this.selectedIndex+1) | translate)} }}</button>
|
||||
</div>
|
||||
<div fxFlex fxLayout="row">
|
||||
<button mat-button
|
||||
color="primary"
|
||||
[disabled]="(isLoading$ | async)"
|
||||
(click)="cancel()">{{ 'action.cancel' | translate }}</button>
|
||||
<button mat-raised-button
|
||||
[disabled]="(isLoading$ | async) || selectedForm.invalid"
|
||||
color="primary"
|
||||
(click)="nextStep()">{{ nextStepButtonLabel$ | async | translate }}</button>
|
||||
<span fxFlex></span>
|
||||
<div fxLayout="row wrap" fxLayoutGap="8px">
|
||||
<button mat-raised-button *ngIf="selectedIndex > 0"
|
||||
[disabled]="(isLoading$ | async)"
|
||||
(click)="previousStep()">{{ 'action.back' | translate }}</button>
|
||||
<button mat-raised-button
|
||||
[disabled]="(isLoading$ | async)"
|
||||
color="primary"
|
||||
(click)="add()">{{ 'action.add' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -13,25 +13,51 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
:host {
|
||||
.mat-dialog-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
.mat-stepper-horizontal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@import "../../../../../scss/constants";
|
||||
|
||||
:host-context(.tb-fullscreen-dialog .mat-dialog-container) {
|
||||
@media #{$mat-lt-sm} {
|
||||
.mat-dialog-content {
|
||||
max-height: 75vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep {
|
||||
.mat-dialog-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.mat-stepper-horizontal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
@media #{$mat-lt-sm} {
|
||||
.mat-step-label {
|
||||
white-space: normal;
|
||||
overflow: visible;
|
||||
.mat-step-text-label {
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-horizontal-content-container {
|
||||
overflow: auto;
|
||||
height: 450px;
|
||||
max-height: 100%;
|
||||
width: 100%;;
|
||||
overflow-y: auto;
|
||||
@media #{$mat-gt-sm} {
|
||||
min-width: 800px;
|
||||
}
|
||||
}
|
||||
.mat-horizontal-stepper-content[aria-expanded=true] {
|
||||
height: 100%;
|
||||
form {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ import {
|
||||
createDeviceProfileTransportConfiguration,
|
||||
DeviceProfile,
|
||||
DeviceProfileType,
|
||||
DeviceTransportType,
|
||||
DeviceTransportType, deviceTransportTypeHintMap,
|
||||
deviceTransportTypeTranslationMap
|
||||
} from '@shared/models/device.models';
|
||||
import { MatHorizontalStepper } from '@angular/material/stepper';
|
||||
@ -35,11 +35,13 @@ import { BaseData, HasId } from '@shared/models/base-data';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { DeviceProfileService } from '@core/http/device-profile.service';
|
||||
import { EntityId } from '@shared/models/id/entity-id';
|
||||
import { BehaviorSubject, Observable, of, Subscription } from 'rxjs';
|
||||
import { Observable, of, Subscription } from 'rxjs';
|
||||
import { map, mergeMap, tap } from 'rxjs/operators';
|
||||
import { DeviceService } from '@core/http/device.service';
|
||||
import { ErrorStateMatcher } from '@angular/material/core';
|
||||
import { StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
|
||||
import { MediaBreakpoints } from '@shared/models/constants';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-device-wizard',
|
||||
@ -54,9 +56,10 @@ export class DeviceWizardDialogComponent extends
|
||||
|
||||
selectedIndex = 0;
|
||||
|
||||
nextStepButtonLabel$ = new BehaviorSubject<string>('action.continue');
|
||||
showNext = true;
|
||||
|
||||
createdProfile = false;
|
||||
createProfile = false;
|
||||
createTransportConfiguration = false;
|
||||
|
||||
entityType = EntityType;
|
||||
|
||||
@ -64,15 +67,19 @@ export class DeviceWizardDialogComponent extends
|
||||
|
||||
deviceTransportTypeTranslations = deviceTransportTypeTranslationMap;
|
||||
|
||||
deviceWizardFormGroup: FormGroup;
|
||||
deviceTransportTypeHints = deviceTransportTypeHintMap;
|
||||
|
||||
profileConfigFormGroup: FormGroup;
|
||||
deviceWizardFormGroup: FormGroup;
|
||||
|
||||
transportConfigFormGroup: FormGroup;
|
||||
|
||||
alarmRulesFormGroup: FormGroup;
|
||||
|
||||
specificConfigFormGroup: FormGroup;
|
||||
credentialsFormGroup: FormGroup;
|
||||
|
||||
customerFormGroup: FormGroup;
|
||||
|
||||
labelPosition = 'end';
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
@ -83,6 +90,7 @@ export class DeviceWizardDialogComponent extends
|
||||
public dialogRef: MatDialogRef<DeviceWizardDialogComponent, boolean>,
|
||||
private deviceProfileService: DeviceProfileService,
|
||||
private deviceService: DeviceService,
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
private fb: FormBuilder) {
|
||||
super(store, router, dialogRef);
|
||||
this.deviceWizardFormGroup = this.fb.group({
|
||||
@ -90,33 +98,32 @@ export class DeviceWizardDialogComponent extends
|
||||
label: [''],
|
||||
gateway: [false],
|
||||
transportType: [DeviceTransportType.DEFAULT, Validators.required],
|
||||
addProfileType: [0],
|
||||
deviceProfileId: [null, Validators.required],
|
||||
newDeviceProfileTitle: [{value: null, disabled: true}],
|
||||
description: ['']
|
||||
}
|
||||
);
|
||||
|
||||
this.profileConfigFormGroup = this.fb.group({
|
||||
addProfileType: [0],
|
||||
deviceProfileId: [null, Validators.required],
|
||||
newDeviceProfileTitle: [{value: null, disabled: true}]
|
||||
}
|
||||
);
|
||||
|
||||
this.subscriptions.push(this.profileConfigFormGroup.get('addProfileType').valueChanges.subscribe(
|
||||
this.subscriptions.push(this.deviceWizardFormGroup.get('addProfileType').valueChanges.subscribe(
|
||||
(addProfileType: number) => {
|
||||
if (addProfileType === 0) {
|
||||
this.profileConfigFormGroup.get('deviceProfileId').setValidators([Validators.required]);
|
||||
this.profileConfigFormGroup.get('deviceProfileId').enable();
|
||||
this.profileConfigFormGroup.get('newDeviceProfileTitle').setValidators(null);
|
||||
this.profileConfigFormGroup.get('newDeviceProfileTitle').disable();
|
||||
this.profileConfigFormGroup.updateValueAndValidity();
|
||||
this.createdProfile = false;
|
||||
this.deviceWizardFormGroup.get('deviceProfileId').setValidators([Validators.required]);
|
||||
this.deviceWizardFormGroup.get('deviceProfileId').enable();
|
||||
this.deviceWizardFormGroup.get('newDeviceProfileTitle').setValidators(null);
|
||||
this.deviceWizardFormGroup.get('newDeviceProfileTitle').disable();
|
||||
this.deviceWizardFormGroup.updateValueAndValidity();
|
||||
this.createProfile = false;
|
||||
this.createTransportConfiguration = false;
|
||||
} else {
|
||||
this.profileConfigFormGroup.get('deviceProfileId').setValidators(null);
|
||||
this.profileConfigFormGroup.get('deviceProfileId').disable();
|
||||
this.profileConfigFormGroup.get('newDeviceProfileTitle').setValidators([Validators.required]);
|
||||
this.profileConfigFormGroup.get('newDeviceProfileTitle').enable();
|
||||
this.profileConfigFormGroup.updateValueAndValidity();
|
||||
this.createdProfile = true;
|
||||
this.deviceWizardFormGroup.get('deviceProfileId').setValidators(null);
|
||||
this.deviceWizardFormGroup.get('deviceProfileId').disable();
|
||||
this.deviceWizardFormGroup.get('newDeviceProfileTitle').setValidators([Validators.required]);
|
||||
this.deviceWizardFormGroup.get('newDeviceProfileTitle').enable();
|
||||
this.deviceWizardFormGroup.updateValueAndValidity();
|
||||
this.createProfile = true;
|
||||
this.createTransportConfiguration = this.deviceWizardFormGroup.get('transportType').value &&
|
||||
DeviceTransportType.DEFAULT !== this.deviceWizardFormGroup.get('transportType').value;
|
||||
}
|
||||
}
|
||||
));
|
||||
@ -135,20 +142,37 @@ export class DeviceWizardDialogComponent extends
|
||||
}
|
||||
);
|
||||
|
||||
this.specificConfigFormGroup = this.fb.group({
|
||||
customerId: [null],
|
||||
this.credentialsFormGroup = this.fb.group({
|
||||
setCredential: [false],
|
||||
credential: [{value: null, disabled: true}]
|
||||
}
|
||||
);
|
||||
|
||||
this.subscriptions.push(this.specificConfigFormGroup.get('setCredential').valueChanges.subscribe((value) => {
|
||||
this.subscriptions.push(this.credentialsFormGroup.get('setCredential').valueChanges.subscribe((value) => {
|
||||
if (value) {
|
||||
this.specificConfigFormGroup.get('credential').enable();
|
||||
this.credentialsFormGroup.get('credential').enable();
|
||||
} else {
|
||||
this.specificConfigFormGroup.get('credential').disable();
|
||||
this.credentialsFormGroup.get('credential').disable();
|
||||
}
|
||||
}));
|
||||
|
||||
this.customerFormGroup = this.fb.group({
|
||||
customerId: [null]
|
||||
}
|
||||
);
|
||||
|
||||
this.labelPosition = this.breakpointObserver.isMatched(MediaBreakpoints['gt-sm']) ? 'end' : 'bottom';
|
||||
|
||||
this.subscriptions.push(this.breakpointObserver
|
||||
.observe(MediaBreakpoints['gt-sm'])
|
||||
.subscribe((state: BreakpointState) => {
|
||||
if (state.matches) {
|
||||
this.labelPosition = 'end';
|
||||
} else {
|
||||
this.labelPosition = 'bottom';
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -171,26 +195,28 @@ export class DeviceWizardDialogComponent extends
|
||||
}
|
||||
|
||||
nextStep(): void {
|
||||
if (this.selectedIndex < this.maxStepperIndex) {
|
||||
this.addDeviceWizardStepper.next();
|
||||
} else {
|
||||
this.add();
|
||||
}
|
||||
this.addDeviceWizardStepper.next();
|
||||
}
|
||||
|
||||
get selectedForm(): FormGroup {
|
||||
const index = !this.createdProfile && this.selectedIndex === this.maxStepperIndex ? 4 : this.selectedIndex;
|
||||
getFormLabel(index: number): string {
|
||||
if (index > 0) {
|
||||
if (!this.createProfile) {
|
||||
index += 2;
|
||||
} else if (!this.createTransportConfiguration) {
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
switch (index) {
|
||||
case 0:
|
||||
return this.deviceWizardFormGroup;
|
||||
return 'device.wizard.device-details';
|
||||
case 1:
|
||||
return this.profileConfigFormGroup;
|
||||
return 'device-profile.transport-configuration';
|
||||
case 2:
|
||||
return this.transportConfigFormGroup;
|
||||
return 'device-profile.alarm-rules';
|
||||
case 3:
|
||||
return this.alarmRulesFormGroup;
|
||||
return 'device.credentials';
|
||||
case 4:
|
||||
return this.specificConfigFormGroup;
|
||||
return 'customer.customer';
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,23 +227,27 @@ export class DeviceWizardDialogComponent extends
|
||||
private deviceProfileTransportTypeChanged(deviceTransportType: DeviceTransportType): void {
|
||||
this.transportConfigFormGroup.patchValue(
|
||||
{transportConfiguration: createDeviceProfileTransportConfiguration(deviceTransportType)});
|
||||
this.createTransportConfiguration = this.createProfile && deviceTransportType &&
|
||||
DeviceTransportType.DEFAULT !== deviceTransportType;
|
||||
}
|
||||
|
||||
private add(): void {
|
||||
this.creatProfile().pipe(
|
||||
mergeMap(profileId => this.createdDevice(profileId)),
|
||||
mergeMap(device => this.saveCredential(device))
|
||||
).subscribe(
|
||||
(created) => {
|
||||
this.dialogRef.close(created);
|
||||
}
|
||||
);
|
||||
add(): void {
|
||||
if (this.allValid()) {
|
||||
this.createDeviceProfile().pipe(
|
||||
mergeMap(profileId => this.createDevice(profileId)),
|
||||
mergeMap(device => this.saveCredentials(device))
|
||||
).subscribe(
|
||||
(created) => {
|
||||
this.dialogRef.close(created);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private creatProfile(): Observable<EntityId> {
|
||||
if (this.profileConfigFormGroup.get('addProfileType').value) {
|
||||
private createDeviceProfile(): Observable<EntityId> {
|
||||
if (this.deviceWizardFormGroup.get('addProfileType').value) {
|
||||
const deviceProfile: DeviceProfile = {
|
||||
name: this.profileConfigFormGroup.get('newDeviceProfileTitle').value,
|
||||
name: this.deviceWizardFormGroup.get('newDeviceProfileTitle').value,
|
||||
type: DeviceProfileType.DEFAULT,
|
||||
transportType: this.deviceWizardFormGroup.get('transportType').value,
|
||||
profileData: {
|
||||
@ -229,11 +259,10 @@ export class DeviceWizardDialogComponent extends
|
||||
return this.deviceProfileService.saveDeviceProfile(deviceProfile).pipe(
|
||||
map(profile => profile.id),
|
||||
tap((profileId) => {
|
||||
this.profileConfigFormGroup.patchValue({
|
||||
this.deviceWizardFormGroup.patchValue({
|
||||
deviceProfileId: profileId,
|
||||
addProfileType: 0
|
||||
});
|
||||
this.addDeviceWizardStepper.selectedIndex = 2;
|
||||
})
|
||||
);
|
||||
} else {
|
||||
@ -241,7 +270,7 @@ export class DeviceWizardDialogComponent extends
|
||||
}
|
||||
}
|
||||
|
||||
private createdDevice(profileId: EntityId = this.profileConfigFormGroup.get('deviceProfileId').value): Observable<BaseData<HasId>> {
|
||||
private createDevice(profileId: EntityId = this.deviceWizardFormGroup.get('deviceProfileId').value): Observable<BaseData<HasId>> {
|
||||
const device = {
|
||||
name: this.deviceWizardFormGroup.get('name').value,
|
||||
label: this.deviceWizardFormGroup.get('label').value,
|
||||
@ -252,21 +281,21 @@ export class DeviceWizardDialogComponent extends
|
||||
},
|
||||
customerId: null
|
||||
};
|
||||
if (this.specificConfigFormGroup.get('customerId').value) {
|
||||
if (this.customerFormGroup.get('customerId').value) {
|
||||
device.customerId = {
|
||||
entityType: EntityType.CUSTOMER,
|
||||
id: this.specificConfigFormGroup.get('customerId').value
|
||||
id: this.customerFormGroup.get('customerId').value
|
||||
};
|
||||
}
|
||||
return this.data.entitiesTableConfig.saveEntity(device);
|
||||
}
|
||||
|
||||
private saveCredential(device: BaseData<HasId>): Observable<boolean> {
|
||||
if (this.specificConfigFormGroup.get('setCredential').value) {
|
||||
private saveCredentials(device: BaseData<HasId>): Observable<boolean> {
|
||||
if (this.credentialsFormGroup.get('setCredential').value) {
|
||||
return this.deviceService.getDeviceCredentials(device.id.id).pipe(
|
||||
mergeMap(
|
||||
(deviceCredentials) => {
|
||||
const deviceCredentialsValue = {...deviceCredentials, ...this.specificConfigFormGroup.value.credential};
|
||||
const deviceCredentialsValue = {...deviceCredentials, ...this.credentialsFormGroup.value.credential};
|
||||
return this.deviceService.saveDeviceCredentials(deviceCredentialsValue);
|
||||
}
|
||||
),
|
||||
@ -275,12 +304,28 @@ export class DeviceWizardDialogComponent extends
|
||||
return of(true);
|
||||
}
|
||||
|
||||
allValid(): boolean {
|
||||
if (this.addDeviceWizardStepper.steps.find((item, index) => {
|
||||
if (item.stepControl.invalid) {
|
||||
item.interacted = true;
|
||||
this.addDeviceWizardStepper.selectedIndex = index;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} )) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
changeStep($event: StepperSelectionEvent): void {
|
||||
this.selectedIndex = $event.selectedIndex;
|
||||
if (this.selectedIndex === this.maxStepperIndex) {
|
||||
this.nextStepButtonLabel$.next('action.add');
|
||||
this.showNext = false;
|
||||
} else {
|
||||
this.nextStepButtonLabel$.next('action.continue');
|
||||
this.showNext = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,7 +296,7 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
|
||||
name: this.translate.instant('device.add-device-text'),
|
||||
icon: 'insert_drive_file',
|
||||
isEnabled: () => true,
|
||||
onAction: ($event) => this.config.table.addEntity($event)
|
||||
onAction: ($event) => this.deviceWizard($event)
|
||||
},
|
||||
{
|
||||
name: this.translate.instant('device.import'),
|
||||
@ -304,12 +304,6 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
|
||||
isEnabled: () => true,
|
||||
onAction: ($event) => this.importDevices($event)
|
||||
},
|
||||
{
|
||||
name: this.translate.instant('device.wizard.device-wizard'),
|
||||
icon: 'library_add',
|
||||
isEnabled: () => true,
|
||||
onAction: ($event) => this.deviceWizard($event)
|
||||
},
|
||||
);
|
||||
}
|
||||
if (deviceScope === 'customer') {
|
||||
|
||||
@ -72,6 +72,14 @@ export const deviceTransportTypeTranslationMap = new Map<DeviceTransportType, st
|
||||
]
|
||||
);
|
||||
|
||||
export const deviceTransportTypeHintMap = new Map<DeviceTransportType, string>(
|
||||
[
|
||||
[DeviceTransportType.DEFAULT, 'device-profile.transport-type-default-hint'],
|
||||
[DeviceTransportType.MQTT, 'device-profile.transport-type-mqtt-hint'],
|
||||
[DeviceTransportType.LWM2M, 'device-profile.transport-type-lwm2m-hint']
|
||||
]
|
||||
);
|
||||
|
||||
export const mqttTransportPayloadTypeTranslationMap = new Map<MqttTransportPayloadType, string>(
|
||||
[
|
||||
[MqttTransportPayloadType.JSON, 'device-profile.mqtt-device-payload-type-json'],
|
||||
|
||||
@ -54,7 +54,8 @@
|
||||
"share-via": "Share via {{provider}}",
|
||||
"continue": "Continue",
|
||||
"discard-changes": "Discard Changes",
|
||||
"download": "Download"
|
||||
"download": "Download",
|
||||
"next-with-label": "Next: {{label}}"
|
||||
},
|
||||
"aggregation": {
|
||||
"aggregation": "Aggregation",
|
||||
@ -760,8 +761,7 @@
|
||||
"wizard": {
|
||||
"device-wizard": "Device Wizard",
|
||||
"device-details": "Device details",
|
||||
"profile-configuration": "Profile configuration",
|
||||
"new-device-profile": "New device profile",
|
||||
"new-device-profile": "Create new device profile",
|
||||
"existing-device-profile": "Select existing device profile",
|
||||
"specific-configuration": "Specific configuration",
|
||||
"customer-to-assign-device": "Customer to assign the device",
|
||||
@ -784,6 +784,8 @@
|
||||
"set-default": "Make device profile default",
|
||||
"delete": "Delete device profile",
|
||||
"copyId": "Copy device profile Id",
|
||||
"new-device-profile-name": "Device profile name",
|
||||
"new-device-profile-name-required": "Device profile name is required.",
|
||||
"name": "Name",
|
||||
"name-required": "Name is required.",
|
||||
"type": "Profile type",
|
||||
@ -792,8 +794,11 @@
|
||||
"transport-type": "Transport type",
|
||||
"transport-type-required": "Transport type is required.",
|
||||
"transport-type-default": "Default",
|
||||
"transport-type-default-hint": "Default transport type",
|
||||
"transport-type-mqtt": "MQTT",
|
||||
"transport-type-mqtt-hint": "MQTT transport type",
|
||||
"transport-type-lwm2m": "LWM2M",
|
||||
"transport-type-lwm2m-hint": "LWM2M transport type",
|
||||
"description": "Description",
|
||||
"default": "Default",
|
||||
"profile-configuration": "Profile configuration",
|
||||
@ -824,7 +829,8 @@
|
||||
"not-valid-multi-character": "Invalid use of a multi-level wildcard character",
|
||||
"single-level-wildcards-hint": "<code>[+]</code> is suitable for any topic filter level. Ex.: <b>v1/devices/+/telemetry</b> or <b>+/devices/+/attributes</b>.",
|
||||
"multi-level-wildcards-hint": "<code>[#]</code> can replace the topic filter itself and must be the last symbol of the topic. Ex.: <b>#</b> or <b>v1/devices/me/#</b>.",
|
||||
"alarm-rules": "Alarm rules ({{count}})",
|
||||
"alarm-rules": "Alarm rules",
|
||||
"alarm-rules-with-count": "Alarm rules ({{count}})",
|
||||
"no-alarm-rules": "No alarm rules configured",
|
||||
"add-alarm-rule": "Add alarm rule",
|
||||
"edit-alarm-rule": "Edit alarm rule",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user