Browse Source

6.12 update

pull/8337/head
Maksym Dudnik 3 years ago
parent
commit
c5a35b1f53
  1. 4
      ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html
  2. 2
      ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts
  3. 27
      ui-ngx/src/app/shared/components/device/gateway-configuration.component.html
  4. 9
      ui-ngx/src/app/shared/components/device/gateway-configuration.component.scss
  5. 128
      ui-ngx/src/app/shared/components/device/gateway-configuration.component.ts
  6. 6
      ui-ngx/src/app/shared/components/device/gateway-connectors.component.html
  7. 56
      ui-ngx/src/app/shared/components/device/gateway-connectors.component.ts
  8. 4
      ui-ngx/src/app/shared/components/device/gateway-logs.component.scss
  9. 2
      ui-ngx/src/app/shared/components/device/gateway-statistics.component.html
  10. 9
      ui-ngx/src/app/shared/components/device/gateway-statistics.component.scss

4
ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html

@ -179,10 +179,10 @@
</mat-step> </mat-step>
</mat-horizontal-stepper> </mat-horizontal-stepper>
<div *ngIf="deviceCredentials" class="commands-container"> <div *ngIf="deviceCredentials" class="commands-container">
<tb-gateway-command *ngIf="device.additionalInfo?.gateway" <tb-gateway-command *ngIf="device?.additionalInfo?.gateway"
[token]="deviceCredentials.credentialsId"> [token]="deviceCredentials.credentialsId">
</tb-gateway-command> </tb-gateway-command>
<tb-device-example-command *ngIf="!device.additionalInfo?.gateway" <tb-device-example-command *ngIf="!device?.additionalInfo?.gateway"
[token]="deviceCredentials.credentialsId"> [token]="deviceCredentials.credentialsId">
</tb-device-example-command> </tb-device-example-command>
</div> </div>

2
ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts

@ -366,6 +366,7 @@ export class DeviceWizardDialogComponent extends
mergeMap( mergeMap(
(deviceCredentials) => { (deviceCredentials) => {
const deviceCredentialsValue = {...deviceCredentials, ...this.credentialsFormGroup.value.credential}; const deviceCredentialsValue = {...deviceCredentials, ...this.credentialsFormGroup.value.credential};
this.deviceCredentials = deviceCredentialsValue;
return this.deviceService.saveDeviceCredentials(deviceCredentialsValue).pipe( return this.deviceService.saveDeviceCredentials(deviceCredentialsValue).pipe(
catchError(e => { catchError(e => {
this.addDeviceWizardStepper.selectedIndex = 1; this.addDeviceWizardStepper.selectedIndex = 1;
@ -387,7 +388,6 @@ export class DeviceWizardDialogComponent extends
}) })
); );
} }
return of(device);
} }
allValid(): boolean { allValid(): boolean {

27
ui-ngx/src/app/shared/components/device/gateway-configuration.component.html

@ -131,9 +131,6 @@
fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> fxFlex="calc(50%-15px)" class="mat-block tb-value-type">
<mat-label translate>security.password</mat-label> <mat-label translate>security.password</mat-label>
<input matInput formControlName="password"/> <input matInput formControlName="password"/>
<mat-error *ngIf="gatewayConfigGroup.get('thingsboard.security.password').hasError('required')">
{{'security.password-required' | translate}}
</mat-error>
<mat-icon class="mat-form-field-infix pe suffix-icon" aria-hidden="false" aria-label="help-icon" <mat-icon class="mat-form-field-infix pe suffix-icon" aria-hidden="false" aria-label="help-icon"
matSuffix style="cursor:pointer;" matSuffix style="cursor:pointer;"
matTooltip="{{'gateway.hints.password' | translate }}">info_outlined matTooltip="{{'gateway.hints.password' | translate }}">info_outlined
@ -466,14 +463,14 @@
<div formGroupName="grpc" fxLayout="column" class="mat-content mat-padding"> <div formGroupName="grpc" fxLayout="column" class="mat-content mat-padding">
<mat-accordion multi> <mat-accordion multi>
<mat-expansion-panel expanded="true" disabled style="padding-top: 20px"> <mat-expansion-panel expanded="true" disabled style="padding-top: 20px">
<div fxLayout="row wrap"> <div fxLayout="row wrap" fxLayout.lt-md="column">
<mat-slide-toggle color="primary" fxFlex="100" formControlName="enabled"> <mat-slide-toggle color="primary" fxFlex="100" formControlName="enabled">
{{ 'gateway.grpc' | translate }} {{ 'gateway.grpc' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle color="primary" fxFlex="100" formControlName="keepalivePermitWithoutCalls"> <mat-slide-toggle color="primary" fxFlex="100" formControlName="keepalivePermitWithoutCalls">
{{ 'gateway.permit-without-calls' | translate }} {{ 'gateway.permit-without-calls' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md="100" class="mat-block tb-value-type">
<mat-label translate>gateway.server-port</mat-label> <mat-label translate>gateway.server-port</mat-label>
<input matInput formControlName="serverPort" type="number" min="0" /> <input matInput formControlName="serverPort" type="number" min="0" />
<mat-error *ngIf="gatewayConfigGroup.get('grpc.serverPort').hasError('required')"> <mat-error *ngIf="gatewayConfigGroup.get('grpc.serverPort').hasError('required')">
@ -489,7 +486,7 @@
{{'gateway.thingsboard-port-pattern' | translate }} {{'gateway.thingsboard-port-pattern' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md="100" class="mat-block tb-value-type">
<mat-label translate>gateway.grpc-keep-alive-timeout</mat-label> <mat-label translate>gateway.grpc-keep-alive-timeout</mat-label>
<input matInput formControlName="keepAliveTimeoutMs" type="number" min="0" /> <input matInput formControlName="keepAliveTimeoutMs" type="number" min="0" />
<mat-error *ngIf="gatewayConfigGroup.get('grpc.keepAliveTimeoutMs').hasError('required')"> <mat-error *ngIf="gatewayConfigGroup.get('grpc.keepAliveTimeoutMs').hasError('required')">
@ -502,7 +499,7 @@
{{'gateway.grpc-keep-alive-timeout-pattern' | translate }} {{'gateway.grpc-keep-alive-timeout-pattern' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md="100" class="mat-block tb-value-type">
<mat-label translate>gateway.grpc-keep-alive</mat-label> <mat-label translate>gateway.grpc-keep-alive</mat-label>
<input matInput formControlName="keepAliveTimeMs" type="number" min="0" /> <input matInput formControlName="keepAliveTimeMs" type="number" min="0" />
<mat-error *ngIf="gatewayConfigGroup.get('grpc.keepAliveTimeMs').hasError('required')"> <mat-error *ngIf="gatewayConfigGroup.get('grpc.keepAliveTimeMs').hasError('required')">
@ -515,7 +512,7 @@
{{'gateway.grpc-keep-alive-pattern' | translate }} {{'gateway.grpc-keep-alive-pattern' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md="100" class="mat-block tb-value-type">
<mat-label translate>gateway.grpc-min-time-between-pings</mat-label> <mat-label translate>gateway.grpc-min-time-between-pings</mat-label>
<input matInput formControlName="minTimeBetweenPingsMs" type="number" min="0" /> <input matInput formControlName="minTimeBetweenPingsMs" type="number" min="0" />
<mat-error *ngIf="gatewayConfigGroup.get('grpc.minTimeBetweenPingsMs').hasError('required')"> <mat-error *ngIf="gatewayConfigGroup.get('grpc.minTimeBetweenPingsMs').hasError('required')">
@ -528,7 +525,7 @@
{{'gateway.grpc-min-time-between-pings-pattern' | translate }} {{'gateway.grpc-min-time-between-pings-pattern' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md="100" class="mat-block tb-value-type">
<mat-label translate>gateway.grpc-max-pings-without-data</mat-label> <mat-label translate>gateway.grpc-max-pings-without-data</mat-label>
<input matInput formControlName="maxPingsWithoutData" type="number" min="0" /> <input matInput formControlName="maxPingsWithoutData" type="number" min="0" />
<mat-error *ngIf="gatewayConfigGroup.get('grpc.maxPingsWithoutData').hasError('required')"> <mat-error *ngIf="gatewayConfigGroup.get('grpc.maxPingsWithoutData').hasError('required')">
@ -541,7 +538,7 @@
{{'gateway.grpc-max-pings-without-data-pattern' | translate }} {{'gateway.grpc-max-pings-without-data-pattern' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md="100" class="mat-block tb-value-type">
<mat-label translate>gateway.grpc-min-ping-interval-without-data</mat-label> <mat-label translate>gateway.grpc-min-ping-interval-without-data</mat-label>
<input matInput formControlName="minPingIntervalWithoutDataMs" type="number" min="0" /> <input matInput formControlName="minPingIntervalWithoutDataMs" type="number" min="0" />
<mat-error *ngIf="gatewayConfigGroup.get('grpc.minPingIntervalWithoutDataMs').hasError('required')"> <mat-error *ngIf="gatewayConfigGroup.get('grpc.minPingIntervalWithoutDataMs').hasError('required')">
@ -592,11 +589,11 @@
{{'gateway.hints.commands' | translate}}</span></mat-panel-title> {{'gateway.hints.commands' | translate}}</span></mat-panel-title>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<div fxLayout="column" formGroupName="statistics"> <div fxLayout="column" formGroupName="statistics">
<div fxLayout="row" formArrayName="commands" <div fxLayout="row" formArrayName="commands"
*ngFor="let commandControl of commandFormArray().controls; let $index = index" *ngFor="let commandControl of commandFormArray().controls; let $index = index"
style="margin-bottom: 15px"> style="margin-bottom: 15px">
<mat-card fxLayout="row wrap" [formGroupName]="$index" class="statistics-block"> <mat-card fxFlex.lt-md fxLayout="row wrap" fxLayout.lt-md="column" [formGroupName]="$index" class="statistics-block">
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md class="mat-block tb-value-type">
<mat-label translate>gateway.statistics.attribute-name</mat-label> <mat-label translate>gateway.statistics.attribute-name</mat-label>
<input matInput formControlName="attributeOnGateway"/> <input matInput formControlName="attributeOnGateway"/>
<mat-error <mat-error
@ -608,7 +605,7 @@
matTooltip="{{'gateway.hints.attribute' | translate }}">info_outlined matTooltip="{{'gateway.hints.attribute' | translate }}">info_outlined
</mat-icon> </mat-icon>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md class="mat-block tb-value-type">
<mat-label translate>gateway.statistics.timeout</mat-label> <mat-label translate>gateway.statistics.timeout</mat-label>
<input matInput formControlName="timeout" type="number" min="0" /> <input matInput formControlName="timeout" type="number" min="0" />
<mat-error <mat-error
@ -628,7 +625,7 @@
matTooltip="{{'gateway.hints.timeout' | translate }}">info_outlined matTooltip="{{'gateway.hints.timeout' | translate }}">info_outlined
</mat-icon> </mat-icon>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="calc(50%-15px)" class="mat-block tb-value-type" style="flex-grow: 0"> <mat-form-field fxFlex="calc(50%-15px)" fxFlex.lt-md class="mat-block tb-value-type" style="flex-grow: 0">
<mat-label translate>gateway.statistics.command</mat-label> <mat-label translate>gateway.statistics.command</mat-label>
<input matInput formControlName="command"/> <input matInput formControlName="command"/>
<mat-error <mat-error

9
ui-ngx/src/app/shared/components/device/gateway-configuration.component.scss

@ -57,6 +57,7 @@
background: transparent !important; background: transparent !important;
margin-bottom: 15px; margin-bottom: 15px;
border: none; border: none;
overflow: auto;
.mat-button-toggle { .mat-button-toggle {
border-radius: 15px; border-radius: 15px;
@ -187,7 +188,7 @@
color: rgba(0, 0, 0, .54); color: rgba(0, 0, 0, .54);
width: fit-content; width: fit-content;
cursor: pointer; cursor: pointer;
text-transform: none!important; text-transform: none !important;
} }
.line-break { .line-break {
@ -197,5 +198,11 @@
textarea { textarea {
resize: none; resize: none;
} }
@media only screen and (max-width: 750px) {
.mat-expansion-panel-header.mat-expanded {
height: auto;
}
}
} }

128
ui-ngx/src/app/shared/components/device/gateway-configuration.component.ts

@ -70,7 +70,7 @@ export const localLogsConfigLabels = new Map<LocalLogsConfigs, string>([
[LocalLogsConfigs.tb_connection, 'TB Connection'], [LocalLogsConfigs.tb_connection, 'TB Connection'],
[LocalLogsConfigs.storage, 'Storage'], [LocalLogsConfigs.storage, 'Storage'],
[LocalLogsConfigs.extension, 'Extension'] [LocalLogsConfigs.extension, 'Extension']
]) ]);
export const logSavingPeriodTranslations = new Map<LogSavingPeriod, string>( export const logSavingPeriodTranslations = new Map<LogSavingPeriod, string>(
[ [
@ -213,6 +213,18 @@ export class GatewayConfigurationComponent implements OnInit {
}) })
}); });
this.gatewayConfigGroup.get('thingsboard.security').valueChanges.subscribe(security => {
if (security.username) {
this.clientIdUserNameFieldsToggle('clientId');
} else if (security.clientId) {
this.clientIdUserNameFieldsToggle('username');
} else if (!security.username && !security.clientId) {
this.clientIdUserNameFieldsToggle();
}
});
this.toggleRpcFields(false);
this.gatewayConfigGroup.get('thingsboard.remoteConfiguration').valueChanges.subscribe(enabled => { this.gatewayConfigGroup.get('thingsboard.remoteConfiguration').valueChanges.subscribe(enabled => {
if (!enabled) { if (!enabled) {
this.openConfigurationConfirmDialog(); this.openConfigurationConfirmDialog();
@ -239,6 +251,10 @@ export class GatewayConfigurationComponent implements OnInit {
} }
}); });
this.gatewayConfigGroup.get('grpc.enabled').valueChanges.subscribe(value => {
this.toggleRpcFields(value);
});
const securityGroup = this.gatewayConfigGroup.get('thingsboard.security') as FormGroup; const securityGroup = this.gatewayConfigGroup.get('thingsboard.security') as FormGroup;
securityGroup.get('type').valueChanges.subscribe(type => { securityGroup.get('type').valueChanges.subscribe(type => {
this.removeAllSecurityValidators(); this.removeAllSecurityValidators();
@ -262,15 +278,15 @@ export class GatewayConfigurationComponent implements OnInit {
securityGroup.get('clientId').updateValueAndValidity(); securityGroup.get('clientId').updateValueAndValidity();
securityGroup.get('username').addValidators([Validators.required]); securityGroup.get('username').addValidators([Validators.required]);
securityGroup.get('username').updateValueAndValidity(); securityGroup.get('username').updateValueAndValidity();
securityGroup.get('password').addValidators([Validators.required]); // securityGroup.get('password').addValidators([Validators.required]);
securityGroup.get('password').updateValueAndValidity(); // securityGroup.get('password').updateValueAndValidity();
} }
securityGroup.updateValueAndValidity(); securityGroup.updateValueAndValidity();
}); });
securityGroup.get('caCert').valueChanges.subscribe(_ => this.cd.detectChanges()) securityGroup.get('caCert').valueChanges.subscribe(_ => this.cd.detectChanges());
securityGroup.get('privateKey').valueChanges.subscribe(_ => this.cd.detectChanges()) securityGroup.get('privateKey').valueChanges.subscribe(_ => this.cd.detectChanges());
securityGroup.get('cert').valueChanges.subscribe(_ => this.cd.detectChanges()) securityGroup.get('cert').valueChanges.subscribe(_ => this.cd.detectChanges());
const storageGroup = this.gatewayConfigGroup.get('storage') as FormGroup; const storageGroup = this.gatewayConfigGroup.get('storage') as FormGroup;
storageGroup.get('type').valueChanges.subscribe(type => { storageGroup.get('type').valueChanges.subscribe(type => {
@ -304,7 +320,8 @@ export class GatewayConfigurationComponent implements OnInit {
this.attributeService.getEntityAttributes(entityId, AttributeScope.CLIENT_SCOPE, this.attributeService.getEntityAttributes(entityId, AttributeScope.CLIENT_SCOPE,
['general_configuration', 'grpc_configuration', 'logs_configuration', 'storage_configuration', 'RemoteLoggingLevel']).pipe( ['general_configuration', 'grpc_configuration', 'logs_configuration', 'storage_configuration', 'RemoteLoggingLevel']).pipe(
mergeMap(attributes => attributes.length ? of(attributes) : this.attributeService.getEntityAttributes( mergeMap(attributes => attributes.length ? of(attributes) : this.attributeService.getEntityAttributes(
entityId, AttributeScope.SHARED_SCOPE, ['general_configuration', 'grpc_configuration', 'logs_configuration', 'storage_configuration', 'RemoteLoggingLevel'])) entityId, AttributeScope.SHARED_SCOPE, ['general_configuration', 'grpc_configuration',
'logs_configuration', 'storage_configuration', 'RemoteLoggingLevel']))
).subscribe(attributes => { ).subscribe(attributes => {
if (attributes.length) { if (attributes.length) {
const general_configuration = attributes.find(attribute => attribute.key === 'general_configuration')?.value; const general_configuration = attributes.find(attribute => attribute.key === 'general_configuration')?.value;
@ -330,6 +347,7 @@ export class GatewayConfigurationComponent implements OnInit {
if (grpc_configuration) { if (grpc_configuration) {
const configObj = {grpc: grpc_configuration}; const configObj = {grpc: grpc_configuration};
this.gatewayConfigGroup.patchValue(configObj, {emitEvent: false}); this.gatewayConfigGroup.patchValue(configObj, {emitEvent: false});
this.toggleRpcFields(grpc_configuration.enabled);
} }
if (logs_configuration) { if (logs_configuration) {
const configObj = {logs: this.logsToObj(logs_configuration)}; const configObj = {logs: this.logsToObj(logs_configuration)};
@ -365,7 +383,7 @@ export class GatewayConfigurationComponent implements OnInit {
this.gatewayConfigGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId); this.gatewayConfigGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId);
this.gatewayConfigGroup.get('thingsboard.security.username').setValue(parsedValue.userName); this.gatewayConfigGroup.get('thingsboard.security.username').setValue(parsedValue.userName);
this.gatewayConfigGroup.get('thingsboard.security.password').setValue(parsedValue.password); this.gatewayConfigGroup.get('thingsboard.security.password').setValue(parsedValue.password);
} else if (credentials.credentialsType === DeviceCredentialsType.X509_CERTIFICATE ) { } else if (credentials.credentialsType === DeviceCredentialsType.X509_CERTIFICATE) {
//if sertificate is present set sertificate as present //if sertificate is present set sertificate as present
} }
}); });
@ -375,24 +393,68 @@ export class GatewayConfigurationComponent implements OnInit {
logsToObj(logsConfig) { logsToObj(logsConfig) {
const logsObject = { const logsObject = {
local: {} local: {}
} };
const logFormat = logsConfig.formatters.LogFormatter.format; const logFormat = logsConfig.formatters.LogFormatter.format;
const dateFormat = logsConfig.formatters.LogFormatter.datefmt; const dateFormat = logsConfig.formatters.LogFormatter.datefmt;
for (const localLogsConfigsKey of Object.keys(LocalLogsConfigs)) { for (const localLogsConfigsKey of Object.keys(LocalLogsConfigs)) {
const handlerKey = localLogsConfigsKey + "Handler"; const handlerKey = localLogsConfigsKey + 'Handler';
logsObject[localLogsConfigsKey] = { logsObject[localLogsConfigsKey] = {
logLevel: logsConfig.loggers[localLogsConfigsKey].level, logLevel: logsConfig.loggers[localLogsConfigsKey].level,
filePath: logsConfig.handlers[handlerKey].filename.split('/'+localLogsConfigsKey)[0], filePath: logsConfig.handlers[handlerKey].filename.split('/' + localLogsConfigsKey)[0],
backupCount: logsConfig.handlers[handlerKey].backupCount, backupCount: logsConfig.handlers[handlerKey].backupCount,
savingTime: logsConfig.handlers[handlerKey].interval, savingTime: logsConfig.handlers[handlerKey].interval,
savingPeriod: logsConfig.handlers[handlerKey].when, savingPeriod: logsConfig.handlers[handlerKey].when,
} };
} }
return {local: logsObject, logFormat, dateFormat}; return {local: logsObject, logFormat, dateFormat};
} }
toggleRpcFields(enable: boolean) {
const grpcGroup = this.gatewayConfigGroup.get('grpc') as FormGroup;
if (enable) {
grpcGroup.get('serverPort').enable();
grpcGroup.get('keepAliveTimeMs').enable();
grpcGroup.get('keepAliveTimeoutMs').enable();
grpcGroup.get('maxPingsWithoutData').enable();
grpcGroup.get('minTimeBetweenPingsMs').enable();
grpcGroup.get('minPingIntervalWithoutDataMs').enable();
} else {
grpcGroup.get('serverPort').disable();
grpcGroup.get('keepAliveTimeMs').disable();
grpcGroup.get('keepAliveTimeoutMs').disable();
grpcGroup.get('maxPingsWithoutData').disable();
grpcGroup.get('minTimeBetweenPingsMs').disable();
grpcGroup.get('minPingIntervalWithoutDataMs').disable();
}
}
clientIdUserNameFieldsToggle(type?: string) {
const clientIdForm = this.gatewayConfigGroup.get('thingsboard.security.clientId');
const usernameForm = this.gatewayConfigGroup.get('thingsboard.security.username');
switch (type) {
case 'clientId':
if (clientIdForm.enabled) {
clientIdForm.disable({emitEvent: false});
}
break;
case 'username':
if (usernameForm.enabled) {
usernameForm.disable({emitEvent: false});
}
break;
default:
if (clientIdForm.disabled) {
clientIdForm.enable({emitEvent: false});
}
if (usernameForm.disabled) {
usernameForm.enable({emitEvent: false});
}
break;
}
}
addCommand(command?): void { addCommand(command?): void {
const data = command || {}; const data = command || {};
const commandsFormArray = this.commandFormArray(); const commandsFormArray = this.commandFormArray();
@ -465,42 +527,42 @@ export class GatewayConfigurationComponent implements OnInit {
disable_existing_loggers: false, disable_existing_loggers: false,
formatters: { formatters: {
LogFormatter: { LogFormatter: {
class: "logging.Formatter", class: 'logging.Formatter',
format: logsObj.logFormat, format: logsObj.logFormat,
datefmt: logsObj.dateFormat, datefmt: logsObj.dateFormat,
} }
}, },
handlers: { handlers: {
consoleHandler: { consoleHandler: {
class: "logging.StreamHandler", class: 'logging.StreamHandler',
formatter: "LogFormatter", formatter: 'LogFormatter',
level: "DEBUG", level: 'DEBUG',
stream: "ext://sys.stdout" stream: 'ext://sys.stdout'
}, },
databaseHandler: { databaseHandler: {
class: "thingsboard_gateway.tb_utility.tb_logger.TimedRotatingFileHandler", class: 'thingsboard_gateway.tb_utility.tb_logger.TimedRotatingFileHandler',
formatter: "LogFormatter", formatter: 'LogFormatter',
filename: "./logs/database.log", filename: './logs/database.log',
backupCount: 1, backupCount: 1,
encoding: "utf-8" encoding: 'utf-8'
} }
}, },
loggers: { loggers: {
database: { database: {
handlers: ["databaseHandler", "consoleHandler"], handlers: ['databaseHandler', 'consoleHandler'],
level: "DEBUG", level: 'DEBUG',
propagate: false propagate: false
} }
}, },
root: { root: {
level: "ERROR", level: 'ERROR',
handlers: [ handlers: [
"consoleHandler" 'consoleHandler'
] ]
} }
} };
for (const key of Object.keys(logsObj.local)) { for (const key of Object.keys(logsObj.local)) {
logAttrObj.handlers[key+"Handler"] = this.createHandlerObj(logsObj.local[key], key); logAttrObj.handlers[key + 'Handler'] = this.createHandlerObj(logsObj.local[key], key);
logAttrObj.loggers[key] = this.createLoggerObj(logsObj.local[key], key); logAttrObj.loggers[key] = this.createLoggerObj(logsObj.local[key], key);
} }
return logAttrObj; return logAttrObj;
@ -508,22 +570,22 @@ export class GatewayConfigurationComponent implements OnInit {
createHandlerObj(logObj, key) { createHandlerObj(logObj, key) {
return { return {
class: "thingsboard_gateway.tb_utility.tb_logger.TimedRotatingFileHandler", class: 'thingsboard_gateway.tb_utility.tb_logger.TimedRotatingFileHandler',
formatter: "LogFormatter", formatter: 'LogFormatter',
filename: `${logObj.filePath}/${key}.log`, filename: `${logObj.filePath}/${key}.log`,
backupCount: logObj.backupCount, backupCount: logObj.backupCount,
interval: logObj.savingTime, interval: logObj.savingTime,
when: logObj.savingPeriod, when: logObj.savingPeriod,
encoding: "utf-8" encoding: 'utf-8'
} };
} }
createLoggerObj(logObj, key) { createLoggerObj(logObj, key) {
return { return {
handlers: [`${key}Handler`, "consoleHandler"], handlers: [`${key}Handler`, 'consoleHandler'],
level: logObj.logLevel, level: logObj.logLevel,
propagate: false propagate: false
} };
} }
saveConfig(): void { saveConfig(): void {

6
ui-ngx/src/app/shared/components/device/gateway-connectors.component.html

@ -16,8 +16,8 @@
--> -->
<form style="height: calc(100% - 7px)" fxLayout="column"> <form style="height: calc(100% - 7px)" fxLayout="column">
<div fxLayout="row" fxLayoutGap="15px" fxFlex class="connector-container"> <div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="15px" fxFlex class="connector-container">
<mat-card fxLayout="column" style="overflow: auto;"> <mat-card fxLayout="column" fxFlex.lt-md style="overflow: auto;">
<mat-toolbar class="mat-mdc-table-toolbar"> <mat-toolbar class="mat-mdc-table-toolbar">
<h2>Connectors</h2> <h2>Connectors</h2>
<span fxFlex></span> <span fxFlex></span>
@ -117,7 +117,7 @@
<mat-divider></mat-divider> <mat-divider></mat-divider>
</mat-card> </mat-card>
<div [formGroup]="connectorForm" fxLayout="column"> <div [formGroup]="connectorForm" fxLayout="column">
<mat-card fxLayout="row" fxLayoutGap="15px"> <mat-card fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="15px" fxLayoutGap.lt-md="5px">
<mat-form-field class="mat-block tb-value-type"> <mat-form-field class="mat-block tb-value-type">
<mat-label>Name</mat-label> <mat-label>Name</mat-label>
<input matInput formControlName="name"/> <input matInput formControlName="name"/>

56
ui-ngx/src/app/shared/components/device/gateway-connectors.component.ts

@ -84,7 +84,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
inactiveConnectorsDataSource: AttributeDatasource; inactiveConnectorsDataSource: AttributeDatasource;
dataSource: MatTableDataSource<AttributeData> dataSource: MatTableDataSource<AttributeData>;
displayedColumns = ['enabled', 'key', 'type', 'actions']; displayedColumns = ['enabled', 'key', 'type', 'actions'];
@ -142,7 +142,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
class: [''], class: [''],
configuration: [''], configuration: [''],
configurationJson: [{}, [Validators.required]] configurationJson: [{}, [Validators.required]]
}) });
this.connectorForm.disable(); this.connectorForm.disable();
} }
@ -172,19 +172,19 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.inactiveConnectors = []; this.inactiveConnectors = [];
this.updateData(true); this.updateData(true);
} }
}) });
} }
} }
saveConnector(): void { saveConnector(): void {
const value = this.connectorForm.value; const value = this.connectorForm.value;
value.configuration = this.camelize(value.name) + ".json"; value.configuration = this.camelize(value.name) + '.json';
if (value.type !== 'grpc') { if (value.type !== 'grpc') {
delete value.key; delete value.key;
} }
const attributesToSave = [{ const attributesToSave = [{
key: value.name, key: value.name,
value: value value
}]; }];
const attributesToDelete = []; const attributesToDelete = [];
const scope = (this.activeConnectors.includes(value.name) || !this.initialConnector) ? AttributeScope.SHARED_SCOPE : AttributeScope.SERVER_SCOPE; const scope = (this.activeConnectors.includes(value.name) || !this.initialConnector) ? AttributeScope.SHARED_SCOPE : AttributeScope.SERVER_SCOPE;
@ -194,8 +194,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
updateActiveConnectors = true; updateActiveConnectors = true;
const activeIndex = this.activeConnectors.indexOf(this.initialConnector.name); const activeIndex = this.activeConnectors.indexOf(this.initialConnector.name);
const inactiveIndex = this.inactiveConnectors.indexOf(this.initialConnector.name); const inactiveIndex = this.inactiveConnectors.indexOf(this.initialConnector.name);
if (activeIndex !== -1) this.activeConnectors.splice(activeIndex, 1); if (activeIndex !== -1) {this.activeConnectors.splice(activeIndex, 1);}
if (inactiveIndex !== -1) this.inactiveConnectors.splice(activeIndex, 1); if (inactiveIndex !== -1) {this.inactiveConnectors.splice(activeIndex, 1);}
} }
if (!this.activeConnectors.includes(value.name) && scope == AttributeScope.SHARED_SCOPE) { if (!this.activeConnectors.includes(value.name) && scope == AttributeScope.SHARED_SCOPE) {
this.activeConnectors.push(value.name); this.activeConnectors.push(value.name);
@ -217,9 +217,9 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
tasks.push(this.attributeService.deleteEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, attributesToDelete)); tasks.push(this.attributeService.deleteEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, attributesToDelete));
} }
forkJoin(tasks).subscribe(_ => { forkJoin(tasks).subscribe(_ => {
this.showToast("Update Successful") this.showToast('Update Successful');
this.updateData(true); this.updateData(true);
}) });
} }
resetSortAndFilter(update: boolean = true) { resetSortAndFilter(update: boolean = true) {
@ -240,15 +240,15 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.pageLink.sortOrder.direction = Direction[this.sort.direction.toUpperCase()]; this.pageLink.sortOrder.direction = Direction[this.sort.direction.toUpperCase()];
this.attributeDataSource.loadAttributes(this.device, AttributeScope.CLIENT_SCOPE, this.pageLink, reload).subscribe(data => { this.attributeDataSource.loadAttributes(this.device, AttributeScope.CLIENT_SCOPE, this.pageLink, reload).subscribe(data => {
this.activeData = data.data.filter(value => this.activeConnectors.includes(value.key)); this.activeData = data.data.filter(value => this.activeConnectors.includes(value.key));
this.combineData() this.combineData();
}); });
this.inactiveConnectorsDataSource.loadAttributes(this.device, AttributeScope.SHARED_SCOPE, this.pageLink, reload).subscribe(data => { this.inactiveConnectorsDataSource.loadAttributes(this.device, AttributeScope.SHARED_SCOPE, this.pageLink, reload).subscribe(data => {
this.inactiveData = data.data.filter(value =>this.inactiveConnectors.includes(value.key)); this.inactiveData = data.data.filter(value =>this.inactiveConnectors.includes(value.key));
this.combineData() this.combineData();
}); });
} }
combineData () { combineData() {
this.dataSource.data = [...this.activeData, ...this.inactiveData]; this.dataSource.data = [...this.activeData, ...this.inactiveData];
} }
@ -268,7 +268,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
class: '', class: '',
configuration: '', configuration: '',
configurationJson: {} configurationJson: {}
}) });
this.initialConnector = null; this.initialConnector = null;
this.connectorForm.markAsPristine(); this.connectorForm.markAsPristine();
} }
@ -279,7 +279,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
} }
const connector = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value; const connector = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value;
if (!connector.configuration) { if (!connector.configuration) {
connector.configuration = ""; connector.configuration = '';
} }
if (!connector.key) { if (!connector.key) {
connector.key = 'auto'; connector.key = 'auto';
@ -303,9 +303,9 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
})); }));
} }
returnType (attribute) { returnType(attribute) {
const value = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value; const value = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value;
return this.gatewayConnectorDefaultTypes.get(value.type) return this.gatewayConnectorDefaultTypes.get(value.type);
} }
deleteConnector(attribute: AttributeData, $event: Event): void { deleteConnector(attribute: AttributeData, $event: Event): void {
@ -321,8 +321,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
tasks.push(this.attributeService.deleteEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, [attribute])); tasks.push(this.attributeService.deleteEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, [attribute]));
const activeIndex = this.activeConnectors.indexOf(attribute.key); const activeIndex = this.activeConnectors.indexOf(attribute.key);
const inactiveIndex = this.inactiveConnectors.indexOf(attribute.key); const inactiveIndex = this.inactiveConnectors.indexOf(attribute.key);
if (activeIndex !== -1) this.activeConnectors.splice(activeIndex, 1); if (activeIndex !== -1) {this.activeConnectors.splice(activeIndex, 1);}
if (inactiveIndex !== -1) this.inactiveConnectors.splice(activeIndex, 1); if (inactiveIndex !== -1) {this.inactiveConnectors.splice(activeIndex, 1);}
tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{ tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{
key: scope == AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors', key: scope == AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors',
value: scope == AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors value: scope == AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors
@ -333,10 +333,10 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.cd.detectChanges(); this.cd.detectChanges();
this.connectorForm.disable(); this.connectorForm.disable();
} }
this.updateData() this.updateData();
}) });
} }
}) });
} }
camelize(str): string { camelize(str): string {
@ -350,8 +350,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
attribute.value = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value; attribute.value = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value;
const params = deepClone(this.ctx.stateController.getStateParams()); const params = deepClone(this.ctx.stateController.getStateParams());
params.connector_logs = attribute; params.connector_logs = attribute;
params.targetEntityParamName = "connector_logs"; params.targetEntityParamName = 'connector_logs';
this.ctx.stateController.openState("connector_logs", params); this.ctx.stateController.openState('connector_logs', params);
} }
connectorRpc(attribute: AttributeData, $event: Event): void { connectorRpc(attribute: AttributeData, $event: Event): void {
@ -361,19 +361,19 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
attribute.value = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value; attribute.value = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value;
const params = deepClone(this.ctx.stateController.getStateParams()); const params = deepClone(this.ctx.stateController.getStateParams());
params.connector_rpc = attribute; params.connector_rpc = attribute;
params.targetEntityParamName = "connector_rpc"; params.targetEntityParamName = 'connector_rpc';
this.ctx.stateController.openState("connector_rpc", params); this.ctx.stateController.openState('connector_rpc', params);
} }
enableConnector(attribute): void { enableConnector(attribute): void {
const wasEnabled = this.activeConnectors.includes(attribute.key); const wasEnabled = this.activeConnectors.includes(attribute.key);
if (wasEnabled) { if (wasEnabled) {
let index = this.activeConnectors.indexOf(attribute.key); const index = this.activeConnectors.indexOf(attribute.key);
this.activeConnectors.splice(index, 1); this.activeConnectors.splice(index, 1);
this.inactiveConnectors.push(attribute.key); this.inactiveConnectors.push(attribute.key);
} else { } else {
let index = this.inactiveConnectors.indexOf(attribute.key); const index = this.inactiveConnectors.indexOf(attribute.key);
this.inactiveConnectors.splice(index, 1); this.inactiveConnectors.splice(index, 1);
this.activeConnectors.push(attribute.key); this.activeConnectors.push(attribute.key);
} }
@ -385,7 +385,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
value: this.inactiveConnectors value: this.inactiveConnectors
}]),]).subscribe(_ => { }]),]).subscribe(_ => {
this.updateData(); this.updateData();
}) });
} }
} }

4
ui-ngx/src/app/shared/components/device/gateway-logs.component.scss

@ -43,8 +43,8 @@
} }
.status-info { .status-info {
color: black; color: blue;
background: rgba(0, 0, 0, 0.1); background: rgba(0, 0, 128, 0.1);
} }
.msg-status-exception { .msg-status-exception {

2
ui-ngx/src/app/shared/components/device/gateway-statistics.component.html

@ -16,7 +16,7 @@
--> -->
<div class="statistics-container" fxLayout="row"> <div class="statistics-container" fxLayout="row" fxLayout.lt-md="column">
<mat-card [formGroup]="statisticForm" *ngIf="!general"> <mat-card [formGroup]="statisticForm" *ngIf="!general">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label>{{'gateway.statistics.statistic' | translate}}</mat-label> <mat-label>{{'gateway.statistics.statistic' | translate}}</mat-label>

9
ui-ngx/src/app/shared/components/device/gateway-statistics.component.scss

@ -21,15 +21,24 @@
.statistics-container { .statistics-container {
height: 100%; height: 100%;
overflow-y: auto;
mat-card { mat-card {
width: 40%; width: 40%;
height: 100%;
margin-right: 35px; margin-right: 35px;
padding: 15px; padding: 15px;
} }
@media only screen and (max-width: 750px) {
mat-card {
width: 100%;
}
}
.chart-box, .chart-container { .chart-box, .chart-container {
height: 100%; height: 100%;
min-height: 300px;
flex-grow: 1; flex-grow: 1;
} }

Loading…
Cancel
Save