committed by
GitHub
22 changed files with 657 additions and 160 deletions
47
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html → ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rpc-parameters/modbus-rpc-parameters/modbus-rpc-parameters.component.html
47
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html → ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rpc-parameters/modbus-rpc-parameters/modbus-rpc-parameters.component.html
@ -0,0 +1,20 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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 { |
|||
.hint-container { |
|||
margin-bottom: 12px; |
|||
} |
|||
} |
|||
10
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rpc-parameters/modbus-rpc-parameters/modbus-rpc-parameters.component.ts
10
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rpc-parameters/modbus-rpc-parameters/modbus-rpc-parameters.component.ts
@ -0,0 +1,48 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2024 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. |
|||
|
|||
--> |
|||
<ng-container [formGroup]="rpcParametersFormGroup"> |
|||
<mat-form-field> |
|||
<mat-label>{{ 'gateway.rpc.method-name' | translate }}</mat-label> |
|||
<input matInput formControlName="methodFilter" |
|||
placeholder="echo"/> |
|||
</mat-form-field> |
|||
<mat-form-field> |
|||
<mat-label>{{ 'gateway.rpc.requestTopicExpression' | translate }}</mat-label> |
|||
<input matInput formControlName="requestTopicExpression" |
|||
placeholder="sensor/${deviceName}/request/${methodName}/${requestId}"/> |
|||
</mat-form-field> |
|||
<mat-slide-toggle class="margin" (click)="$event.stopPropagation()" formControlName="withResponse"> |
|||
{{ 'gateway.rpc.withResponse' | translate }} |
|||
</mat-slide-toggle> |
|||
<mat-form-field *ngIf="rpcParametersFormGroup.get('withResponse')?.value"> |
|||
<mat-label>{{ 'gateway.rpc.responseTopicExpression' | translate }}</mat-label> |
|||
<input matInput formControlName="responseTopicExpression" |
|||
placeholder="sensor/${deviceName}/response/${methodName}/${requestId}"/> |
|||
</mat-form-field> |
|||
<mat-form-field *ngIf="rpcParametersFormGroup.get('withResponse')?.value"> |
|||
<mat-label>{{ 'gateway.rpc.responseTimeout' | translate }}</mat-label> |
|||
<input matInput formControlName="responseTimeout" type="number" |
|||
placeholder="10000" min="10" step="1"/> |
|||
</mat-form-field> |
|||
<mat-form-field> |
|||
<mat-label>{{ 'gateway.rpc.valueExpression' | translate }}</mat-label> |
|||
<input matInput formControlName="valueExpression" |
|||
placeholder="${params}"/> |
|||
</mat-form-field> |
|||
</ng-container> |
|||
|
|||
@ -0,0 +1,24 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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 { |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.mat-mdc-slide-toggle.margin { |
|||
margin-bottom: 10px; |
|||
margin-left: 10px; |
|||
} |
|||
} |
|||
@ -0,0 +1,139 @@ |
|||
///
|
|||
/// Copyright © 2016-2024 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 { |
|||
ChangeDetectionStrategy, |
|||
Component, |
|||
forwardRef, |
|||
OnDestroy, |
|||
} from '@angular/core'; |
|||
import { |
|||
ControlValueAccessor, |
|||
FormBuilder, |
|||
NG_VALIDATORS, |
|||
NG_VALUE_ACCESSOR, |
|||
UntypedFormGroup, |
|||
ValidationErrors, |
|||
Validator, Validators, |
|||
} from '@angular/forms'; |
|||
import { SharedModule } from '@shared/shared.module'; |
|||
import { CommonModule } from '@angular/common'; |
|||
import { Subject } from 'rxjs'; |
|||
import { takeUntil, tap } from 'rxjs/operators'; |
|||
import { |
|||
integerRegex, |
|||
noLeadTrailSpacesRegex, |
|||
RPCTemplateConfigMQTT |
|||
} from '@home/components/widget/lib/gateway/gateway-widget.models'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-mqtt-rpc-parameters', |
|||
templateUrl: './mqtt-rpc-parameters.component.html', |
|||
styleUrls: ['./mqtt-rpc-parameters.component.scss'], |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
providers: [ |
|||
{ |
|||
provide: NG_VALUE_ACCESSOR, |
|||
useExisting: forwardRef(() => MqttRpcParametersComponent), |
|||
multi: true |
|||
}, |
|||
{ |
|||
provide: NG_VALIDATORS, |
|||
useExisting: forwardRef(() => MqttRpcParametersComponent), |
|||
multi: true |
|||
} |
|||
], |
|||
standalone: true, |
|||
imports: [ |
|||
CommonModule, |
|||
SharedModule, |
|||
], |
|||
}) |
|||
export class MqttRpcParametersComponent implements ControlValueAccessor, Validator, OnDestroy { |
|||
|
|||
rpcParametersFormGroup: UntypedFormGroup; |
|||
|
|||
private onChange: (value: RPCTemplateConfigMQTT) => void = (_) => {}; |
|||
private onTouched: () => void = () => {}; |
|||
|
|||
private destroy$ = new Subject<void>(); |
|||
|
|||
constructor(private fb: FormBuilder) { |
|||
this.rpcParametersFormGroup = this.fb.group({ |
|||
methodFilter: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], |
|||
requestTopicExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], |
|||
responseTopicExpression: [{ value: null, disabled: true }, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], |
|||
responseTimeout: [{ value: null, disabled: true }, [Validators.min(10), Validators.pattern(integerRegex)]], |
|||
valueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], |
|||
withResponse: [false, []], |
|||
}); |
|||
|
|||
this.observeValueChanges(); |
|||
this.observeWithResponse(); |
|||
} |
|||
|
|||
ngOnDestroy(): void { |
|||
this.destroy$.next(); |
|||
this.destroy$.complete(); |
|||
} |
|||
|
|||
registerOnChange(fn: (value: RPCTemplateConfigMQTT) => void): void { |
|||
this.onChange = fn; |
|||
} |
|||
|
|||
registerOnTouched(fn: () => void): void { |
|||
this.onTouched = fn; |
|||
} |
|||
|
|||
validate(): ValidationErrors | null { |
|||
return this.rpcParametersFormGroup.valid ? null : { |
|||
rpcParametersFormGroup: { valid: false } |
|||
}; |
|||
} |
|||
|
|||
writeValue(value: RPCTemplateConfigMQTT): void { |
|||
this.rpcParametersFormGroup.patchValue(value, {emitEvent: false}); |
|||
this.toggleResponseFields(value.withResponse); |
|||
} |
|||
|
|||
private observeValueChanges(): void { |
|||
this.rpcParametersFormGroup.valueChanges.pipe( |
|||
takeUntil(this.destroy$) |
|||
).subscribe((value) => { |
|||
this.onChange(value); |
|||
this.onTouched(); |
|||
}); |
|||
} |
|||
|
|||
private observeWithResponse(): void { |
|||
this.rpcParametersFormGroup.get('withResponse').valueChanges.pipe( |
|||
tap((isActive: boolean) => this.toggleResponseFields(isActive)), |
|||
takeUntil(this.destroy$), |
|||
).subscribe(); |
|||
} |
|||
|
|||
private toggleResponseFields(enabled: boolean): void { |
|||
const responseTopicControl = this.rpcParametersFormGroup.get('responseTopicExpression'); |
|||
const responseTimeoutControl = this.rpcParametersFormGroup.get('responseTimeout'); |
|||
if (enabled) { |
|||
responseTopicControl.enable(); |
|||
responseTimeoutControl.enable(); |
|||
} else { |
|||
responseTopicControl.disable(); |
|||
responseTimeoutControl.disable(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2024 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. |
|||
|
|||
--> |
|||
<ng-container [formGroup]="rpcParametersFormGroup"> |
|||
<div class="tb-form-hint tb-primary-fill tb-flex no-padding-top hint-container"> |
|||
{{ 'gateway.rpc.hint.opc-method' | translate }} |
|||
</div> |
|||
<mat-form-field class="tb-flex"> |
|||
<mat-label>{{ 'gateway.rpc.method' | translate }}</mat-label> |
|||
<input matInput formControlName="method" placeholder="multiply"/> |
|||
</mat-form-field> |
|||
<fieldset class="tb-form-panel stroked arguments-container" fxLayout="column" formArrayName="arguments"> |
|||
<strong> |
|||
<span class="fields-label">{{ 'gateway.rpc.arguments' | translate }}</span> |
|||
</strong> |
|||
<div fxFlex fxLayout="row" fxLayoutGap="10px" fxLayoutAlign="center center" |
|||
*ngFor="let argumentFormGroup of rpcParametersFormGroup.get('arguments')['controls']; let i = index" [formGroup]="argumentFormGroup"> |
|||
<div class="tb-form-row column-xs type-container" fxLayoutAlign="space-between center"> |
|||
<div class="tb-required" translate>gateway.type</div> |
|||
<div class="tb-flex no-gap"> |
|||
<mat-form-field class="tb-flex no-gap fill-width" appearance="outline" subscriptSizing="dynamic"> |
|||
<mat-select formControlName="type"> |
|||
<mat-select-trigger> |
|||
<div class="tb-flex align-center"> |
|||
<mat-icon class="tb-mat-18" [svgIcon]="valueTypes.get(argumentFormGroup.get('type').value)?.icon"> |
|||
</mat-icon> |
|||
<span>{{ valueTypes.get(argumentFormGroup.get('type').value)?.name | translate }}</span> |
|||
</div> |
|||
</mat-select-trigger> |
|||
<mat-option *ngFor="let valueType of valueTypeKeys" [value]="valueType"> |
|||
<mat-icon class="tb-mat-20" svgIcon="{{ valueTypes.get(valueType).icon }}"> |
|||
</mat-icon> |
|||
<span>{{ valueTypes.get(valueType).name | translate }}</span> |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
</div> |
|||
</div> |
|||
<div class="tb-form-row column-xs value-container" fxLayoutAlign="space-between center"> |
|||
<div class="tb-required" translate>gateway.value</div> |
|||
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic" class="tb-inline-field flex tb-suffix-absolute"> |
|||
<ng-container [ngSwitch]="argumentFormGroup.get('type').value"> |
|||
<input *ngSwitchCase="MappingValueType.STRING" matInput required formControlName="string" |
|||
placeholder="{{ 'gateway.set' | translate }}" /> |
|||
<input *ngSwitchCase="MappingValueType.INTEGER" matInput required formControlName="integer" type="number" |
|||
placeholder="{{ 'gateway.set' | translate }}" /> |
|||
<input *ngSwitchCase="MappingValueType.DOUBLE" matInput required formControlName="double" type="number" |
|||
placeholder="{{ 'gateway.set' | translate }}" /> |
|||
<mat-select *ngSwitchCase="MappingValueType.BOOLEAN" formControlName="boolean"> |
|||
<mat-option [value]="true">true</mat-option> |
|||
<mat-option [value]="false">false</mat-option> |
|||
</mat-select> |
|||
</ng-container> |
|||
<mat-icon matSuffix |
|||
matTooltipPosition="above" |
|||
matTooltipClass="tb-error-tooltip" |
|||
[matTooltip]="('gateway.value-required') | translate" |
|||
*ngIf="argumentFormGroup.get(argumentFormGroup.get('type').value).hasError('required') |
|||
&& argumentFormGroup.get(argumentFormGroup.get('type').value).touched" |
|||
class="tb-error"> |
|||
warning |
|||
</mat-icon> |
|||
</mat-form-field> |
|||
</div> |
|||
<button mat-icon-button (click)="removeArgument(i)" |
|||
class="tb-box-button" |
|||
matTooltip="{{ 'gateway.rpc.remove' | translate }}" |
|||
matTooltipPosition="above"> |
|||
<mat-icon>delete</mat-icon> |
|||
</button> |
|||
</div> |
|||
<button mat-raised-button |
|||
fxFlexAlign="start" |
|||
(click)="addArgument()"> |
|||
{{ 'gateway.rpc.add-argument' | translate }} |
|||
</button> |
|||
</fieldset> |
|||
</ng-container> |
|||
|
|||
@ -0,0 +1,32 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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 { |
|||
.arguments-container { |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
.type-container { |
|||
width: 40%; |
|||
} |
|||
|
|||
.value-container { |
|||
width: 50%; |
|||
} |
|||
|
|||
.hint-container { |
|||
margin-bottom: 12px; |
|||
} |
|||
} |
|||
@ -0,0 +1,169 @@ |
|||
///
|
|||
/// Copyright © 2016-2024 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 { |
|||
ChangeDetectionStrategy, |
|||
ChangeDetectorRef, |
|||
Component, |
|||
forwardRef, |
|||
OnDestroy, |
|||
} from '@angular/core'; |
|||
import { |
|||
ControlValueAccessor, |
|||
FormArray, |
|||
FormBuilder, |
|||
FormGroup, |
|||
NG_VALIDATORS, |
|||
NG_VALUE_ACCESSOR, |
|||
UntypedFormGroup, |
|||
ValidationErrors, |
|||
Validator, Validators, |
|||
} from '@angular/forms'; |
|||
import { SharedModule } from '@shared/shared.module'; |
|||
import { CommonModule } from '@angular/common'; |
|||
import { Subject } from 'rxjs'; |
|||
import { takeUntil } from 'rxjs/operators'; |
|||
import { |
|||
integerRegex, |
|||
MappingValueType, |
|||
mappingValueTypesMap, |
|||
noLeadTrailSpacesRegex, |
|||
OPCTypeValue, |
|||
RPCTemplateConfigOPC |
|||
} from '@home/components/widget/lib/gateway/gateway-widget.models'; |
|||
import { isDefinedAndNotNull, isEqual } from '@core/utils'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-opc-rpc-parameters', |
|||
templateUrl: './opc-rpc-parameters.component.html', |
|||
styleUrls: ['./opc-rpc-parameters.component.scss'], |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
providers: [ |
|||
{ |
|||
provide: NG_VALUE_ACCESSOR, |
|||
useExisting: forwardRef(() => OpcRpcParametersComponent), |
|||
multi: true |
|||
}, |
|||
{ |
|||
provide: NG_VALIDATORS, |
|||
useExisting: forwardRef(() => OpcRpcParametersComponent), |
|||
multi: true |
|||
} |
|||
], |
|||
standalone: true, |
|||
imports: [ |
|||
CommonModule, |
|||
SharedModule, |
|||
], |
|||
}) |
|||
export class OpcRpcParametersComponent implements ControlValueAccessor, Validator, OnDestroy { |
|||
|
|||
rpcParametersFormGroup: UntypedFormGroup; |
|||
|
|||
readonly valueTypeKeys: MappingValueType[] = Object.values(MappingValueType); |
|||
readonly MappingValueType = MappingValueType; |
|||
readonly valueTypes = mappingValueTypesMap; |
|||
|
|||
private onChange: (value: RPCTemplateConfigOPC) => void = (_) => {} ; |
|||
private onTouched: () => void = () => {}; |
|||
|
|||
private destroy$ = new Subject<void>(); |
|||
|
|||
constructor(private fb: FormBuilder, private cdr: ChangeDetectorRef) { |
|||
this.rpcParametersFormGroup = this.fb.group({ |
|||
method: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], |
|||
arguments: this.fb.array([]), |
|||
}); |
|||
|
|||
this.observeValueChanges(); |
|||
} |
|||
|
|||
ngOnDestroy(): void { |
|||
this.destroy$.next(); |
|||
this.destroy$.complete(); |
|||
} |
|||
|
|||
registerOnChange(fn: (value: RPCTemplateConfigOPC) => void): void { |
|||
this.onChange = fn; |
|||
} |
|||
|
|||
registerOnTouched(fn: () => void): void { |
|||
this.onTouched = fn; |
|||
} |
|||
|
|||
validate(): ValidationErrors | null { |
|||
return this.rpcParametersFormGroup.valid ? null : { |
|||
rpcParametersFormGroup: { valid: false } |
|||
}; |
|||
} |
|||
|
|||
writeValue(params: RPCTemplateConfigOPC): void { |
|||
this.clearArguments(); |
|||
params.arguments?.map(({type, value}) => ({type, [type]: value })) |
|||
.forEach(argument => this.addArgument(argument as OPCTypeValue)); |
|||
this.cdr.markForCheck(); |
|||
this.rpcParametersFormGroup.get('method').patchValue(params.method); |
|||
} |
|||
|
|||
private observeValueChanges(): void { |
|||
this.rpcParametersFormGroup.valueChanges.pipe( |
|||
takeUntil(this.destroy$) |
|||
).subscribe(params => { |
|||
const updatedArguments = params.arguments.map(({type, ...config}) => ({type, value: config[type]})); |
|||
this.onChange({method: params.method, arguments: updatedArguments}); |
|||
this.onTouched(); |
|||
}); |
|||
} |
|||
|
|||
removeArgument(index: number): void { |
|||
(this.rpcParametersFormGroup.get('arguments') as FormArray).removeAt(index); |
|||
} |
|||
|
|||
addArgument(value: OPCTypeValue = {} as OPCTypeValue): void { |
|||
const fromGroup = this.fb.group({ |
|||
type: [value.type ?? MappingValueType.STRING], |
|||
string: [ |
|||
value.string ?? { value: '', disabled: !(isEqual(value, {}) || value.string)}, |
|||
[Validators.required, Validators.pattern(noLeadTrailSpacesRegex)] |
|||
], |
|||
integer: [ |
|||
{value: value.integer ?? 0, disabled: !isDefinedAndNotNull(value.integer)}, |
|||
[Validators.required, Validators.pattern(integerRegex)] |
|||
], |
|||
double: [{value: value.double ?? 0, disabled: !isDefinedAndNotNull(value.double)}, [Validators.required]], |
|||
boolean: [{value: value.boolean ?? false, disabled: !isDefinedAndNotNull(value.boolean)}, [Validators.required]], |
|||
}); |
|||
this.observeTypeChange(fromGroup); |
|||
(this.rpcParametersFormGroup.get('arguments') as FormArray).push(fromGroup, {emitEvent: false}); |
|||
} |
|||
|
|||
clearArguments(): void { |
|||
const formArray = this.rpcParametersFormGroup.get('arguments') as FormArray; |
|||
while (formArray.length !== 0) { |
|||
formArray.removeAt(0); |
|||
} |
|||
} |
|||
|
|||
private observeTypeChange(dataKeyFormGroup: FormGroup): void { |
|||
dataKeyFormGroup.get('type').valueChanges |
|||
.pipe(takeUntil(this.destroy$)) |
|||
.subscribe(type => { |
|||
dataKeyFormGroup.disable({emitEvent: false}); |
|||
dataKeyFormGroup.get('type').enable({emitEvent: false}); |
|||
dataKeyFormGroup.get(type).enable({emitEvent: false}); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
///
|
|||
/// Copyright © 2016-2024 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 { Pipe, PipeTransform } from '@angular/core'; |
|||
|
|||
@Pipe({ |
|||
name: 'getRpcTemplateArrayView', |
|||
standalone: true, |
|||
}) |
|||
export class RpcTemplateArrayViewPipe implements PipeTransform { |
|||
|
|||
transform(values: {value: string | boolean | number}[]): string { |
|||
return values.map(({value}) => value.toString()).join(', '); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue