Browse Source

UI: Refactoring lwm2m

pull/3980/head
Vladyslav_Prykhodko 6 years ago
parent
commit
e6a3ee2725
  1. 27
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts
  2. 21
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts
  3. 81
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.html
  4. 22
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.scss
  5. 127
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts
  6. 8
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances.component.html
  7. 4
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.html
  8. 53
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts
  9. 49
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts
  10. 1
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/profile-config.models.ts

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

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, forwardRef, Inject, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Inject, Input } 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 { import {
DEFAULT_CLIENT_HOLD_OFF_TIME, DEFAULT_CLIENT_HOLD_OFF_TIME,
@ -48,7 +48,7 @@ import { TranslateService } from '@ngx-translate/core';
] ]
}) })
export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAccessor, Validators { export class Lwm2mDeviceConfigServerComponent implements ControlValueAccessor {
private requiredValue: boolean; private requiredValue: boolean;
@ -82,7 +82,7 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
public fb: FormBuilder, public fb: FormBuilder,
private deviceProfileService: DeviceProfileService, private deviceProfileService: DeviceProfileService,
@Inject(WINDOW) private window: Window) { @Inject(WINDOW) private window: Window) {
this.serverFormGroup = this.getServerGroup(); this.serverFormGroup = this.initServerGroup();
this.serverFormGroup.get('securityMode').valueChanges.pipe( this.serverFormGroup.get('securityMode').valueChanges.pipe(
startWith(null), startWith(null),
pairwise() pairwise()
@ -101,9 +101,6 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
}); });
} }
ngOnInit(): void {
}
private updateValueFields = (serverData: ServerSecurityConfig): void => { private updateValueFields = (serverData: ServerSecurityConfig): void => {
serverData.bootstrapServerIs = this.bootstrapServerIs; serverData.bootstrapServerIs = this.bootstrapServerIs;
this.serverFormGroup.patchValue(serverData, {emitEvent: false}); this.serverFormGroup.patchValue(serverData, {emitEvent: false});
@ -187,17 +184,17 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
} }
private getServerGroup = (): FormGroup => { private initServerGroup = (): FormGroup => {
const port = this.bootstrapServerIs ? DEFAULT_PORT_BOOTSTRAP_NO_SEC : DEFAULT_PORT_SERVER_NO_SEC; const port = this.bootstrapServerIs ? DEFAULT_PORT_BOOTSTRAP_NO_SEC : DEFAULT_PORT_SERVER_NO_SEC;
return this.fb.group({ return this.fb.group({
host: [this.window.location.hostname, this.required ? [Validators.required] : []], host: [this.window.location.hostname, this.required ? Validators.required : ''],
port: [port, this.required ? [Validators.required] : []], port: [port, this.required ? Validators.required : ''],
bootstrapServerIs: [this.bootstrapServerIs, []], bootstrapServerIs: [this.bootstrapServerIs, ''],
securityMode: [this.fb.control(SECURITY_CONFIG_MODE.NO_SEC), []], securityMode: [this.fb.control(SECURITY_CONFIG_MODE.NO_SEC)],
serverPublicKey: ['', this.required ? [Validators.required] : []], serverPublicKey: ['', this.required ? Validators.required : ''],
clientHoldOffTime: [DEFAULT_CLIENT_HOLD_OFF_TIME, this.required ? [Validators.required] : []], clientHoldOffTime: [DEFAULT_CLIENT_HOLD_OFF_TIME, this.required ? Validators.required : ''],
serverId: [DEFAULT_ID_SERVER, this.required ? [Validators.required] : []], serverId: [DEFAULT_ID_SERVER, this.required ? Validators.required : ''],
bootstrapServerAccountTimeout: ['', this.required ? [Validators.required] : []], bootstrapServerAccountTimeout: ['', this.required ? Validators.required : ''],
}); });
} }

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

@ -15,7 +15,7 @@
/// ///
import { DeviceProfileTransportConfiguration, DeviceTransportType } from '@shared/models/device.models'; import { DeviceProfileTransportConfiguration, DeviceTransportType } from '@shared/models/device.models';
import { Component, forwardRef, Inject, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Inject, Input } 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 { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state'; import { AppState } from '@app/core/core.state';
@ -54,11 +54,11 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
private disabled = false; private disabled = false;
lwm2mDeviceProfileTransportConfFormGroup: FormGroup; lwm2mDeviceProfileTransportConfFormGroup: FormGroup;
observeAttr = OBSERVE_ATTR as string; observeAttr = OBSERVE_ATTR;
observe = OBSERVE as string; observe = OBSERVE;
attribute = ATTR as string; attribute = ATTR;
telemetry = TELEMETRY as string; telemetry = TELEMETRY;
keyName = KEY_NAME as string; keyName = KEY_NAME;
bootstrapServers: string; bootstrapServers: string;
bootstrapServer: string; bootstrapServer: string;
lwm2mServer: string; lwm2mServer: string;
@ -73,7 +73,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
this.requiredValue = coerceBooleanProperty(value); this.requiredValue = coerceBooleanProperty(value);
} }
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private fb: FormBuilder, private fb: FormBuilder,
@ -81,7 +81,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
@Inject(WINDOW) private window: Window) { @Inject(WINDOW) private window: Window) {
this.lwm2mDeviceProfileTransportConfFormGroup = this.fb.group({ this.lwm2mDeviceProfileTransportConfFormGroup = this.fb.group({
objectIds: [{}, Validators.required], objectIds: [{}, Validators.required],
observeAttrTelemetry: [{clientLwM2M: [] as ObjectLwM2M[]}, Validators.required], observeAttrTelemetry: [{clientLwM2M: []}, Validators.required],
shortId: [null, Validators.required], shortId: [null, Validators.required],
lifetime: [null, Validators.required], lifetime: [null, Validators.required],
defaultMinPeriod: [null, Validators.required], defaultMinPeriod: [null, Validators.required],
@ -116,12 +116,11 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
} }
writeValue(value: any | null): void { writeValue(value: any | null): void {
value = (Object.keys(value).length === 0) ? getDefaultProfileConfig() : value; this.configurationValue = (Object.keys(value).length === 0) ? getDefaultProfileConfig() : value;
this.lwm2mDeviceProfileTransportConfFormGroup.patchValue({ this.lwm2mDeviceProfileTransportConfFormGroup.patchValue({
configurationJson: value configurationJson: this.configurationValue
}, },
{emitEvent: false}); {emitEvent: false});
this.configurationValue = this.lwm2mDeviceProfileTransportConfFormGroup.getRawValue().configurationJson;
this.initWriteValue(); this.initWriteValue();
} }

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

@ -15,43 +15,46 @@
limitations under the License. limitations under the License.
--> -->
<mat-form-field appearance="standard" [formGroup]="lwm2mObjectListFormGroup" class="lwm2m-instances-list mat-block"> <section [formGroup]="instancesListFormGroup" class="lwm2m-instances-list">
<mat-label>{{ 'device-profile.lwm2m.instances-list' | translate }}</mat-label> <mat-form-field class="mat-block">
<mat-chip-list #chipList formControlName="instancesIdsList"> <mat-label>{{ 'device-profile.lwm2m.instances-list' | translate }}</mat-label>
<mat-chip <mat-chip-list>
*ngFor="let instanceIdInputFor of instancesIdsList" <mat-chip
[selectable]="true" *ngFor="let instanceId of instancesId"
[removable]="true" [selectable]="true"
(removed)="remove(instanceIdInputFor)"> [removable]="true"
{{instanceIdInputFor}} (removed)="remove(instanceId)">
<mat-icon matChipRemove>close</mat-icon> {{instanceId}}
</mat-chip> <mat-icon matChipRemove>close</mat-icon>
<mat-form-field class="mat-block" fxFlexFill style="width: auto"> </mat-chip>
<mat-label>{{ 'device-profile.lwm2m.instances-input' | translate }}</mat-label> </mat-chip-list>
<input fxFlexFill matInput type="number" </mat-form-field>
placeholder="{{'device-profile.lwm2m.instances-input-holder' | translate}}" <mat-form-field class="mat-block">
formControlName="instanceIdInput" <mat-label>{{ 'device-profile.lwm2m.instances-input' | translate }}</mat-label>
#instanceIdInput <input fxFlexFill matInput type="number"
(focusin)="onFocus()" [min]="instanceIdValueMin"
(click)="add(instanceIdInput.valueAsNumber)" [max]="instanceIdValueMax"
(keydown)="onkeydown($event)" placeholder="{{'device-profile.lwm2m.instances-input-holder' | translate}}"
[matChipInputFor]="chipList"> formControlName="instanceIdInput">
<mat-error *ngIf="lwm2mObjectListFormGroup.get('instanceIdInput').hasError('min')"> <button mat-icon-button matSuffix
{{ translate.get('device-profile.lwm2m.valid-id-instance-no-min', { (click)="add()" type="button">
instance: instanceIdInput.value.toString(), min: instanceIdValueMin.toString() <mat-icon>add</mat-icon>
}) | async }} </button>
</mat-error> <mat-error *ngIf="instancesListFormGroup.get('instanceIdInput').hasError('min')">
<mat-error *ngIf="lwm2mObjectListFormGroup.get('instanceIdInput').hasError('max')"> {{ translate.get('device-profile.lwm2m.valid-id-instance-no-min', {
{{ translate.get('device-profile.lwm2m.valid-id-instance-no-max', { instance: instanceId, min: instanceIdValueMin
instance: instanceIdInput.value.toString(), max: instanceIdValueMax.toString() }) | async }}
}) | async }} </mat-error>
</mat-error> <mat-error *ngIf="instancesListFormGroup.get('instanceIdInput').hasError('max')">
<mat-error *ngIf="lwm2mObjectListFormGroup.get('instanceIdInput').errors?.notIsNaNValid"> {{ translate.get('device-profile.lwm2m.valid-id-instance-no-max', {
{{ translate.get('device-profile.lwm2m.instances-input-holder', { instance: instanceId, max: instanceIdValueMax
instance: instanceIdInput.value.toString(), max: instanceIdValueMax.toString() }) | async }}
}) | async }} </mat-error>
</mat-error> <mat-error *ngIf="instancesListFormGroup.get('instanceIdInput').hasError('pattern')">
</mat-form-field> {{ translate.get('device-profile.lwm2m.instances-input-holder', {
</mat-chip-list> instance: instanceId, max: instanceIdValueMax
</mat-form-field> }) | async }}
</mat-error>
</mat-form-field>
</section>

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

@ -1,22 +0,0 @@
/**
* 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.
*/
:host ::ng-deep {
mat-form-field.lwm2m-instances-list {
& > .mat-form-field-wrapper > .mat-form-field-underline {
display: none;
}
}
}

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

@ -14,35 +14,18 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { Component, forwardRef, } from '@angular/core';
Component, import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
forwardRef,
Input,
OnInit,
ViewChild,
ElementRef,
} 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 { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { MatChipList } from '@angular/material/chips'; import { INSTANCES_ID_VALUE_MAX, INSTANCES_ID_VALUE_MIN, KEY_REGEXP_NUMBER } from './profile-config.models';
import {
INSTANCES_ID_VALUE_MAX,
INSTANCES_ID_VALUE_MIN
} from './profile-config.models';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { DeviceProfileService } from '@core/http/device-profile.service'; import { DeviceProfileService } from '@core/http/device-profile.service';
@Component({ @Component({
selector: 'tb-profile-lwm2m-object-add-instances-list', selector: 'tb-profile-lwm2m-object-add-instances-list',
templateUrl: './lwm2m-object-add-instances-list.component.html', templateUrl: './lwm2m-object-add-instances-list.component.html',
styleUrls: ['./lwm2m-object-add-instances-list.component.scss'], styleUrls: [],
providers: [{ providers: [{
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent), useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent),
@ -51,31 +34,13 @@ import { DeviceProfileService } from '@core/http/device-profile.service';
}) })
export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccessor { export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccessor {
private requiredValue: boolean; private disabled = false;
private disabled = false as boolean; private dirty = false;
private dirty = false as boolean;
lwm2mObjectListFormGroup: FormGroup; instancesListFormGroup: FormGroup;
instancesIdsList: Set<number> | null; instancesId = new Set<number>();
filteredObjectsList: Array<number>; instanceIdValueMin = INSTANCES_ID_VALUE_MIN;
instanceIdValueMin = INSTANCES_ID_VALUE_MIN as number; instanceIdValueMax = INSTANCES_ID_VALUE_MAX;
instanceIdValueMax = INSTANCES_ID_VALUE_MAX as number;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
const newVal = coerceBooleanProperty(value);
if (this.requiredValue !== newVal) {
this.requiredValue = newVal;
this.updateValidators();
}
}
@ViewChild('instanceIdInput') instanceIdInput: ElementRef<HTMLInputElement>;
@ViewChild('chipList', {static: true}) chipList: MatChipList;
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };
@ -83,19 +48,14 @@ export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccesso
public translate: TranslateService, public translate: TranslateService,
private deviceProfileService: DeviceProfileService, private deviceProfileService: DeviceProfileService,
private fb: FormBuilder) { private fb: FormBuilder) {
this.lwm2mObjectListFormGroup = this.fb.group({ this.instancesListFormGroup = this.fb.group({
instancesIdsList: [null], instanceIdInput: [null, [
instanceIdInput: [null] Validators.min(this.instanceIdValueMin),
Validators.max(this.instanceIdValueMax),
Validators.pattern(KEY_REGEXP_NUMBER)]]
}); });
} }
private updateValidators = (): void => {
this.lwm2mObjectListFormGroup.get('instanceIdInput').setValidators([
Validators.min(this.instanceIdValueMin),
Validators.max(this.instanceIdValueMax)]);
this.lwm2mObjectListFormGroup.get('instanceIdInput').updateValueAndValidity();
}
registerOnChange(fn: any): void { registerOnChange(fn: any): void {
this.propagateChange = fn; this.propagateChange = fn;
} }
@ -106,68 +66,35 @@ export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccesso
setDisabledState(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (isDisabled) { if (isDisabled) {
this.lwm2mObjectListFormGroup.disable({emitEvent: false}); this.instancesListFormGroup.disable({emitEvent: false});
} else { } else {
this.lwm2mObjectListFormGroup.enable({emitEvent: false}); this.instancesListFormGroup.enable({emitEvent: false});
} }
} }
writeValue(value: Set<number>): void { writeValue(value: Set<number>): void {
this.instancesIdsList = new Set<number>();
if (value && value.size) { if (value && value.size) {
value.forEach(item => this.instancesIdsList.add(item)); this.instancesId = value;
this.lwm2mObjectListFormGroup.get('instancesIdsList').setValue(this.instancesIdsList);
} }
this.updateValidators();
this.dirty = false; this.dirty = false;
} }
add = (value: number): void => { add = (): void => {
if (!isNaN(value) && this.lwm2mObjectListFormGroup.get('instanceIdInput').valid) { if (this.instancesListFormGroup.get('instanceIdInput').valid) {
this.instancesIdsList.add(value); this.instancesId.add(this.instanceId);
this.lwm2mObjectListFormGroup.get('instancesIdsList').setValue(this.instancesIdsList); this.instancesListFormGroup.get('instanceIdInput').setValue(null);
this.propagateChange(this.instancesIdsList); this.propagateChange(this.instancesId);
this.dirty = true; this.dirty = true;
} }
this.clear();
} }
remove = (object: number): void => { remove = (object: number): void => {
this.instancesIdsList.delete(object); this.instancesId.delete(object);
this.lwm2mObjectListFormGroup.get('instancesIdsList').setValue(this.instancesIdsList); this.propagateChange(this.instancesId);
this.propagateChange(this.instancesIdsList);
this.dirty = true; this.dirty = true;
this.clear();
}
//
// displayFn(object?: number): number | undefined {
// return object ? object : undefined;
// }
private clear = (): void => {
this.lwm2mObjectListFormGroup.get('instanceIdInput').patchValue(null, {emitEvent: true});
this.instanceIdInput.nativeElement.value = '';
setTimeout(() => {
this.instanceIdInput.nativeElement.blur();
this.instanceIdInput.nativeElement.focus();
}, 0);
} }
onkeydown = (e: KeyboardEvent): boolean => { get instanceId(): number {
if (e.keyCode === 189 || e.keyCode === 187 || e.keyCode === 109 || e.keyCode === 107) { return this.instancesListFormGroup.get('instanceIdInput').value;
return false;
} else if (e.keyCode === 8) {
if (this.lwm2mObjectListFormGroup.get('instanceIdInput').value == null) {
this.clear();
}
this.instanceIdInput.nativeElement.focus();
}
}
onFocus = (): void => {
if (this.dirty) {
this.lwm2mObjectListFormGroup.get('instanceIdInput').updateValueAndValidity({onlySelf: true, emitEvent: true});
this.dirty = false;
}
} }
} }

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

@ -30,11 +30,9 @@
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content> <div mat-dialog-content>
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async">
<div class="mat-padding"> <tb-profile-lwm2m-object-add-instances-list
<tb-profile-lwm2m-object-add-instances-list formControlName="instancesIds">
formControlName="instancesIds"> </tb-profile-lwm2m-object-add-instances-list>
</tb-profile-lwm2m-object-add-instances-list>
</div>
</fieldset> </fieldset>
</div> </div>
<div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center"> <div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center">

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

@ -16,7 +16,7 @@
--> -->
<mat-form-field appearance="standard" [formGroup]="lwm2mObjectListFormGroup" class="mat-block"> <mat-form-field appearance="standard" [formGroup]="lwm2mListFormGroup" class="mat-block">
<mat-chip-list #chipList formControlName="objectsList"> <mat-chip-list #chipList formControlName="objectsList">
<mat-chip <mat-chip
*ngFor="let objectLwm2m of objectsList" *ngFor="let objectLwm2m of objectsList"
@ -49,7 +49,7 @@
</span> </span>
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
<mat-error *ngIf="lwm2mObjectListFormGroup.get('objectsList').hasError('required')"> <mat-error *ngIf="lwm2mListFormGroup.get('objectsList').hasError('required')">
{{ 'device-profile.lwm2m.object-list-empty' | translate }} {{ 'device-profile.lwm2m.object-list-empty' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>

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

@ -19,8 +19,6 @@ import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Valida
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { MatChipList } from '@angular/material/chips';
import { MatAutocomplete } from '@angular/material/autocomplete';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { filter, map, mergeMap, share, tap } from 'rxjs/operators'; import { filter, map, mergeMap, share, tap } from 'rxjs/operators';
import { ObjectLwM2M } from './profile-config.models'; import { ObjectLwM2M } from './profile-config.models';
@ -43,9 +41,9 @@ import { Direction } from '@shared/models/page/sort-order';
export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, Validators { export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, Validators {
private requiredValue: boolean; private requiredValue: boolean;
private dirty = false as boolean; private dirty = false;
lwm2mObjectListFormGroup: FormGroup; lwm2mListFormGroup: FormGroup;
modelValue: Array<number> | null; modelValue: Array<number> | null;
objectsList: Array<ObjectLwM2M> = []; objectsList: Array<ObjectLwM2M> = [];
filteredObjectsList: Observable<Array<ObjectLwM2M>>; filteredObjectsList: Observable<Array<ObjectLwM2M>>;
@ -72,8 +70,6 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
removeList = new EventEmitter<any>(); removeList = new EventEmitter<any>();
@ViewChild('objectInput') objectInput: ElementRef<HTMLInputElement>; @ViewChild('objectInput') objectInput: ElementRef<HTMLInputElement>;
@ViewChild('objectAutocomplete') matAutocomplete: MatAutocomplete;
@ViewChild('chipList', {static: true}) chipList: MatChipList;
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };
@ -81,15 +77,15 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
public translate: TranslateService, public translate: TranslateService,
private deviceProfileService: DeviceProfileService, private deviceProfileService: DeviceProfileService,
private fb: FormBuilder) { private fb: FormBuilder) {
this.lwm2mObjectListFormGroup = this.fb.group({ this.lwm2mListFormGroup = this.fb.group({
objectsList: [this.objectsList], objectsList: [this.objectsList],
objectLwm2m: [null, this.required ? [Validators.required] : []] objectLwm2m: [null, this.required ? [Validators.required] : []]
}); });
} }
private updateValidators = (): void => { private updateValidators = (): void => {
this.lwm2mObjectListFormGroup.get('objectLwm2m').setValidators(this.required ? [Validators.required] : []); this.lwm2mListFormGroup.get('objectLwm2m').setValidators(this.required ? [Validators.required] : []);
this.lwm2mObjectListFormGroup.get('objectLwm2m').updateValueAndValidity(); this.lwm2mListFormGroup.get('objectLwm2m').updateValueAndValidity();
} }
registerOnChange(fn: any): void { registerOnChange(fn: any): void {
@ -100,7 +96,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
} }
ngOnInit() { ngOnInit() {
this.filteredObjectsList = this.lwm2mObjectListFormGroup.get('objectLwm2m').valueChanges this.filteredObjectsList = this.lwm2mListFormGroup.get('objectLwm2m').valueChanges
.pipe( .pipe(
tap((value) => { tap((value) => {
if (value && typeof value !== 'string') { if (value && typeof value !== 'string') {
@ -110,21 +106,17 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
} }
}), }),
filter((value) => typeof value === 'string'), filter((value) => typeof value === 'string'),
map((value) => value ? (typeof value === 'string' ? value : value.name) : ''),
mergeMap(name => this.fetchListObjects(name)), mergeMap(name => this.fetchListObjects(name)),
share() share()
); );
} }
ngAfterViewInit = (): void => {
}
setDisabledState(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (isDisabled) { if (isDisabled) {
this.lwm2mObjectListFormGroup.disable({emitEvent: false}); this.lwm2mListFormGroup.disable({emitEvent: false});
} else { } else {
this.lwm2mObjectListFormGroup.enable({emitEvent: false}); this.lwm2mListFormGroup.enable({emitEvent: false});
} }
} }
@ -134,35 +126,22 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
if (value.hasOwnProperty(objectIds) && value[objectIds] != null && value[objectIds].length > 0) { if (value.hasOwnProperty(objectIds) && value[objectIds] != null && value[objectIds].length > 0) {
this.modelValue = [...value[objectIds]]; this.modelValue = [...value[objectIds]];
this.objectsList = value.objectsList; this.objectsList = value.objectsList;
this.lwm2mObjectListFormGroup.get('objectsList').setValue(this.objectsList);
} else { } else {
this.objectsList = []; this.objectsList = [];
this.lwm2mObjectListFormGroup.get('objectsList').setValue(this.objectsList);
this.modelValue = null; this.modelValue = null;
} }
this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);
this.dirty = true; this.dirty = true;
} }
// reset() { private add(object: ObjectLwM2M): void {
// this.objectsList = [];
// this.lwm2mObjectListFormGroup.get('objectsList').setValue(this.objectsList);
// this.modelValue = null;
// if (this.objectInput) {
// this.objectInput.nativeElement.value = '';
// }
// this.lwm2mObjectListFormGroup.get('objectLwm2m').patchValue('', {emitEvent: false});
// this.propagateChange(this.modelValue);
// this.dirty = true;
// }
private add = (object: ObjectLwM2M): void => {
if (!this.modelValue || this.modelValue.indexOf(object.id) === -1) { if (!this.modelValue || this.modelValue.indexOf(object.id) === -1) {
if (!this.modelValue) { if (!this.modelValue) {
this.modelValue = []; this.modelValue = [];
} }
this.modelValue.push(object.id); this.modelValue.push(object.id);
this.objectsList.push(object); this.objectsList.push(object);
this.lwm2mObjectListFormGroup.get('objectsList').setValue(this.objectsList); this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);
this.addList.next(this.objectsList); this.addList.next(this.objectsList);
} }
this.propagateChange(this.modelValue); this.propagateChange(this.modelValue);
@ -173,7 +152,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
let index = this.objectsList.indexOf(object); let index = this.objectsList.indexOf(object);
if (index >= 0) { if (index >= 0) {
this.objectsList.splice(index, 1); this.objectsList.splice(index, 1);
this.lwm2mObjectListFormGroup.get('objectsList').setValue(this.objectsList); this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);
index = this.modelValue.indexOf(object.id); index = this.modelValue.indexOf(object.id);
this.modelValue.splice(index, 1); this.modelValue.splice(index, 1);
this.removeList.next(object); this.removeList.next(object);
@ -189,9 +168,11 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
return object ? object.name : undefined; return object ? object.name : undefined;
} }
// @TODO: add support page size
// @TODO: filter for id + name
private fetchListObjects = (searchText?: string): Observable<Array<ObjectLwM2M>> => { private fetchListObjects = (searchText?: string): Observable<Array<ObjectLwM2M>> => {
this.searchText = searchText; this.searchText = searchText;
const pageLink = new PageLink(10, 0, searchText, { const pageLink = new PageLink(50, 0, searchText, {
property: 'name', property: 'name',
direction: Direction.ASC direction: Direction.ASC
}); });
@ -202,14 +183,14 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
onFocus = (): void => { onFocus = (): void => {
if (this.dirty) { if (this.dirty) {
this.lwm2mObjectListFormGroup.get('objectLwm2m').updateValueAndValidity({onlySelf: true, emitEvent: true}); this.lwm2mListFormGroup.get('objectLwm2m').updateValueAndValidity({onlySelf: true, emitEvent: true});
this.dirty = false; this.dirty = false;
} }
} }
private clear = (value: string = ''): void => { private clear = (value: string = ''): void => {
this.objectInput.nativeElement.value = value; this.objectInput.nativeElement.value = value;
this.lwm2mObjectListFormGroup.get('objectLwm2m').patchValue(value, {emitEvent: true}); this.lwm2mListFormGroup.get('objectLwm2m').patchValue(value, {emitEvent: true});
setTimeout(() => { setTimeout(() => {
this.objectInput.nativeElement.blur(); this.objectInput.nativeElement.blur();
this.objectInput.nativeElement.focus(); this.objectInput.nativeElement.focus();

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

@ -171,7 +171,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
} }
private updateValidators = (): void => { private updateValidators = (): void => {
this.observeAttrTelemetryFormGroup.get('clientLwM2M').setValidators(this.required ? [Validators.required] : []); this.observeAttrTelemetryFormGroup.get('clientLwM2M').setValidators(this.required ? Validators.required : []);
this.observeAttrTelemetryFormGroup.get('clientLwM2M').updateValueAndValidity(); this.observeAttrTelemetryFormGroup.get('clientLwM2M').updateValueAndValidity();
} }
@ -188,7 +188,6 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
return false; return false;
} }
getChecked = (instance: AbstractControl, type: string): boolean => { getChecked = (instance: AbstractControl, type: string): boolean => {
const resources = instance.get('resources').value as ResourceLwM2M[]; const resources = instance.get('resources').value as ResourceLwM2M[];
return isDefinedAndNotNull(resources) && resources.every(resource => resource[type]); return isDefinedAndNotNull(resources) && resources.every(resource => resource[type]);
@ -221,15 +220,11 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
$event.stopPropagation(); $event.stopPropagation();
$event.preventDefault(); $event.preventDefault();
} }
const instancesIds = new Set<number>();
object.instances.forEach(inst => {
instancesIds.add(inst.id);
});
this.dialog.open<Lwm2mObjectAddInstancesComponent, Lwm2mObjectAddInstancesData, object>(Lwm2mObjectAddInstancesComponent, { this.dialog.open<Lwm2mObjectAddInstancesComponent, Lwm2mObjectAddInstancesData, object>(Lwm2mObjectAddInstancesComponent, {
disableClose: true, disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: { data: {
instancesIds: this.setInstancesIds(object.instances), instancesIds: this.instancesToSetId(object.instances),
objectName: object.name, objectName: object.name,
objectId: object.id objectId: object.id
} }
@ -243,21 +238,15 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
} }
private updateInstancesIds = (data: Lwm2mObjectAddInstancesData): void => { private updateInstancesIds = (data: Lwm2mObjectAddInstancesData): void => {
const valueNew = new Set<number>(); const instances = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M[])
const valueOld = new Set<number>(); .find(objectLwM2M => objectLwM2M.id === data.objectId).instances;
data.instancesIds.forEach(value => { const valueOld = this.instancesToSetId(instances);
valueNew.add(value);
}); if (!isEqual(valueOld, data.instancesIds)) {
const oldInstances = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M []) const idsDel = this.diffBetweenSet(valueOld, data.instancesIds);
.find(e => e.id === data.objectId).instances; const idsAdd = this.diffBetweenSet(data.instancesIds, valueOld);
oldInstances.forEach(inst => {
valueOld.add(inst.id);
});
if (!isEqual(valueOld, valueNew)) {
const idsDel = this.diffBetweenSet(valueOld, valueNew);
const idsAdd = this.diffBetweenSet(valueNew, valueOld);
if (idsAdd.size) { if (idsAdd.size) {
this.addInstancesNew(data.objectId, idsAdd); this.addInstancesNew(data.objectId, idsAdd, instances.find(instance => instance.id === 0));
} }
if (idsDel.size) { if (idsDel.size) {
this.deleteInstances(data.objectId, idsDel); this.deleteInstances(data.objectId, idsDel);
@ -276,13 +265,11 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
}); });
} }
private addInstancesNew = (objectId: number, idsAdd: Set<number>): void => { private addInstancesNew = (objectId: number, idsAdd: Set<number>, instance: Instance): void => {
const instancesValue = (this.observeAttrTelemetryFormGroup.get('clientLwM2M').value as ObjectLwM2M [])
.find(objectLwM2M => objectLwM2M.id === objectId).instances;
const instancesFormArray = ((this.observeAttrTelemetryFormGroup.get('clientLwM2M') as FormArray).controls const instancesFormArray = ((this.observeAttrTelemetryFormGroup.get('clientLwM2M') as FormArray).controls
.find(e => e.value.id === objectId).get('instances') as FormArray) as FormArray; .find(e => e.value.id === objectId).get('instances') as FormArray) as FormArray;
idsAdd.forEach(x => { idsAdd.forEach(x => {
const instanceNew = deepClone(instancesValue[0]) as Instance; const instanceNew = deepClone(instance);
instanceNew.resources.forEach(r => { instanceNew.resources.forEach(r => {
r.attribute = false; r.attribute = false;
r.telemetry = false; r.telemetry = false;
@ -296,17 +283,11 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
(instancesFormArray.controls as FormGroup[]).sort((a, b) => a.value.id - b.value.id); (instancesFormArray.controls as FormGroup[]).sort((a, b) => a.value.id - b.value.id);
} }
private diffBetweenSet = (firstSet: Set<any>, secondSet: Set<any>): Set<any> => { private diffBetweenSet<T>(firstSet: Set<T>, secondSet: Set<T>): Set<T> {
return new Set([...Array.from(firstSet)].filter(x => !secondSet.has(x))); return new Set([...Array.from(firstSet)].filter(x => !secondSet.has(x)));
} }
private setInstancesIds = (instances: Instance []): Set<number> => { private instancesToSetId = (instances: Instance[]): Set<number> => {
const instancesIds = new Set<number>(); return new Set(instances.map(x => x.id));
if (instances && instances.length) {
instances.forEach(inst => {
instancesIds.add(inst.id);
});
}
return instancesIds;
} }
} }

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

@ -33,6 +33,7 @@ export const DEFAULT_BOOTSTRAP_SERVER_ACCOUNT_TIME_OUT = 0;
export const LEN_MAX_PUBLIC_KEY_RPK = 182; export const LEN_MAX_PUBLIC_KEY_RPK = 182;
export const LEN_MAX_PUBLIC_KEY_X509 = 3000; export const LEN_MAX_PUBLIC_KEY_X509 = 3000;
export const KEY_REGEXP_HEX_DEC = /^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$/; export const KEY_REGEXP_HEX_DEC = /^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$/;
export const KEY_REGEXP_NUMBER = /^\d*$/;
export const INSTANCES_ID_VALUE_MIN = 0; export const INSTANCES_ID_VALUE_MIN = 0;
export const INSTANCES_ID_VALUE_MAX = 65535; export const INSTANCES_ID_VALUE_MAX = 65535;

Loading…
Cancel
Save