Merge pull request #11656 from maxunbearable/fix/4413-gateway-fixes

Gateway UI improvements and minor bug fixes
This commit is contained in:
Igor Kulikov 2024-09-20 16:15:06 +03:00 committed by GitHub
commit 8a5cc8cad5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 54 additions and 38 deletions

View File

@ -74,8 +74,8 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTB
getDowngradedVersion(): GatewayConnector<MQTTLegacyBasicConfig> {
const { requestsMapping, mapping, ...restConfig } = this.connector.configurationJson as MQTTBasicConfig_v3_5_2;
const updatedRequestsMapping =
MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record<RequestType, RequestMappingData[]>);
const updatedRequestsMapping = requestsMapping
? MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record<RequestType, RequestMappingData[]>) : {};
const updatedMapping = MqttVersionMappingUtil.mapMappingToDowngradedVersion(mapping);
return {

View File

@ -28,6 +28,7 @@ import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { SharedModule } from '@shared/shared.module';
import { CommonModule } from '@angular/common';
import { GatewayConfigValue } from '@home/components/widget/lib/gateway/configuration/models/gateway-configuration.models';
@Component({
selector: 'tb-gateway-advanced-configuration',
@ -83,8 +84,8 @@ export class GatewayAdvancedConfigurationComponent implements OnDestroy, Control
this.onTouched = fn;
}
writeValue(basicConfig: unknown): void {
this.advancedFormControl.reset(basicConfig, {emitEvent: false});
writeValue(advancedConfig: GatewayConfigValue): void {
this.advancedFormControl.reset(advancedConfig, {emitEvent: false});
}
validate(): ValidationErrors | null {

View File

@ -640,10 +640,11 @@
</mat-form-field>
</section>
<button mat-icon-button (click)="removeCommandControl($index, $event)"
class="tb-box-button"
[disabled]="!basicFormGroup.get('thingsboard.remoteConfiguration').value"
matTooltip="{{ 'gateway.statistics.remove' | translate }}"
matTooltipPosition="above">
<mat-icon>close</mat-icon>
<mat-icon>delete</mat-icon>
</button>
</div>
<button mat-stroked-button color="primary"

View File

@ -20,7 +20,7 @@ import {
FormGroup,
} from '@angular/forms';
import { EntityId } from '@shared/models/id/entity-id';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { MatDialogRef } from '@angular/material/dialog';
import { AttributeService } from '@core/http/attribute.service';
import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetry.models';
import { DeviceService } from '@core/http/device.service';
@ -40,7 +40,9 @@ import {
GatewayConfigSecurity,
GatewayConfigValue,
GatewayGeneralConfig,
GatewayGRPCConfig,
GatewayLogsConfig,
GatewayStorageConfig,
LocalLogs,
LogAttribute,
LogConfig,
@ -113,7 +115,7 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
this.gatewayConfigGroup.get('basicConfig').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
const advancedControl = this.gatewayConfigGroup.get('advancedConfig');
if (!isEqual(advancedControl.value, value)) {
if (!isEqual(advancedControl.value, value) && this.gatewayConfigGroup.get('mode').value === ConfigurationModes.BASIC) {
advancedControl.patchValue(value, {emitEvent: false});
}
});
@ -121,7 +123,7 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
this.gatewayConfigGroup.get('advancedConfig').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
const basicControl = this.gatewayConfigGroup.get('basicConfig');
if (!isEqual(basicControl.value, value)) {
if (!isEqual(basicControl.value, value) && this.gatewayConfigGroup.get('mode').value === ConfigurationModes.ADVANCED) {
basicControl.patchValue(value, {emitEvent: false});
}
});
@ -320,10 +322,10 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
private updateConfigs(attributes: AttributeData[]): void {
const formValue: GatewayConfigValue = {
thingsboard: null,
grpc: null,
logs: null,
storage: null,
thingsboard: {} as GatewayGeneralConfig,
grpc: {} as GatewayGRPCConfig,
logs: {} as GatewayLogsConfig,
storage: {} as GatewayStorageConfig,
mode: ConfigurationModes.BASIC
};

View File

@ -27,7 +27,24 @@ import { GatewayLogLevel } from '@home/components/widget/lib/gateway/gateway-for
export interface GatewayConfigValue {
mode: ConfigurationModes;
thingsboard: GatewayGeneralConfig;
storage: {
storage: GatewayStorageConfig;
grpc: GatewayGRPCConfig;
connectors?: GatewayConnector[];
logs: GatewayLogsConfig;
}
export interface GatewayGRPCConfig {
enabled: boolean;
serverPort: number;
keepAliveTimeMs: number;
keepAliveTimeoutMs: number;
keepalivePermitWithoutCalls: boolean;
maxPingsWithoutData: number;
minTimeBetweenPingsMs: number;
minPingIntervalWithoutDataMs: number;
}
export interface GatewayStorageConfig {
type: StorageTypes;
read_records_count?: number;
max_records_count?: number;
@ -38,19 +55,6 @@ export interface GatewayConfigValue {
data_file_path?: string;
messages_ttl_check_in_hours?: number;
messages_ttl_in_days?: number;
};
grpc: {
enabled: boolean;
serverPort: number;
keepAliveTimeMs: number;
keepAliveTimeoutMs: number;
keepalivePermitWithoutCalls: boolean;
maxPingsWithoutData: number;
minTimeBetweenPingsMs: number;
minPingIntervalWithoutDataMs: number;
};
connectors?: GatewayConnector[];
logs: GatewayLogsConfig;
}
export interface GatewayGeneralConfig {

View File

@ -256,10 +256,11 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
private getMappingValue(value: ConnectorMapping): MappingValue {
switch (this.mappingType) {
case MappingType.DATA:
const converterType = ConvertorTypeTranslationsMap.get((value as ConverterConnectorMapping).converter?.type);
return {
topicFilter: (value as ConverterConnectorMapping).topicFilter,
QoS: (value as ConverterConnectorMapping).subscriptionQos,
converter: this.translate.instant(ConvertorTypeTranslationsMap.get((value as ConverterConnectorMapping).converter?.type) || '')
converter: converterType ? this.translate.instant(converterType) : ''
};
case MappingType.REQUESTS:
let details: string;

View File

@ -54,7 +54,9 @@
</div>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" tbTruncateWithTooltip translate>gateway.security</div>
<div class="fixed-title-width" tb-hint-tooltip-icon="{{ 'gateway.hints.security-policy' | translate }}">
<div tbTruncateWithTooltip>{{ 'gateway.security-policy' | translate }}</div>
</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="security">

View File

@ -297,12 +297,13 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
}
private hasSameConfig(sharedDataConfigJson: ConnectorBaseInfo, connectorDataConfigJson: ConnectorBaseInfo): boolean {
const { name, id, enableRemoteLogging, logLevel, ...sharedDataConfig } = sharedDataConfigJson;
const { name, id, enableRemoteLogging, logLevel, configVersion, ...sharedDataConfig } = sharedDataConfigJson;
const {
name: connectorName,
id: connectorId,
enableRemoteLogging: connectorEnableRemoteLogging,
logLevel: connectorLogLevel,
configVersion: connectorConfigVersion,
...connectorConfig
} = connectorDataConfigJson;

View File

@ -208,6 +208,7 @@ export interface ConnectorBaseInfo {
id: string;
enableRemoteLogging: boolean;
logLevel: GatewayLogLevel;
configVersion: string | number;
}
export type MQTTBasicConfig = MQTTBasicConfig_v3_5_2 | MQTTLegacyBasicConfig;

View File

@ -35,9 +35,10 @@ import {
export class OpcVersionMappingUtil {
static mapServerToUpgradedVersion(server: LegacyServerConfig): ServerConfig {
const { mapping, disableSubscriptions, ...restServer } = server;
const { mapping, disableSubscriptions, pollPeriodInMillis, ...restServer } = server;
return {
...restServer,
pollPeriodInMillis: pollPeriodInMillis ?? 5000,
enableSubscriptions: !disableSubscriptions,
};
}

View File

@ -3254,6 +3254,7 @@
"sub-check-period": "Subscription check period (ms)",
"sub-check-period-error": "Subscription check period should be at least {{min}} (ms).",
"security": "Security",
"security-policy": "Security policy",
"security-type": "Security type",
"security-types": {
"access-token": "Access Token",
@ -3460,6 +3461,7 @@
"file": "Your data will be stored in separated files and will be saved even after the gateway restart.",
"sqlite": "Your data will be stored in file based database. And will be saved even after the gateway restart.",
"opc-timeout": "Timeout in milliseconds for connecting to OPC-UA server.",
"security-policy": "Security Policy defines the security mechanisms to be applied.",
"scan-period": "Period in milliseconds to rescan the server.",
"sub-check-period": "Period to check the subscriptions in the OPC-UA server.",
"enable-subscription": "If true - the gateway will subscribe to interesting nodes and wait for data update and if false - the gateway will rescan OPC-UA server every scanPeriodInMillis.",