Browse Source

1st batch of minor fixes

pull/10011/head
dudnikmaksim 3 years ago
parent
commit
871e4d405d
  1. 1
      ui-ngx/src/app/core/utils.ts
  2. 5
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog.ts
  3. 29
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html
  4. 6
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.scss
  5. 95
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts
  6. 47
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts
  7. 11
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
  8. 752
      ui-ngx/src/assets/locale/locale.constant-en_US.json

1
ui-ngx/src/app/core/utils.ts

@ -26,6 +26,7 @@ import { TranslateService } from '@ngx-translate/core';
import { serverErrorCodesTranslations } from '@shared/models/constants'; import { serverErrorCodesTranslations } from '@shared/models/constants';
const varsRegex = /\${([^}]*)}/g; const varsRegex = /\${([^}]*)}/g;
export const noLeadTrailSpacesRegex: RegExp = /^(?! )[A-Za-z0-9 ]*(?<! )$/;
export function onParentScrollOrWindowResize(el: Node): Observable<Event> { export function onParentScrollOrWindowResize(el: Node): Observable<Event> {
const scrollSubject = new Subject<Event>(); const scrollSubject = new Subject<Event>();

5
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog.ts

@ -44,7 +44,7 @@ export class GatewayServiceRPCConnectorTemplateDialogComponent extends DialogCom
super(store, router, dialogRef); super(store, router, dialogRef);
this.config = this.data.config; this.config = this.data.config;
this.templates = this.data.templates; this.templates = this.data.templates;
this.templateNameCtrl = this.fb.control('', [Validators.required]) this.templateNameCtrl = this.fb.control('', [Validators.required]);
} }
validateDuplicateName(c: UntypedFormControl) { validateDuplicateName(c: UntypedFormControl) {
@ -57,6 +57,7 @@ export class GatewayServiceRPCConnectorTemplateDialogComponent extends DialogCom
} }
save(): void { save(): void {
this.dialogRef.close(this.templateNameCtrl.value); this.templateNameCtrl.setValue(this.templateNameCtrl.value.trim());
if (this.templateNameCtrl.valid) this.dialogRef.close(this.templateNameCtrl.value);
} }
} }

29
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html

@ -22,7 +22,7 @@
<ng-container [ngSwitch]="connectorType"> <ng-container [ngSwitch]="connectorType">
<ng-template [ngSwitchCase]="ConnectorType.MQTT"> <ng-template [ngSwitchCase]="ConnectorType.MQTT">
<mat-form-field> <mat-form-field>
<mat-label>{{ 'gateway.rpc.method-filter' | translate }}</mat-label> <mat-label>{{ 'gateway.rpc.methodFilter' | translate }}</mat-label>
<input matInput formControlName="methodFilter" <input matInput formControlName="methodFilter"
placeholder="echo"/> placeholder="echo"/>
</mat-form-field> </mat-form-field>
@ -65,11 +65,15 @@
<mat-label>{{ 'gateway.rpc.functionCode' | translate }}</mat-label> <mat-label>{{ 'gateway.rpc.functionCode' | translate }}</mat-label>
<mat-select formControlName="functionCode"> <mat-select formControlName="functionCode">
<mat-option *ngFor="let code of codesArray" [value]="code"> <mat-option *ngFor="let code of codesArray" [value]="code">
{{ code }} {{ modbusCodesTranslate.get(code) | translate}}
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<mat-form-field *ngIf="commandForm.get('functionCode').value>4">
<mat-label>{{ 'gateway.rpc.value' | translate }}</mat-label>
<input matInput formControlName="value" placeholder="value"/>
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutGap="10px"> <div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field fxFlex="50"> <mat-form-field fxFlex="50">
<mat-label>{{ 'gateway.rpc.address' | translate }}</mat-label> <mat-label>{{ 'gateway.rpc.address' | translate }}</mat-label>
@ -233,11 +237,7 @@
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label>{{ 'gateway.rpc.encoding' | translate }}</mat-label> <mat-label>{{ 'gateway.rpc.encoding' | translate }}</mat-label>
<mat-select formControlName="encoding"> <input matInput formControlName="encoding" placeholder="{{socketEncodings[0]}}"/>
<mat-option *ngFor="let encoding of socketEncodings" [value]="encoding">
{{ encoding }}
</mat-option>
</mat-select>
</mat-form-field> </mat-form-field>
<mat-slide-toggle class="mat-slide margin" formControlName="withResponse"> <mat-slide-toggle class="mat-slide margin" formControlName="withResponse">
{{ 'gateway.rpc.withResponse' | translate }} {{ 'gateway.rpc.withResponse' | translate }}
@ -269,12 +269,15 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-slide-toggle class="mat-slide margin" formControlName="withResponse">
{{ 'gateway.rpc.withResponse' | translate }}
</mat-slide-toggle>
<fieldset class="fields border" fxLayout="column" fxLayoutGap="10px" formArrayName="oid"> <fieldset class="fields border" fxLayout="column" fxLayoutGap="10px" formArrayName="oid">
<span class="fields-label">{{ 'gateway.rpc.oids' | translate }}*</span> <span class="fields-label">{{ 'gateway.rpc.oids' | translate }}*</span>
<div fxFlex fxLayout="row" fxLayoutGap="10px" fxLayoutAlign="center center" <div fxFlex fxLayout="row" fxLayoutGap="10px" fxLayoutAlign="center center"
*ngFor="let control of getFormArrayControls('oid'); let i = index"> *ngFor="let control of getFormArrayControls('oid'); let i = index">
<mat-form-field appearance="outline" fxFlex> <mat-form-field appearance="outline" fxFlex>
<input matInput [formControl]="control"/> <input matInput [formControl]="control" required/>
</mat-form-field> </mat-form-field>
<mat-icon style="cursor:pointer;" <mat-icon style="cursor:pointer;"
fxFlex="30px" fxFlex="30px"
@ -296,8 +299,8 @@
</mat-form-field> </mat-form-field>
<div fxFlex fxLayout="row" fxLayoutGap="10px"> <div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field class="mat-block" fxFlex="33"> <mat-form-field class="mat-block" fxFlex="33">
<mat-label>{{ 'gateway.rpc.HTTPMethod' | translate }}</mat-label> <mat-label>{{ 'gateway.rpc.httpMethod' | translate }}</mat-label>
<mat-select formControlName="HTTPMethod"> <mat-select formControlName="httpMethod">
<mat-option *ngFor="let method of hTTPMethods" [value]="method"> <mat-option *ngFor="let method of hTTPMethods" [value]="method">
{{ method }} {{ method }}
</mat-option> </mat-option>
@ -476,7 +479,7 @@
<ng-container *ngTemplateOutlet="OPCUAForm"></ng-container> <ng-container *ngTemplateOutlet="OPCUAForm"></ng-container>
</ng-template> </ng-template>
<ng-template [ngSwitchCase]="ConnectorType.OPCUA" #OPCUAForm> <ng-template [ngSwitchCase]="ConnectorType.OPCUA" #OPCUAForm>
<mat-form-field> <mat-form-field >
<mat-label>{{ 'gateway.rpc.method' | translate }}</mat-label> <mat-label>{{ 'gateway.rpc.method' | translate }}</mat-label>
<input matInput formControlName="method" placeholder="multiply"/> <input matInput formControlName="method" placeholder="multiply"/>
</mat-form-field> </mat-form-field>
@ -485,9 +488,8 @@
<div fxFlex fxLayout="row" fxLayoutGap="10px" fxLayoutAlign="center center" <div fxFlex fxLayout="row" fxLayoutGap="10px" fxLayoutAlign="center center"
*ngFor="let control of getFormArrayControls('arguments'); let i = index"> *ngFor="let control of getFormArrayControls('arguments'); let i = index">
<mat-form-field appearance="outline" fxFlex> <mat-form-field appearance="outline" fxFlex>
<input matInput [formControl]="control"/> <input matInput [formControl]="control" required/>
</mat-form-field> </mat-form-field>
<mat-icon style="cursor:pointer;" <mat-icon style="cursor:pointer;"
fxFlex="30px" fxFlex="30px"
(click)="removeOCPUAArguments(i)" (click)="removeOCPUAArguments(i)"
@ -502,7 +504,6 @@
</fieldset> </fieldset>
</ng-template> </ng-template>
<ng-template ngSwitchDefault> <ng-template ngSwitchDefault>
{{'dsadas'}}
<mat-form-field> <mat-form-field>
<mat-label>{{ 'gateway.statistics.command' | translate }}</mat-label> <mat-label>{{ 'gateway.statistics.command' | translate }}</mat-label>
<input matInput formControlName="command"/> <input matInput formControlName="command"/>

6
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.scss

@ -48,9 +48,9 @@
::ng-deep .mat-mdc-form-field-subscript-wrapper { ::ng-deep .mat-mdc-form-field-subscript-wrapper {
display: none; display: none;
} }
::ng-deep .mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__leading, ::ng-deep .mdc-text-field--outlined:not(.mdc-text-field--invalid) .mdc-notched-outline__leading,
::ng-deep .mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__notch, ::ng-deep .mdc-text-field--outlined:not(.mdc-text-field--invalid) .mdc-notched-outline__notch,
::ng-deep .mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__trailing { ::ng-deep .mdc-text-field--outlined:not(.mdc-text-field--invalid) .mdc-notched-outline__trailing {
border-color: #e0e0e0; border-color: #e0e0e0;
} }

95
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts

@ -34,7 +34,7 @@ import {
CANByteOrders, CANByteOrders,
ConnectorType, ConnectorType,
GatewayConnectorDefaultTypesTranslates, GatewayConnectorDefaultTypesTranslates,
HTTPMethods, HTTPMethods, ModbusCodesTranslate,
ModbusCommandTypes, ModbusCommandTypes,
RPCCommand, RPCCommand,
RPCTemplateConfig, RPCTemplateConfig,
@ -50,7 +50,7 @@ import {
JsonObjectEditDialogData JsonObjectEditDialogData
} from '@shared/components/dialog/json-object-edit-dialog.component'; } from '@shared/components/dialog/json-object-edit-dialog.component';
import { jsonRequired } from '@shared/components/json-object-edit.component'; import { jsonRequired } from '@shared/components/json-object-edit.component';
import { deepClone } from '@core/utils'; import { deepClone, noLeadTrailSpacesRegex } from '@core/utils';
@Component({ @Component({
selector: 'tb-gateway-service-rpc-connector', selector: 'tb-gateway-service-rpc-connector',
@ -97,6 +97,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
SocketMethodProcessingsTranslates = SocketMethodProcessingsTranslates; SocketMethodProcessingsTranslates = SocketMethodProcessingsTranslates;
SNMPMethodsTranslations = SNMPMethodsTranslations; SNMPMethodsTranslations = SNMPMethodsTranslations;
gatewayConnectorDefaultTypesTranslates = GatewayConnectorDefaultTypesTranslates; gatewayConnectorDefaultTypesTranslates = GatewayConnectorDefaultTypesTranslates;
modbusCodesTranslate = ModbusCodesTranslate;
urlPattern = new RegExp( urlPattern = new RegExp(
'^(https?:\\/\\/)?' + // protocol '^(https?:\\/\\/)?' + // protocol
@ -139,7 +140,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
break; break;
} }
if (this.commandForm.valid) { if (this.commandForm.valid) {
this.propagateChange({...this.commandForm.value,...value}); this.propagateChange({...this.commandForm.value, ...value});
} }
}) })
} }
@ -150,126 +151,138 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
switch (type) { switch (type) {
case ConnectorType.MQTT: case ConnectorType.MQTT:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodFilter: [null, [Validators.required]], methodFilter: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
requestTopicExpression: [null, [Validators.required]], requestTopicExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
responseTopicExpression: [null, []], responseTopicExpression: [null, [Validators.pattern(noLeadTrailSpacesRegex)]],
responseTimeout: [null, [Validators.min(10), Validators.pattern("^[0-9]*$")]], responseTimeout: [null, [Validators.min(10), Validators.pattern("^[0-9]*$")]],
valueExpression: [null, [Validators.required]], valueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
}) })
break; break;
case ConnectorType.MODBUS: case ConnectorType.MODBUS:
formGroup = this.fb.group({ formGroup = this.fb.group({
tag: [null, [Validators.required]], tag: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
type: [null, [Validators.required]], type: [null, [Validators.required]],
functionCode: [null, [Validators.required]], functionCode: [null, [Validators.required]],
value: [null, []],
address: [null, [Validators.required, Validators.min(0), Validators.pattern("^[0-9]*$")]], address: [null, [Validators.required, Validators.min(0), Validators.pattern("^[0-9]*$")]],
objectsCount: [null, [Validators.required, Validators.min(0), Validators.pattern("^[0-9]*$")]] objectsCount: [null, [Validators.required, Validators.min(0), Validators.pattern("^[0-9]*$")]]
}) })
const valueForm = formGroup.get('value');
formGroup.get('functionCode').valueChanges.subscribe(value => {
if (value > 4) {
valueForm.addValidators([Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]);
} else {
valueForm.clearValidators();
valueForm.setValue(null);
}
valueForm.updateValueAndValidity();
})
break; break;
case ConnectorType.BACNET: case ConnectorType.BACNET:
formGroup = this.fb.group({ formGroup = this.fb.group({
method: [null, [Validators.required]], method: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
requestType: [null, [Validators.required]], requestType: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
requestTimeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]], requestTimeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]],
objectType: [null, []], objectType: [null, []],
identifier: [null, [Validators.required, Validators.min(1), Validators.pattern("^[0-9]*$")]], identifier: [null, [Validators.required, Validators.min(1), Validators.pattern("^[0-9]*$")]],
propertyId: [null, [Validators.required]] propertyId: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]]
}) })
break; break;
case ConnectorType.BLE: case ConnectorType.BLE:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodRPC: [null, [Validators.required]], methodRPC: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
characteristicUUID: [null, [Validators.required]], characteristicUUID: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
methodProcessing: [null, [Validators.required]], methodProcessing: [null, [Validators.required]],
withResponse: [false, []] withResponse: [false, []]
}) })
break; break;
case ConnectorType.CAN: case ConnectorType.CAN:
formGroup = this.fb.group({ formGroup = this.fb.group({
method: [null, [Validators.required]], method: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
nodeID: [null, [Validators.required, Validators.min(0), Validators.pattern("^[0-9]*$")]], nodeID: [null, [Validators.required, Validators.min(0), Validators.pattern("^[0-9]*$")]],
isExtendedID: [false, []], isExtendedID: [false, []],
isFD: [false, []], isFD: [false, []],
bitrateSwitch: [false, []], bitrateSwitch: [false, []],
dataLength: [null, [Validators.min(1), Validators.pattern("^[0-9]*$")]], dataLength: [null, [Validators.min(1), Validators.pattern("^[0-9]*$")]],
dataByteorder: [null, []], dataByteorder: [null, []],
dataBefore: [null, []], dataBefore: [null, [Validators.pattern(noLeadTrailSpacesRegex), Validators.pattern(/^[0-9A-Fa-f]+$/)]],
dataAfter: [null, []], dataAfter: [null, [Validators.pattern(noLeadTrailSpacesRegex), Validators.pattern(/^[0-9A-Fa-f]+$/)]],
dataInHEX: [null, []], dataInHEX: [null, [Validators.pattern(noLeadTrailSpacesRegex), Validators.pattern(/^[0-9A-Fa-f]+$/)]],
dataExpression: [null, []] dataExpression: [null, [Validators.pattern(noLeadTrailSpacesRegex)]]
}) })
break; break;
case ConnectorType.FTP: case ConnectorType.FTP:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodFilter: [null, [Validators.required]], methodFilter: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
valueExpression: [null, [Validators.required]] valueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]]
}) })
break; break;
case ConnectorType.OCPP: case ConnectorType.OCPP:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodRPC: [null, [Validators.required]], methodRPC: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
valueExpression: [null, [Validators.required]], valueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
withResponse: [false, []] withResponse: [false, []]
}) })
break; break;
case ConnectorType.SOCKET: case ConnectorType.SOCKET:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodRPC: [null, [Validators.required]], methodRPC: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
methodProcessing: [null, [Validators.required]], methodProcessing: [null, [Validators.required]],
encoding: [null, [Validators.required]], encoding: [SocketEncodings.UTF_8, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
withResponse: [false, []] withResponse: [false, []]
}) })
break; break;
case ConnectorType.XMPP: case ConnectorType.XMPP:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodRPC: [null, [Validators.required]], methodRPC: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
valueExpression: [null, [Validators.required]], valueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
withResponse: [false, []] withResponse: [false, []]
}) })
break; break;
case ConnectorType.SNMP: case ConnectorType.SNMP:
formGroup = this.fb.group({ formGroup = this.fb.group({
requestFilter: [null, [Validators.required]], requestFilter: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
method: [null, [Validators.required]], method: [null, [Validators.required]],
withResponse: [false, []],
oid: this.fb.array([], [Validators.required]) oid: this.fb.array([], [Validators.required])
}) })
break; break;
case ConnectorType.REST: case ConnectorType.REST:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodFilter: [null, [Validators.required]], methodFilter: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
HTTPMethod: [null, [Validators.required]], httpMethod: [null, [Validators.required]],
requestUrlExpression: [null, [Validators.required, Validators.pattern(this.urlPattern)]], requestUrlExpression: [null, [Validators.required, Validators.pattern(this.urlPattern)]],
responseTimeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]], responseTimeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]],
timeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]], timeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]],
tries: [null, [Validators.required, Validators.min(1), Validators.pattern("^[0-9]*$")]], tries: [null, [Validators.required, Validators.min(1), Validators.pattern("^[0-9]*$")]],
valueExpression: [null, [Validators.required]], valueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
httpHeaders: this.fb.array([]), httpHeaders: this.fb.array([]),
security: this.fb.array([]) security: this.fb.array([])
}) })
break; break;
case ConnectorType.REQUEST: case ConnectorType.REQUEST:
formGroup = this.fb.group({ formGroup = this.fb.group({
methodFilter: [null, [Validators.required]], methodFilter: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
httpMethod: [null, [Validators.required]], httpMethod: [null, [Validators.required]],
requestUrlExpression: [null, [Validators.required, Validators.pattern(this.urlPattern)]], requestUrlExpression: [null, [Validators.required, Validators.pattern(this.urlPattern)]],
responseTimeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]], responseTimeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]],
timeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]], timeout: [null, [Validators.required, Validators.min(10), Validators.pattern("^[0-9]*$")]],
tries: [null, [Validators.required, Validators.min(1), Validators.pattern("^[0-9]*$")]], tries: [null, [Validators.required, Validators.min(1), Validators.pattern("^[0-9]*$")]],
requestValueExpression: [null, [Validators.required]], requestValueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
responseValueExpression: [null, []], responseValueExpression: [null, [Validators.pattern(noLeadTrailSpacesRegex)]],
httpHeaders: this.fb.array([]), httpHeaders: this.fb.array([]),
}) })
break; break;
case ConnectorType.OPCUA: case ConnectorType.OPCUA:
case ConnectorType.OPCUA_ASYNCIO: case ConnectorType.OPCUA_ASYNCIO:
formGroup = this.fb.group({ formGroup = this.fb.group({
method: [null, [Validators.required]], method: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
arguments: this.fb.array([]), arguments: this.fb.array([]),
}) })
break; break;
default: default:
formGroup = this.fb.group({ formGroup = this.fb.group({
command: [null, [Validators.required]], command: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
params: ['{}', [jsonRequired]], params: ['{}', [jsonRequired]],
}) })
@ -280,7 +293,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
addSNMPoid(value: string = null) { addSNMPoid(value: string = null) {
const oidsFA = this.commandForm.get('oid') as FormArray; const oidsFA = this.commandForm.get('oid') as FormArray;
if (oidsFA) { if (oidsFA) {
oidsFA.push(this.fb.control(value, [Validators.required]), {emitEvent: false}); oidsFA.push(this.fb.control(value, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]), {emitEvent: false});
} }
} }
@ -292,8 +305,8 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
addHTTPHeader(value: { headerName: string, value: string } = {headerName: null, value: null}) { addHTTPHeader(value: { headerName: string, value: string } = {headerName: null, value: null}) {
const headerFA = this.commandForm.get('httpHeaders') as FormArray; const headerFA = this.commandForm.get('httpHeaders') as FormArray;
const formGroup = this.fb.group({ const formGroup = this.fb.group({
headerName: [value.headerName, [Validators.required]], headerName: [value.headerName, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
value: [value.value, [Validators.required]] value: [value.value, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]]
}) })
if (headerFA) { if (headerFA) {
headerFA.push(formGroup, {emitEvent: false}); headerFA.push(formGroup, {emitEvent: false});
@ -308,8 +321,8 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
addHTTPSecurity(value: { securityName: string, value: string } = {securityName: null, value: null}) { addHTTPSecurity(value: { securityName: string, value: string } = {securityName: null, value: null}) {
const securityFA = this.commandForm.get('security') as FormArray; const securityFA = this.commandForm.get('security') as FormArray;
const formGroup = this.fb.group({ const formGroup = this.fb.group({
securityName: [value.securityName, [Validators.required]], securityName: [value.securityName, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
value: [value.value, [Validators.required]] value: [value.value, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]]
}) })
if (securityFA) { if (securityFA) {
securityFA.push(formGroup, {emitEvent: false}); securityFA.push(formGroup, {emitEvent: false});
@ -328,7 +341,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
addOCPUAArguments(value: string = null) { addOCPUAArguments(value: string = null) {
const oidsFA = this.commandForm.get('arguments') as FormArray; const oidsFA = this.commandForm.get('arguments') as FormArray;
if (oidsFA) { if (oidsFA) {
oidsFA.push(this.fb.control(value), {emitEvent: false}); oidsFA.push(this.fb.control(value, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]), {emitEvent: false});
} }
} }

47
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts

@ -170,29 +170,32 @@ export class GatewayServiceRPCComponent implements OnInit {
data: {config: this.commandForm.value.params, templates: this.templates} data: {config: this.commandForm.value.params, templates: this.templates}
}).afterClosed().subscribe( }).afterClosed().subscribe(
(res) => { (res) => {
const templateAttribute: RPCTemplate = { if (res) {
name: res, console.log(res);
config: this.commandForm.value.params const templateAttribute: RPCTemplate = {
} name: res,
const templatesArray = this.templates; config: this.commandForm.value.params
const existingIndex = templatesArray.findIndex(template=>{
return template.name == templateAttribute.name;
})
if (existingIndex > -1 ){
templatesArray.splice(existingIndex, 1)
}
templatesArray.push(templateAttribute)
const key = `${this.connectorType}_template`;
this.attributeService.saveEntityAttributes(
{
id: this.ctx.defaultSubscription.targetDeviceId,
entityType: EntityType.DEVICE
} }
, AttributeScope.SERVER_SCOPE, [{ const templatesArray = this.templates;
key, const existingIndex = templatesArray.findIndex(template => {
value: templatesArray return template.name == templateAttribute.name;
}]).subscribe(() => { })
}) if (existingIndex > -1) {
templatesArray.splice(existingIndex, 1)
}
templatesArray.push(templateAttribute)
const key = `${this.connectorType}_template`;
this.attributeService.saveEntityAttributes(
{
id: this.ctx.defaultSubscription.targetDeviceId,
entityType: EntityType.DEVICE
}
, AttributeScope.SERVER_SCOPE, [{
key,
value: templatesArray
}]).subscribe(() => {
})
}
} }
); );
} }

11
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts

@ -172,6 +172,17 @@ export enum ModbusCommandTypes {
Float64 = '64float' Float64 = '64float'
} }
export const ModbusCodesTranslate = new Map<number, string>([
[1, 'gateway.rpc.read-coils'],
[2, 'gateway.rpc.read-discrete-inputs'],
[3, 'gateway.rpc.read-multiple-holding-registers'],
[4, 'gateway.rpc.read-input-registers'],
[5, 'gateway.rpc.write-single-coil'],
[6, 'gateway.rpc.write-single-holding-register'],
[15, 'gateway.rpc.write-multiple-coils'],
[16, 'gateway.rpc.write-multiple-holding-registers']
])
export enum BACnetRequestTypes { export enum BACnetRequestTypes {
WriteProperty = 'writeProperty', WriteProperty = 'writeProperty',
ReadProperty = 'readProperty' ReadProperty = 'readProperty'

752
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -203,117 +203,117 @@
"error-verification-url": "A domain name shouldn't contain symbols '/' and ':'. Example: thingsboard.io", "error-verification-url": "A domain name shouldn't contain symbols '/' and ':'. Example: thingsboard.io",
"connection-settings": "Connection settings", "connection-settings": "Connection settings",
"oauth2": { "oauth2": {
"access-token-uri": "Access token URI", "access-token-uri": "Access token URI",
"access-token-uri-required": "Access token URI is required.", "access-token-uri-required": "Access token URI is required.",
"activate-user": "Activate user", "activate-user": "Activate user",
"add-domain": "Add domain", "add-domain": "Add domain",
"delete-domain": "Delete domain", "delete-domain": "Delete domain",
"add-provider": "Add provider", "add-provider": "Add provider",
"delete-provider": "Delete provider", "delete-provider": "Delete provider",
"allow-user-creation": "Allow user creation", "allow-user-creation": "Allow user creation",
"always-fullscreen": "Always fullscreen", "always-fullscreen": "Always fullscreen",
"authorization-uri": "Authorization URI", "authorization-uri": "Authorization URI",
"authorization-uri-required": "Authorization URI is required.", "authorization-uri-required": "Authorization URI is required.",
"client-authentication-method": "Client authentication method", "client-authentication-method": "Client authentication method",
"client-id": "Client ID", "client-id": "Client ID",
"client-id-required": "Client ID is required.", "client-id-required": "Client ID is required.",
"client-id-max-length": "Client ID should be less than 256", "client-id-max-length": "Client ID should be less than 256",
"client-secret": "Client secret", "client-secret": "Client secret",
"client-secret-required": "Client secret is required.", "client-secret-required": "Client secret is required.",
"client-secret-max-length": "Client secret should be less than 2049", "client-secret-max-length": "Client secret should be less than 2049",
"custom-setting": "Custom settings", "custom-setting": "Custom settings",
"customer-name-pattern": "Customer name pattern", "customer-name-pattern": "Customer name pattern",
"customer-name-pattern-max-length": "Customer name pattern should be less than 256", "customer-name-pattern-max-length": "Customer name pattern should be less than 256",
"default-dashboard-name": "Default dashboard name", "default-dashboard-name": "Default dashboard name",
"default-dashboard-name-max-length": "Default dashboard name should be less than 256", "default-dashboard-name-max-length": "Default dashboard name should be less than 256",
"delete-domain-text": "Be careful, after the confirmation a domain and all provider data will be unavailable.", "delete-domain-text": "Be careful, after the confirmation a domain and all provider data will be unavailable.",
"delete-domain-title": "Are you sure you want to delete settings the domain '{{domainName}}'?", "delete-domain-title": "Are you sure you want to delete settings the domain '{{domainName}}'?",
"delete-registration-text": "Be careful, after the confirmation a provider data will be unavailable.", "delete-registration-text": "Be careful, after the confirmation a provider data will be unavailable.",
"delete-registration-title": "Are you sure you want to delete the provider '{{name}}'?", "delete-registration-title": "Are you sure you want to delete the provider '{{name}}'?",
"email-attribute-key": "Email attribute key", "email-attribute-key": "Email attribute key",
"email-attribute-key-required": "Email attribute key is required.", "email-attribute-key-required": "Email attribute key is required.",
"email-attribute-key-max-length": "Email attribute key should be less than 32", "email-attribute-key-max-length": "Email attribute key should be less than 32",
"first-name-attribute-key": "First name attribute key", "first-name-attribute-key": "First name attribute key",
"first-name-attribute-key-max-length": "First name attribute key should be less than 32", "first-name-attribute-key-max-length": "First name attribute key should be less than 32",
"general": "General", "general": "General",
"jwk-set-uri": "JSON Web Key URI", "jwk-set-uri": "JSON Web Key URI",
"last-name-attribute-key": "Last name attribute key", "last-name-attribute-key": "Last name attribute key",
"last-name-attribute-key-max-length": "Last name attribute key should be less than 32", "last-name-attribute-key-max-length": "Last name attribute key should be less than 32",
"login-button-icon": "Login button icon", "login-button-icon": "Login button icon",
"login-button-label": "Provider label", "login-button-label": "Provider label",
"login-button-label-placeholder": "Login with $(Provider label)", "login-button-label-placeholder": "Login with $(Provider label)",
"login-button-label-required": "Label is required.", "login-button-label-required": "Label is required.",
"login-provider": "Login provider", "login-provider": "Login provider",
"mapper": "Mapper", "mapper": "Mapper",
"new-domain": "New domain", "new-domain": "New domain",
"oauth2": "OAuth2", "oauth2": "OAuth2",
"password-max-length": "Password should be less than 256", "password-max-length": "Password should be less than 256",
"redirect-uri-template": "Redirect URI template", "redirect-uri-template": "Redirect URI template",
"copy-redirect-uri": "Copy redirect URI", "copy-redirect-uri": "Copy redirect URI",
"registration-id": "Registration ID", "registration-id": "Registration ID",
"registration-id-required": "Registration ID is required.", "registration-id-required": "Registration ID is required.",
"registration-id-unique": "Registration ID need to unique for the system.", "registration-id-unique": "Registration ID need to unique for the system.",
"scope": "Scope", "scope": "Scope",
"scope-required": "Scope is required.", "scope-required": "Scope is required.",
"tenant-name-pattern": "Tenant name pattern", "tenant-name-pattern": "Tenant name pattern",
"tenant-name-pattern-required": "Tenant name pattern is required.", "tenant-name-pattern-required": "Tenant name pattern is required.",
"tenant-name-pattern-max-length": "Tenant name pattern ishould be less than 256", "tenant-name-pattern-max-length": "Tenant name pattern ishould be less than 256",
"tenant-name-strategy": "Tenant name strategy", "tenant-name-strategy": "Tenant name strategy",
"type": "Mapper type", "type": "Mapper type",
"uri-pattern-error": "Invalid URI format.", "uri-pattern-error": "Invalid URI format.",
"url": "URL", "url": "URL",
"url-pattern": "Invalid URL format.", "url-pattern": "Invalid URL format.",
"url-required": "URL is required.", "url-required": "URL is required.",
"url-max-length": "URL should be less than 256", "url-max-length": "URL should be less than 256",
"user-info-uri": "User info URI", "user-info-uri": "User info URI",
"user-info-uri-required": "User info URI is required.", "user-info-uri-required": "User info URI is required.",
"username-max-length": "User name should be less than 256", "username-max-length": "User name should be less than 256",
"user-name-attribute-name": "User name attribute key", "user-name-attribute-name": "User name attribute key",
"user-name-attribute-name-required": "User name attribute key is required", "user-name-attribute-name-required": "User name attribute key is required",
"protocol": "Protocol", "protocol": "Protocol",
"domain-schema-http": "HTTP", "domain-schema-http": "HTTP",
"domain-schema-https": "HTTPS", "domain-schema-https": "HTTPS",
"domain-schema-mixed": "HTTP+HTTPS", "domain-schema-mixed": "HTTP+HTTPS",
"enable": "Enable OAuth2 settings", "enable": "Enable OAuth2 settings",
"domains": "Domains", "domains": "Domains",
"mobile-apps": "Mobile applications", "mobile-apps": "Mobile applications",
"no-mobile-apps": "No applications configured", "no-mobile-apps": "No applications configured",
"mobile-package": "Application package", "mobile-package": "Application package",
"mobile-package-placeholder": "Ex.: my.example.app", "mobile-package-placeholder": "Ex.: my.example.app",
"mobile-package-hint": "For Android: your own unique Application ID. For iOS: Product bundle identifier.", "mobile-package-hint": "For Android: your own unique Application ID. For iOS: Product bundle identifier.",
"mobile-package-unique": "Application package must be unique.", "mobile-package-unique": "Application package must be unique.",
"mobile-app-secret": "Application secret", "mobile-app-secret": "Application secret",
"invalid-mobile-app-secret": "Application secret must contain only alphanumeric characters and must be between 16 and 2048 characters long.", "invalid-mobile-app-secret": "Application secret must contain only alphanumeric characters and must be between 16 and 2048 characters long.",
"copy-mobile-app-secret": "Copy application secret", "copy-mobile-app-secret": "Copy application secret",
"add-mobile-app": "Add application", "add-mobile-app": "Add application",
"delete-mobile-app": "Delete application info", "delete-mobile-app": "Delete application info",
"providers": "Providers", "providers": "Providers",
"platform-web": "Web", "platform-web": "Web",
"platform-android": "Android", "platform-android": "Android",
"platform-ios": "iOS", "platform-ios": "iOS",
"all-platforms": "All platforms", "all-platforms": "All platforms",
"smtp-provider": "SMTP provider", "smtp-provider": "SMTP provider",
"allowed-platforms": "Allowed platforms", "allowed-platforms": "Allowed platforms",
"authentication": "Authentication", "authentication": "Authentication",
"basic": "Basic", "basic": "Basic",
"provider": "Provider", "provider": "Provider",
"redirect-url": "Redirect URI", "redirect-url": "Redirect URI",
"domain-name": "Domain name", "domain-name": "Domain name",
"redirect-url-template": "Redirect URI template", "redirect-url-template": "Redirect URI template",
"microsoft-tenant-id": "Directory (tenant) Id", "microsoft-tenant-id": "Directory (tenant) Id",
"microsoft-tenant-id-required": "Directory (tenant) Id is required", "microsoft-tenant-id-required": "Directory (tenant) Id is required",
"token-uri": "Token URI", "token-uri": "Token URI",
"token-uri-required": "Token URI is required", "token-uri-required": "Token URI is required",
"redirect-uri": "Redirect URI", "redirect-uri": "Redirect URI",
"google-provider": "Google", "google-provider": "Google",
"microsoft-provider": "Office 365", "microsoft-provider": "Office 365",
"sendgrid-provider": "Sendgrid", "sendgrid-provider": "Sendgrid",
"custom-provider": "Custom", "custom-provider": "Custom",
"generate-access-token": "Generate access token", "generate-access-token": "Generate access token",
"update-access-token": "Update access token", "update-access-token": "Update access token",
"access-token-status": "Access token status:", "access-token-status": "Access token status:",
"token-status-generated": "generated", "token-status-generated": "generated",
"token-status-not-generated": "not generated" "token-status-not-generated": "not generated"
}, },
"smpp-provider": { "smpp-provider": {
"smpp-version": "SMPP version", "smpp-version": "SMPP version",
@ -410,7 +410,7 @@
"no-auto-commit-entities-prompt": "No entities configured for auto-commit", "no-auto-commit-entities-prompt": "No entities configured for auto-commit",
"delete-auto-commit-settings-title": "Are you sure you want to delete auto-commit settings?", "delete-auto-commit-settings-title": "Are you sure you want to delete auto-commit settings?",
"delete-auto-commit-settings-text": "Be careful, after the confirmation the auto-commit settings will be removed and auto-commit will be disabled for all entities.", "delete-auto-commit-settings-text": "Be careful, after the confirmation the auto-commit settings will be removed and auto-commit will be disabled for all entities.",
"2fa": { "2fa": {
"2fa": "Two-factor authentication", "2fa": "Two-factor authentication",
"available-providers": "Available providers", "available-providers": "Available providers",
"issuer-name": "Issuer name", "issuer-name": "Issuer name",
@ -471,7 +471,7 @@
"slack-api-token": "Slack API token", "slack-api-token": "Slack API token",
"slack": "Slack", "slack": "Slack",
"slack-settings": "Slack settings" "slack-settings": "Slack settings"
}, },
"alarm": { "alarm": {
"alarm": "Alarm", "alarm": "Alarm",
"alarms": "Alarms", "alarms": "Alarms",
@ -582,7 +582,7 @@
"oldest-first": "Oldest first", "oldest-first": "Oldest first",
"newest-first": "Newest first", "newest-first": "Newest first",
"activity": "Activity", "activity": "Activity",
"export": "Export to CSV", "export": "Export to CSV",
"author": "Author", "author": "Author",
"created-date": "Created date", "created-date": "Created date",
"edited-date": "Edited date", "edited-date": "Edited date",
@ -683,7 +683,7 @@
"assign-assets": "Assign assets", "assign-assets": "Assign assets",
"assign-assets-text": "Assign { count, plural, =1 {1 asset} other {# assets} } to customer", "assign-assets-text": "Assign { count, plural, =1 {1 asset} other {# assets} } to customer",
"assign-asset-to-edge-title": "Assign Asset(s) To Edge", "assign-asset-to-edge-title": "Assign Asset(s) To Edge",
"assign-asset-to-edge-text":"Please select the assets to assign to the edge", "assign-asset-to-edge-text": "Please select the assets to assign to the edge",
"delete-assets": "Delete assets", "delete-assets": "Delete assets",
"unassign-assets": "Unassign assets", "unassign-assets": "Unassign assets",
"unassign-assets-action-title": "Unassign { count, plural, =1 {1 asset} other {# assets} } from customer", "unassign-assets-action-title": "Unassign { count, plural, =1 {1 asset} other {# assets} } from customer",
@ -1304,7 +1304,7 @@
"assign-device-to-customer": "Assign Device(s) To Customer", "assign-device-to-customer": "Assign Device(s) To Customer",
"assign-device-to-customer-text": "Please select the devices to assign to the customer", "assign-device-to-customer-text": "Please select the devices to assign to the customer",
"assign-device-to-edge-title": "Assign Device(s) To Edge", "assign-device-to-edge-title": "Assign Device(s) To Edge",
"assign-device-to-edge-text":"Please select the devices to assign to the edge", "assign-device-to-edge-text": "Please select the devices to assign to the edge",
"make-public": "Make device public", "make-public": "Make device public",
"make-private": "Make device private", "make-private": "Make device private",
"no-devices-text": "No devices found", "no-devices-text": "No devices found",
@ -1357,34 +1357,34 @@
"generate-password": "Generate Password", "generate-password": "Generate Password",
"generate-access-token": "Generate Access Token", "generate-access-token": "Generate Access Token",
"lwm2m-security-config": { "lwm2m-security-config": {
"identity": "Client Identity", "identity": "Client Identity",
"identity-required": "Client Identity is required.", "identity-required": "Client Identity is required.",
"identity-tooltip": "The PSK identifier is an arbitrary PSK identifier up to 128 bytes, as described in the standard [RFC7925].\nThe PSK identifier MUST first be converted to a character string and then encoded into octets using UTF-8.", "identity-tooltip": "The PSK identifier is an arbitrary PSK identifier up to 128 bytes, as described in the standard [RFC7925].\nThe PSK identifier MUST first be converted to a character string and then encoded into octets using UTF-8.",
"client-key": "Client Key", "client-key": "Client Key",
"client-key-required": "Client Key is required.", "client-key-required": "Client Key is required.",
"client-key-tooltip-prk": "RPK public key or id must be in the standard [RFC7250] and encoded to Base64 format!", "client-key-tooltip-prk": "RPK public key or id must be in the standard [RFC7250] and encoded to Base64 format!",
"client-key-tooltip-psk": "PSK key must be in the standard [RFC4279] and HexDec format: 32, 64, 128 characters!", "client-key-tooltip-psk": "PSK key must be in the standard [RFC4279] and HexDec format: 32, 64, 128 characters!",
"endpoint": "Endpoint Client Name", "endpoint": "Endpoint Client Name",
"endpoint-required": "Endpoint Client Name is required.", "endpoint-required": "Endpoint Client Name is required.",
"client-public-key": "Client public key", "client-public-key": "Client public key",
"client-public-key-hint": "If client public key is empty, the trusted certificate will be used", "client-public-key-hint": "If client public key is empty, the trusted certificate will be used",
"client-public-key-tooltip": "X509 public key must be in DER-encoded X509v3 format and support exclusively EC algorithm and then encoded to Base64 format!", "client-public-key-tooltip": "X509 public key must be in DER-encoded X509v3 format and support exclusively EC algorithm and then encoded to Base64 format!",
"mode": "Security config mode", "mode": "Security config mode",
"client-tab": "Client Security Config", "client-tab": "Client Security Config",
"client-certificate": "Client certificate", "client-certificate": "Client certificate",
"bootstrap-tab": "Bootstrap Client", "bootstrap-tab": "Bootstrap Client",
"bootstrap-server": "Bootstrap Server", "bootstrap-server": "Bootstrap Server",
"lwm2m-server": "LwM2M Server", "lwm2m-server": "LwM2M Server",
"client-publicKey-or-id": "Client Public Key or Id", "client-publicKey-or-id": "Client Public Key or Id",
"client-publicKey-or-id-required": "Client Public Key or Id is required.", "client-publicKey-or-id-required": "Client Public Key or Id is required.",
"client-publicKey-or-id-tooltip-psk": "The PSK identifier is an arbitrary PSK identifier up to 128 bytes, as described in the standard [RFC7925].\nThe PSK identifier MUST first be converted to a character string and then encoded into octets using UTF-8.", "client-publicKey-or-id-tooltip-psk": "The PSK identifier is an arbitrary PSK identifier up to 128 bytes, as described in the standard [RFC7925].\nThe PSK identifier MUST first be converted to a character string and then encoded into octets using UTF-8.",
"client-publicKey-or-id-tooltip-rpk": "RPK public key or id must be in the standard [RFC7250] and encoded to Base64 format!", "client-publicKey-or-id-tooltip-rpk": "RPK public key or id must be in the standard [RFC7250] and encoded to Base64 format!",
"client-publicKey-or-id-tooltip-x509": "X509 public key must be in DER-encoded X509v3 format and support exclusively EC algorithm and then encoded to Base64 format", "client-publicKey-or-id-tooltip-x509": "X509 public key must be in DER-encoded X509v3 format and support exclusively EC algorithm and then encoded to Base64 format",
"client-secret-key": "Client Secret Key", "client-secret-key": "Client Secret Key",
"client-secret-key-required": "Client Secret Key is required.", "client-secret-key-required": "Client Secret Key is required.",
"client-secret-key-tooltip-psk": "PSK key must be in the standard [RFC4279] and HexDec format: 32, 64, 128 characters!", "client-secret-key-tooltip-psk": "PSK key must be in the standard [RFC4279] and HexDec format: 32, 64, 128 characters!",
"client-secret-key-tooltip-prk": "RPK secret key must be in PKCS_8 format (DER encoding, standard [RFC5958]) and then encoded to Base64 format!", "client-secret-key-tooltip-prk": "RPK secret key must be in PKCS_8 format (DER encoding, standard [RFC5958]) and then encoded to Base64 format!",
"client-secret-key-tooltip-x509": "X509 secret key must be in PKCS_8 format (DER encoding, standard [RFC5958]) and then encoded to Base64 format!" "client-secret-key-tooltip-x509": "X509 secret key must be in PKCS_8 format (DER encoding, standard [RFC5958]) and then encoded to Base64 format!"
}, },
"client-id": "Client ID", "client-id": "Client ID",
"client-id-pattern": "Contains invalid character.", "client-id-pattern": "Contains invalid character.",
@ -1704,13 +1704,13 @@
"schedule-specific-time": "Active at a specific time", "schedule-specific-time": "Active at a specific time",
"schedule-custom": "Custom", "schedule-custom": "Custom",
"schedule-day": { "schedule-day": {
"monday": "Monday", "monday": "Monday",
"tuesday": "Tuesday", "tuesday": "Tuesday",
"wednesday": "Wednesday", "wednesday": "Wednesday",
"thursday": "Thursday", "thursday": "Thursday",
"friday": "Friday", "friday": "Friday",
"saturday": "Saturday", "saturday": "Saturday",
"sunday": "Sunday" "sunday": "Sunday"
}, },
"schedule-days": "Days", "schedule-days": "Days",
"schedule-time": "Time", "schedule-time": "Time",
@ -2336,7 +2336,7 @@
"make-private-entity-view-title": "Are you sure you want to make the entity view '{{entityViewName}}' private?", "make-private-entity-view-title": "Are you sure you want to make the entity view '{{entityViewName}}' private?",
"make-private-entity-view-text": "After the confirmation the entity view and all its data will be made private and won't be accessible by others.", "make-private-entity-view-text": "After the confirmation the entity view and all its data will be made private and won't be accessible by others.",
"assign-entity-view-to-edge": "Assign Entity View(s) To Edge", "assign-entity-view-to-edge": "Assign Entity View(s) To Edge",
"assign-entity-view-to-edge-text":"Please select the entity views to assign to the edge", "assign-entity-view-to-edge-text": "Please select the entity views to assign to the edge",
"unassign-entity-view-from-edge-title": "Are you sure you want to unassign the entity view '{{entityViewName}}'?", "unassign-entity-view-from-edge-title": "Are you sure you want to unassign the entity view '{{entityViewName}}'?",
"unassign-entity-view-from-edge-text": "After the confirmation the entity view will be unassigned and won't be accessible by the edge.", "unassign-entity-view-from-edge-text": "After the confirmation the entity view will be unassigned and won't be accessible by the edge.",
"unassign-entity-views-from-edge-action-title": "Unassign { count, plural, =1 {1 entity view} other {# entity views} } from edge", "unassign-entity-views-from-edge-action-title": "Unassign { count, plural, =1 {1 entity view} other {# entity views} } from edge",
@ -2550,105 +2550,105 @@
"invalid-file-error": "Invalid extension file" "invalid-file-error": "Invalid extension file"
}, },
"feature": { "feature": {
"advanced-features": "Advanced features" "advanced-features": "Advanced features"
}, },
"filter": { "filter": {
"add": "Add filter", "add": "Add filter",
"edit": "Edit filter", "edit": "Edit filter",
"name": "Filter name", "name": "Filter name",
"name-required": "Filter name is required.", "name-required": "Filter name is required.",
"duplicate-filter": "Filter with same name is already exists.", "duplicate-filter": "Filter with same name is already exists.",
"filters": "Filters", "filters": "Filters",
"unable-delete-filter-title": "Unable to delete filter", "unable-delete-filter-title": "Unable to delete filter",
"unable-delete-filter-text": "Filter '{{filter}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}", "unable-delete-filter-text": "Filter '{{filter}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
"duplicate-filter-error": "Duplicate filter found '{{filter}}'.<br>Filters must be unique within the dashboard.", "duplicate-filter-error": "Duplicate filter found '{{filter}}'.<br>Filters must be unique within the dashboard.",
"missing-key-filters-error": "Key filters is missing for filter '{{filter}}'.", "missing-key-filters-error": "Key filters is missing for filter '{{filter}}'.",
"filter": "Filter", "filter": "Filter",
"editable": "Editable", "editable": "Editable",
"no-filters-found": "No filters found.", "no-filters-found": "No filters found.",
"no-filter-text": "No filter specified", "no-filter-text": "No filter specified",
"add-filter-prompt": "Please add filter", "add-filter-prompt": "Please add filter",
"no-filter-matching": "'{{filter}}' not found.", "no-filter-matching": "'{{filter}}' not found.",
"create-new-filter": "Create a new one!", "create-new-filter": "Create a new one!",
"create-new": "Create new", "create-new": "Create new",
"filter-required": "Filter is required.", "filter-required": "Filter is required.",
"operation": { "operation": {
"operation": "Operation", "operation": "Operation",
"equal": "equal", "equal": "equal",
"not-equal": "not equal", "not-equal": "not equal",
"starts-with": "starts with", "starts-with": "starts with",
"ends-with": "ends with", "ends-with": "ends with",
"contains": "contains", "contains": "contains",
"not-contains": "not contains", "not-contains": "not contains",
"greater": "greater than", "greater": "greater than",
"less": "less than", "less": "less than",
"greater-or-equal": "greater or equal", "greater-or-equal": "greater or equal",
"less-or-equal": "less or equal", "less-or-equal": "less or equal",
"and": "and", "and": "and",
"or": "or", "or": "or",
"in": "in", "in": "in",
"not-in": "not in" "not-in": "not in"
}, },
"ignore-case": "ignore case", "ignore-case": "ignore case",
"value": "Value", "value": "Value",
"remove-filter": "Remove filter", "remove-filter": "Remove filter",
"duplicate-filter-action": "Duplicate filter", "duplicate-filter-action": "Duplicate filter",
"preview": "Filter preview", "preview": "Filter preview",
"no-filters": "No filters configured", "no-filters": "No filters configured",
"add-filter": "Add filter", "add-filter": "Add filter",
"add-complex-filter": "Add complex filter", "add-complex-filter": "Add complex filter",
"add-complex": "Add complex", "add-complex": "Add complex",
"complex-filter": "Complex filter", "complex-filter": "Complex filter",
"edit-complex-filter": "Edit complex filter", "edit-complex-filter": "Edit complex filter",
"edit-filter-user-params": "Edit filter predicate user parameters", "edit-filter-user-params": "Edit filter predicate user parameters",
"filter-user-params": "Filter predicate user parameters", "filter-user-params": "Filter predicate user parameters",
"user-parameters": "User parameters", "user-parameters": "User parameters",
"display-label": "Label to display", "display-label": "Label to display",
"autogenerated-label": "Auto generate label", "autogenerated-label": "Auto generate label",
"order-priority": "Field order priority", "order-priority": "Field order priority",
"key-filter": "Key filter", "key-filter": "Key filter",
"key-filters": "Key filters", "key-filters": "Key filters",
"key-name": "Key name", "key-name": "Key name",
"key-name-required": "Key name is required.", "key-name-required": "Key name is required.",
"key-type": { "key-type": {
"key-type": "Key type", "key-type": "Key type",
"attribute": "Attribute", "attribute": "Attribute",
"timeseries": "Timeseries", "timeseries": "Timeseries",
"entity-field": "Entity field", "entity-field": "Entity field",
"constant": "Constant", "constant": "Constant",
"client-attribute": "Client attribute", "client-attribute": "Client attribute",
"server-attribute": "Server attribute", "server-attribute": "Server attribute",
"shared-attribute": "Shared attribute" "shared-attribute": "Shared attribute"
}, },
"value-type": { "value-type": {
"value-type": "Value type", "value-type": "Value type",
"string": "String", "string": "String",
"numeric": "Numeric", "numeric": "Numeric",
"boolean": "Boolean", "boolean": "Boolean",
"date-time": "Datetime" "date-time": "Datetime"
}, },
"value-type-required": "Key value type is required.", "value-type-required": "Key value type is required.",
"key-value-type-change-title": "Are you sure you want to change key value type?", "key-value-type-change-title": "Are you sure you want to change key value type?",
"key-value-type-change-message": "If you confirm new value type all entered key filters will be removed.", "key-value-type-change-message": "If you confirm new value type all entered key filters will be removed.",
"no-key-filters": "No key filters configured", "no-key-filters": "No key filters configured",
"add-key-filter": "Add key filter", "add-key-filter": "Add key filter",
"remove-key-filter": "Remove key filter", "remove-key-filter": "Remove key filter",
"edit-key-filter": "Edit key filter", "edit-key-filter": "Edit key filter",
"date": "Date", "date": "Date",
"time": "Time", "time": "Time",
"current-tenant": "Current tenant", "current-tenant": "Current tenant",
"current-customer": "Current customer", "current-customer": "Current customer",
"current-user": "Current user", "current-user": "Current user",
"current-device": "Current device", "current-device": "Current device",
"default-value": "Default value", "default-value": "Default value",
"dynamic-source-type": "Dynamic source type", "dynamic-source-type": "Dynamic source type",
"dynamic-value": "Dynamic value", "dynamic-value": "Dynamic value",
"no-dynamic-value": "No dynamic value", "no-dynamic-value": "No dynamic value",
"source-attribute": "Source attribute", "source-attribute": "Source attribute",
"switch-to-dynamic-value": "Switch to dynamic value", "switch-to-dynamic-value": "Switch to dynamic value",
"switch-to-default-value": "Switch to default value", "switch-to-default-value": "Switch to default value",
"inherit-owner": "Inherit from owner", "inherit-owner": "Inherit from owner",
"source-attribute-not-set": "If source attribute isn't set" "source-attribute-not-set": "If source attribute isn't set"
}, },
"fullscreen": { "fullscreen": {
"expand": "Expand to fullscreen", "expand": "Expand to fullscreen",
@ -2814,7 +2814,7 @@
"remove": "Remove", "remove": "Remove",
"requestFilter": "Request Filter", "requestFilter": "Request Filter",
"requestUrlExpression": "Request URL Expression", "requestUrlExpression": "Request URL Expression",
"HTTPMethod": "HTTP Method", "httpMethod": "HTTP Method",
"timeout": "Timeout", "timeout": "Timeout",
"tries": "Tries", "tries": "Tries",
"httpHeaders": "HTTP Headers", "httpHeaders": "HTTP Headers",
@ -2847,9 +2847,17 @@
"save-template": "Save template", "save-template": "Save template",
"template-name": "Template name", "template-name": "Template name",
"template-name-required": "Template name is required.", "template-name-required": "Template name is required.",
"template-name-duplicate": "The name is already used." "template-name-duplicate": "Template with such name already exists, it will be updated.",
"command": "Command",
"params": "Params",
"read-coils": "01: Read Coils",
"read-discrete-inputs": "02: Read Discrete Inputs",
"read-multiple-holding-registers": "03: Read Multiple Holding Registers",
"read-input-registers": "04: Read Input Registers",
"write-single-coil": "05: Write Single Coil",
"write-single-holding-register": "06: Write Single Holding Register",
"write-multiple-coils": "15: Write Multiple Coils",
"write-multiple-holding-registers": "16: Write Multiple Holding Registers"
}, },
"other": "Other", "other": "Other",
"save-tip": "Save configuration file", "save-tip": "Save configuration file",
@ -3057,22 +3065,22 @@
"access-token": "Access token", "access-token": "Access token",
"x509": "X.509", "x509": "X.509",
"mqtt": { "mqtt": {
"client-id": "MQTT client ID", "client-id": "MQTT client ID",
"user-name": "MQTT user name", "user-name": "MQTT user name",
"password": "MQTT password" "password": "MQTT password"
}, },
"lwm2m": { "lwm2m": {
"client-endpoint": "LwM2M endpoint client name", "client-endpoint": "LwM2M endpoint client name",
"security-config-mode": "LwM2M security config mode", "security-config-mode": "LwM2M security config mode",
"client-identity": "LwM2M client identity", "client-identity": "LwM2M client identity",
"client-key": "LwM2M client key", "client-key": "LwM2M client key",
"client-cert": "LwM2M client public key", "client-cert": "LwM2M client public key",
"bootstrap-server-security-mode": "LwM2M bootstrap server security mode", "bootstrap-server-security-mode": "LwM2M bootstrap server security mode",
"bootstrap-server-secret-key": "LwM2M bootstrap server secret key", "bootstrap-server-secret-key": "LwM2M bootstrap server secret key",
"bootstrap-server-public-key-id": "LwM2M bootstrap server public key or id", "bootstrap-server-public-key-id": "LwM2M bootstrap server public key or id",
"lwm2m-server-security-mode": "LwM2M server security mode", "lwm2m-server-security-mode": "LwM2M server security mode",
"lwm2m-server-secret-key": "LwM2M server secret key", "lwm2m-server-secret-key": "LwM2M server secret key",
"lwm2m-server-public-key-id": "LwM2M server public key or id" "lwm2m-server-public-key-id": "LwM2M server public key or id"
}, },
"snmp": { "snmp": {
"host": "SNMP host", "host": "SNMP host",
@ -3086,7 +3094,7 @@
"routing-key": "Edge key", "routing-key": "Edge key",
"secret": "Edge secret" "secret": "Edge secret"
}, },
"stepper-text":{ "stepper-text": {
"select-file": "Select a file", "select-file": "Select a file",
"configuration": "Import configuration", "configuration": "Import configuration",
"column-type": "Select columns type", "column-type": "Select columns type",
@ -3477,69 +3485,69 @@
} }
}, },
"ota-update": { "ota-update": {
"add": "Add package", "add": "Add package",
"assign-firmware": "Assigned firmware", "assign-firmware": "Assigned firmware",
"assign-firmware-required": "Assigned firmware is required", "assign-firmware-required": "Assigned firmware is required",
"assign-software": "Assigned software", "assign-software": "Assigned software",
"assign-software-required": "Assigned software is required", "assign-software-required": "Assigned software is required",
"auto-generate-checksum": "Auto-generate checksum", "auto-generate-checksum": "Auto-generate checksum",
"checksum": "Checksum", "checksum": "Checksum",
"checksum-hint": "If checksum is empty, it will be generated automatically", "checksum-hint": "If checksum is empty, it will be generated automatically",
"checksum-algorithm": "Checksum algorithm", "checksum-algorithm": "Checksum algorithm",
"checksum-copied-message": "Package checksum has been copied to clipboard", "checksum-copied-message": "Package checksum has been copied to clipboard",
"change-firmware": "Change of the firmware may cause update of { count, plural, =1 {1 device} other {# devices} }.", "change-firmware": "Change of the firmware may cause update of { count, plural, =1 {1 device} other {# devices} }.",
"change-software": "Change of the software may cause update of { count, plural, =1 {1 device} other {# devices} }.", "change-software": "Change of the software may cause update of { count, plural, =1 {1 device} other {# devices} }.",
"chose-compatible-device-profile": "The uploaded package will be available only for devices with the chosen profile.", "chose-compatible-device-profile": "The uploaded package will be available only for devices with the chosen profile.",
"chose-firmware-distributed-device": "Choose firmware that will be distributed to the devices", "chose-firmware-distributed-device": "Choose firmware that will be distributed to the devices",
"chose-software-distributed-device": "Choose software that will be distributed to the devices", "chose-software-distributed-device": "Choose software that will be distributed to the devices",
"content-type": "Content type", "content-type": "Content type",
"copy-checksum": "Copy checksum", "copy-checksum": "Copy checksum",
"copy-direct-url": "Copy direct URL", "copy-direct-url": "Copy direct URL",
"copyId": "Copy package Id", "copyId": "Copy package Id",
"copied": "Copied!", "copied": "Copied!",
"delete": "Delete package", "delete": "Delete package",
"delete-ota-update-text": "Be careful, after the confirmation the OTA update will become unrecoverable.", "delete-ota-update-text": "Be careful, after the confirmation the OTA update will become unrecoverable.",
"delete-ota-update-title": "Are you sure you want to delete the OTA update '{{title}}'?", "delete-ota-update-title": "Are you sure you want to delete the OTA update '{{title}}'?",
"delete-ota-updates-text": "Be careful, after the confirmation all selected OTA updates will be removed.", "delete-ota-updates-text": "Be careful, after the confirmation all selected OTA updates will be removed.",
"delete-ota-updates-title": "Are you sure you want to delete { count, plural, =1 {1 OTA update} other {# OTA updates} }?", "delete-ota-updates-title": "Are you sure you want to delete { count, plural, =1 {1 OTA update} other {# OTA updates} }?",
"description": "Description", "description": "Description",
"direct-url": "Direct URL", "direct-url": "Direct URL",
"direct-url-copied-message": "Package direct URL has been copied to clipboard", "direct-url-copied-message": "Package direct URL has been copied to clipboard",
"direct-url-required": "Direct URL is required", "direct-url-required": "Direct URL is required",
"download": "Download package", "download": "Download package",
"drop-file": "Drop a package file or click to select a file to upload.", "drop-file": "Drop a package file or click to select a file to upload.",
"drop-package-file-or": "Drag and drop a package file or", "drop-package-file-or": "Drag and drop a package file or",
"file-name": "File name", "file-name": "File name",
"file-size": "File size", "file-size": "File size",
"file-size-bytes": "File size in bytes", "file-size-bytes": "File size in bytes",
"idCopiedMessage": "Package Id has been copied to clipboard", "idCopiedMessage": "Package Id has been copied to clipboard",
"no-firmware-matching": "No compatible Firmware OTA Update packages matching '{{entity}}' were found.", "no-firmware-matching": "No compatible Firmware OTA Update packages matching '{{entity}}' were found.",
"no-firmware-text": "No compatible Firmware OTA Update packages provisioned.", "no-firmware-text": "No compatible Firmware OTA Update packages provisioned.",
"no-packages-text": "No packages found", "no-packages-text": "No packages found",
"no-software-matching": "No compatible Software OTA Update packages matching '{{entity}}' were found.", "no-software-matching": "No compatible Software OTA Update packages matching '{{entity}}' were found.",
"no-software-text": "No compatible Software OTA Update packages provisioned.", "no-software-text": "No compatible Software OTA Update packages provisioned.",
"ota-update": "OTA update", "ota-update": "OTA update",
"ota-update-details": "OTA update details", "ota-update-details": "OTA update details",
"ota-updates": "OTA updates", "ota-updates": "OTA updates",
"package-type": "Package type", "package-type": "Package type",
"packages-repository": "Packages repository", "packages-repository": "Packages repository",
"search": "Search packages", "search": "Search packages",
"selected-package": "{ count, plural, =1 {1 package} other {# packages} } selected", "selected-package": "{ count, plural, =1 {1 package} other {# packages} } selected",
"title": "Title", "title": "Title",
"title-required": "Title is required.", "title-required": "Title is required.",
"title-max-length": "Title should be less than 256", "title-max-length": "Title should be less than 256",
"types": { "types": {
"firmware": "Firmware", "firmware": "Firmware",
"software": "Software" "software": "Software"
}, },
"upload-binary-file": "Upload binary file", "upload-binary-file": "Upload binary file",
"use-external-url": "Use external URL", "use-external-url": "Use external URL",
"version": "Version", "version": "Version",
"version-required": "Version is required.", "version-required": "Version is required.",
"version-tag": "Version tag", "version-tag": "Version tag",
"version-tag-hint": "Custom tag should match the package version reported by your device.", "version-tag-hint": "Custom tag should match the package version reported by your device.",
"version-max-length": "Version should be less than 256", "version-max-length": "Version should be less than 256",
"warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type." "warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type."
}, },
"position": { "position": {
"top": "Top", "top": "Top",
@ -3860,11 +3868,11 @@
"test-with-this-message": "{{test}} with this message" "test-with-this-message": "{{test}} with this message"
}, },
"timezone": { "timezone": {
"timezone": "Timezone", "timezone": "Timezone",
"select-timezone": "Select timezone", "select-timezone": "Select timezone",
"no-timezones-matching": "No timezones matching '{{timezone}}' were found.", "no-timezones-matching": "No timezones matching '{{timezone}}' were found.",
"timezone-required": "Timezone is required.", "timezone-required": "Timezone is required.",
"browser-time": "Browser Time" "browser-time": "Browser Time"
}, },
"queue": { "queue": {
"queue-name": "Queue", "queue-name": "Queue",
@ -3903,7 +3911,7 @@
"delete-queue-text": "Be careful, after the confirmation the queue and all related data will become unrecoverable.", "delete-queue-text": "Be careful, after the confirmation the queue and all related data will become unrecoverable.",
"delete-queues-text": "After the confirmation all selected queues will be deleted and won't be accessible.", "delete-queues-text": "After the confirmation all selected queues will be deleted and won't be accessible.",
"search": "Search queue", "search": "Search queue",
"add" : "Add queue", "add": "Add queue",
"details": "Queue details", "details": "Queue details",
"topic": "Topic", "topic": "Topic",
"submit-settings": "Submit settings", "submit-settings": "Submit settings",
@ -4198,30 +4206,30 @@
"seconds": "Seconds", "seconds": "Seconds",
"advanced": "Advanced", "advanced": "Advanced",
"predefined": { "predefined": {
"yesterday": "Yesterday", "yesterday": "Yesterday",
"day-before-yesterday": "Day before yesterday", "day-before-yesterday": "Day before yesterday",
"this-day-last-week": "This day last week", "this-day-last-week": "This day last week",
"previous-week": "Previous week (Sun - Sat)", "previous-week": "Previous week (Sun - Sat)",
"previous-week-iso": "Previous week (Mon - Sun)", "previous-week-iso": "Previous week (Mon - Sun)",
"previous-month": "Previous month", "previous-month": "Previous month",
"previous-quarter": "Previous quarter", "previous-quarter": "Previous quarter",
"previous-half-year": "Previous half year", "previous-half-year": "Previous half year",
"previous-year": "Previous year", "previous-year": "Previous year",
"current-hour": "Current hour", "current-hour": "Current hour",
"current-day": "Current day", "current-day": "Current day",
"current-day-so-far": "Current day so far", "current-day-so-far": "Current day so far",
"current-week": "Current week (Sun - Sat)", "current-week": "Current week (Sun - Sat)",
"current-week-iso": "Current week (Mon - Sun)", "current-week-iso": "Current week (Mon - Sun)",
"current-week-so-far": "Current week so far (Sun - Sat)", "current-week-so-far": "Current week so far (Sun - Sat)",
"current-week-iso-so-far": "Current week so far (Mon - Sun)", "current-week-iso-so-far": "Current week so far (Mon - Sun)",
"current-month": "Current month", "current-month": "Current month",
"current-month-so-far": "Current month so far", "current-month-so-far": "Current month so far",
"current-quarter": "Current quarter", "current-quarter": "Current quarter",
"current-quarter-so-far": "Current quarter so far", "current-quarter-so-far": "Current quarter so far",
"current-half-year": "Current half year", "current-half-year": "Current half year",
"current-half-year-so-far": "Current half year so far", "current-half-year-so-far": "Current half year so far",
"current-year": "Current year", "current-year": "Current year",
"current-year-so-far": "Current year so far" "current-year-so-far": "Current year so far"
} }
}, },
"timeunit": { "timeunit": {
@ -4990,16 +4998,16 @@
"popover-style": "Popover style", "popover-style": "Popover style",
"open-new-browser-tab": "Open in a new browser tab", "open-new-browser-tab": "Open in a new browser tab",
"mobile": { "mobile": {
"action-type": "Mobile action type", "action-type": "Mobile action type",
"action-type-required": "Mobile action type is required", "action-type-required": "Mobile action type is required",
"take-picture-from-gallery": "Take picture from gallery", "take-picture-from-gallery": "Take picture from gallery",
"take-photo": "Take photo", "take-photo": "Take photo",
"map-direction": "Open map directions", "map-direction": "Open map directions",
"map-location": "Open map location", "map-location": "Open map location",
"scan-qr-code": "Scan QR Code", "scan-qr-code": "Scan QR Code",
"make-phone-call": "Make phone call", "make-phone-call": "Make phone call",
"get-location": "Get phone location", "get-location": "Get phone location",
"take-screenshot": "Take screenshot" "take-screenshot": "Take screenshot"
} }
}, },
"widgets-bundle": { "widgets-bundle": {
@ -6677,7 +6685,7 @@
"card-click": "On card click" "card-click": "On card click"
} }
}, },
"paginator" : { "paginator": {
"items-per-page": "Items per page:", "items-per-page": "Items per page:",
"first-page-label": "First page", "first-page-label": "First page",
"last-page-label": "Last page", "last-page-label": "Last page",

Loading…
Cancel
Save