Browse Source

UI: Device profile autocomplete. Device profile data.

pull/3477/head
Igor Kulikov 6 years ago
parent
commit
1e87c72818
  1. 10
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  2. 67
      ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.html
  3. 261
      ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts
  4. 53
      ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.html
  5. 101
      ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts
  6. 4
      ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html
  7. 24
      ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.html
  8. 97
      ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.ts
  9. 24
      ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.html
  10. 97
      ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.ts
  11. 27
      ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.html
  12. 103
      ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.ts
  13. 43
      ui-ngx/src/app/modules/home/pages/device/data/device-data.component.html
  14. 94
      ui-ngx/src/app/modules/home/pages/device/data/device-data.component.ts
  15. 27
      ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.html
  16. 106
      ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.ts
  17. 11
      ui-ngx/src/app/modules/home/pages/device/device.component.html
  18. 43
      ui-ngx/src/app/modules/home/pages/device/device.component.ts
  19. 10
      ui-ngx/src/app/modules/home/pages/device/device.module.ts
  20. 2
      ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts
  21. 36
      ui-ngx/src/app/shared/models/device.models.ts
  22. 4
      ui-ngx/src/assets/locale/locale.constant-en_US.json

10
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -94,6 +94,8 @@ import { DeviceProfileDataComponent } from './profile/device-profile-data.compon
import { DeviceProfileComponent } from './profile/device-profile.component'; import { DeviceProfileComponent } from './profile/device-profile.component';
import { DefaultDeviceProfileTransportConfigurationComponent } from './profile/device/default-device-profile-transport-configuration.component'; import { DefaultDeviceProfileTransportConfigurationComponent } from './profile/device/default-device-profile-transport-configuration.component';
import { DeviceProfileTransportConfigurationComponent } from './profile/device/device-profile-transport-configuration.component'; import { DeviceProfileTransportConfigurationComponent } from './profile/device/device-profile-transport-configuration.component';
import { DeviceProfileDialogComponent } from './profile/device-profile-dialog.component';
import { DeviceProfileAutocompleteComponent } from './profile/device-profile-autocomplete.component';
@NgModule({ @NgModule({
declarations: declarations:
@ -165,12 +167,14 @@ import { DeviceProfileTransportConfigurationComponent } from './profile/device/d
TenantProfileDataComponent, TenantProfileDataComponent,
TenantProfileComponent, TenantProfileComponent,
TenantProfileDialogComponent, TenantProfileDialogComponent,
DeviceProfileAutocompleteComponent,
DefaultDeviceProfileConfigurationComponent, DefaultDeviceProfileConfigurationComponent,
DeviceProfileConfigurationComponent, DeviceProfileConfigurationComponent,
DefaultDeviceProfileTransportConfigurationComponent, DefaultDeviceProfileTransportConfigurationComponent,
DeviceProfileTransportConfigurationComponent, DeviceProfileTransportConfigurationComponent,
DeviceProfileDataComponent, DeviceProfileDataComponent,
DeviceProfileComponent DeviceProfileComponent,
DeviceProfileDialogComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -231,12 +235,14 @@ import { DeviceProfileTransportConfigurationComponent } from './profile/device/d
TenantProfileDataComponent, TenantProfileDataComponent,
TenantProfileComponent, TenantProfileComponent,
TenantProfileDialogComponent, TenantProfileDialogComponent,
DeviceProfileAutocompleteComponent,
DefaultDeviceProfileConfigurationComponent, DefaultDeviceProfileConfigurationComponent,
DeviceProfileConfigurationComponent, DeviceProfileConfigurationComponent,
DefaultDeviceProfileTransportConfigurationComponent, DefaultDeviceProfileTransportConfigurationComponent,
DeviceProfileTransportConfigurationComponent, DeviceProfileTransportConfigurationComponent,
DeviceProfileDataComponent, DeviceProfileDataComponent,
DeviceProfileComponent DeviceProfileComponent,
DeviceProfileDialogComponent
], ],
providers: [ providers: [
WidgetComponentService, WidgetComponentService,

67
ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.html

@ -0,0 +1,67 @@
<!--
Copyright © 2016-2020 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.
-->
<mat-form-field [formGroup]="selectDeviceProfileFormGroup" class="mat-block">
<input matInput type="text" placeholder="{{ 'device-profile.device-profile' | translate }}"
#deviceProfileInput
formControlName="deviceProfile"
[required]="required"
(keydown)="deviceProfileEnter($event)"
(keypress)="deviceProfileEnter($event)"
[matAutocomplete]="deviceProfileAutocomplete">
<button *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').value && !disabled"
type="button"
matSuffix mat-button mat-icon-button aria-label="Clear"
(click)="clear()">
<mat-icon class="material-icons">close</mat-icon>
</button>
<button *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').value && !disabled"
type="button"
matSuffix mat-button mat-icon-button aria-label="Edit"
matTooltip="{{ 'device-profile.edit' | translate }}"
matTooltipPosition="above"
(click)="editDeviceProfile($event)">
<mat-icon class="material-icons">edit</mat-icon>
</button>
<mat-autocomplete
class="tb-autocomplete"
#deviceProfileAutocomplete="matAutocomplete"
[displayWith]="displayDeviceProfileFn">
<mat-option *ngFor="let deviceProfile of filteredDeviceProfiles | async" [value]="deviceProfile">
<span [innerHTML]="deviceProfile.name | highlight:searchText"></span>
</mat-option>
<mat-option *ngIf="!(filteredDeviceProfiles | async)?.length" [value]="null" class="tb-not-found">
<div class="tb-not-found-content" (click)="$event.stopPropagation()">
<div *ngIf="!textIsNotEmpty(searchText); else searchNotEmpty">
<span translate>device-profile.no-device-profiles-found</span>
</div>
<ng-template #searchNotEmpty>
<span>
{{ translate.get('device-profile.no-device-profiles-matching',
{entity: truncate.transform(searchText, true, 6, &apos;...&apos;)}) | async }}
</span>
</ng-template>
<span>
<a translate (click)="createDeviceProfile($event, searchText)">device-profile.create-new-device-profile</a>
</span>
</div>
</mat-option>
</mat-autocomplete>
<mat-error *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').hasError('required')">
{{ 'device-profile.device-profile-required' | translate }}
</mat-error>
</mat-form-field>

261
ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts

@ -0,0 +1,261 @@
///
/// Copyright © 2016-2020 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, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Observable } from 'rxjs';
import { PageLink } from '@shared/models/page/page-link';
import { Direction } from '@shared/models/page/sort-order';
import { map, mergeMap, startWith, tap } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { entityIdEquals } from '@shared/models/id/entity-id';
import { TruncatePipe } from '@shared//pipe/truncate.pipe';
import { ENTER } from '@angular/cdk/keycodes';
import { MatDialog } from '@angular/material/dialog';
import { DeviceProfileId } from '@shared/models/id/device-profile-id';
import {
createDeviceProfileConfiguration,
createDeviceProfileTransportConfiguration,
DeviceProfile,
DeviceProfileInfo,
DeviceProfileType,
DeviceTransportType
} from '@shared/models/device.models';
import { DeviceProfileService } from '@core/http/device-profile.service';
import { DeviceProfileDialogComponent, DeviceProfileDialogData } from './device-profile-dialog.component';
@Component({
selector: 'tb-device-profile-autocomplete',
templateUrl: './device-profile-autocomplete.component.html',
styleUrls: [],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DeviceProfileAutocompleteComponent),
multi: true
}]
})
export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, OnInit {
selectDeviceProfileFormGroup: FormGroup;
modelValue: DeviceProfileId | null;
@Input()
selectDefaultProfile = false;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
@Output()
deviceProfileUpdated = new EventEmitter<DeviceProfileId>();
@Output()
deviceProfileChanged = new EventEmitter<DeviceProfileInfo>();
@ViewChild('deviceProfileInput', {static: true}) deviceProfileInput: ElementRef;
filteredDeviceProfiles: Observable<Array<DeviceProfileInfo>>;
searchText = '';
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
public translate: TranslateService,
public truncate: TruncatePipe,
private deviceProfileService: DeviceProfileService,
private fb: FormBuilder,
private dialog: MatDialog) {
this.selectDeviceProfileFormGroup = this.fb.group({
deviceProfile: [null]
});
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
ngOnInit() {
this.filteredDeviceProfiles = this.selectDeviceProfileFormGroup.get('deviceProfile').valueChanges
.pipe(
tap((value: DeviceProfileInfo | string) => {
let modelValue: DeviceProfileInfo | null;
if (typeof value === 'string' || !value) {
modelValue = null;
} else {
modelValue = value;
}
this.updateView(modelValue);
}),
startWith<string | DeviceProfileInfo>(''),
map(value => value ? (typeof value === 'string' ? value : value.name) : ''),
mergeMap(name => this.fetchDeviceProfiles(name) )
);
}
selectDefaultDeviceProfileIfNeeded(): void {
if (this.selectDefaultProfile && !this.modelValue) {
this.deviceProfileService.getDefaultDeviceProfileInfo().subscribe(
(profile) => {
if (profile) {
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(profile, {emitEvent: false});
this.updateView(profile);
}
}
);
}
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
writeValue(value: DeviceProfileId | null): void {
this.searchText = '';
if (value != null) {
this.deviceProfileService.getDeviceProfileInfo(value.id).subscribe(
(profile) => {
this.modelValue = new DeviceProfileId(profile.id.id);
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(profile, {emitEvent: true});
}
);
} else {
this.modelValue = null;
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: true});
this.selectDefaultDeviceProfileIfNeeded();
}
}
updateView(deviceProfile: DeviceProfileInfo | null) {
const idValue = deviceProfile ? new DeviceProfileId(deviceProfile.id.id) : null;
if (!entityIdEquals(this.modelValue, idValue)) {
this.modelValue = idValue;
this.propagateChange(this.modelValue);
this.deviceProfileChanged.emit(deviceProfile);
}
}
displayDeviceProfileFn(profile?: DeviceProfileInfo): string | undefined {
return profile ? profile.name : undefined;
}
fetchDeviceProfiles(searchText?: string): Observable<Array<DeviceProfileInfo>> {
this.searchText = searchText;
const pageLink = new PageLink(10, 0, searchText, {
property: 'name',
direction: Direction.ASC
});
return this.deviceProfileService.getDeviceProfileInfos(pageLink, {ignoreLoading: true}).pipe(
map(pageData => {
return pageData.data;
})
);
}
clear() {
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: true});
setTimeout(() => {
this.deviceProfileInput.nativeElement.blur();
this.deviceProfileInput.nativeElement.focus();
}, 0);
}
textIsNotEmpty(text: string): boolean {
return (text && text.length > 0);
}
deviceProfileEnter($event: KeyboardEvent) {
if ($event.keyCode === ENTER) {
$event.preventDefault();
if (!this.modelValue) {
this.createDeviceProfile($event, this.searchText);
}
}
}
createDeviceProfile($event: Event, profileName: string) {
$event.preventDefault();
const deviceProfile: DeviceProfile = {
id: null,
name: profileName,
type: DeviceProfileType.DEFAULT,
transportType: DeviceTransportType.DEFAULT,
profileData: {
configuration: createDeviceProfileConfiguration(DeviceProfileType.DEFAULT),
transportConfiguration: createDeviceProfileTransportConfiguration(DeviceTransportType.DEFAULT)
}
};
this.openDeviceProfileDialog(deviceProfile, true);
}
editDeviceProfile($event: Event) {
$event.preventDefault();
this.deviceProfileService.getDeviceProfile(this.modelValue.id).subscribe(
(deviceProfile) => {
this.openDeviceProfileDialog(deviceProfile, false);
}
);
}
openDeviceProfileDialog(deviceProfile: DeviceProfile, isAdd: boolean) {
this.dialog.open<DeviceProfileDialogComponent, DeviceProfileDialogData,
DeviceProfile>(DeviceProfileDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
isAdd,
deviceProfile
}
}).afterClosed().subscribe(
(savedDeviceProfile) => {
if (!savedDeviceProfile) {
setTimeout(() => {
this.deviceProfileInput.nativeElement.blur();
this.deviceProfileInput.nativeElement.focus();
}, 0);
} else {
this.deviceProfileService.getDeviceProfileInfo(savedDeviceProfile.id.id).subscribe(
(profile) => {
this.modelValue = new DeviceProfileId(profile.id.id);
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(profile, {emitEvent: true});
if (isAdd) {
this.propagateChange(this.modelValue);
} else {
this.deviceProfileUpdated.next(savedDeviceProfile.id);
}
this.deviceProfileChanged.emit(profile);
}
);
}
}
);
}
}

53
ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.html

@ -0,0 +1,53 @@
<!--
Copyright © 2016-2020 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.
-->
<form (ngSubmit)="save()" style="min-width: 600px;">
<mat-toolbar color="primary">
<h2>{{ (isAdd ? 'device-profile.add' : 'device-profile.edit' ) | translate }}</h2>
<span fxFlex></span>
<button mat-icon-button
(click)="cancel()"
type="button">
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content>
<tb-device-profile
#deviceProfileComponent
[standalone]="true"
[entity]="deviceProfile"
[isEdit]="true">
</tb-device-profile>
</div>
<div mat-dialog-actions fxLayoutAlign="end center">
<button mat-raised-button color="primary"
type="submit"
[disabled]="(isLoading$ | async) || deviceProfileComponent.entityForm?.invalid || !deviceProfileComponent.entityForm?.dirty">
{{ (isAdd ? 'action.add' : 'action.save') | translate }}
</button>
<button mat-button color="primary"
type="button"
cdkFocusInitial
[disabled]="(isLoading$ | async)"
(click)="cancel()">
{{ 'action.cancel' | translate }}
</button>
</div>
</form>

101
ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts

@ -0,0 +1,101 @@
///
/// Copyright © 2016-2020 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 {
AfterViewInit,
Component,
ComponentFactoryResolver,
Inject,
Injector,
SkipSelf,
ViewChild
} from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { FormControl, FormGroupDirective, NgForm } from '@angular/forms';
import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router';
import { DeviceProfile } from '@shared/models/device.models';
import { DeviceProfileComponent } from './device-profile.component';
import { DeviceProfileService } from '@core/http/device-profile.service';
export interface DeviceProfileDialogData {
deviceProfile: DeviceProfile;
isAdd: boolean;
}
@Component({
selector: 'tb-device-profile-dialog',
templateUrl: './device-profile-dialog.component.html',
providers: [{provide: ErrorStateMatcher, useExisting: DeviceProfileDialogComponent}],
styleUrls: []
})
export class DeviceProfileDialogComponent extends
DialogComponent<DeviceProfileDialogComponent, DeviceProfile> implements ErrorStateMatcher, AfterViewInit {
isAdd: boolean;
deviceProfile: DeviceProfile;
submitted = false;
@ViewChild('deviceProfileComponent', {static: true}) deviceProfileComponent: DeviceProfileComponent;
constructor(protected store: Store<AppState>,
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: DeviceProfileDialogData,
public dialogRef: MatDialogRef<DeviceProfileDialogComponent, DeviceProfile>,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
private deviceProfileService: DeviceProfileService) {
super(store, router, dialogRef);
this.isAdd = this.data.isAdd;
this.deviceProfile = this.data.deviceProfile;
}
ngAfterViewInit(): void {
if (this.isAdd) {
setTimeout(() => {
this.deviceProfileComponent.entityForm.markAsDirty();
}, 0);
}
}
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const originalErrorState = this.errorStateMatcher.isErrorState(control, form);
const customErrorState = !!(control && control.invalid && this.submitted);
return originalErrorState || customErrorState;
}
cancel(): void {
this.dialogRef.close(null);
}
save(): void {
this.submitted = true;
if (this.deviceProfileComponent.entityForm.valid) {
this.deviceProfile = {...this.deviceProfile, ...this.deviceProfileComponent.entityFormValue()};
this.deviceProfileService.saveDeviceProfile(this.deviceProfile).subscribe(
(deviceProfile) => {
this.dialogRef.close(deviceProfile);
}
);
}
}
}

4
ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html

@ -18,10 +18,10 @@
<div [formGroup]="deviceProfileTransportConfigurationFormGroup"> <div [formGroup]="deviceProfileTransportConfigurationFormGroup">
<div [ngSwitch]="transportType"> <div [ngSwitch]="transportType">
<ng-template [ngSwitchCase]="deviceTransportType.DEFAULT"> <ng-template [ngSwitchCase]="deviceTransportType.DEFAULT">
<tb-default-device-profile-configuration <tb-default-device-profile-transport-configuration
[required]="required" [required]="required"
formControlName="configuration"> formControlName="configuration">
</tb-default-device-profile-configuration> </tb-default-device-profile-transport-configuration>
</ng-template> </ng-template>
</div> </div>
</div> </div>

24
ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.html

@ -0,0 +1,24 @@
<!--
Copyright © 2016-2020 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.
-->
<form [formGroup]="defaultDeviceConfigurationFormGroup" style="padding-bottom: 16px;">
<tb-json-object-edit
[required]="required"
label="{{ 'device-profile.type-default' | translate }}"
formControlName="configuration">
</tb-json-object-edit>
</form>

97
ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.ts

@ -0,0 +1,97 @@
///
/// Copyright © 2016-2020 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, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {
DefaultDeviceConfiguration,
DeviceConfiguration,
DeviceProfileType
} from '@shared/models/device.models';
@Component({
selector: 'tb-default-device-configuration',
templateUrl: './default-device-configuration.component.html',
styleUrls: [],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DefaultDeviceConfigurationComponent),
multi: true
}]
})
export class DefaultDeviceConfigurationComponent implements ControlValueAccessor, OnInit {
defaultDeviceConfigurationFormGroup: FormGroup;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
private fb: FormBuilder) {
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
ngOnInit() {
this.defaultDeviceConfigurationFormGroup = this.fb.group({
configuration: [null, Validators.required]
});
this.defaultDeviceConfigurationFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (this.disabled) {
this.defaultDeviceConfigurationFormGroup.disable({emitEvent: false});
} else {
this.defaultDeviceConfigurationFormGroup.enable({emitEvent: false});
}
}
writeValue(value: DefaultDeviceConfiguration | null): void {
this.defaultDeviceConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false});
}
private updateModel() {
let configuration: DeviceConfiguration = null;
if (this.defaultDeviceConfigurationFormGroup.valid) {
configuration = this.defaultDeviceConfigurationFormGroup.getRawValue().configuration;
configuration.type = DeviceProfileType.DEFAULT;
}
this.propagateChange(configuration);
}
}

24
ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.html

@ -0,0 +1,24 @@
<!--
Copyright © 2016-2020 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.
-->
<form [formGroup]="defaultDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;">
<tb-json-object-edit
[required]="required"
label="{{ 'device-profile.transport-type-default' | translate }}"
formControlName="configuration">
</tb-json-object-edit>
</form>

97
ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.ts

@ -0,0 +1,97 @@
///
/// Copyright © 2016-2020 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, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {
DefaultDeviceTransportConfiguration,
DeviceTransportConfiguration,
DeviceTransportType
} from '@shared/models/device.models';
@Component({
selector: 'tb-default-device-transport-configuration',
templateUrl: './default-device-transport-configuration.component.html',
styleUrls: [],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DefaultDeviceTransportConfigurationComponent),
multi: true
}]
})
export class DefaultDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit {
defaultDeviceTransportConfigurationFormGroup: FormGroup;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
private fb: FormBuilder) {
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
ngOnInit() {
this.defaultDeviceTransportConfigurationFormGroup = this.fb.group({
configuration: [null, Validators.required]
});
this.defaultDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (this.disabled) {
this.defaultDeviceTransportConfigurationFormGroup.disable({emitEvent: false});
} else {
this.defaultDeviceTransportConfigurationFormGroup.enable({emitEvent: false});
}
}
writeValue(value: DefaultDeviceTransportConfiguration | null): void {
this.defaultDeviceTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false});
}
private updateModel() {
let configuration: DeviceTransportConfiguration = null;
if (this.defaultDeviceTransportConfigurationFormGroup.valid) {
configuration = this.defaultDeviceTransportConfigurationFormGroup.getRawValue().configuration;
configuration.type = DeviceTransportType.DEFAULT;
}
this.propagateChange(configuration);
}
}

27
ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.html

@ -0,0 +1,27 @@
<!--
Copyright © 2016-2020 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.
-->
<div [formGroup]="deviceConfigurationFormGroup">
<div [ngSwitch]="type">
<ng-template [ngSwitchCase]="deviceProfileType.DEFAULT">
<tb-default-device-configuration
[required]="required"
formControlName="configuration">
</tb-default-device-configuration>
</ng-template>
</div>
</div>

103
ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.ts

@ -0,0 +1,103 @@
///
/// Copyright © 2016-2020 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, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DeviceConfiguration, DeviceProfileType } from '@shared/models/device.models';
import { deepClone } from '@core/utils';
@Component({
selector: 'tb-device-configuration',
templateUrl: './device-configuration.component.html',
styleUrls: [],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DeviceConfigurationComponent),
multi: true
}]
})
export class DeviceConfigurationComponent implements ControlValueAccessor, OnInit {
deviceProfileType = DeviceProfileType;
deviceConfigurationFormGroup: FormGroup;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
type: DeviceProfileType;
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
private fb: FormBuilder) {
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
ngOnInit() {
this.deviceConfigurationFormGroup = this.fb.group({
configuration: [null, Validators.required]
});
this.deviceConfigurationFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (this.disabled) {
this.deviceConfigurationFormGroup.disable({emitEvent: false});
} else {
this.deviceConfigurationFormGroup.enable({emitEvent: false});
}
}
writeValue(value: DeviceConfiguration | null): void {
this.type = value?.type;
const configuration = deepClone(value);
if (configuration) {
delete configuration.type;
}
this.deviceConfigurationFormGroup.patchValue({configuration}, {emitEvent: false});
}
private updateModel() {
let configuration: DeviceConfiguration = null;
if (this.deviceConfigurationFormGroup.valid) {
configuration = this.deviceConfigurationFormGroup.getRawValue().configuration;
configuration.type = this.type;
}
this.propagateChange(configuration);
}
}

43
ui-ngx/src/app/modules/home/pages/device/data/device-data.component.html

@ -0,0 +1,43 @@
<!--
Copyright © 2016-2020 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.
-->
<div [formGroup]="deviceDataFormGroup" style="padding-bottom: 16px;">
<mat-accordion multi="true">
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<div translate>device.device-configuration</div>
</mat-panel-title>
</mat-expansion-panel-header>
<tb-device-configuration
formControlName="configuration"
required>
</tb-device-configuration>
</mat-expansion-panel>
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<div translate>device.transport-configuration</div>
</mat-panel-title>
</mat-expansion-panel-header>
<tb-device-transport-configuration
formControlName="transportConfiguration"
required>
</tb-device-transport-configuration>
</mat-expansion-panel>
</mat-accordion>
</div>

94
ui-ngx/src/app/modules/home/pages/device/data/device-data.component.ts

@ -0,0 +1,94 @@
///
/// Copyright © 2016-2020 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, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DeviceData } from '@shared/models/device.models';
@Component({
selector: 'tb-device-data',
templateUrl: './device-data.component.html',
styleUrls: [],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DeviceDataComponent),
multi: true
}]
})
export class DeviceDataComponent implements ControlValueAccessor, OnInit {
deviceDataFormGroup: FormGroup;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
private fb: FormBuilder) {
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
ngOnInit() {
this.deviceDataFormGroup = this.fb.group({
configuration: [null, Validators.required],
transportConfiguration: [null, Validators.required]
});
this.deviceDataFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (this.disabled) {
this.deviceDataFormGroup.disable({emitEvent: false});
} else {
this.deviceDataFormGroup.enable({emitEvent: false});
}
}
writeValue(value: DeviceData | null): void {
this.deviceDataFormGroup.patchValue({configuration: value?.configuration}, {emitEvent: false});
this.deviceDataFormGroup.patchValue({transportConfiguration: value?.transportConfiguration}, {emitEvent: false});
}
private updateModel() {
let deviceData: DeviceData = null;
if (this.deviceDataFormGroup.valid) {
deviceData = this.deviceDataFormGroup.getRawValue();
}
this.propagateChange(deviceData);
}
}

27
ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.html

@ -0,0 +1,27 @@
<!--
Copyright © 2016-2020 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.
-->
<div [formGroup]="deviceTransportConfigurationFormGroup">
<div [ngSwitch]="transportType">
<ng-template [ngSwitchCase]="deviceTransportType.DEFAULT">
<tb-default-device-transport-configuration
[required]="required"
formControlName="configuration">
</tb-default-device-transport-configuration>
</ng-template>
</div>
</div>

106
ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.ts

@ -0,0 +1,106 @@
///
/// Copyright © 2016-2020 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, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {
DeviceTransportConfiguration,
DeviceTransportType
} from '@shared/models/device.models';
import { deepClone } from '@core/utils';
@Component({
selector: 'tb-device-transport-configuration',
templateUrl: './device-transport-configuration.component.html',
styleUrls: [],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DeviceTransportConfigurationComponent),
multi: true
}]
})
export class DeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit {
deviceTransportType = DeviceTransportType;
deviceTransportConfigurationFormGroup: FormGroup;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
transportType: DeviceTransportType;
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
private fb: FormBuilder) {
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
ngOnInit() {
this.deviceTransportConfigurationFormGroup = this.fb.group({
configuration: [null, Validators.required]
});
this.deviceTransportConfigurationFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (this.disabled) {
this.deviceTransportConfigurationFormGroup.disable({emitEvent: false});
} else {
this.deviceTransportConfigurationFormGroup.enable({emitEvent: false});
}
}
writeValue(value: DeviceTransportConfiguration | null): void {
this.transportType = value?.type;
const configuration = deepClone(value);
if (configuration) {
delete configuration.type;
}
this.deviceTransportConfigurationFormGroup.patchValue({configuration}, {emitEvent: false});
}
private updateModel() {
let configuration: DeviceTransportConfiguration = null;
if (this.deviceTransportConfigurationFormGroup.valid) {
configuration = this.deviceTransportConfigurationFormGroup.getRawValue().configuration;
configuration.type = this.transportType;
}
this.propagateChange(configuration);
}
}

11
ui-ngx/src/app/modules/home/pages/device/device.component.html

@ -83,6 +83,13 @@
{{ 'device.name-required' | translate }} {{ 'device.name-required' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<tb-device-profile-autocomplete
[selectDefaultProfile]="isAdd"
required
formControlName="deviceProfileId"
(deviceProfileUpdated)="onDeviceProfileUpdated()"
(deviceProfileChanged)="onDeviceProfileChanged($event)">
</tb-device-profile-autocomplete>
<tb-entity-subtype-autocomplete <tb-entity-subtype-autocomplete
formControlName="type" formControlName="type"
[required]="true" [required]="true"
@ -93,6 +100,10 @@
<mat-label translate>device.label</mat-label> <mat-label translate>device.label</mat-label>
<input matInput formControlName="label"> <input matInput formControlName="label">
</mat-form-field> </mat-form-field>
<tb-device-data
formControlName="deviceData"
required>
</tb-device-data>
<div formGroupName="additionalInfo" fxLayout="column"> <div formGroupName="additionalInfo" fxLayout="column">
<mat-checkbox fxFlex formControlName="gateway" style="padding-bottom: 16px;"> <mat-checkbox fxFlex formControlName="gateway" style="padding-bottom: 16px;">
{{ 'device.is-gateway' | translate }} {{ 'device.is-gateway' | translate }}

43
ui-ngx/src/app/modules/home/pages/device/device.component.ts

@ -19,7 +19,16 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { EntityComponent } from '../../components/entity/entity.component'; import { EntityComponent } from '../../components/entity/entity.component';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DeviceInfo } from '@shared/models/device.models'; import {
createDeviceConfiguration,
createDeviceProfileConfiguration, createDeviceTransportConfiguration,
DeviceData,
DeviceInfo,
DeviceProfileData,
DeviceProfileInfo,
DeviceProfileType,
DeviceTransportType
} from '@shared/models/device.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
import { ActionNotificationShow } from '@core/notification/notification.actions'; import { ActionNotificationShow } from '@core/notification/notification.actions';
@ -126,4 +135,36 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
); );
} }
} }
onDeviceProfileUpdated() {
this.entitiesTableConfig.table.updateData(false);
}
onDeviceProfileChanged(deviceProfile: DeviceProfileInfo) {
if (deviceProfile) {
const deviceProfileType: DeviceProfileType = deviceProfile.type;
const deviceTransportType: DeviceTransportType = deviceProfile.transportType;
let deviceData: DeviceData = this.entityForm.getRawValue().deviceData;
if (!deviceData) {
deviceData = {
configuration: createDeviceConfiguration(deviceProfileType),
transportConfiguration: createDeviceTransportConfiguration(deviceTransportType)
};
this.entityForm.patchValue({deviceData});
} else {
let changed = false;
if (deviceData.configuration.type !== deviceProfileType) {
deviceData.configuration = createDeviceConfiguration(deviceProfileType);
changed = true;
}
if (deviceData.transportConfiguration.type !== deviceTransportType) {
deviceData.transportConfiguration = createDeviceTransportConfiguration(deviceTransportType);
changed = true;
}
if (changed) {
this.entityForm.patchValue({deviceData});
}
}
}
}
} }

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

@ -24,9 +24,19 @@ import { DeviceCredentialsDialogComponent } from '@modules/home/pages/device/dev
import { HomeDialogsModule } from '../../dialogs/home-dialogs.module'; import { HomeDialogsModule } from '../../dialogs/home-dialogs.module';
import { HomeComponentsModule } from '@modules/home/components/home-components.module'; import { HomeComponentsModule } from '@modules/home/components/home-components.module';
import { DeviceTabsComponent } from '@home/pages/device/device-tabs.component'; import { DeviceTabsComponent } from '@home/pages/device/device-tabs.component';
import { DefaultDeviceConfigurationComponent } from './data/default-device-configuration.component';
import { DeviceConfigurationComponent } from './data/device-configuration.component';
import { DeviceDataComponent } from './data/device-data.component';
import { DefaultDeviceTransportConfigurationComponent } from './data/default-device-transport-configuration.component';
import { DeviceTransportConfigurationComponent } from './data/device-transport-configuration.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
DefaultDeviceConfigurationComponent,
DeviceConfigurationComponent,
DefaultDeviceTransportConfigurationComponent,
DeviceTransportConfigurationComponent,
DeviceDataComponent,
DeviceComponent, DeviceComponent,
DeviceTabsComponent, DeviceTabsComponent,
DeviceTableHeaderComponent, DeviceTableHeaderComponent,

2
ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts

@ -86,6 +86,8 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
this.config.entityTranslations = entityTypeTranslations.get(EntityType.DEVICE); this.config.entityTranslations = entityTypeTranslations.get(EntityType.DEVICE);
this.config.entityResources = entityTypeResources.get(EntityType.DEVICE); this.config.entityResources = entityTypeResources.get(EntityType.DEVICE);
this.config.addDialogStyle = {width: '600px'};
this.config.deleteEntityTitle = device => this.translate.instant('device.delete-device-title', { deviceName: device.name }); this.config.deleteEntityTitle = device => this.translate.instant('device.delete-device-title', { deviceName: device.name });
this.config.deleteEntityContent = () => this.translate.instant('device.delete-device-text'); this.config.deleteEntityContent = () => this.translate.instant('device.delete-device-text');
this.config.deleteEntitiesTitle = count => this.translate.instant('device.delete-devices-title', {count}); this.config.deleteEntitiesTitle = count => this.translate.instant('device.delete-devices-title', {count});

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

@ -91,6 +91,19 @@ export function createDeviceProfileConfiguration(type: DeviceProfileType): Devic
return configuration; return configuration;
} }
export function createDeviceConfiguration(type: DeviceProfileType): DeviceConfiguration {
let configuration: DeviceConfiguration = null;
if (type) {
switch (type) {
case DeviceProfileType.DEFAULT:
const defaultConfiguration: DefaultDeviceConfiguration = {};
configuration = {...defaultConfiguration, type: DeviceProfileType.DEFAULT};
break;
}
}
return configuration;
}
export function createDeviceProfileTransportConfiguration(type: DeviceTransportType): DeviceProfileTransportConfiguration { export function createDeviceProfileTransportConfiguration(type: DeviceTransportType): DeviceProfileTransportConfiguration {
let transportConfiguration: DeviceProfileTransportConfiguration = null; let transportConfiguration: DeviceProfileTransportConfiguration = null;
if (type) { if (type) {
@ -112,6 +125,27 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT
return transportConfiguration; return transportConfiguration;
} }
export function createDeviceTransportConfiguration(type: DeviceTransportType): DeviceTransportConfiguration {
let transportConfiguration: DeviceTransportConfiguration = null;
if (type) {
switch (type) {
case DeviceTransportType.DEFAULT:
const defaultTransportConfiguration: DefaultDeviceTransportConfiguration = {};
transportConfiguration = {...defaultTransportConfiguration, type: DeviceTransportType.DEFAULT};
break;
case DeviceTransportType.MQTT:
const mqttTransportConfiguration: MqttDeviceTransportConfiguration = {};
transportConfiguration = {...mqttTransportConfiguration, type: DeviceTransportType.MQTT};
break;
case DeviceTransportType.LWM2M:
const lwm2mTransportConfiguration: Lwm2mDeviceTransportConfiguration = {};
transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M};
break;
}
}
return transportConfiguration;
}
export interface DeviceProfileData { export interface DeviceProfileData {
configuration: DeviceProfileConfiguration; configuration: DeviceProfileConfiguration;
transportConfiguration: DeviceProfileTransportConfiguration; transportConfiguration: DeviceProfileTransportConfiguration;
@ -121,7 +155,7 @@ export interface DeviceProfile extends BaseData<DeviceProfileId> {
tenantId?: TenantId; tenantId?: TenantId;
name: string; name: string;
description?: string; description?: string;
default: boolean; default?: boolean;
type: DeviceProfileType; type: DeviceProfileType;
transportType: DeviceTransportType; transportType: DeviceTransportType;
defaultRuleChainId?: RuleChainId; defaultRuleChainId?: RuleChainId;

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

@ -748,7 +748,9 @@
"import": "Import device", "import": "Import device",
"device-file": "Device file", "device-file": "Device file",
"search": "Search devices", "search": "Search devices",
"selected-devices": "{ count, plural, 1 {1 device} other {# devices} } selected" "selected-devices": "{ count, plural, 1 {1 device} other {# devices} } selected",
"device-configuration": "Device configuration",
"transport-configuration": "Transport configuration"
}, },
"device-profile": { "device-profile": {
"device-profile": "Device profile", "device-profile": "Device profile",

Loading…
Cancel
Save