Browse Source

UI: Refactoring gateway connectors configuration

pull/11101/head
Vladyslav_Prykhodko 2 years ago
parent
commit
5813ce515d
  1. 120
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.html
  2. 16
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts
  3. 80
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/general-config/general-config.component.html
  4. 52
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/general-config/general-config.component.ts
  5. 48
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.ts
  6. 25
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts
  7. 15
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts
  8. 1
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/public-api.ts
  9. 9
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component.ts
  10. 4
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/server-config/server-config.component.html
  11. 18
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/server-config/server-config.component.ts
  12. 5
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component.ts
  13. 86
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html
  14. 53
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts
  15. 83
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
  16. 2
      ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts

120
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.html

@ -15,72 +15,72 @@
limitations under the License.
-->
<div class="tb-form-panel no-border no-padding padding-top" [formGroup]="brokerConfigFormGroup">
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width tb-required" translate>gateway.host</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="host" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="('gateway.host-required') | translate"
*ngIf="brokerConfigFormGroup.get('host').hasError('required')
<div class="tb-form-panel no-border no-padding padding-top" [formGroup]="brokerConfigFormGroup">
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width tb-required" translate>gateway.host</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="host" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="('gateway.host-required') | translate"
*ngIf="brokerConfigFormGroup.get('host').hasError('required')
&& brokerConfigFormGroup.get('host').touched"
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width tb-required" translate>gateway.port</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" min="{{portLimits.MIN}}" max="{{portLimits.MAX}}"
name="value" formControlName="port" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="portErrorTooltip"
*ngIf="(brokerConfigFormGroup.get('port').hasError('required') ||
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width tb-required" translate>gateway.port</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" min="{{portLimits.MIN}}" max="{{portLimits.MAX}}"
name="value" formControlName="port" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="portErrorTooltip"
*ngIf="(brokerConfigFormGroup.get('port').hasError('required') ||
brokerConfigFormGroup.get('port').hasError('min') ||
brokerConfigFormGroup.get('port').hasError('max')) &&
brokerConfigFormGroup.get('port').touched"
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.mqtt-version</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="version">
<mat-option *ngFor="let version of mqttVersions" [value]="version.value">{{ version.name }}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.mqtt-version</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="version">
<mat-option *ngFor="let version of mqttVersions" [value]="version.value">{{ version.name }}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.client-id</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="clientId" placeholder="{{ 'gateway.set' | translate }}"/>
<button type="button"
matSuffix
mat-icon-button
aria-label="Generate"
matTooltip="{{ 'gateway.generate-client-id' | translate }}"
matTooltipPosition="above"
(click)="generate('clientId')"
*ngIf="!brokerConfigFormGroup.get('clientId').value">
<mat-icon>autorenew</mat-icon>
</button>
</mat-form-field>
</div>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.client-id</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="clientId" placeholder="{{ 'gateway.set' | translate }}"/>
<button type="button"
matSuffix
mat-icon-button
aria-label="Generate"
matTooltip="{{ 'gateway.generate-client-id' | translate }}"
matTooltipPosition="above"
(click)="generate('clientId')"
*ngIf="!brokerConfigFormGroup.get('clientId').value">
<mat-icon>autorenew</mat-icon>
</button>
</mat-form-field>
</div>
<tb-security-config formControlName="security">
</tb-security-config>
</div>
<tb-security-config formControlName="security">
</tb-security-config>
</div>

16
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts

@ -14,13 +14,7 @@
/// limitations under the License.
///
import {
ChangeDetectionStrategy,
Component,
forwardRef,
inject,
OnDestroy,
} from '@angular/core';
import { ChangeDetectionStrategy, Component, forwardRef, OnDestroy } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
@ -72,13 +66,13 @@ export class BrokerConfigControlComponent implements ControlValueAccessor, Valid
mqttVersions = MqttVersions;
portLimits = PortLimits;
onChange!: (value: string) => void;
onTouched!: () => void;
private onChange: (value: string) => void;
private onTouched: () => void;
private translate = inject(TranslateService);
private destroy$ = new Subject<void>();
constructor(private fb: FormBuilder) {
constructor(private fb: FormBuilder,
private translate: TranslateService) {
this.brokerConfigFormGroup = this.fb.group({
name: ['', []],
host: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],

80
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/general-config/general-config.component.html

@ -1,80 +0,0 @@
<!--
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.
-->
<div class="tb-form-panel no-border no-padding padding-top" [formGroup]="parentFormGroup">
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width tb-required" translate>gateway.name</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput autocomplete="off" name="value" formControlName="name" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="(parentFormGroup.get('name').hasError('duplicateName') ?
'gateway.connector-duplicate-name' : 'gateway.name-required') | translate"
*ngIf="(parentFormGroup.get('name').hasError('required') && parentFormGroup.get('name').touched) ||
parentFormGroup.get('name').hasError('duplicateName')"
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
</div>
<div *ngIf="parentFormGroup.get('type').value === connectorType.CUSTOM" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.connectors-table-class</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="class" placeholder="{{ 'gateway.set' | translate }}"/>
</mat-form-field>
</div>
</div>
<div *ngIf="parentFormGroup.get('type').value === connectorType.GRPC" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.connectors-table-key</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="key" placeholder="{{ 'gateway.set' | translate }}"/>
</mat-form-field>
</div>
</div>
<div class="tb-form-panel stroked">
<div class="tb-form-panel-title" translate>gateway.logs-configuration</div>
<div class="tb-form-row" fxLayoutAlign="space-between center">
<mat-slide-toggle class="mat-slide" formControlName="enableRemoteLogging">
<mat-label>
{{ 'gateway.enable-remote-logging' | translate }}
</mat-label>
</mat-slide-toggle>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.remote-logging-level</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="logLevel">
<mat-option *ngFor="let logLevel of gatewayLogLevel" [value]="logLevel">{{ logLevel }}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="parentFormGroup.get('type').value === connectorType.MQTT" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<mat-slide-toggle class="mat-slide" formControlName="sendDataOnlyOnChange">
<mat-label tb-hint-tooltip-icon="{{ 'gateway.send-change-data-hint' | translate }}">
{{ 'gateway.send-change-data' | translate }}
</mat-label>
</mat-slide-toggle>
</div>
</div>

52
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/general-config/general-config.component.ts

@ -1,52 +0,0 @@
///
/// 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,
inject,
} from '@angular/core';
import {
ControlContainer,
FormGroup,
} from '@angular/forms';
import {
ConnectorType,
GatewayLogLevel,
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { SharedModule } from '@shared/shared.module';
import { CommonModule } from '@angular/common';
@Component({
selector: 'tb-general-config',
templateUrl: './general-config.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
SharedModule,
],
})
export class GeneralConfigComponent {
gatewayLogLevel = Object.values(GatewayLogLevel);
connectorType = ConnectorType;
get parentFormGroup(): FormGroup {
return this.parentContainer.control as FormGroup;
}
private parentContainer = inject(ControlContainer);
}

48
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.ts

@ -25,7 +25,6 @@ import {
OnInit,
ViewChild,
} from '@angular/core';
import { PageLink } from '@shared/models/page/page-link';
import { TranslateService } from '@ngx-translate/core';
import { MatDialog } from '@angular/material/dialog';
import { DialogService } from '@core/services/dialog.service';
@ -33,7 +32,6 @@ import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, take, takeUntil } from 'rxjs/operators';
import {
ControlValueAccessor,
FormArray,
FormBuilder,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
@ -54,7 +52,7 @@ import {
RequestType,
RequestTypesTranslationsMap
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { CollectionViewer, DataSource } from '@angular/cdk/collections';
import { DataSource } from '@angular/cdk/collections';
import { MappingDialogComponent } from '@home/components/widget/lib/gateway/dialog/mapping-dialog.component';
import { isDefinedAndNotNull, isUndefinedOrNull } from '@core/utils';
import { coerceBoolean } from '@shared/decorators/coercion';
@ -82,8 +80,10 @@ import { CommonModule } from '@angular/common';
imports: [CommonModule, SharedModule]
})
export class MappingTableComponent implements ControlValueAccessor, Validator, AfterViewInit, OnInit, OnDestroy {
@Input()
@coerceBoolean()
@Input() required = false;
required = false;
@Input()
set mappingType(value: MappingType) {
@ -92,6 +92,10 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
}
}
get mappingType(): MappingType {
return this.mappingTypeValue;
}
@ViewChild('searchInput') searchInputField: ElementRef;
mappingTypeTranslationsMap = MappingTypeTranslationsMap;
@ -107,12 +111,8 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
mappingFormGroup: UntypedFormArray;
textSearch = this.fb.control('', {nonNullable: true});
get mappingType(): MappingType {
return this.mappingTypeValue;
}
onChange: (value: string) => void = () => {};
onTouched: () => void = () => {};
private onChange: (value: string) => void = () => {};
private onTouched: () => void = () => {};
private destroy$ = new Subject<void>();
@ -149,7 +149,7 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
takeUntil(this.destroy$)
).subscribe((text) => {
const searchText = text.trim();
this.updateTableData(this.mappingFormGroup.value, searchText.trim())
this.updateTableData(this.mappingFormGroup.value, searchText.trim());
});
}
@ -162,8 +162,8 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
}
writeValue(connectorMappings: ConnectorMapping[]): void {
(this.mappingFormGroup as FormArray).clear();
this.pushDataAsFormArrays(connectorMappings)
this.mappingFormGroup.clear();
this.pushDataAsFormArrays(connectorMappings);
}
validate(): ValidationErrors | null {
@ -213,12 +213,11 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
});
}
updateTableData(value: ConnectorMapping[], textSearch?: string): void {
let tableValue =
value.map((value: ConnectorMapping) => this.getMappingValue(value));
private updateTableData(value: ConnectorMapping[], textSearch?: string): void {
let tableValue = value.map(mappingValue => this.getMappingValue(mappingValue));
if (textSearch) {
tableValue = tableValue.filter(value =>
Object.values(value).some(val =>
tableValue = tableValue.filter(mappingValue =>
Object.values(mappingValue).some(val =>
val.toString().toLowerCase().includes(textSearch.toLowerCase())
)
);
@ -259,7 +258,7 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
converter: this.translate.instant(ConvertorTypeTranslationsMap.get((value as ConverterConnectorMapping).converter?.type) || '')
};
case MappingType.REQUESTS:
let details;
let details: string;
if ((value as RequestMappingData).requestType === RequestType.ATTRIBUTE_UPDATE) {
details = (value as RequestMappingData).requestValue.attributeFilter;
} else if ((value as RequestMappingData).requestType === RequestType.SERVER_SIDE_RPC) {
@ -315,22 +314,17 @@ export class MappingDatasource implements DataSource<{[key: string]: any}> {
private mappingSubject = new BehaviorSubject<Array<{[key: string]: any}>>([]);
private allMappings: Observable<Array<{[key: string]: any}>>;
constructor() {}
connect(collectionViewer: CollectionViewer): Observable<Array<{[key: string]: any}>> {
connect(): Observable<Array<{[key: string]: any}>> {
return this.mappingSubject.asObservable();
}
disconnect(collectionViewer: CollectionViewer): void {
disconnect(): void {
this.mappingSubject.complete();
}
loadMappings(mappings: Array<{[key: string]: any}>, pageLink?: PageLink, reload: boolean = false): void {
if (reload) {
this.allMappings = null;
}
loadMappings(mappings: Array<{[key: string]: any}>): void {
this.mappingSubject.next(mappings);
}

25
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts

@ -14,14 +14,7 @@
/// limitations under the License.
///
import {
ChangeDetectionStrategy,
Component,
forwardRef,
Input,
OnDestroy,
TemplateRef,
} from '@angular/core';
import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, TemplateRef } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
@ -33,7 +26,6 @@ import {
} from '@angular/forms';
import {
ConnectorBaseConfig,
ConnectorType,
MappingType,
RequestMappingData,
RequestType,
@ -44,8 +36,7 @@ import {
BrokerConfigControlComponent,
MappingTableComponent,
SecurityConfigComponent,
WorkersConfigControlComponent,
GeneralConfigComponent
WorkersConfigControlComponent
} from '@home/components/widget/lib/gateway/connectors-configuration/public-api';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
@ -75,7 +66,6 @@ import { isObject } from 'lodash';
WorkersConfigControlComponent,
BrokerConfigControlComponent,
MappingTableComponent,
GeneralConfigComponent,
],
styles: [`
:host {
@ -90,15 +80,16 @@ import { isObject } from 'lodash';
})
export class MqttBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy {
@Input() generalTabContent: TemplateRef<GeneralConfigComponent>;
@Input()
generalTabContent: TemplateRef<any>;
mappingTypes = MappingType;
basicFormGroup: FormGroup;
onChange!: (value: string) => void;
onTouched!: () => void;
private onChange: (value: string) => void;
private onTouched: () => void;
protected readonly connectorType = ConnectorType;
private destroy$ = new Subject<void>();
constructor(private fb: FormBuilder) {
@ -157,7 +148,7 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator
if (isObject(value)) {
Object.keys(value).forEach((configKey: string) => {
for (let mapping of value[configKey]) {
for (const mapping of value[configKey]) {
mappingConfigs.push({
requestType: configKey,
requestValue: mapping

15
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts

@ -14,14 +14,7 @@
/// limitations under the License.
///
import {
ChangeDetectionStrategy,
Component,
forwardRef,
Input,
OnDestroy,
TemplateRef,
} from '@angular/core';
import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, TemplateRef } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
@ -43,8 +36,7 @@ import {
MappingTableComponent,
SecurityConfigComponent,
ServerConfigComponent,
WorkersConfigControlComponent,
GeneralConfigComponent
WorkersConfigControlComponent
} from '@home/components/widget/lib/gateway/connectors-configuration/public-api';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
@ -73,7 +65,6 @@ import { Subject } from 'rxjs';
WorkersConfigControlComponent,
BrokerConfigControlComponent,
MappingTableComponent,
GeneralConfigComponent,
ServerConfigComponent,
],
styles: [`
@ -89,7 +80,7 @@ import { Subject } from 'rxjs';
})
export class OpcUaBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy {
@Input() generalTabContent: TemplateRef<GeneralConfigComponent>;
@Input() generalTabContent: TemplateRef<any>;
mappingTypes = MappingType;
basicFormGroup: FormGroup;

1
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/public-api.ts

@ -24,4 +24,3 @@ export * from './broker-config-control/broker-config-control.component';
export * from './workers-config-control/workers-config-control.component';
export * from './opc-ua-basic-config/opc-ua-basic-config.component';
export * from './mqtt-basic-config/mqtt-basic-config.component';
export * from './general-config/general-config.component';

9
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component.ts

@ -68,21 +68,22 @@ import { CommonModule } from '@angular/common';
]
})
export class SecurityConfigComponent implements ControlValueAccessor, OnInit, OnDestroy {
@Input()
title: string = 'gateway.security';
title = 'gateway.security';
@Input()
@coerceBoolean()
extendCertificatesModel = false;
BrokerSecurityType = SecurityType;
securityTypes = Object.values(SecurityType);
securityTypes = Object.values(SecurityType) as SecurityType[];
modeTypes = Object.values(ModeType);
SecurityTypeTranslationsMap = SecurityTypeTranslationsMap;
securityFormGroup: UntypedFormGroup;
onChange!: (value: string) => void;
onTouched!: () => void;
private onChange: (value: string) => void;
private onTouched: () => void;
private destroy$ = new Subject<void>();

4
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/server-config/server-config.component.html

@ -58,7 +58,7 @@
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="security">
<mat-option *ngFor="let version of serverSecurityTypes" [value]="version.value">{{ version.name }}</mat-option>
<mat-option *ngFor="let version of securityPolicyTypes" [value]="version.value">{{ version.name }}</mat-option>
</mat-select>
</mat-form-field>
</div>
@ -119,7 +119,7 @@
</mat-label>
</mat-slide-toggle>
</div>
<tb-security-config [formControl]="serverConfigFormGroup.get('identity')"
<tb-security-config formControlName="identity"
[extendCertificatesModel]="true">
</tb-security-config>
</div>

18
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/server-config/server-config.component.ts

@ -14,12 +14,7 @@
/// limitations under the License.
///
import {
ChangeDetectionStrategy,
Component,
forwardRef,
OnDestroy
} from '@angular/core';
import { ChangeDetectionStrategy, Component, forwardRef, OnDestroy } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
@ -32,9 +27,9 @@ import {
} from '@angular/forms';
import {
noLeadTrailSpacesRegex,
SecurityType,
ServerConfig,
ServerSecurityTypes
SecurityPolicy,
SecurityPolicyTypes,
ServerConfig
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { SharedModule } from '@shared/shared.module';
import { CommonModule } from '@angular/common';
@ -67,7 +62,8 @@ import { takeUntil } from 'rxjs/operators';
]
})
export class ServerConfigComponent implements ControlValueAccessor, Validator, OnDestroy {
serverSecurityTypes = ServerSecurityTypes;
securityPolicyTypes = SecurityPolicyTypes;
serverConfigFormGroup: UntypedFormGroup;
onChange!: (value: string) => void;
@ -84,7 +80,7 @@ export class ServerConfigComponent implements ControlValueAccessor, Validator, O
enableSubscriptions: [true, []],
subCheckPeriodInMillis: [10, [Validators.required, Validators.min(10)]],
showMap: [false, []],
security: [SecurityType.BASIC128, []],
security: [SecurityPolicy.BASIC128, []],
identity: [{}, [Validators.required]]
});

5
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component.ts

@ -57,10 +57,11 @@ import { takeUntil } from 'rxjs/operators';
]
})
export class WorkersConfigControlComponent implements OnDestroy, ControlValueAccessor, Validator {
workersConfigFormGroup: UntypedFormGroup;
onChange!: (value: string) => void;
onTouched!: () => void;
private onChange: (value: string) => void;
private onTouched: () => void;
private destroy$ = new Subject<void>();

86
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html

@ -156,9 +156,7 @@
{{ initialConnector?.type ? gatewayConnectorDefaultTypes.get(initialConnector.type) : '' }}
{{ 'gateway.configuration' | translate }}
</div>
<tb-toggle-select *ngIf="initialConnector &&
(initialConnector.type === connectorType.MQTT ||
initialConnector.type === connectorType.OPCUA)"
<tb-toggle-select *ngIf="initialConnector && allowBasicConfig.has(initialConnector.type)"
formControlName="mode" appearance="fill">
<tb-toggle-option [value]="connectorConfigurationModes.BASIC">
{{ 'gateway.basic' | translate }}
@ -173,19 +171,18 @@
class="no-data-found" translate>
gateway.select-connector
</span>
<ng-template #generalTabContent>
<tb-general-config></tb-general-config>
</ng-template>
<section class="tb-form-panel section-container no-border no-padding tb-flex space-between" *ngIf="initialConnector">
<ng-container *ngIf="connectorForm.get('mode')?.value === connectorConfigurationModes.BASIC else defaultConfig">
<tb-mqtt-basic-config *ngIf="(initialConnector.type === connectorType.MQTT)"
formControlName="basicConfig"
[generalTabContent]="generalTabContent">
</tb-mqtt-basic-config>
<tb-opc-ua-basic-config *ngIf="(initialConnector.type === connectorType.OPCUA)"
<ng-container [ngSwitch]="initialConnector.type">
<tb-mqtt-basic-config *ngSwitchCase="connectorType.MQTT"
formControlName="basicConfig"
[generalTabContent]="generalTabContent">
</tb-opc-ua-basic-config>
</tb-mqtt-basic-config>
<tb-opc-ua-basic-config *ngSwitchCase="connectorType.OPCUA"
formControlName="basicConfig"
[generalTabContent]="generalTabContent">
</tb-opc-ua-basic-config>
</ng-container>
</ng-container>
<ng-template #defaultConfig>
<mat-tab-group>
@ -215,3 +212,68 @@
</section>
</section>
</div>
<ng-template #generalTabContent>
<section [formGroup]="connectorForm" class="tb-form-panel no-border no-padding padding-top section-container flex">
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center" >
<div class="fixed-title-width tb-required" translate>gateway.name</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput autocomplete="off" name="value" formControlName="name" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="(connectorForm.get('name').hasError('duplicateName') ?
'gateway.connector-duplicate-name' : 'gateway.name-required') | translate"
*ngIf="(connectorForm.get('name').hasError('required') && connectorForm.get('name').touched) ||
connectorForm.get('name').hasError('duplicateName')"
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
</div>
<div *ngIf="connectorForm.get('type').value === connectorType.CUSTOM" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.connectors-table-class</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="class" placeholder="{{ 'gateway.set' | translate }}"/>
</mat-form-field>
</div>
</div>
<div *ngIf="connectorForm.get('type').value === connectorType.GRPC" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.connectors-table-key</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="key" placeholder="{{ 'gateway.set' | translate }}"/>
</mat-form-field>
</div>
</div>
<div class="tb-form-panel stroked">
<div class="tb-form-panel-title" translate>gateway.logs-configuration</div>
<div class="tb-form-row" fxLayoutAlign="space-between center">
<mat-slide-toggle class="mat-slide" formControlName="enableRemoteLogging">
<mat-label>
{{ 'gateway.enable-remote-logging' | translate }}
</mat-label>
</mat-slide-toggle>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" translate>gateway.remote-logging-level</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="logLevel">
<mat-option *ngFor="let logLevel of gatewayLogLevel" [value]="logLevel">{{ logLevel }}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="connectorForm.get('type').value === connectorType.MQTT" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<mat-slide-toggle class="mat-slide" formControlName="sendDataOnlyOnChange">
<mat-label tb-hint-tooltip-icon="{{ 'gateway.send-change-data-hint' | translate }}">
{{ 'gateway.send-change-data' | translate }}
</mat-label>
</mat-slide-toggle>
</div>
</section>
</ng-template>

53
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts

@ -21,20 +21,12 @@ import {
ElementRef,
Input,
NgZone,
ViewChild,
OnDestroy,
ViewChild
} from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import {
FormBuilder,
FormControl,
FormGroup,
FormGroupDirective,
NgForm,
UntypedFormControl,
ValidatorFn,
Validators
} from '@angular/forms';
import { FormBuilder, FormControl, FormGroup, UntypedFormControl, ValidatorFn, Validators } from '@angular/forms';
import { EntityId } from '@shared/models/id/entity-id';
import { AttributeService } from '@core/http/attribute.service';
import { TranslateService } from '@ngx-translate/core';
@ -72,7 +64,7 @@ import { ErrorStateMatcher } from '@angular/material/core';
import { PageData } from '@shared/models/page/page-data';
export class ForceErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
isErrorState(control: FormControl | null): boolean {
return (control && control.invalid);
}
}
@ -83,7 +75,7 @@ export class ForceErrorStateMatcher implements ErrorStateMatcher {
providers: [{ provide: ErrorStateMatcher, useClass: ForceErrorStateMatcher }],
styleUrls: ['./gateway-connectors.component.scss']
})
export class GatewayConnectorComponent extends PageComponent implements AfterViewInit {
export class GatewayConnectorComponent extends PageComponent implements AfterViewInit, OnDestroy {
@Input()
ctx: WidgetContext;
@ -98,6 +90,13 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
connectorType = ConnectorType;
allowBasicConfig = new Set<ConnectorType>([
ConnectorType.MQTT,
ConnectorType.OPCUA
]);
gatewayLogLevel = Object.values(GatewayLogLevel);
dataSource: MatTableDataSource<AttributeData>;
displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions'];
@ -137,7 +136,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
onDataUpdated: () => this.ctx.ngZone.run(() => {
this.onDataUpdated();
}),
onDataUpdateError: (subscription, e) => this.ctx.ngZone.run(() => {
onDataUpdateError: (_, e) => this.ctx.ngZone.run(() => {
this.onDataUpdateError(e);
})
}
@ -196,7 +195,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
defaultConfig[0].value);
this.cd.detectChanges();
}
})
});
}
});
@ -214,11 +213,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
const basicConfig = this.connectorForm.get('basicConfig');
const type = this.connectorForm.get('type').value;
const mode = this.connectorForm.get('mode').value;
if (
!isEqual(config, basicConfig?.value) &&
(type === ConnectorType.MQTT || type === ConnectorType.OPCUA) &&
mode === ConnectorConfigurationModes.ADVANCED
) {
if (!isEqual(config, basicConfig?.value) && this.allowBasicConfig.has(type) && mode === ConnectorConfigurationModes.ADVANCED) {
this.connectorForm.get('basicConfig').patchValue(config, {emitEvent: false});
}
});
@ -350,7 +345,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
...value.configurationJson.workers,
}
}
}
};
}
private updateData(reload: boolean = false): void {
@ -607,11 +602,15 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
const wasEnabled = this.activeConnectors.includes(key);
if (wasEnabled) {
const index = this.activeConnectors.indexOf(key);
if (index !== -1) this.activeConnectors.splice(index, 1);
if (index !== -1) {
this.activeConnectors.splice(index, 1);
}
this.inactiveConnectors.push(key);
} else {
const index = this.inactiveConnectors.indexOf(key);
if (index !== -1) this.inactiveConnectors.splice(index, 1);
if (index !== -1) {
this.inactiveConnectors.splice(index, 1);
}
this.activeConnectors.push(key);
}
}
@ -689,12 +688,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
const configJson = this.connectorForm.get('configurationJson');
const type = this.connectorForm.get('type').value;
const mode = this.connectorForm.get('mode').value;
if (
!isEqual(config, configJson?.value) &&
(type === ConnectorType.MQTT || type === ConnectorType.OPCUA) &&
mode === ConnectorConfigurationModes.BASIC
) {
const newConfig = { ...configJson.value, ...config };
if (!isEqual(config, configJson?.value) && this.allowBasicConfig.has(type) && mode === ConnectorConfigurationModes.BASIC) {
const newConfig = {...configJson.value, ...config};
this.connectorForm.get('configurationJson').patchValue(newConfig, {emitEvent: false});
}
});

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

@ -18,7 +18,7 @@ import { ResourcesService } from '@core/services/resources.service';
import { Observable } from 'rxjs';
import { ValueTypeData } from '@shared/models/constants';
export const noLeadTrailSpacesRegex: RegExp = /^(?! )[\S\s]*(?<! )$/;
export const noLeadTrailSpacesRegex = /^(?! )[\S\s]*(?<! )$/;
export enum StorageTypes {
MEMORY = 'memory',
@ -288,15 +288,16 @@ export const GatewayConnectorDefaultTypesTranslatesMap = new Map<ConnectorType,
]);
export interface RPCCommand {
command: string,
params: any,
time: number
command: string;
params: any;
time: number;
}
export enum ModbusCommandTypes {
Bits = 'bits',
Bit = 'bit',
// eslint-disable-next-line id-blacklist
String = 'string',
Bytes = 'bytes',
Int8 = '8int',
@ -321,7 +322,7 @@ export const ModbusCodesTranslate = new Map<number, string>([
[6, 'gateway.rpc.write-single-holding-register'],
[15, 'gateway.rpc.write-multiple-coils'],
[16, 'gateway.rpc.write-multiple-holding-registers']
])
]);
export enum BACnetRequestTypes {
WriteProperty = 'writeProperty',
@ -330,8 +331,8 @@ export enum BACnetRequestTypes {
export const BACnetRequestTypesTranslates = new Map<BACnetRequestTypes, string>([
[BACnetRequestTypes.WriteProperty, 'gateway.rpc.write-property'],
[BACnetRequestTypes.ReadProperty, "gateway.rpc.read-property"]
])
[BACnetRequestTypes.ReadProperty, 'gateway.rpc.read-property']
]);
export enum BACnetObjectTypes {
BinaryInput = 'binaryInput',
@ -349,7 +350,7 @@ export const BACnetObjectTypesTranslates = new Map<BACnetObjectTypes, string>([
[BACnetObjectTypes.BinaryInput, 'gateway.rpc.binary-input'],
[BACnetObjectTypes.BinaryValue, 'gateway.rpc.binary-value'],
[BACnetObjectTypes.AnalogValue, 'gateway.rpc.analog-value']
])
]);
export enum BLEMethods {
WRITE = 'write',
@ -361,7 +362,7 @@ export const BLEMethodsTranslates = new Map<BLEMethods, string>([
[BLEMethods.WRITE, 'gateway.rpc.write'],
[BLEMethods.READ, 'gateway.rpc.read'],
[BLEMethods.SCAN, 'gateway.rpc.scan'],
])
]);
export enum CANByteOrders {
LITTLE = 'LITTLE',
@ -374,18 +375,18 @@ export enum SocketMethodProcessings {
export const SocketMethodProcessingsTranslates = new Map<SocketMethodProcessings, string>([
[SocketMethodProcessings.WRITE, 'gateway.rpc.write']
])
]);
export enum SNMPMethods {
SET = 'set',
MULTISET = "multiset",
GET = "get",
BULKWALK = "bulkwalk",
TABLE = "table",
MULTIGET = "multiget",
GETNEXT = "getnext",
BULKGET = "bulkget",
WALKS = "walk"
MULTISET = 'multiset',
GET = 'get',
BULKWALK = 'bulkwalk',
TABLE = 'table',
MULTIGET = 'multiget',
GETNEXT = 'getnext',
BULKGET = 'bulkget',
WALKS = 'walk'
}
export const SNMPMethodsTranslations = new Map<SNMPMethods, string>([
@ -398,7 +399,7 @@ export const SNMPMethodsTranslations = new Map<SNMPMethods, string>([
[SNMPMethods.GETNEXT, 'gateway.rpc.get-next'],
[SNMPMethods.BULKGET, 'gateway.rpc.bulk-get'],
[SNMPMethods.WALKS, 'gateway.rpc.walk']
])
]);
export enum HTTPMethods {
CONNECT = 'CONNECT',
@ -427,8 +428,8 @@ export interface RPCTemplateConfig {
}
export interface SaveRPCTemplateData {
config: RPCTemplateConfig,
templates: Array<RPCTemplate>
config: RPCTemplateConfig;
templates: Array<RPCTemplate>;
}
export interface LogLink {
@ -445,33 +446,33 @@ export interface GatewayLogData {
}
export interface AddConnectorConfigData {
dataSourceData: Array<any>
dataSourceData: Array<any>;
}
export interface CreatedConnectorConfigData {
type: ConnectorType,
name: string,
logLevel: GatewayLogLevel,
useDefaults: boolean,
sendDataOnlyOnChange: boolean,
configurationJson?: {[key: string]: any}
type: ConnectorType;
name: string;
logLevel: GatewayLogLevel;
useDefaults: boolean;
sendDataOnlyOnChange: boolean;
configurationJson?: {[key: string]: any};
}
export interface MappingDataKey {
key: string,
value: any,
type: MappingValueType
key: string;
value: any;
type: MappingValueType;
}
export interface RpcMethodsMapping {
method: string,
arguments: Array<MappingDataKey>
method: string;
arguments: Array<MappingDataKey>;
}
export interface MappingInfo {
mappingType: MappingType,
value: {[key: string]: any},
buttonTitle: string
mappingType: MappingType;
value: {[key: string]: any};
buttonTitle: string;
}
export enum ConnectorConfigurationModes {
@ -727,14 +728,14 @@ export const DataConversionTranslationsMap = new Map<ConvertorType, string>(
]
);
export enum SecurityType {
export enum SecurityPolicy {
BASIC128 = 'Basic128Rsa15',
BASIC256 = 'Basic256',
BASIC256SHA = 'Basic256Sha256'
}
export const ServerSecurityTypes = [
{ value: 'Basic128Rsa15', name: 'Basic128RSA15' },
{ value: 'Basic256', name: 'Basic256' },
{ value: 'Basic256Sha256', name: 'Basic256SHA256' }
export const SecurityPolicyTypes = [
{ value: SecurityPolicy.BASIC128, name: 'Basic128RSA15' },
{ value: SecurityPolicy.BASIC256, name: 'Basic256' },
{ value: SecurityPolicy.BASIC256SHA, name: 'Basic256SHA256' }
];

2
ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts

@ -111,7 +111,6 @@ import {
TypeValuePanelComponent,
BrokerConfigControlComponent,
WorkersConfigControlComponent,
GeneralConfigComponent,
MqttBasicConfigComponent,
OpcUaBasicConfigComponent,
} from '@home/components/widget/lib/gateway/connectors-configuration/public-api';
@ -194,7 +193,6 @@ import {
BrokerConfigControlComponent,
WorkersConfigControlComponent,
ServerConfigComponent,
GeneralConfigComponent,
MqttBasicConfigComponent,
MappingTableComponent,
OpcUaBasicConfigComponent,

Loading…
Cancel
Save