Browse Source

UI: Refactoring lwm2m

pull/3980/head
Vladyslav_Prykhodko 6 years ago
parent
commit
c8814f7cfa
  1. 1
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  2. 19
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts
  3. 88
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html
  4. 30
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts
  5. 8
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts
  6. 7
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances.component.html
  7. 7
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances.component.ts
  8. 50
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts
  9. 13
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.html
  10. 59
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.ts
  11. 18
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.html
  12. 114
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts
  13. 15
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/profile-config.models.ts
  14. 2
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.html
  15. 10
      ui-ngx/src/app/shared/components/json-object-edit.component.ts
  16. 2
      ui-ngx/src/app/shared/models/device.models.ts

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

@ -307,7 +307,6 @@ import { Lwm2mProfileComponentsModule } from '@home/components/profile/device/lw
EditAlarmDetailsDialogComponent,
DeviceProfileProvisionConfigurationComponent,
AlarmScheduleComponent,
// Lwm2mProfileComponentsModule,
SmsProviderConfigurationComponent,
AwsSnsProviderConfigurationComponent,
TwilioSmsProviderConfigurationComponent

19
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts

@ -15,19 +15,18 @@
///
import { Component, forwardRef, Inject, Input, OnInit } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators
} from '@angular/forms';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import {
SECURITY_CONFIG_MODE,
SECURITY_CONFIG_MODE_NAMES,
ServerSecurityConfig,
DEFAULT_CLIENT_HOLD_OFF_TIME,
DEFAULT_ID_SERVER,
DEFAULT_PORT_BOOTSTRAP_NO_SEC,
DEFAULT_PORT_SERVER_NO_SEC,
DEFAULT_CLIENT_HOLD_OFF_TIME,
DEFAULT_ID_SERVER, LEN_MAX_PUBLIC_KEY_RPK, LEN_MAX_PUBLIC_KEY_X509, KEY_REGEXP_HEX_DEC
KEY_REGEXP_HEX_DEC,
LEN_MAX_PUBLIC_KEY_RPK,
LEN_MAX_PUBLIC_KEY_X509,
SECURITY_CONFIG_MODE,
SECURITY_CONFIG_MODE_NAMES,
ServerSecurityConfig
} from './profile-config.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';

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

@ -46,50 +46,52 @@
<div class="tb-panel-title">{{ 'device-profile.lwm2m.servers' | translate | uppercase }}</div>
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="column">
<div fxLayout="row" fxLayoutGap="8px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.short-id' | translate }}</mat-label>
<input matInput type="number" formControlName="shortId" required>
<mat-error *ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('shortId').hasError('required')">
{{ 'device-profile.lwm2m.short-id' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.lifetime' | translate }}</mat-label>
<input matInput type="number" formControlName="lifetime" required>
<mat-error *ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('lifetime').hasError('required')">
{{ 'device-profile.lwm2m.lifetime' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<ng-template matExpansionPanelContent>
<div fxLayout="column">
<div fxLayout="row" fxLayoutGap="8px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.short-id' | translate }}</mat-label>
<input matInput type="number" formControlName="shortId" required>
<mat-error *ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('shortId').hasError('required')">
{{ 'device-profile.lwm2m.short-id' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.lifetime' | translate }}</mat-label>
<input matInput type="number" formControlName="lifetime" required>
<mat-error *ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('lifetime').hasError('required')">
{{ 'device-profile.lwm2m.lifetime' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
</div>
<div fxLayout="row" fxLayoutGap="8px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.default-min-period' | translate }}</mat-label>
<input matInput type="number" formControlName="defaultMinPeriod" required>
<mat-error
*ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('defaultMinPeriod').hasError('required')">
{{ 'device-profile.lwm2m.default-min-period' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.binding' | translate }}</mat-label>
<input matInput type="text" formControlName="binding" required>
<mat-error *ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('binding').hasError('required')">
{{ 'device-profile.lwm2m.binding' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
</div>
<div>
<mat-checkbox formControlName="notifIfDisabled" color="primary">
{{ 'device-profile.lwm2m.notif-if-disabled' | translate }}
</mat-checkbox>
</div>
</div>
<div fxLayout="row" fxLayoutGap="8px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.default-min-period' | translate }}</mat-label>
<input matInput type="number" formControlName="defaultMinPeriod" required>
<mat-error
*ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('defaultMinPeriod').hasError('required')">
{{ 'device-profile.lwm2m.default-min-period' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.binding' | translate }}</mat-label>
<input matInput type="text" formControlName="binding" required>
<mat-error *ngIf="lwm2mDeviceProfileTransportConfFormGroup.get('binding').hasError('required')">
{{ 'device-profile.lwm2m.binding' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>
</mat-form-field>
</div>
<div>
<mat-checkbox formControlName="notifIfDisabled" color="primary">
{{ 'device-profile.lwm2m.notif-if-disabled' | translate }}
</mat-checkbox>
</div>
</div>
</ng-template>
</mat-expansion-panel>
</mat-accordion>
<mat-accordion multi="true" class="mat-body-1">

30
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts

@ -14,26 +14,23 @@
/// limitations under the License.
///
import {
DeviceProfileTransportConfiguration,
DeviceTransportType
} from '@shared/models/device.models';
import {
Component,
forwardRef, Inject,
Input,
OnInit
} from '@angular/core';
import { DeviceProfileTransportConfiguration, DeviceTransportType } from '@shared/models/device.models';
import { Component, forwardRef, Inject, 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 {
ATTR,
getDefaultProfileConfig,
Instance,
KEY_NAME,
ObjectLwM2M,
OBSERVE,
OBSERVE_ATTR,
TELEMETRY,
ObjectLwM2M, getDefaultProfileConfig, KEY_NAME, Instance, ProfileConfigModels, ResourceLwM2M
ProfileConfigModels,
ResourceLwM2M,
TELEMETRY
} from './profile-config.models';
import { DeviceProfileService } from '@core/http/device-profile.service';
import { deepClone, isUndefined } from '@core/utils';
@ -50,7 +47,7 @@ import { isNotNullOrUndefined } from 'codelyzer/util/isNotNullOrUndefined';
multi: true
}]
})
export class Lwm2mDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, Validators {
export class Lwm2mDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, Validators {
private configurationValue: ProfileConfigModels;
private requiredValue: boolean;
@ -65,7 +62,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
bootstrapServers: string;
bootstrapServer: string;
lwm2mServer: string;
sortFunction: {};
sortFunction: (key: string, value: object) => object;
get required(): boolean {
return this.requiredValue;
@ -99,6 +96,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
this.updateModel();
}
});
this.sortFunction = this.sortObjectKeyPathJson;
}
registerOnChange(fn: any): void {
@ -108,10 +106,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
registerOnTouched(fn: any): void {
}
ngOnInit() {
this.sortFunction = this.sortObjectKeyPathJson;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {

8
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts

@ -49,7 +49,7 @@ import { DeviceProfileService } from '@core/http/device-profile.service';
multi: true
}]
})
export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccessor, OnInit, Validators {
export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccessor {
private requiredValue: boolean;
private disabled = false as boolean;
@ -103,12 +103,6 @@ export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccesso
registerOnTouched(fn: any): void {
}
ngOnInit() {
}
ngAfterViewInit(): void {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {

7
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances.component.html

@ -15,7 +15,7 @@
limitations under the License.
-->
<form [formGroup]="jsonFormGroup" (ngSubmit)="add()" style="min-width: 400px;">
<form [formGroup]="instancesFormGroup" (ngSubmit)="add()" style="min-width: 400px;">
<mat-toolbar fxLayout="row" color="primary">
<b><i>{{data.objectName}}</i></b> &nbsp;&nbsp; (object&nbsp;[<b>{{data.objectId}}</b>])
<span fxFlex></span>
@ -38,16 +38,15 @@
</fieldset>
</div>
<div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center">
<span fxFlex></span>
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()">
{{ 'action.cancel' | translate }}
</button>
<button mat-button mat-raised-button color="primary"
<button mat-raised-button color="primary"
type="submit"
[disabled]="(isLoading$ | async) || jsonFormGroup.invalid || !jsonFormGroup.dirty">
[disabled]="(isLoading$ | async) || instancesFormGroup.invalid || !instancesFormGroup.dirty">
{{ 'action.save' | translate }}
</button>
</div>

7
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances.component.ts

@ -35,7 +35,7 @@ export interface Lwm2mObjectAddInstancesData {
})
export class Lwm2mObjectAddInstancesComponent extends DialogComponent<Lwm2mObjectAddInstancesComponent, object> implements OnInit {
jsonFormGroup: FormGroup;
instancesFormGroup: FormGroup;
submitted = false;
constructor(protected store: Store<AppState>,
@ -46,9 +46,8 @@ export class Lwm2mObjectAddInstancesComponent extends DialogComponent<Lwm2mObjec
super(store, router, dialogRef);
}
ngOnInit(): void {
this.jsonFormGroup = this.fb.group({
this.instancesFormGroup = this.fb.group({
instancesIds: this.data.instancesIds
});
}
@ -58,7 +57,7 @@ export class Lwm2mObjectAddInstancesComponent extends DialogComponent<Lwm2mObjec
}
add(): void {
this.data.instancesIds = this.jsonFormGroup.get('instancesIds').value;
this.data.instancesIds = this.instancesFormGroup.get('instancesIds').value;
this.dialogRef.close(this.data);
}
}

50
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts

@ -14,34 +14,20 @@
/// limitations under the License.
///
import {
Component,
forwardRef,
Input,
OnInit,
ViewChild,
ElementRef,
Output,
EventEmitter
} from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
FormGroup,
NG_VALUE_ACCESSOR, Validators
} from '@angular/forms';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {Store} from '@ngrx/store';
import {AppState} from '@core/core.state';
import {MatChipList} from '@angular/material/chips';
import {MatAutocomplete} from '@angular/material/autocomplete';
import {Observable} from 'rxjs';
import {filter, map, mergeMap, share, tap} from 'rxjs/operators';
import {ObjectLwM2M} from './profile-config.models';
import {TranslateService} from '@ngx-translate/core';
import {DeviceProfileService} from '@core/http/device-profile.service';
import {PageLink} from '@shared/models/page/page-link';
import {Direction} from '@shared/models/page/sort-order';
import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { MatChipList } from '@angular/material/chips';
import { MatAutocomplete } from '@angular/material/autocomplete';
import { Observable } from 'rxjs';
import { filter, map, mergeMap, share, tap } from 'rxjs/operators';
import { ObjectLwM2M } from './profile-config.models';
import { TranslateService } from '@ngx-translate/core';
import { DeviceProfileService } from '@core/http/device-profile.service';
import { PageLink } from '@shared/models/page/page-link';
import { Direction } from '@shared/models/page/sort-order';
@Component({
selector: 'tb-profile-lwm2m-object-list',
@ -63,8 +49,8 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
modelValue: Array<number> | null;
objectsList: Array<ObjectLwM2M> = [];
filteredObjectsList: Observable<Array<ObjectLwM2M>>;
disabled = false as boolean;
searchText = '' as string;
disabled = false;
searchText = '';
get required(): boolean {
return this.requiredValue;
@ -210,9 +196,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
direction: Direction.ASC
});
return this.deviceProfileService.getLwm2mObjectsPage(pageLink, {ignoreLoading: true}).pipe(
map(pageData => {
return pageData.data;
})
map(pageData => pageData.data)
);
}

13
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.html

@ -17,12 +17,10 @@
-->
<section [formGroup]="resourceFormGroup" class="mat-padding">
<div fxLayout="row" fxFill formArrayName="resources"
*ngFor="let resourceLwM2M of resourceLwm2mFormArray(resourceFormGroup).controls; let z = index; trackBy: trackByParams">
<div class="vertical-padding" fxLayout="column" fxFill [formGroupName]="z">
<div fxLayout="row" fxFill [fxShow]="!z">
<div fxFlex="55">
<!-- <mat-label translate>device-profile.lwm2m.resource-label</mat-label>-->
</div>
*ngFor="let resourceLwM2M of resourceFormArray.controls; let i = index; trackBy: trackByParams">
<div class="vertical-padding" fxLayout="column" fxFill [formGroupName]="i">
<div fxLayout="row" fxFill [fxShow]="!i">
<div fxFlex="55"></div>
<div fxFlex="10" fxLayoutAlign="start center">
<b>
<mat-label translate>device-profile.lwm2m.observe-label</mat-label>
@ -72,10 +70,9 @@
{{ 'device-profile.lwm2m.key-name_label' | translate }}</mat-label>
<input matInput type="text" formControlName="keyName" required
matTooltip="{{'device-profile.lwm2m.key-name-tip' | translate}}"
(input)="updateValueKeyName($event, z)"
(input)="updateValueKeyName($event, i)"
matTooltipPosition="above">
<mat-error *ngIf="resourceLwM2M.get('keyName').hasError('required')">
{{ 'device-profile.lwm2m.key-name' | translate }}
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
</mat-error>

59
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resource.component.ts

@ -14,20 +14,12 @@
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import {
ControlValueAccessor,
FormArray, FormBuilder,
FormGroup,
NG_VALUE_ACCESSOR, Validators
} from '@angular/forms';
import {
CAMEL_CASE_REGEXP,
ResourceLwM2M
} from '@home/components/profile/device/lwm2m/profile-config.models';
import { Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, FormArray, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { ResourceLwM2M } from '@home/components/profile/device/lwm2m/profile-config.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { deepClone } from '@core/utils';
import _ from 'lodash';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
@Component({
@ -43,12 +35,12 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
]
})
export class Lwm2mObserveAttrTelemetryResourceComponent implements ControlValueAccessor, OnInit, Validators {
export class Lwm2mObserveAttrTelemetryResourceComponent implements ControlValueAccessor {
private requiredValue: boolean;
resourceFormGroup: FormGroup;
disabled = false as boolean;
disabled = false;
get required(): boolean {
return this.requiredValue;
@ -61,9 +53,12 @@ export class Lwm2mObserveAttrTelemetryResourceComponent implements ControlValueA
this.requiredValue = newVal;
}
}
constructor(private store: Store<AppState>,
private fb: FormBuilder) {
this.resourceFormGroup = this.fb.group({resources: this.fb.array([])});
this.resourceFormGroup = this.fb.group({
resources: this.fb.array([])
});
this.resourceFormGroup.valueChanges.subscribe(value => {
if (!this.disabled) {
this.propagateChangeState(value.resources);
@ -71,9 +66,6 @@ export class Lwm2mObserveAttrTelemetryResourceComponent implements ControlValueA
});
}
ngOnInit(): void {
}
registerOnTouched(fn: any): void {
}
@ -85,10 +77,6 @@ export class Lwm2mObserveAttrTelemetryResourceComponent implements ControlValueA
return this.resourceFormGroup.get('resources') as FormArray;
}
resourceLwm2mFormArray = (instance: FormGroup): FormArray => {
return instance.get('resources') as FormArray;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {
@ -98,31 +86,16 @@ export class Lwm2mObserveAttrTelemetryResourceComponent implements ControlValueA
}
}
getDisabledState = (): boolean => {
return this.disabled;
}
updateValueKeyName = (event: any, z: number): void => {
this.resourceFormArray.at(z).patchValue( {keyName: this.keysToCamel(deepClone(event.target.value))} );
}
private keysToCamel = (o: any): string => {
const val = o.split(' ');
const playStore = [];
val.forEach((item, k) => {
item = item.replace(CAMEL_CASE_REGEXP, '');
item = (k === 0) ? item.charAt(0).toLowerCase() + item.substr(1) : item.charAt(0).toUpperCase() + item.substr(1);
playStore.push(item);
});
return playStore.join('');
updateValueKeyName = (event: Event, index: number): void => {
this.resourceFormArray.at(index).patchValue({keyName: _.camelCase((event.target as HTMLInputElement).value)});
}
private createResourceLwM2M = (resourcesLwM2MJson: ResourceLwM2M []): void => {
if (resourcesLwM2MJson.length === this.resourceFormArray.length) {
this.resourceFormArray.patchValue(resourcesLwM2MJson, {emitEvent: false});
createResourceLwM2M(resourcesLwM2M: ResourceLwM2M[]): void {
if (resourcesLwM2M.length === this.resourceFormArray.length) {
this.resourceFormArray.patchValue(resourcesLwM2M, {emitEvent: false});
} else {
this.resourceFormArray.clear();
resourcesLwM2MJson.forEach(resourceLwM2M => {
resourcesLwM2M.forEach(resourceLwM2M => {
this.resourceFormArray.push(this.fb.group({
id: resourceLwM2M.id,
name: resourceLwM2M.name,

18
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.html

@ -19,7 +19,7 @@
<section [formGroup]="observeAttrTelemetryFormGroup" class="mat-padding">
<mat-accordion multi="true" class="mat-body-1" formArrayName="clientLwM2M">
<mat-expansion-panel
*ngFor="let objectLwM2M of clientLwM2MFormArray(observeAttrTelemetryFormGroup).controls; let i = index; trackBy: trackByParams"
*ngFor="let objectLwM2M of clientLwM2MFormArray.controls; let i = index; trackBy: trackByParams"
[formGroupName]="i">
<mat-expansion-panel-header>
<mat-panel-title fxLayoutAlign="space-between">
@ -34,8 +34,8 @@
</button>
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="column" fxLayoutGap="8px" formArrayName="instances">
<ng-template matExpansionPanelContent>
<ng-template matExpansionPanelContent>
<div fxLayout="column" fxLayoutGap="8px" formArrayName="instances">
<mat-expansion-panel
*ngFor="let instances of instancesLwm2mFormArray(objectLwM2M).controls; let y = index;"
[formGroupName]="y"
@ -50,7 +50,7 @@
</div>
<div class="checkbox-padding" fxFlex="10">
<mat-checkbox color="primary"
[formControlName]="observe"
[disabled]="this.disabled"
[checked]="getChecked(instances, 'observe')"
(click)="$event.stopPropagation()"
(change)="changeInstanceResourcesCheckBox($event.checked, instances, 'observe')"
@ -61,7 +61,8 @@
</mat-checkbox>
</div>
<div class="checkbox-padding" fxFlex="10">
<mat-checkbox [formControlName]="attribute" color="warn"
<mat-checkbox color="warn"
[disabled]="this.disabled"
[checked]="getChecked(instances, 'attribute')"
(click)="$event.stopPropagation()"
(change)="changeInstanceResourcesCheckBox($event.checked, instances, 'attribute')"
@ -72,7 +73,8 @@
</mat-checkbox>
</div>
<div class="checkbox-padding" fxFlex="10">
<mat-checkbox [formControlName]="telemetry" color="primary"
<mat-checkbox color="primary"
[disabled]="this.disabled"
[checked]="getChecked(instances, 'telemetry')"
(click)="$event.stopPropagation()"
(change)="changeInstanceResourcesCheckBox($event.checked, instances, 'telemetry')"
@ -95,8 +97,8 @@
</tb-profile-lwm2m-observe-attr-telemetry-resource>
</ng-template>
</mat-expansion-panel>
</ng-template>
</div>
</div>
</ng-template>
</mat-expansion-panel>
</mat-accordion>
</section>

114
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts

@ -15,7 +15,7 @@
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Input } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -28,16 +28,8 @@ import {
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {
ATTR,
Instance,
ObjectLwM2M,
OBSERVE,
ResourceLwM2M,
TELEMETRY
} from './profile-config.models';
import { isNotNullOrUndefined } from 'codelyzer/util/isNotNullOrUndefined';
import { deepClone, isUndefined } from '@core/utils';
import { Instance, ObjectLwM2M, ResourceLwM2M } from './profile-config.models';
import { deepClone, isDefinedAndNotNull, isEqual, isUndefined } from '@core/utils';
import { MatDialog } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
import {
@ -58,24 +50,17 @@ import {
]
})
export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor, OnInit, Validators {
export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor {
private requiredValue: boolean;
valuePrev = null as any;
observeAttrTelemetryFormGroup: FormGroup;
observe = OBSERVE as string;
attribute = ATTR as string;
telemetry = TELEMETRY as string;
get required(): boolean {
return this.requiredValue;
}
@Input()
disabled: boolean;
// tslint:disable-next-line:adjacent-overload-signatures
@Input()
set required(value: boolean) {
const newVal = coerceBooleanProperty(value);
@ -85,6 +70,9 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
}
}
@Input()
disabled: boolean;
constructor(private store: Store<AppState>,
private fb: FormBuilder,
private dialog: MatDialog,
@ -99,9 +87,6 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
});
}
ngOnInit(): void {
}
private propagateChange = (v: any) => { };
@ -139,10 +124,6 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
}
}
getDisabledState = (): boolean => {
return this.disabled;
}
writeValue(value: any): void {
this.buildClientObjectsLwM2M(value.clientLwM2M);
}
@ -153,8 +134,8 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
);
}
private createObjectsLwM2M = (objectsLwM2MJson: ObjectLwM2M []): FormArray => {
return this.fb.array(objectsLwM2MJson.map((objectLwM2M) => {
private createObjectsLwM2M = (objectsLwM2M: ObjectLwM2M[]): FormArray => {
return this.fb.array(objectsLwM2M.map((objectLwM2M) => {
return this.fb.group({
id: objectLwM2M.id,
name: objectLwM2M.name,
@ -165,20 +146,17 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
}));
}
private createInstanceLwM2M = (instanceLwM2MJson: Instance []): FormArray => {
return this.fb.array(instanceLwM2MJson.map((instanceLwM2M) => {
private createInstanceLwM2M = (instancesLwM2M: Instance[]): FormArray => {
return this.fb.array(instancesLwM2M.map((instanceLwM2M) => {
return this.fb.group({
id: instanceLwM2M.id,
[this.observe]: {value: false, disabled: this.disabled},
[this.attribute]: {value: false, disabled: this.disabled},
[this.telemetry]: {value: false, disabled: this.disabled},
resources: {value: instanceLwM2M.resources, disabled: this.disabled}
});
}));
}
clientLwM2MFormArray = (formGroup: FormGroup): FormArray => {
return formGroup.get('clientLwM2M') as FormArray;
get clientLwM2MFormArray(): FormArray {
return this.observeAttrTelemetryFormGroup.get('clientLwM2M') as FormArray;
}
instancesLwm2mFormArray = (objectLwM2M: AbstractControl): FormArray => {
@ -186,7 +164,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
}
changeInstanceResourcesCheckBox = (value: boolean, instance: AbstractControl, type: string): void => {
const resources = instance.get('resources').value as ResourceLwM2M [];
const resources = instance.get('resources').value as ResourceLwM2M[];
resources.forEach(resource => resource[type] = value);
instance.get('resources').patchValue(resources);
this.propagateChange(this.observeAttrTelemetryFormGroup.value);
@ -202,26 +180,18 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
}
getIndeterminate = (instance: AbstractControl, type: string): boolean => {
const resources = instance.get('resources').value as ResourceLwM2M [];
if (isNotNullOrUndefined(resources)) {
const isType = (element) => element[type] === true;
const checkedResource = resources.filter(isType);
if (checkedResource.length === 0) { return false; }
else if (checkedResource.length === resources.length) {
instance.patchValue({[type]: true});
return false;
} else { return true; }
const resources = instance.get('resources').value as ResourceLwM2M[];
if (isDefinedAndNotNull(resources)) {
const checkedResource = resources.filter(resource => resource[type]);
return checkedResource.length !== 0 && checkedResource.length !== resources.length;
}
return false;
}
getChecked = (instance: AbstractControl, type: string): boolean => {
const resources = instance.get('resources').value as ResourceLwM2M [];
if (isNotNullOrUndefined(resources)) {
return resources.some(resource => resource[type]);
}
return false;
const resources = instance.get('resources').value as ResourceLwM2M[];
return isDefinedAndNotNull(resources) && resources.every(resource => resource[type]);
}
getExpended = (objectLwM2M: AbstractControl): boolean => {
@ -265,7 +235,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
}
}).afterClosed().subscribe(
(res: Lwm2mObjectAddInstancesData | undefined) => {
if (isNotNullOrUndefined(res)) {
if (isDefinedAndNotNull(res)) {
this.updateInstancesIds(res);
}
}
@ -278,43 +248,41 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
data.instancesIds.forEach(value => {
valueNew.add(value);
});
const oldInstances = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M []).
find(e => e.id === data.objectId).instances;
const oldInstances = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M [])
.find(e => e.id === data.objectId).instances;
oldInstances.forEach(inst => {
valueOld.add(inst.id);
});
if (JSON.stringify(Array.from(valueOld)) !== JSON.stringify(Array.from(valueNew))) {
const idsDel = this.diffBetweenSet(valueNew, this.deepCloneSet(valueOld));
const idsAdd = this.diffBetweenSet(valueOld, this.deepCloneSet(valueNew));
if (!isEqual(valueOld, valueNew)) {
const idsDel = this.diffBetweenSet(valueOld, valueNew);
const idsAdd = this.diffBetweenSet(valueNew, valueOld);
if (idsAdd.size) {
this.addInstancesNew(data.objectId, idsAdd);
}
if (idsDel.size) {
this.delInstances(data.objectId, idsDel);
this.deleteInstances(data.objectId, idsDel);
}
}
}
private delInstances = (objectId: number, idsDel: Set<number>): void => {
let isIdIndex = (element) => element.id === objectId;
const objectIndex = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M []).findIndex(isIdIndex);
private deleteInstances = (objectId: number, idsDel: Set<number>): void => {
const objectIndex = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M[])
.findIndex(element => element.id === objectId);
idsDel.forEach(x => {
isIdIndex = (element) => element.value.id === x;
const instancesFormArray = ((this.observeAttrTelemetryFormGroup.get('clientLwM2M') as FormArray)
.controls[objectIndex].get('instances') as FormArray);
const instanceIndex = instancesFormArray.controls.findIndex(isIdIndex);
.at(objectIndex).get('instances') as FormArray);
const instanceIndex = instancesFormArray.value.findIndex(element => element.id === x);
instancesFormArray.removeAt(instanceIndex);
});
}
private addInstancesNew = (objectId: number, idsAdd: Set<number>): void => {
const instancesValue = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M [])
.find(e => e.id === objectId).instances;
.find(objectLwM2M => objectLwM2M.id === objectId).instances;
const instancesFormArray = ((this.observeAttrTelemetryFormGroup.get('clientLwM2M') as FormArray).controls
.find(e => e.value.id === objectId).get('instances') as FormArray) as FormArray;
idsAdd.forEach(x => {
const instanceNew = deepClone(instancesValue[0]) as Instance;
instanceNew.id = x;
instanceNew.resources.forEach(r => {
r.attribute = false;
r.telemetry = false;
@ -322,28 +290,14 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
});
instancesFormArray.push(this.fb.group({
id: x,
[this.observe]: {value: false, disabled: this.disabled},
[this.attribute]: {value: false, disabled: this.disabled},
[this.telemetry]: {value: false, disabled: this.disabled},
resources: {value: instanceNew.resources, disabled: this.disabled}
}));
});
(instancesFormArray.controls as FormGroup[]).sort((a, b) => a.value.id - b.value.id);
}
private deepCloneSet = (oldSet: Set<any>): Set<any> => {
const newSet = new Set<number>();
oldSet.forEach(p => {
newSet.add(p);
});
return newSet;
}
private diffBetweenSet = (firstSet: Set<any>, secondSet: Set<any>): Set<any> => {
firstSet.forEach(p => {
secondSet.delete(p);
});
return secondSet;
return new Set([...Array.from(firstSet)].filter(x => !secondSet.has(x)));
}
private setInstancesIds = (instances: Instance []): Set<number> => {

15
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/profile-config.models.ts

@ -33,7 +33,6 @@ export const DEFAULT_BOOTSTRAP_SERVER_ACCOUNT_TIME_OUT = 0;
export const LEN_MAX_PUBLIC_KEY_RPK = 182;
export const LEN_MAX_PUBLIC_KEY_X509 = 3000;
export const KEY_REGEXP_HEX_DEC = /^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$/;
export const CAMEL_CASE_REGEXP = /[-_&@.,*+!?^${}()|[\]\\]/g;
export const INSTANCES_ID_VALUE_MIN = 0;
export const INSTANCES_ID_VALUE_MAX = 65535;
@ -82,12 +81,14 @@ interface BootstrapSecurityConfig {
export interface ProfileConfigModels {
bootstrap: BootstrapSecurityConfig;
observeAttr: {
observe: string [],
attribute: string [],
telemetry: string [],
keyName: []
};
observeAttr: ObservableAttributes;
}
export interface ObservableAttributes {
observe: string[];
attribute: string[];
telemetry: string[];
keyName: string[];
}
export function getDefaultBootstrapServersSecurityConfig(): BootstrapServersSecurityConfig {

2
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.html

@ -35,7 +35,7 @@
required
>
</tb-entity-gateway-select>
<div fxLayout="column">profile-tab
<div fxLayout="column">
<mat-form-field fxFlex>
<mat-label>{{'gateway.security-type' | translate }}</mat-label>
<mat-select formControlName="securityType" >

10
ui-ngx/src/app/shared/components/json-object-edit.component.ts

@ -61,8 +61,7 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va
@Input() editorStyle: { [klass: string]: any };
// tslint:disable-next-line:ban-types
@Input() sort: Function;
@Input() sort: (key: string, value: any) => any;
private requiredValue: boolean;
@ -227,10 +226,9 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va
try {
if (this.modelValue) {
this.contentValue = JSON.stringify(this.modelValue, isUndefined(this.sort) ? null :
// tslint:disable-next-line:no-shadowed-variable
(key, value) => {
return this.sort(key, value);
this.contentValue = JSON.stringify(this.modelValue, isUndefined(this.sort) ? undefined :
(key, objectValue) => {
return this.sort(key, objectValue);
}, 2);
this.objectValid = true;
} else {

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

@ -454,8 +454,6 @@ export interface DeviceCredentials extends BaseData<DeviceCredentialsId> {
credentialsType: DeviceCredentialsType;
credentialsId: string;
credentialsValue: string;
credentialsLwKey: string;
credentialsLwValue: string;
}
export interface DeviceCredentialMQTTBasic {

Loading…
Cancel
Save