Browse Source
* lwm2m: front start add attributes Lwm2m * lwm2m: front finish add attributes Lwm2m for resources * lwm2m: front add attributes Lwm2m for resources if isAttribte or isTelemetry * lwm2m: front add attributes Lwm2m for objects if isAttribte or isTelemetry * lwm2m: back add resource one * lwm2m: back fix bug resource controller testpull/4400/head
committed by
GitHub
27 changed files with 1065 additions and 179 deletions
@ -0,0 +1,53 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2021 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<form [formGroup]="attributeLwm2mDialogFormGroup" (ngSubmit)="save()" style="width: 500px;"> |
|||
<mat-toolbar color="primary"> |
|||
<div fxFlex fxLayout="column" fxLayoutAlign="start"> |
|||
<h2>{{ (readonly ? 'device-profile.lwm2m.attribute-lwm2m-toolbar-view' : |
|||
'device-profile.lwm2m.attribute-lwm2m-toolbar-edit') | translate }}</h2> |
|||
</div> |
|||
<span fxFlex></span> |
|||
<button mat-icon-button |
|||
(click)="cancel()" |
|||
type="button"> |
|||
<mat-icon class="material-icons">close</mat-icon> |
|||
</button> |
|||
</mat-toolbar> |
|||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> |
|||
</mat-progress-bar> |
|||
<div mat-dialog-content> |
|||
<tb-lwm2m-attributes-key-list |
|||
formControlName="keyFilters" |
|||
titleText="{{data.destName}}"> |
|||
</tb-lwm2m-attributes-key-list> |
|||
</div> |
|||
<div mat-dialog-actions fxLayoutAlign="end center"> |
|||
<button mat-button color="primary" |
|||
type="button" |
|||
[disabled]="(isLoading$ | async)" |
|||
(click)="cancel()" cdkFocusInitial> |
|||
{{ (readonly ? 'action.close' : 'action.cancel') | translate }} |
|||
</button> |
|||
<button mat-raised-button color="primary" |
|||
*ngIf="!readonly" |
|||
type="submit" |
|||
[disabled]="(isLoading$ | async) || attributeLwm2mDialogFormGroup.invalid || !attributeLwm2mDialogFormGroup.dirty"> |
|||
{{ 'action.save' | translate }} |
|||
</button> |
|||
</div> |
|||
</form> |
|||
@ -0,0 +1,90 @@ |
|||
///
|
|||
/// Copyright © 2016-2021 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import {Component, Inject, OnInit, SkipSelf} from "@angular/core"; |
|||
import {ErrorStateMatcher} from "@angular/material/core"; |
|||
import {DialogComponent} from "@shared/components/dialog.component"; |
|||
import {Store} from "@ngrx/store"; |
|||
import {AppState} from "@core/core.state"; |
|||
import {Router} from "@angular/router"; |
|||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; |
|||
import {FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm} from "@angular/forms"; |
|||
import {TranslateService} from "@ngx-translate/core"; |
|||
import {JsonObject} from "@angular/compiler-cli/ngcc/src/packages/entry_point"; |
|||
|
|||
export interface Lwm2mAttributesDialogData { |
|||
readonly: boolean; |
|||
attributeLwm2m: JsonObject; |
|||
destName: string |
|||
} |
|||
|
|||
@Component({ |
|||
selector: 'tb-lwm2m-attributes-dialog', |
|||
templateUrl: './lwm2m-attributes-dialog.component.html', |
|||
styleUrls: ['./lwm2m-attributes.component.scss'], |
|||
providers: [{provide: ErrorStateMatcher, useExisting: Lwm2mAttributesDialogComponent}], |
|||
}) |
|||
export class Lwm2mAttributesDialogComponent extends DialogComponent<Lwm2mAttributesDialogComponent, Object> implements OnInit, ErrorStateMatcher { |
|||
|
|||
readonly = this.data.readonly; |
|||
|
|||
attributeLwm2m = this.data.attributeLwm2m; |
|||
|
|||
submitted = false; |
|||
|
|||
dirtyValue = false; |
|||
|
|||
attributeLwm2mDialogFormGroup: FormGroup; |
|||
|
|||
constructor(protected store: Store<AppState>, |
|||
protected router: Router, |
|||
@Inject(MAT_DIALOG_DATA) public data: Lwm2mAttributesDialogData, |
|||
@SkipSelf() private errorStateMatcher: ErrorStateMatcher, |
|||
public dialogRef: MatDialogRef<Lwm2mAttributesDialogComponent, object>, |
|||
private fb: FormBuilder, |
|||
public translate: TranslateService) { |
|||
super(store, router, dialogRef); |
|||
|
|||
this.attributeLwm2mDialogFormGroup = this.fb.group({ |
|||
keyFilters: [{}, []] |
|||
}); |
|||
this.attributeLwm2mDialogFormGroup.patchValue({keyFilters: this.attributeLwm2m}); |
|||
this.attributeLwm2mDialogFormGroup.get('keyFilters').valueChanges.subscribe((attributes) => { |
|||
this.attributeLwm2m = attributes; |
|||
}); |
|||
if (this.readonly) { |
|||
this.attributeLwm2mDialogFormGroup.disable({emitEvent: false}); |
|||
} |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
} |
|||
|
|||
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { |
|||
const originalErrorState = this.errorStateMatcher.isErrorState(control, form); |
|||
const customErrorState = !!(control && control.invalid && this.submitted); |
|||
return originalErrorState || customErrorState; |
|||
} |
|||
|
|||
save(): void { |
|||
this.submitted = true; |
|||
this.dialogRef.close(this.attributeLwm2m); |
|||
} |
|||
|
|||
cancel(): void { |
|||
this.dialogRef.close(null); |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2021 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. |
|||
|
|||
--> |
|||
<section fxLayout="column" class="tb-kv-map" [formGroup]="kvListFormGroup"> |
|||
<div> |
|||
<mat-label translate class="tb-title no-padding">device-profile.lwm2m.attribute-lwm2m-destination</mat-label> |
|||
<mat-label class="tb-editor-area-title-panel">{{ titleText }}</mat-label> |
|||
</div> |
|||
<div fxLayout="row" fxLayoutGap="8px" style="max-height: 40px; margin-top: 8px;"> |
|||
<mat-label fxFlex class="tb-title no-padding" translate>device-profile.lwm2m.attribute-lwm2m-name</mat-label> |
|||
<mat-label fxFlex class="tb-title no-padding" translate>device-profile.lwm2m.attribute-lwm2m-value</mat-label> |
|||
<div [fxShow]="!disabled" style="width: 40px;"></div> |
|||
</div> |
|||
<div fxLayout="column" formArrayName="keyVals" |
|||
*ngFor="let keyValControl of keyValsFormArray().controls; let $index = index"> |
|||
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> |
|||
<mat-form-field class="mat-block" style="max-heights: 400px"> |
|||
<mat-label></mat-label> |
|||
<mat-select [formControl]="keyValControl.get('key')"> |
|||
<mat-option *ngFor="let attributeLwm2m of attrKeys" |
|||
[value]="attributeLwm2m"> |
|||
{{ attributeLwm2mMap.get(attrKey[attributeLwm2m]) }} |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
<mat-form-field fxFlex floatLabel="always" hideRequiredMarker class="mat-block" |
|||
style="max-height: 40px;"> |
|||
<mat-label></mat-label> |
|||
<input [formControl]="keyValControl.get('value')" matInput |
|||
placeholder="{{ ('key-val.value') | translate }}"/> |
|||
</mat-form-field> |
|||
<button mat-button mat-icon-button color="primary" |
|||
[fxShow]="!disabled" |
|||
type="button" |
|||
(click)="removeKeyVal($index)" |
|||
[disabled]="isLoading$ | async" |
|||
matTooltip="{{ 'device-profile.lwm2m.attribute-lwm2m-remove-tip' | translate }}" |
|||
matTooltipPosition="above"> |
|||
<mat-icon>close</mat-icon> |
|||
</button> |
|||
</div> |
|||
<mat-error *ngIf="keyValControl.get('key').hasError('required')" style="font-size: smaller"> |
|||
{{ 'device-profile.lwm2m.key-name' | translate }} |
|||
<strong>{{ 'device-profile.lwm2m.required' | translate }}</strong> |
|||
</mat-error> |
|||
<mat-error fxLayout="row" *ngIf="keyValControl.get('key').hasError('validAttributeKey')" |
|||
style="font-size: smaller"> |
|||
{{ 'device-profile.lwm2m.valid-attribute-lwm2m-key' | translate: {attrEnums: attrKeys} }} |
|||
</mat-error> |
|||
<mat-error fxLayout="row" *ngIf="keyValControl.get('value').hasError('validAttributeValue')" |
|||
style="font-size: smaller"> |
|||
{{ 'device-profile.lwm2m.valid-attribute-lwm2m-value' | translate: {attrEnums: attrKeys} }} |
|||
</mat-error> |
|||
</div> |
|||
<span [fxShow]="!keyValsFormArray().length" |
|||
fxLayoutAlign="center center" [ngClass]="{'disabled': disabled}" |
|||
class="no-data-found" translate>{{noDataText ? noDataText : 'device-profile.lwm2m.no-data'}}</span> |
|||
<div style="margin-top: 8px;"> |
|||
<button mat-button mat-raised-button color="primary" |
|||
[fxShow]="!disabled" |
|||
[disabled]="isLoading$ | async" |
|||
(click)="addKeyVal()" |
|||
type="button" |
|||
matTooltip="{{ 'device-profile.lwm2m.attribute-lwm2m-add-tip' | translate }}" |
|||
matTooltipPosition="above"> |
|||
{{ 'action.add' | translate }} |
|||
</button> |
|||
</div> |
|||
</section> |
|||
@ -0,0 +1,227 @@ |
|||
///
|
|||
/// Copyright © 2016-2021 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import {Component, forwardRef, Input, OnInit} from "@angular/core"; |
|||
import { |
|||
AbstractControl, |
|||
ControlValueAccessor, |
|||
FormArray, |
|||
FormBuilder, |
|||
FormControl, |
|||
FormGroup, |
|||
NG_VALIDATORS, |
|||
NG_VALUE_ACCESSOR, |
|||
Validator, |
|||
Validators |
|||
} from "@angular/forms"; |
|||
import {Subscription} from "rxjs"; |
|||
import {PageComponent} from "@shared/components/page.component"; |
|||
import {Store} from "@ngrx/store"; |
|||
import {AppState} from "@core/core.state"; |
|||
import { |
|||
ATTRIBUTE_KEYS, |
|||
ATTRIBUTE_LWM2M_ENUM, |
|||
ATTRIBUTE_LWM2M_MAP |
|||
} from "@home/components/profile/device/lwm2m/lwm2m-profile-config.models"; |
|||
import {isDefinedAndNotNull, isEmpty, isEmptyStr, isUndefinedOrNull} from "@core/utils"; |
|||
|
|||
|
|||
@Component({ |
|||
selector: 'tb-lwm2m-attributes-key-list', |
|||
templateUrl: './lwm2m-attributes-key-list.component.html', |
|||
styleUrls: ['./lwm2m-attributes.component.scss'], |
|||
providers: [ |
|||
{ |
|||
provide: NG_VALUE_ACCESSOR, |
|||
useExisting: forwardRef(() => Lwm2mAttributesKeyListComponent), |
|||
multi: true |
|||
}, |
|||
{ |
|||
provide: NG_VALIDATORS, |
|||
useExisting: forwardRef(() => Lwm2mAttributesKeyListComponent), |
|||
multi: true, |
|||
} |
|||
] |
|||
}) |
|||
export class Lwm2mAttributesKeyListComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator { |
|||
|
|||
attrKeys = ATTRIBUTE_KEYS; |
|||
|
|||
attrKey = ATTRIBUTE_LWM2M_ENUM; |
|||
|
|||
attributeLwm2mMap = ATTRIBUTE_LWM2M_MAP; |
|||
|
|||
@Input() disabled: boolean; |
|||
|
|||
@Input() titleText: string; |
|||
|
|||
@Input() noDataText: string; |
|||
|
|||
kvListFormGroup: FormGroup; |
|||
|
|||
private propagateChange = null; |
|||
|
|||
private valueChangeSubscription: Subscription = null; |
|||
|
|||
constructor(protected store: Store<AppState>, |
|||
private fb: FormBuilder) { |
|||
super(store); |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
this.kvListFormGroup = this.fb.group({}); |
|||
this.kvListFormGroup.addControl('keyVals', |
|||
this.fb.array([])); |
|||
} |
|||
|
|||
keyValsFormArray(): FormArray { |
|||
return this.kvListFormGroup.get('keyVals') as FormArray; |
|||
} |
|||
|
|||
registerOnChange(fn: any): void { |
|||
this.propagateChange = fn; |
|||
} |
|||
|
|||
registerOnTouched(fn: any): void { |
|||
} |
|||
|
|||
setDisabledState?(isDisabled: boolean): void { |
|||
this.disabled = isDisabled; |
|||
if (this.disabled) { |
|||
this.kvListFormGroup.disable({emitEvent: false}); |
|||
} else { |
|||
this.kvListFormGroup.enable({emitEvent: false}); |
|||
} |
|||
} |
|||
|
|||
writeValue(keyValMap: { [key: string]: string }): void { |
|||
if (this.valueChangeSubscription) { |
|||
this.valueChangeSubscription.unsubscribe(); |
|||
} |
|||
const keyValsControls: Array<AbstractControl> = []; |
|||
if (keyValMap) { |
|||
for (const property of Object.keys(keyValMap)) { |
|||
if (Object.prototype.hasOwnProperty.call(keyValMap, property)) { |
|||
keyValsControls.push(this.fb.group({ |
|||
key: [property, [Validators.required, this.attributeLwm2mKeyValidator]], |
|||
value: [keyValMap[property], this.attributeLwm2mValueValidator(property)] |
|||
})); |
|||
} |
|||
} |
|||
} |
|||
this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls)); |
|||
this.valueChangeSubscription = this.kvListFormGroup.valueChanges.subscribe(() => { |
|||
// this.updateValidate();
|
|||
this.updateModel(); |
|||
}); |
|||
if (this.disabled) { |
|||
this.kvListFormGroup.disable({emitEvent: false}); |
|||
} else { |
|||
this.kvListFormGroup.enable({emitEvent: false}); |
|||
} |
|||
} |
|||
|
|||
public removeKeyVal(index: number) { |
|||
(this.kvListFormGroup.get('keyVals') as FormArray).removeAt(index); |
|||
} |
|||
|
|||
public addKeyVal() { |
|||
const keyValsFormArray = this.kvListFormGroup.get('keyVals') as FormArray; |
|||
keyValsFormArray.push(this.fb.group({ |
|||
key: ['', [Validators.required, this.attributeLwm2mKeyValidator]], |
|||
value: ['', []] |
|||
})); |
|||
} |
|||
|
|||
public validate(c?: FormControl) { |
|||
const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; |
|||
let valid = true; |
|||
for (const entry of kvList) { |
|||
if (isUndefinedOrNull(entry.key) || isEmptyStr(entry.key) || !ATTRIBUTE_KEYS.includes(entry.key)) { |
|||
valid = false; |
|||
break; |
|||
} |
|||
if (entry.key !== 'ver' && isNaN(Number(entry.value))) { |
|||
valid = false; |
|||
break; |
|||
} |
|||
} |
|||
return (valid) ? null : { |
|||
keyVals: { |
|||
valid: false, |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
private updateValidate (c?: FormControl) { |
|||
const kvList = this.kvListFormGroup.get('keyVals') as FormArray; |
|||
kvList.controls.forEach(fg => { |
|||
if (fg.get('key').value==='ver') { |
|||
fg.get('value').setValidators(null); |
|||
fg.get('value').setErrors(null); |
|||
} |
|||
else { |
|||
fg.get('value').setValidators(this.attributeLwm2mValueNumberValidator); |
|||
fg.get('value').setErrors(this.attributeLwm2mValueNumberValidator(fg.get('value'))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private updateModel() { |
|||
this.updateValidate(); |
|||
if (this.validate() === null) { |
|||
const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; |
|||
const keyValMap: { [key: string]: string | number } = {}; |
|||
kvList.forEach((entry) => { |
|||
if (isUndefinedOrNull(entry.value) || entry.key === 'ver' || isEmptyStr(entry.value.toString())) { |
|||
keyValMap[entry.key] = entry.value.toString(); |
|||
} else { |
|||
keyValMap[entry.key] = Number(entry.value) |
|||
} |
|||
}); |
|||
this.propagateChange(keyValMap); |
|||
} |
|||
else { |
|||
this.propagateChange(null); |
|||
} |
|||
} |
|||
|
|||
|
|||
private attributeLwm2mKeyValidator = (control: AbstractControl) => { |
|||
const key = control.value as string; |
|||
if (isDefinedAndNotNull(key) && !isEmpty(key)) { |
|||
if (!ATTRIBUTE_KEYS.includes(key)) { |
|||
return { |
|||
validAttributeKey: true |
|||
}; |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
private attributeLwm2mValueNumberValidator = (control: AbstractControl) => { |
|||
if (isNaN(Number(control.value)) || Number(control.value) < 0) { |
|||
return { |
|||
'validAttributeValue': true |
|||
}; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
private attributeLwm2mValueValidator = (property: string): Object [] => { |
|||
return property === 'ver'? [] : [this.attributeLwm2mValueNumberValidator]; |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2021 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<div fxLayout="row" [formGroup]="attributeLwm2mFormGroup"> |
|||
<div fxFlex fxLayout="column" class="resource-name-lw-end" fxLayoutAlign="center" |
|||
[matTooltip]="isToolTipLabel()" matTooltipPosition="above"> |
|||
{{attributeLwm2mToString()}} |
|||
</div> |
|||
<button type="button" |
|||
[disabled]="isDisableBtn()" |
|||
mat-button mat-icon-button |
|||
(click)="editAttributesLwm2m($event)" |
|||
[matTooltip]="(isIconView() ? 'action.view' : isIconEditAdd() ? 'action.edit' : 'action.add' ) | translate" |
|||
matTooltipPosition="above"> |
|||
<mat-icon |
|||
class="material-icons">{{isIconView() ? 'visibility' : isIconEditAdd() ? 'edit' : 'add' }}</mat-icon> |
|||
</button> |
|||
</div> |
|||
@ -0,0 +1,61 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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 { |
|||
.tb-kv-map { |
|||
span.no-data-found { |
|||
position: relative; |
|||
display: flex; |
|||
height: 40px; |
|||
|
|||
&.disabled { |
|||
color: rgba(0, 0, 0, .38); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
:host ::ng-deep { |
|||
.mat-form-field-wrapper { |
|||
padding-bottom: 0; |
|||
} |
|||
.mat-form-field-infix { |
|||
border-top: 0; |
|||
} |
|||
.mat-form-field-underline { |
|||
bottom: 0; |
|||
} |
|||
} |
|||
|
|||
.vertical-padding { |
|||
padding: 0 0 10px 20px; |
|||
} |
|||
|
|||
.resource-name-lw-end{ |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
text-align:end; |
|||
//width: 80px; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.resource-name-lw{ |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
@ -0,0 +1,159 @@ |
|||
///
|
|||
/// Copyright © 2016-2021 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import {Component, EventEmitter, forwardRef, Inject, Input, Output} from "@angular/core"; |
|||
import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR} from "@angular/forms"; |
|||
import {coerceBooleanProperty} from "@angular/cdk/coercion"; |
|||
import {Store} from "@ngrx/store"; |
|||
import {AppState} from "@core/core.state"; |
|||
import {DeviceProfileService} from "@core/http/device-profile.service"; |
|||
import {WINDOW} from "@core/services/window.service"; |
|||
import {deepClone, isDefinedAndNotNull, isEmpty} from "@core/utils"; |
|||
import { |
|||
Lwm2mAttributesDialogComponent, |
|||
Lwm2mAttributesDialogData |
|||
} from "@home/components/profile/device/lwm2m/lwm2m-attributes-dialog.component"; |
|||
import {MatDialog} from "@angular/material/dialog"; |
|||
import {TranslateService} from "@ngx-translate/core"; |
|||
import {ATTRIBUTE_LWM2M_LABEL} from "@home/components/profile/device/lwm2m/lwm2m-profile-config.models"; |
|||
|
|||
|
|||
@Component({ |
|||
selector: 'tb-profile-lwm2m-attributes', |
|||
templateUrl: './lwm2m-attributes.component.html', |
|||
styleUrls: ['./lwm2m-attributes.component.scss'], |
|||
providers: [{ |
|||
provide: NG_VALUE_ACCESSOR, |
|||
useExisting: forwardRef(() => Lwm2mAttributesComponent), |
|||
multi: true |
|||
}] |
|||
}) |
|||
export class Lwm2mAttributesComponent implements ControlValueAccessor { |
|||
attributeLwm2mFormGroup: FormGroup; |
|||
attributeLwm2mLabel = ATTRIBUTE_LWM2M_LABEL; |
|||
|
|||
private requiredValue: boolean; |
|||
private dirty = false; |
|||
|
|||
@Input() |
|||
attributeLwm2m: {}; |
|||
|
|||
@Input() |
|||
isAttributeTelemetry: boolean; |
|||
|
|||
@Input() |
|||
destName: string; |
|||
|
|||
@Input() |
|||
disabled: boolean; |
|||
|
|||
@Output() |
|||
updateAttributeLwm2m = new EventEmitter<any>(); |
|||
|
|||
@Input() |
|||
set required(value: boolean) { |
|||
this.requiredValue = coerceBooleanProperty(value); |
|||
} |
|||
|
|||
private propagateChange = (v: any) => { |
|||
} |
|||
|
|||
constructor(private store: Store<AppState>, |
|||
private dialog: MatDialog, |
|||
private fb: FormBuilder, |
|||
private deviceProfileService: DeviceProfileService, |
|||
private translate: TranslateService, |
|||
@Inject(WINDOW) private window: Window) {} |
|||
|
|||
registerOnChange(fn: any): void { |
|||
this.propagateChange = fn; |
|||
} |
|||
|
|||
registerOnTouched(fn: any): void { |
|||
} |
|||
|
|||
setDisabledState(isDisabled: boolean): void { |
|||
this.disabled = isDisabled; |
|||
if (isDisabled) { |
|||
this.attributeLwm2mFormGroup.disable({emitEvent: false}); |
|||
} else { |
|||
this.attributeLwm2mFormGroup.enable({emitEvent: false}); |
|||
} |
|||
} |
|||
|
|||
ngOnInit() { |
|||
this.attributeLwm2mFormGroup = this.fb.group({ |
|||
attributeLwm2m: [this.attributeLwm2m] |
|||
}); |
|||
} |
|||
|
|||
writeValue(value: {} | null): void {} |
|||
|
|||
attributeLwm2mToString = (): string => { |
|||
return this.isIconEditAdd () ? this.attributeLwm2mLabelToString() : this.translate.instant('device-profile.lwm2m.no-data'); |
|||
} |
|||
|
|||
private attributeLwm2mLabelToString = (): string => { |
|||
let label = JSON.stringify(this.attributeLwm2m); |
|||
label = deepClone(label.replace('{', '')); |
|||
label = deepClone(label.replace('}', '')); |
|||
this.attributeLwm2mLabel.forEach((value: string, key: string) => { |
|||
const dest = '\"' + key + '\"\:'; |
|||
label = deepClone(label.replace(dest, value)); |
|||
}); |
|||
return label; |
|||
} |
|||
|
|||
isDisableBtn (): boolean { |
|||
return this.disabled || this.isAttributeTelemetry ? !(isDefinedAndNotNull(this.attributeLwm2m) && |
|||
!isEmpty(this.attributeLwm2m) && this.disabled) : this.disabled; |
|||
} |
|||
|
|||
isIconView (): boolean { |
|||
return this.isAttributeTelemetry || this.disabled; |
|||
} |
|||
|
|||
isIconEditAdd (): boolean { |
|||
return isDefinedAndNotNull(this.attributeLwm2m) && !isEmpty(this.attributeLwm2m); |
|||
} |
|||
|
|||
isToolTipLabel (): string { |
|||
return this.disabled ? this.translate.instant('device-profile.lwm2m.attribute-lwm2m-tip') : |
|||
this.isAttributeTelemetry ? this.translate.instant('device-profile.lwm2m.attribute-lwm2m-disable-tip') : |
|||
this.translate.instant('device-profile.lwm2m.attribute-lwm2m-tip'); |
|||
} |
|||
|
|||
public editAttributesLwm2m = ($event: Event): void => { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
} |
|||
this.dialog.open<Lwm2mAttributesDialogComponent, Lwm2mAttributesDialogData, Object>(Lwm2mAttributesDialogComponent, { |
|||
disableClose: true, |
|||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], |
|||
data: { |
|||
readonly: this.disabled, |
|||
attributeLwm2m: this.disabled ? this.attributeLwm2m : deepClone(this.attributeLwm2m), |
|||
destName: this.destName |
|||
} |
|||
}).afterClosed().subscribe((result) => { |
|||
if (result) { |
|||
this.attributeLwm2m = result; |
|||
this.attributeLwm2mFormGroup.patchValue({attributeLwm2m: this.attributeLwm2m}); |
|||
this.updateAttributeLwm2m.next(this.attributeLwm2m); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue