Commit c14e2c81b1840a9160496b0baa431fb1e13d66be

Authored by Vladyslav_Prykhodko
1 parent f770f407

UI: Refactoring LwM2M

@@ -82,7 +82,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -82,7 +82,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
82 private deviceProfileService: DeviceProfileService, 82 private deviceProfileService: DeviceProfileService,
83 @Inject(WINDOW) private window: Window) { 83 @Inject(WINDOW) private window: Window) {
84 this.lwm2mDeviceProfileFormGroup = this.fb.group({ 84 this.lwm2mDeviceProfileFormGroup = this.fb.group({
85 - objectIds: [[], Validators.required], 85 + objectIds: [null, Validators.required],
86 observeAttrTelemetry: [null, Validators.required], 86 observeAttrTelemetry: [null, Validators.required],
87 shortId: [null, Validators.required], 87 shortId: [null, Validators.required],
88 lifetime: [null, Validators.required], 88 lifetime: [null, Validators.required],
@@ -96,15 +96,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -96,15 +96,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
96 configurationJson: [null, Validators.required] 96 configurationJson: [null, Validators.required]
97 }); 97 });
98 this.lwm2mDeviceProfileFormGroup.valueChanges.subscribe((value) => { 98 this.lwm2mDeviceProfileFormGroup.valueChanges.subscribe((value) => {
99 - if (!this.disabled) {  
100 - this.updateDeviceProfileValue(value);  
101 - } 99 + this.updateDeviceProfileValue(value);
102 }); 100 });
103 this.lwm2mDeviceConfigFormGroup.valueChanges.subscribe(() => { 101 this.lwm2mDeviceConfigFormGroup.valueChanges.subscribe(() => {
104 - console.warn('config form');  
105 - if (!this.disabled) {  
106 - this.updateModel();  
107 - } 102 + this.updateModel();
108 }); 103 });
109 this.sortFunction = this.sortObjectKeyPathJson; 104 this.sortFunction = this.sortObjectKeyPathJson;
110 } 105 }
@@ -188,7 +183,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -188,7 +183,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
188 183
189 private updateDeviceProfileValue(config): void { 184 private updateDeviceProfileValue(config): void {
190 if (this.lwm2mDeviceProfileFormGroup.valid) { 185 if (this.lwm2mDeviceProfileFormGroup.valid) {
191 - this.upDateObserveAttrTelemetryFromGroupToJson(config.observeAttrTelemetry.clientLwM2M); 186 + this.updateObserveAttrTelemetryFromGroupToJson(config.observeAttrTelemetry.clientLwM2M);
192 this.configurationValue.bootstrap.bootstrapServer = config.bootstrapServer; 187 this.configurationValue.bootstrap.bootstrapServer = config.bootstrapServer;
193 this.configurationValue.bootstrap.lwm2mServer = config.lwm2mServer; 188 this.configurationValue.bootstrap.lwm2mServer = config.lwm2mServer;
194 const bootstrapServers = this.configurationValue.bootstrap.servers; 189 const bootstrapServers = this.configurationValue.bootstrap.servers;
@@ -225,9 +220,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -225,9 +220,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
225 this.updateKeyNameObjects(keyNameJson, clientObserveAttrTelemetry); 220 this.updateKeyNameObjects(keyNameJson, clientObserveAttrTelemetry);
226 } 221 }
227 } 222 }
228 - clientObserveAttrTelemetry.forEach(obj => {  
229 - obj.instances.sort((a, b) => a.id - b.id);  
230 - });  
231 return {clientLwM2M: clientObserveAttrTelemetry}; 223 return {clientLwM2M: clientObserveAttrTelemetry};
232 } 224 }
233 225
@@ -239,8 +231,8 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -239,8 +231,8 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
239 private addInstances = (attribute: string[], telemetry: string[], clientObserveAttrTelemetry: ObjectLwM2M[]): void => { 231 private addInstances = (attribute: string[], telemetry: string[], clientObserveAttrTelemetry: ObjectLwM2M[]): void => {
240 const instancesPath = attribute.concat(telemetry) 232 const instancesPath = attribute.concat(telemetry)
241 .filter(instance => !instance.includes('/0/')) 233 .filter(instance => !instance.includes('/0/'))
242 - .map(instance => this.convertPathToInstance(instance))  
243 - .sort(); 234 + .map(instance => instance.slice(1, instance.lastIndexOf('/')))
  235 + .sort(this.sortPath);
244 236
245 new Set(instancesPath).forEach(path => { 237 new Set(instancesPath).forEach(path => {
246 const pathParameter = Array.from(path.split('/'), Number); 238 const pathParameter = Array.from(path.split('/'), Number);
@@ -253,24 +245,14 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -253,24 +245,14 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
253 }); 245 });
254 } 246 }
255 247
256 - private convertPathToInstance = (path: string): string => {  
257 - const [objectId, instanceId] = path.substring(1).split('/');  
258 - return `${objectId}/${instanceId}`;  
259 - }  
260 -  
261 private updateObserveAttrTelemetryObjects = (parameters: string[], clientObserveAttrTelemetry: ObjectLwM2M[], 248 private updateObserveAttrTelemetryObjects = (parameters: string[], clientObserveAttrTelemetry: ObjectLwM2M[],
262 nameParameter: string): void => { 249 nameParameter: string): void => {
263 parameters.forEach(parameter => { 250 parameters.forEach(parameter => {
264 const [objectId, instanceId, resourceId] = Array.from(parameter.substring(1).split('/'), Number); 251 const [objectId, instanceId, resourceId] = Array.from(parameter.substring(1).split('/'), Number);
265 - clientObserveAttrTelemetry  
266 - .forEach(key => {  
267 - if (key.id === objectId) {  
268 - const instance = key.instances.find(itrInstance => itrInstance.id === instanceId);  
269 - if (isDefinedAndNotNull(instance)) {  
270 - instance.resources.find(resource => resource.id === resourceId)[nameParameter] = true;  
271 - }  
272 - }  
273 - }); 252 + clientObserveAttrTelemetry.find(objectLwm2m => objectLwm2m.id === objectId)
  253 + .instances.find(itrInstance => itrInstance.id === instanceId)
  254 + .resources.find(resource => resource.id === resourceId)
  255 + [nameParameter] = true;
274 }); 256 });
275 } 257 }
276 258
@@ -278,62 +260,60 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -278,62 +260,60 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
278 const keyName = JSON.parse(JSON.stringify(nameJson)); 260 const keyName = JSON.parse(JSON.stringify(nameJson));
279 Object.keys(keyName).forEach(key => { 261 Object.keys(keyName).forEach(key => {
280 const [objectId, instanceId, resourceId] = Array.from(key.substring(1).split('/'), Number); 262 const [objectId, instanceId, resourceId] = Array.from(key.substring(1).split('/'), Number);
281 - clientObserveAttrTelemetry  
282 - .forEach(object => {  
283 - if (object.id === objectId) {  
284 - object.instances  
285 - .find(instance => instance.id === instanceId).resources  
286 - .find(resource => resource.id === resourceId).keyName = keyName[key];  
287 - }  
288 - }); 263 + clientObserveAttrTelemetry.find(objectLwm2m => objectLwm2m.id === objectId)
  264 + .instances.find(instance => instance.id === instanceId)
  265 + .resources.find(resource => resource.id === resourceId)
  266 + .keyName = keyName[key];
289 }); 267 });
290 } 268 }
291 269
292 - private upDateObserveAttrTelemetryFromGroupToJson = (val: ObjectLwM2M[]): void => { 270 + private updateObserveAttrTelemetryFromGroupToJson = (val: ObjectLwM2M[]): void => {
293 const observeArray: Array<string> = []; 271 const observeArray: Array<string> = [];
294 const attributeArray: Array<string> = []; 272 const attributeArray: Array<string> = [];
295 const telemetryArray: Array<string> = []; 273 const telemetryArray: Array<string> = [];
296 const observeJson: ObjectLwM2M[] = JSON.parse(JSON.stringify(val)); 274 const observeJson: ObjectLwM2M[] = JSON.parse(JSON.stringify(val));
  275 + const paths = new Set<string>();
297 let pathObj; 276 let pathObj;
298 let pathInst; 277 let pathInst;
299 let pathRes; 278 let pathRes;
300 observeJson.forEach(obj => { 279 observeJson.forEach(obj => {
301 - Object.entries(obj).forEach(([key, value]) => { 280 + for (const [key, value] of Object.entries(obj)) {
302 if (key === 'id') { 281 if (key === 'id') {
303 pathObj = value; 282 pathObj = value;
304 } 283 }
305 if (key === 'instances') { 284 if (key === 'instances') {
306 - const instancesJson = JSON.parse(JSON.stringify(value)) as Instance[]; 285 + const instancesJson = value as Instance[];
307 if (instancesJson.length > 0) { 286 if (instancesJson.length > 0) {
308 instancesJson.forEach(instance => { 287 instancesJson.forEach(instance => {
309 - Object.entries(instance).forEach(([instanceKey, instanceValue]) => { 288 + for (const [instanceKey, instanceValue] of Object.entries(instance)) {
310 if (instanceKey === 'id') { 289 if (instanceKey === 'id') {
311 pathInst = instanceValue; 290 pathInst = instanceValue;
312 } 291 }
313 if (instanceKey === 'resources') { 292 if (instanceKey === 'resources') {
314 - const resourcesJson = JSON.parse(JSON.stringify(instanceValue)) as ResourceLwM2M[]; 293 + const resourcesJson = instanceValue as ResourceLwM2M[];
315 if (resourcesJson.length > 0) { 294 if (resourcesJson.length > 0) {
316 resourcesJson.forEach(res => { 295 resourcesJson.forEach(res => {
317 - Object.entries(res).forEach(([resourceKey, resourceValue]) => { 296 + for (const [resourceKey, idResource] of Object.entries(res)) {
318 if (resourceKey === 'id') { 297 if (resourceKey === 'id') {
319 - // pathRes = resourceValue  
320 - pathRes = '/' + pathObj + '/' + pathInst + '/' + resourceValue;  
321 - } else if (resourceKey === 'observe' && resourceValue) { 298 + pathRes = `/${pathObj}/${pathInst}/${idResource}`;
  299 + } else if (resourceKey === 'observe' && idResource) {
322 observeArray.push(pathRes); 300 observeArray.push(pathRes);
323 - } else if (resourceKey === 'attribute' && resourceValue) { 301 + } else if (resourceKey === 'attribute' && idResource) {
324 attributeArray.push(pathRes); 302 attributeArray.push(pathRes);
325 - } else if (resourceKey === 'telemetry' && resourceValue) { 303 + paths.add(pathRes);
  304 + } else if (resourceKey === 'telemetry' && idResource) {
326 telemetryArray.push(pathRes); 305 telemetryArray.push(pathRes);
  306 + paths.add(pathRes);
327 } 307 }
328 - }); 308 + }
329 }); 309 });
330 } 310 }
331 } 311 }
332 - }); 312 + }
333 }); 313 });
334 } 314 }
335 } 315 }
336 - }); 316 + }
337 }); 317 });
338 if (isUndefined(this.configurationValue[this.observeAttr])) { 318 if (isUndefined(this.configurationValue[this.observeAttr])) {
339 this.configurationValue[this.observeAttr] = { 319 this.configurationValue[this.observeAttr] = {
@@ -346,7 +326,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -346,7 +326,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
346 this.configurationValue[this.observeAttr][this.attribute] = attributeArray; 326 this.configurationValue[this.observeAttr][this.attribute] = attributeArray;
347 this.configurationValue[this.observeAttr][this.telemetry] = telemetryArray; 327 this.configurationValue[this.observeAttr][this.telemetry] = telemetryArray;
348 } 328 }
349 - this.updateKeyName(); 329 + this.updateKeyName(paths);
350 } 330 }
351 331
352 sortObjectKeyPathJson = (key: string, value: object): object => { 332 sortObjectKeyPathJson = (key: string, value: object): object => {
@@ -366,23 +346,13 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -366,23 +346,13 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
366 } 346 }
367 347
368 private sortPath = (a, b): number => { 348 private sortPath = (a, b): number => {
369 - const aLC = Array.from(a.substring(1).split('/'), Number);  
370 - const bLC = Array.from(b.substring(1).split('/'), Number);  
371 - return aLC[0] === bLC[0] ? aLC[1] - bLC[1] : aLC[0] - bLC[0]; 349 + return a.localeCompare(b, undefined, {
  350 + numeric: true,
  351 + sensitivity: 'base'
  352 + });
372 } 353 }
373 354
374 - private updateKeyName = (): void => {  
375 - const paths = new Set<string>();  
376 - if (this.configurationValue[this.observeAttr][this.attribute]) {  
377 - this.configurationValue[this.observeAttr][this.attribute].forEach(path => {  
378 - paths.add(path);  
379 - });  
380 - }  
381 - if (this.configurationValue[this.observeAttr][this.telemetry]) {  
382 - this.configurationValue[this.observeAttr][this.telemetry].forEach(path => {  
383 - paths.add(path);  
384 - });  
385 - } 355 + private updateKeyName = (paths: Set<string>): void => {
386 const keyNameNew = {}; 356 const keyNameNew = {};
387 paths.forEach(path => { 357 paths.forEach(path => {
388 const pathParameter = this.findIndexesForIds(path); 358 const pathParameter = this.findIndexesForIds(path);
@@ -395,19 +365,19 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -395,19 +365,19 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
395 } 365 }
396 366
397 private findIndexesForIds = (path: string): number[] => { 367 private findIndexesForIds = (path: string): number[] => {
398 - const pathParameter = Array.from(path.substring(1).split('/'), Number); 368 + const [objectId, instanceId, resourceId] = Array.from(path.substring(1).split('/'), Number);
  369 + // TODO: All paths to map
399 const pathParameterIndexes: number[] = []; 370 const pathParameterIndexes: number[] = [];
400 - const objectsOld = deepClone(  
401 - this.lwm2mDeviceProfileFormGroup.get('observeAttrTelemetry').value.clientLwM2M) as ObjectLwM2M[];  
402 - let isIdIndex = (element) => element.id === pathParameter[0]; 371 + const objectsOld = this.lwm2mDeviceProfileFormGroup.get('observeAttrTelemetry').value.clientLwM2M as ObjectLwM2M[];
  372 + let isIdIndex = (element) => element.id === objectId;
403 const objIndex = objectsOld.findIndex(isIdIndex); 373 const objIndex = objectsOld.findIndex(isIdIndex);
404 if (objIndex >= 0) { 374 if (objIndex >= 0) {
405 pathParameterIndexes.push(objIndex); 375 pathParameterIndexes.push(objIndex);
406 - isIdIndex = (element) => element.id === pathParameter[1]; 376 + isIdIndex = (element) => element.id === instanceId;
407 const instIndex = objectsOld[objIndex].instances.findIndex(isIdIndex); 377 const instIndex = objectsOld[objIndex].instances.findIndex(isIdIndex);
408 if (instIndex >= 0) { 378 if (instIndex >= 0) {
409 pathParameterIndexes.push(instIndex); 379 pathParameterIndexes.push(instIndex);
410 - isIdIndex = (element) => element.id === pathParameter[2]; 380 + isIdIndex = (element) => element.id === resourceId;
411 const resIndex = objectsOld[objIndex].instances[instIndex].resources.findIndex(isIdIndex); 381 const resIndex = objectsOld[objIndex].instances[instIndex].resources.findIndex(isIdIndex);
412 if (resIndex >= 0) { 382 if (resIndex >= 0) {
413 pathParameterIndexes.push(resIndex); 383 pathParameterIndexes.push(resIndex);
@@ -456,16 +426,16 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -456,16 +426,16 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
456 if (index >= 0) { 426 if (index >= 0) {
457 objectsOld.splice(index, 1); 427 objectsOld.splice(index, 1);
458 } 428 }
459 - this.updateObserveAttrTelemetryObjectFormGroup(objectsOld);  
460 this.removeObserveAttrTelemetryFromJson(this.observe, value.id); 429 this.removeObserveAttrTelemetryFromJson(this.observe, value.id);
461 this.removeObserveAttrTelemetryFromJson(this.telemetry, value.id); 430 this.removeObserveAttrTelemetryFromJson(this.telemetry, value.id);
462 this.removeObserveAttrTelemetryFromJson(this.attribute, value.id); 431 this.removeObserveAttrTelemetryFromJson(this.attribute, value.id);
463 this.removeKeyNameFromJson(value.id); 432 this.removeKeyNameFromJson(value.id);
  433 + this.updateObserveAttrTelemetryObjectFormGroup(objectsOld);
464 this.upDateJsonAllConfig(); 434 this.upDateJsonAllConfig();
465 } 435 }
466 436
467 private removeObserveAttrTelemetryFromJson = (observeAttrTel: string, id: number): void => { 437 private removeObserveAttrTelemetryFromJson = (observeAttrTel: string, id: number): void => {
468 - const isIdIndex = (element: string) => element.startsWith(`/${id}`); 438 + const isIdIndex = (element) => element.startsWith(`/${id}`);
469 let index = this.configurationValue[this.observeAttr][observeAttrTel].findIndex(isIdIndex); 439 let index = this.configurationValue[this.observeAttr][observeAttrTel].findIndex(isIdIndex);
470 while (index >= 0) { 440 while (index >= 0) {
471 this.configurationValue[this.observeAttr][observeAttrTel].splice(index, 1); 441 this.configurationValue[this.observeAttr][observeAttrTel].splice(index, 1);
@@ -19,18 +19,17 @@ import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Valida @@ -19,18 +19,17 @@ import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Valida
19 import { coerceBooleanProperty } from '@angular/cdk/coercion'; 19 import { coerceBooleanProperty } from '@angular/cdk/coercion';
20 import { Store } from '@ngrx/store'; 20 import { Store } from '@ngrx/store';
21 import { AppState } from '@core/core.state'; 21 import { AppState } from '@core/core.state';
22 -import { Observable, of } from 'rxjs';  
23 -import { filter, map, mergeMap, tap } from 'rxjs/operators'; 22 +import { Observable } from 'rxjs';
  23 +import { filter, map, mergeMap, publishReplay, refCount, tap } from 'rxjs/operators';
24 import { ObjectLwM2M } from './profile-config.models'; 24 import { ObjectLwM2M } from './profile-config.models';
25 import { TranslateService } from '@ngx-translate/core'; 25 import { TranslateService } from '@ngx-translate/core';
26 import { DeviceProfileService } from '@core/http/device-profile.service'; 26 import { DeviceProfileService } from '@core/http/device-profile.service';
27 import { Direction } from '@shared/models/page/sort-order'; 27 import { Direction } from '@shared/models/page/sort-order';
28 -import { isDefined, isDefinedAndNotNull, isEmptyStr } from '@core/utils'; 28 +import { isDefined, isDefinedAndNotNull, isEmptyStr, isString } from '@core/utils';
29 29
30 @Component({ 30 @Component({
31 selector: 'tb-profile-lwm2m-object-list', 31 selector: 'tb-profile-lwm2m-object-list',
32 templateUrl: './lwm2m-object-list.component.html', 32 templateUrl: './lwm2m-object-list.component.html',
33 - styleUrls: [],  
34 providers: [ 33 providers: [
35 { 34 {
36 provide: NG_VALUE_ACCESSOR, 35 provide: NG_VALUE_ACCESSOR,
@@ -42,10 +41,10 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -42,10 +41,10 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
42 41
43 private requiredValue: boolean; 42 private requiredValue: boolean;
44 private dirty = false; 43 private dirty = false;
45 - private allObjectsList: Observable<Array<ObjectLwM2M>>; 44 + private lw2mModels: Observable<Array<ObjectLwM2M>>;
  45 + private modelValue: Array<number> = [];
46 46
47 lwm2mListFormGroup: FormGroup; 47 lwm2mListFormGroup: FormGroup;
48 - modelValue: Array<number> | null;  
49 objectsList: Array<ObjectLwM2M> = []; 48 objectsList: Array<ObjectLwM2M> = [];
50 filteredObjectsList: Observable<Array<ObjectLwM2M>>; 49 filteredObjectsList: Observable<Array<ObjectLwM2M>>;
51 disabled = false; 50 disabled = false;
@@ -57,11 +56,8 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -57,11 +56,8 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
57 56
58 @Input() 57 @Input()
59 set required(value: boolean) { 58 set required(value: boolean) {
60 - const newVal = coerceBooleanProperty(value);  
61 - if (this.requiredValue !== newVal) {  
62 - this.requiredValue = newVal;  
63 - this.updateValidators();  
64 - } 59 + this.requiredValue = coerceBooleanProperty(value);
  60 + this.updateValidators();
65 } 61 }
66 62
67 @Output() 63 @Output()
@@ -73,7 +69,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -73,7 +69,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
73 @ViewChild('objectInput') objectInput: ElementRef<HTMLInputElement>; 69 @ViewChild('objectInput') objectInput: ElementRef<HTMLInputElement>;
74 70
75 private propagateChange = (v: any) => { 71 private propagateChange = (v: any) => {
76 - }; 72 + }
77 73
78 constructor(private store: Store<AppState>, 74 constructor(private store: Store<AppState>,
79 public translate: TranslateService, 75 public translate: TranslateService,
@@ -81,7 +77,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -81,7 +77,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
81 private fb: FormBuilder) { 77 private fb: FormBuilder) {
82 this.lwm2mListFormGroup = this.fb.group({ 78 this.lwm2mListFormGroup = this.fb.group({
83 objectsList: [this.objectsList], 79 objectsList: [this.objectsList],
84 - objectLwm2m: [null, this.required ? [Validators.required] : []] 80 + objectLwm2m: ['']
85 }); 81 });
86 } 82 }
87 83
@@ -104,11 +100,10 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -104,11 +100,10 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
104 if (value && typeof value !== 'string') { 100 if (value && typeof value !== 'string') {
105 this.add(value); 101 this.add(value);
106 } else if (value === null) { 102 } else if (value === null) {
107 - this.clear(this.objectInput.nativeElement.value); 103 + this.clear();
108 } 104 }
109 }), 105 }),
110 - filter((value) => typeof value === 'string'),  
111 - // map(value => value ? value : ''), 106 + filter(searchText => isString(searchText)),
112 mergeMap(searchText => this.fetchListObjects(searchText)) 107 mergeMap(searchText => this.fetchListObjects(searchText))
113 ); 108 );
114 } 109 }
@@ -127,23 +122,21 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -127,23 +122,21 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
127 122
128 writeValue(value: any): void { 123 writeValue(value: any): void {
129 this.searchText = ''; 124 this.searchText = '';
130 - const objectIds = 'objectIds';  
131 - if (value.hasOwnProperty(objectIds) && value[objectIds] != null && value[objectIds].length > 0) {  
132 - this.modelValue = [...value[objectIds]];  
133 - this.objectsList = value.objectsList;  
134 - } else {  
135 - this.objectsList = [];  
136 - this.modelValue = null; 125 + if (isDefinedAndNotNull(value)) {
  126 + if (Array.isArray(value.objectIds)) {
  127 + this.modelValue = value.objectIds;
  128 + this.objectsList = value.objectsList;
  129 + } else {
  130 + this.objectsList = [];
  131 + this.modelValue = [];
  132 + }
  133 + this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList, {emitEvents: false});
  134 + this.dirty = false;
137 } 135 }
138 - this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);  
139 - this.dirty = true;  
140 } 136 }
141 137
142 private add(object: ObjectLwM2M): void { 138 private add(object: ObjectLwM2M): void {
143 - if (!this.modelValue || this.modelValue.indexOf(object.id) === -1) {  
144 - if (!this.modelValue) {  
145 - this.modelValue = [];  
146 - } 139 + if (this.modelValue.indexOf(object.id) === -1) {
147 this.modelValue.push(object.id); 140 this.modelValue.push(object.id);
148 this.objectsList.push(object); 141 this.objectsList.push(object);
149 this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList); 142 this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);
@@ -176,41 +169,42 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -176,41 +169,42 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
176 const filters = {names: [], ids: []}; 169 const filters = {names: [], ids: []};
177 if (isDefinedAndNotNull(searchText) && !isEmptyStr(searchText)) { 170 if (isDefinedAndNotNull(searchText) && !isEmptyStr(searchText)) {
178 const ids = searchText.match(/\d+/g); 171 const ids = searchText.match(/\d+/g);
179 - filters.ids = isDefinedAndNotNull(ids) ? ids.map(Number) as [] : filters.ids;  
180 - const names = searchText.trim().split(" ") as [];  
181 - filters.names = names; 172 + filters.ids = ids !== null ? ids.map(Number) : filters.ids;
  173 + filters.names = searchText.trim().toUpperCase().split(' ');
182 } 174 }
183 - const predicate = objectLwM2M => filters.names.filter(word => objectLwM2M.name.toUpperCase().includes(word.toUpperCase())).length>0 175 + const predicate = objectLwM2M => filters.names.find(word => objectLwM2M.name.toUpperCase().includes(word))
184 || filters.ids.includes(objectLwM2M.id); 176 || filters.ids.includes(objectLwM2M.id);
185 - return this.getListModels().pipe( 177 + return this.getLwM2mModels().pipe(
186 map(objectLwM2Ms => searchText ? objectLwM2Ms.filter(predicate) : objectLwM2Ms) 178 map(objectLwM2Ms => searchText ? objectLwM2Ms.filter(predicate) : objectLwM2Ms)
187 ); 179 );
188 } 180 }
189 181
190 - private getListModels(): Observable<Array<ObjectLwM2M>> {  
191 - if (!this.allObjectsList) { 182 + private getLwM2mModels(): Observable<Array<ObjectLwM2M>> {
  183 + if (!this.lw2mModels) {
192 const sortOrder = { 184 const sortOrder = {
193 property: 'name', 185 property: 'name',
194 direction: Direction.ASC 186 direction: Direction.ASC
195 }; 187 };
196 - this.allObjectsList = this.deviceProfileService.getLwm2mObjects(sortOrder, null, null).pipe(  
197 - mergeMap(objectsList => of(objectsList)) 188 + this.lw2mModels = this.deviceProfileService.getLwm2mObjects(sortOrder).pipe(
  189 + publishReplay(1),
  190 + refCount()
198 ); 191 );
199 } 192 }
200 - return this.allObjectsList; 193 + return this.lw2mModels;
201 } 194 }
202 195
203 196
204 onFocus = (): void => { 197 onFocus = (): void => {
205 - if (this.dirty) { 198 + if (!this.dirty) {
206 this.lwm2mListFormGroup.get('objectLwm2m').updateValueAndValidity({onlySelf: true, emitEvent: true}); 199 this.lwm2mListFormGroup.get('objectLwm2m').updateValueAndValidity({onlySelf: true, emitEvent: true});
207 - this.dirty = false; 200 + this.dirty = true;
208 } 201 }
209 } 202 }
210 203
211 private clear = (value: string = ''): void => { 204 private clear = (value: string = ''): void => {
212 this.objectInput.nativeElement.value = value; 205 this.objectInput.nativeElement.value = value;
213 - this.lwm2mListFormGroup.get('objectLwm2m').patchValue(value, {emitEvent: true}); 206 + this.searchText = '';
  207 + this.lwm2mListFormGroup.get('objectLwm2m').patchValue(value);
214 setTimeout(() => { 208 setTimeout(() => {
215 this.objectInput.nativeElement.blur(); 209 this.objectInput.nativeElement.blur();
216 this.objectInput.nativeElement.focus(); 210 this.objectInput.nativeElement.focus();
@@ -16,23 +16,24 @@ @@ -16,23 +16,24 @@
16 16
17 --> 17 -->
18 18
19 -<section [formGroup]="observeAttrTelemetryFormGroup" class="mat-padding"> 19 +<section [formGroup]="observeAttrTelemetryFormGroup">
20 <mat-accordion multi="true" class="mat-body-1" formArrayName="clientLwM2M"> 20 <mat-accordion multi="true" class="mat-body-1" formArrayName="clientLwM2M">
21 <mat-expansion-panel 21 <mat-expansion-panel
22 - *ngFor="let objectLwM2M of clientLwM2MFormArray.controls; let i = index; trackBy: trackByParams" 22 + *ngFor="let objectLwM2M of clientLwM2MFormArray.controls; let i = index;"
23 [formGroupName]="i"> 23 [formGroupName]="i">
24 <mat-expansion-panel-header> 24 <mat-expansion-panel-header>
25 - <mat-panel-title fxLayoutAlign="space-between">  
26 - <div class="tb-panel-title"><b><i>{{ objectLwM2M.get('name').value}}</i></b> (object [<b>{{ objectLwM2M.get('id').value}}</b>])</div>  
27 - <button type="button"  
28 - *ngIf="!disabled"  
29 - [fxShow]="objectLwM2M.get('multiple').value"  
30 - mat-button mat-icon-button (click)="addInstances($event, objectLwM2M.value)"  
31 - matTooltip="{{'device-profile.lwm2m.add-instances-tip' | translate}}"  
32 - matTooltipPosition="above">  
33 - <mat-icon class="material-icons">{{'add'}}</mat-icon>  
34 - </button> 25 + <mat-panel-title fxLayoutAlign="start center">
  26 + <b><i>{{ objectLwM2M.get('name').value}}</i></b>&nbsp;&lt;id: {{ objectLwM2M.get('id').value}}>
35 </mat-panel-title> 27 </mat-panel-title>
  28 + <mat-panel-description fxLayoutAlign="end center" *ngIf="!disabled">
  29 + <button type="button"
  30 + [fxShow]="objectLwM2M.get('multiple').value"
  31 + mat-button mat-icon-button (click)="addInstances($event, objectLwM2M.value)"
  32 + matTooltip="{{'device-profile.lwm2m.add-instances-tip' | translate}}"
  33 + matTooltipPosition="above">
  34 + <mat-icon class="material-icons">{{'add'}}</mat-icon>
  35 + </button>
  36 + </mat-panel-description>
36 </mat-expansion-panel-header> 37 </mat-expansion-panel-header>
37 <ng-template matExpansionPanelContent> 38 <ng-template matExpansionPanelContent>
38 <div fxLayout="column" fxLayoutGap="8px" formArrayName="instances"> 39 <div fxLayout="column" fxLayoutGap="8px" formArrayName="instances">
@@ -176,7 +176,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -176,7 +176,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
176 this.observeAttrTelemetryFormGroup.get('clientLwM2M').updateValueAndValidity(); 176 this.observeAttrTelemetryFormGroup.get('clientLwM2M').updateValueAndValidity();
177 } 177 }
178 178
179 - trackByParams = (index: number): number => { 179 + trackByParams = (index: number, element: any): number => {
180 return index; 180 return index;
181 } 181 }
182 182