Browse Source

new fixes & updates

pull/8337/head
Maksym Dudnik 3 years ago
parent
commit
9dfe9d0b7f
  1. 40
      application/src/main/data/json/demo/dashboards/gateway_list.json
  2. 2
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-configuration.component.html
  3. 5
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-configuration.component.ts
  4. 2
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html
  5. 73
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts
  6. 2
      ui-ngx/src/assets/locale/locale.constant-en_US.json

40
application/src/main/data/json/demo/dashboards/gateway_list.json

@ -434,20 +434,6 @@
"settings": {},
"_hash": 0.9806146353493157
},
{
"name": "Status",
"type": "attribute",
"label": "active",
"color": "#f44336",
"settings": {},
"_hash": 0.7141801635241265,
"aggregationType": null,
"units": null,
"decimals": null,
"funcBody": null,
"usePostProcessing": true,
"postFuncBody": "var newValue = value == 'true' ? \"Active\" : \"Inactive\";\r\nreturn newValue;"
},
{
"name": "activeDevices",
"type": "attribute",
@ -479,6 +465,20 @@
"color": "#e91e63",
"settings": {},
"_hash": 0.36755550699981954
},
{
"name": "active",
"type": "attribute",
"label": "Status",
"color": "#e91e63",
"settings": {},
"_hash": 0.10301612696488416,
"aggregationType": null,
"units": null,
"decimals": null,
"funcBody": null,
"usePostProcessing": true,
"postFuncBody": "var newValue = value == 'true' ? \"Active\" : \"Inactive\";\nreturn newValue;"
}
],
"alarmFilterConfig": {
@ -550,7 +550,7 @@
"padding": "8px",
"settings": {
"useMarkdownTextFunction": true,
"markdownTextFunction": "var blockData = '';\n\nfunction createDataBlock(value, label, mobile) {\n blockData += `\n <mat-card style=\"flex-grow: 1; width: ${mobile? '100%': 'auto'}; min-height: ${mobile? 'auto': '57px'}\">\n <div class=\"divider\"></div>\n <mat-divider vertical style=\"height:100%\"></mat-divider>\n <mat-card-header>\n <mat-card-subtitle>${label}</mat-card-subtitle>\n </mat-card-header>\n <mat-card-content> ${value}</mat-card-content>\n </mat-card>`;\n}\ncreateDataBlock(data[0].Name, \"Gateway Name\", ctx.isMobile);\ncreateDataBlock(data[0].Type, \"Gateway Type\");\ncreateDataBlock(data[0].active, \"Status\");\ncreateDataBlock(data[1]?data[1].count:0, \"Active Devices\");\ncreateDataBlock(data[2]?data[2][\"count 2\"]:0, \"Inactive Devices\");\ncreateDataBlock(data[0].active_connectors?JSON.parse(data[0].active_connectors).length:0, \"Enabled Connectors\");\ncreateDataBlock(data[0].inactive_connectors?JSON.parse(data[0].inactive_connectors).length:0, \"Disabled Connectors\");\nreturn `<div fxLayout=\"row wrap\" fxLayoutGap=\"8px\" class=\"cards-container\">${blockData}</div>`;",
"markdownTextFunction": "var blockData = '';\n\nfunction createDataBlock(value, label, mobile) {\n blockData += `\n <mat-card style=\"flex-grow: 1; width: ${mobile? '100%': 'auto'}; min-height: ${mobile? 'auto': '57px'}\">\n <div class=\"divider\"></div>\n <mat-divider vertical style=\"height:100%\"></mat-divider>\n <mat-card-header>\n <mat-card-subtitle>${label}</mat-card-subtitle>\n </mat-card-header>\n <mat-card-content> ${value}</mat-card-content>\n </mat-card>`;\n}\ncreateDataBlock(data[0].Name, \"Gateway Name\", ctx.isMobile);\ncreateDataBlock(data[0].Type, \"Gateway Type\");\ncreateDataBlock(data[0].Status, \"Status\");\ncreateDataBlock(data[1]?data[1].count:0, \"Active Devices\");\ncreateDataBlock(data[2]?data[2][\"count 2\"]:0, \"Inactive Devices\");\ncreateDataBlock(data[0].active_connectors?JSON.parse(data[0].active_connectors).length:0, \"Enabled Connectors\");\ncreateDataBlock(data[0].inactive_connectors?JSON.parse(data[0].inactive_connectors).length:0, \"Disabled Connectors\");\nreturn `<div fxLayout=\"row wrap\" fxLayoutGap=\"8px\" class=\"cards-container\">${blockData}</div>`;",
"applyDefaultMarkdownStyle": false,
"markdownCss": ".divider {\n position: absolute;\n width: 3px;\n top: 8px;\n border-radius: 2px;\n bottom: 8px;\n border: 1px solid rgba(31, 70, 144, 1);\n background-color: rgba(31, 70, 144, 1);\n left: 10px;\n}\n.mdc-card {\n position: relative;\n padding-left: 10px;\n margin-bottom: 1px;\n}\n\n.mat-mdc-card-subtitle {\n font-weight: 400;\n font-size: 12px;\n}\n\n.mat-mdc-card-header {\n padding: 8px 16px 0;\n}\n\n.mat-mdc-card-content:last-child {\n padding-bottom: 8px;\n font-size: 16px;\n}\n\n.cards-container {\n height: calc(100% - 1px);\n justify-content: stretch;\n align-items: center;\n margin-bottom: 1px;\n}"
},
@ -1385,13 +1385,16 @@
"padding": "8px",
"settings": {
"enableSearch": true,
"enableSelectColumnDisplay": true,
"enableStickyHeader": true,
"enableStickyAction": true,
"showCellActionsMenu": true,
"reserveSpaceForHiddenAction": "true",
"showTimestamp": true,
"showMilliseconds": false,
"displayPagination": false,
"displayPagination": true,
"useEntityLabel": false,
"defaultPageSize": 10,
"hideEmptyLines": true,
"disableStickyHeader": false,
"useRowStyleFunction": false
@ -1714,13 +1717,16 @@
"padding": "8px",
"settings": {
"enableSearch": true,
"enableSelectColumnDisplay": true,
"enableStickyHeader": true,
"enableStickyAction": true,
"showCellActionsMenu": true,
"reserveSpaceForHiddenAction": "true",
"showTimestamp": true,
"showMilliseconds": false,
"displayPagination": false,
"displayPagination": true,
"useEntityLabel": false,
"defaultPageSize": 10,
"hideEmptyLines": true,
"disableStickyHeader": false,
"useRowStyleFunction": false

2
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-configuration.component.html

@ -683,7 +683,7 @@
</mat-icon>
</mat-form-field>
</mat-card>
<button mat-icon-button (click)="removeCommandControl($index)"
<button mat-icon-button (click)="removeCommandControl($index, $event)"
[disabled]="!gatewayConfigGroup.get('thingsboard.remoteConfiguration').value"
matTooltip="{{ 'gateway.statistics.remove' | translate }}"
matTooltipPosition="above">

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

@ -227,8 +227,6 @@ export class GatewayConfigurationComponent implements OnInit {
})
});
console.log(this.gatewayConfigGroup)
this.gatewayConfigGroup.get('thingsboard.security.password').valueChanges.subscribe(password => {
if (password && password !== '') {
this.gatewayConfigGroup.get('thingsboard.security.username').setValidators([Validators.required]);
@ -507,7 +505,8 @@ export class GatewayConfigurationComponent implements OnInit {
return this.gatewayConfigGroup.get('thingsboard.statistics.commands') as FormArray;
}
removeCommandControl(index: number): void {
removeCommandControl(index: number, event: any): void {
if (event.pointerType === '') return;
this.commandFormArray().removeAt(index);
this.gatewayConfigGroup.markAsDirty();
}

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

@ -66,7 +66,7 @@
'status-block': true,
'status-sync':isConnectorSynced(attribute),
'status-unsync':!isConnectorSynced(attribute)
}">{{isConnectorSynced(attribute)?'Synchronised' : 'Unsynchronised'}}</div>
}">{{isConnectorSynced(attribute)?'sync' : 'out of sync'}}</div>
</mat-cell>
</ng-container>
<ng-container matColumnDef="actions" stickyEnd>

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

@ -18,7 +18,7 @@ import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, NgZone,
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FormBuilder, FormGroup, UntypedFormControl, ValidatorFn, Validators } from '@angular/forms';
import { EntityId } from '@shared/models/id/entity-id';
import { MatDialog } from '@angular/material/dialog';
import { AttributeService } from '@core/http/attribute.service';
@ -120,6 +120,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
inactiveData: Array<any> = [];
initialConnector: gatewayConnector;
constructor(protected router: Router,
protected store: Store<AppState>,
protected fb: FormBuilder,
@ -138,7 +140,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.inactiveConnectorsDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate);
this.dataSource = new MatTableDataSource<AttributeData>([]);
this.connectorForm = this.fb.group({
name: ['', [Validators.required]],
name: ['', [Validators.required, this.uniqNameRequired()]],
type: ['', [Validators.required]],
logLevel: ['', [Validators.required]],
key: ['auto'],
@ -149,9 +151,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.connectorForm.disable();
}
initialConnector: gatewayConnector;
ngAfterViewInit() {
this.connectorForm.valueChanges.subscribe(() => {
this.cd.detectChanges();
@ -169,9 +168,9 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors'])).subscribe(attributes => {
if (attributes.length) {
this.activeConnectors = attributes[0].length ? attributes[0][0].value : [];
this.activeConnectors = typeof this.activeConnectors === 'string' ? JSON.parse(this.activeConnectors): this.activeConnectors;
this.activeConnectors = typeof this.activeConnectors === 'string' ? JSON.parse(this.activeConnectors) : this.activeConnectors;
this.inactiveConnectors = attributes[1].length ? attributes[1][0].value : [];
this.inactiveConnectors = typeof this.inactiveConnectors === 'string' ? JSON.parse(this.inactiveConnectors): this.inactiveConnectors;
this.inactiveConnectors = typeof this.inactiveConnectors === 'string' ? JSON.parse(this.inactiveConnectors) : this.inactiveConnectors;
this.updateData(true);
} else {
this.activeConnectors = [];
@ -182,6 +181,27 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
}
}
uniqNameRequired(): ValidatorFn {
return (c: UntypedFormControl) => {
const newName = c.value.trim().toLowerCase();
const found = this.dataSource.data.find((connectorAttr) => {
const connectorData = typeof connectorAttr.value === 'string' ? JSON.parse(connectorAttr.value) : connectorAttr.value;
return connectorData.name.toLowerCase() === newName;
});
if (found) {
if (this.initialConnector && this.initialConnector.name.toLowerCase() === newName) {
return null;
}
return {
duplicateName: {
valid: false
}
};
}
return null;
};
}
saveConnector(): void {
const value = this.connectorForm.value;
value.configuration = this.camelize(value.name) + '.json';
@ -204,8 +224,12 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
updateActiveConnectors = true;
const activeIndex = this.activeConnectors.indexOf(this.initialConnector.name);
const inactiveIndex = this.inactiveConnectors.indexOf(this.initialConnector.name);
if (activeIndex !== -1) {this.activeConnectors.splice(activeIndex, 1);}
if (inactiveIndex !== -1) {this.inactiveConnectors.splice(activeIndex, 1);}
if (activeIndex !== -1) {
this.activeConnectors.splice(activeIndex, 1);
}
if (inactiveIndex !== -1) {
this.inactiveConnectors.splice(activeIndex, 1);
}
}
if (!this.activeConnectors.includes(value.name) && scope == AttributeScope.SHARED_SCOPE) {
this.activeConnectors.push(value.name);
@ -253,17 +277,22 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.combineData();
});
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.sharedAttributeData = data.data.filter(value => this.activeConnectors.includes(value.key));
this.combineData();
});
}
isConnectorSynced(attribute: AttributeData) {
const connectorData = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value;
const connectorData = typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value;
if (!connectorData.ts) return false;
const sharedIndex = this.sharedAttributeData.findIndex(data=>{
const sharedData = typeof data.value === 'string' ? JSON.parse(data.value): data.value;
const clientIndex = this.activeData.findIndex(data => {
const sharedData = typeof data.value === 'string' ? JSON.parse(data.value) : data.value;
return sharedData.name === connectorData.name;
})
if (clientIndex == -1) return false;
const sharedIndex = this.sharedAttributeData.findIndex(data => {
const sharedData = typeof data.value === 'string' ? JSON.parse(data.value) : data.value;
return sharedData.name === connectorData.name && sharedData.ts && sharedData.ts <= connectorData.ts;
})
return sharedIndex !== -1;
@ -298,7 +327,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
if (this.connectorForm.disabled) {
this.connectorForm.enable();
}
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) {
connector.configuration = '';
}
@ -325,8 +354,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
}
returnType(attribute) {
const value = typeof attribute.value === 'string' ? JSON.parse(attribute.value): attribute.value;
return this.gatewayConnectorDefaultTypes.get(value.type);
const value = typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value;
return this.gatewayConnectorDefaultTypes.get(value.type);
}
deleteConnector(attribute: AttributeData, $event: Event): void {
@ -342,8 +371,12 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
tasks.push(this.attributeService.deleteEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, [attribute]));
const activeIndex = this.activeConnectors.indexOf(attribute.key);
const inactiveIndex = this.inactiveConnectors.indexOf(attribute.key);
if (activeIndex !== -1) {this.activeConnectors.splice(activeIndex, 1);}
if (inactiveIndex !== -1) {this.inactiveConnectors.splice(activeIndex, 1);}
if (activeIndex !== -1) {
this.activeConnectors.splice(activeIndex, 1);
}
if (inactiveIndex !== -1) {
this.inactiveConnectors.splice(activeIndex, 1);
}
tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{
key: scope == AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors',
value: scope == AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors
@ -368,7 +401,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
if ($event) {
$event.stopPropagation();
}
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());
params.connector_logs = attribute;
params.targetEntityParamName = 'connector_logs';
@ -379,7 +412,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
if ($event) {
$event.stopPropagation();
}
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());
params.connector_rpc = attribute;
params.targetEntityParamName = 'connector_rpc';

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

@ -2736,7 +2736,7 @@
"send-period-required": "Statistic send period is required",
"send-period-min": "Statistic send period can not be less then 60",
"send-period-pattern": "Statistic send period is not valid",
"check-connectors-configuration": "Check connectors configuration (in s)",
"check-connectors-configuration": "Check connectors configuration (in sec)",
"check-connectors-configuration-required": "Check connectors configuration is required",
"check-connectors-configuration-min": "Check connectors configuration can not be less then 1",
"check-connectors-configuration-pattern": "Check connectors configuration is not valid",

Loading…
Cancel
Save