diff --git a/application/src/main/data/json/demo/dashboards/gateway_list.json b/application/src/main/data/json/demo/dashboards/gateway_list.json
index 5d4760fb37..24b547c8bc 100644
--- a/application/src/main/data/json/demo/dashboards/gateway_list.json
+++ b/application/src/main/data/json/demo/dashboards/gateway_list.json
@@ -479,6 +479,14 @@
"funcBody": null,
"usePostProcessing": true,
"postFuncBody": "var newValue = value == 'true' ? \"Active\" : \"Inactive\";\nreturn newValue;"
+ },
+ {
+ "name": "ALL_ERRORS_COUNT",
+ "type": "timeseries",
+ "label": "ALL_ERRORS_COUNT",
+ "color": "#ffeb3b",
+ "settings": {},
+ "_hash": 0.2770587478725004
}
],
"alarmFilterConfig": {
@@ -550,7 +558,7 @@
"padding": "8px",
"settings": {
"useMarkdownTextFunction": true,
- "markdownTextFunction": "var blockData = '';\nfunction createDataBlock(value, label, dividerStyle, mobile) {\n blockData += `\n \n \n \n \n ${label}\n \n ${value}\n `;\n}\ncreateDataBlock(data[0].Status, \"Status\", data[0].Status === \"Active\"? 'divider-green' : 'divider-red');\ncreateDataBlock(data[0].Name, \"Gateway Name\", '', ctx.isMobile);\ncreateDataBlock(data[0].Type, \"Gateway Type\", '');\ncreateDataBlock((data[1]?data[1].count:0) + \" | \" + (data[2]?data[2][\"count 2\"]:0), \"Devices\", '');\ncreateDataBlock((data[0].active_connectors?JSON.parse(data[0].active_connectors).length:0) + \" | \" + (data[0].inactive_connectors?JSON.parse(data[0].inactive_connectors).length:0), \"Connectors\", '');\nreturn `
${blockData}
`;",
+ "markdownTextFunction": "var blockData = '';\nfunction createDataBlock(value, label, dividerStyle, mobile) {\n blockData += `\n \n \n \n \n ${label}\n \n ${value}\n `;\n}\ncreateDataBlock(data[0].Status, \"Status\", data[0].Status === \"Active\"? 'divider-green' : 'divider-red');\ncreateDataBlock(data[0].Name, \"Gateway Name\", '', ctx.isMobile);\ncreateDataBlock(data[0].Type, \"Gateway Type\", '');\ncreateDataBlock(\n `${(data[1]?data[1].count:0)} `\n + \" | \" + \n `${(data[2]?data[2][\"count 2\"]:0)} `\n , \"Devices\", '');\ncreateDataBlock(\n `${(data[0].active_connectors?JSON.parse(data[0].active_connectors).length:0)} `\n + \" | \" + \n `${(data[0].inactive_connectors?JSON.parse(data[0].inactive_connectors).length:0)} `\n , \"Connectors\", '');\ncreateDataBlock(data[0].ALL_ERRORS_COUNT || 0, \"Errors\", (data[0].ALL_ERRORS_COUNT || 0) === 0 ? 'divider-green' : 'divider-red');\nreturn `${blockData}
`;",
"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.divider-green .divider {\n border: 1px solid rgb(25,128,56);\n background-color: rgb(25,128,56);\n}\n\n.divider-green .mat-mdc-card-content {\n color: rgb(25,128,56);\n}\n\n.divider-red .divider {\n border: 1px solid rgb(203,37,48);\n background-color: rgb(203,37,48);\n}\n\n.divider-red .mat-mdc-card-content {\n color: rgb(203,37,48);\n}\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}"
},
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html
index f35754aea2..652f73fa1b 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html
@@ -69,6 +69,20 @@
}">{{isConnectorSynced(attribute)?'sync' : 'out of sync'}}
+
+
+ {{ 'gateway.connectors-table-status' | translate }}
+
+
+ 0,
+ 'noErrors': +getErrorsCount(attribute) == 0 || getErrorsCount(attribute) == ''
+ }">
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss
index 6d5a6c4585..87e099d652 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss
@@ -90,6 +90,22 @@
mat-row {
cursor: pointer;
}
+
+ .dot {
+ height: 25px;
+ width: 25px;
+ background-color: #bbb;
+ border-radius: 50%;
+ display: inline-block;
+ }
+
+ .hasErrors {
+ background-color: rgb(203, 37, 48);
+ }
+
+ .noErrors {
+ background-color: rgb(25, 128, 56);
+ }
}
:host ::ng-deep tb-json-object-edit > div {
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts
index dccf0e8657..f673f67cf4 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts
@@ -39,6 +39,10 @@ import { DialogService } from '@core/services/dialog.service';
import { WidgetContext } from '@home/models/widget-component.models';
import { deepClone } from '@core/utils';
import { NULL_UUID } from '@shared/models/id/has-uuid';
+import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
+import { DatasourceType, widgetType } from '@shared/models/widget.models';
+import { UtilsService } from '@core/services/utils.service';
+import { EntityType } from '@shared/models/entity-type.models';
export interface gatewayConnector {
@@ -88,7 +92,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
dataSource: MatTableDataSource;
- displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'actions'];
+ displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions'];
gatewayConnectorDefaultTypes = GatewayConnectorDefaultTypesTranslates;
@@ -123,6 +127,19 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
initialConnector: gatewayConnector;
+ subscriptionOptions: WidgetSubscriptionOptions = {
+ callbacks: {
+ onDataUpdated: () => this.ctx.ngZone.run(() => {
+ this.onDataUpdated();
+ }),
+ onDataUpdateError: (subscription, e) => this.ctx.ngZone.run(() => {
+ this.onDataUpdateError(e);
+ })
+ }
+ };
+
+ subscription: IWidgetSubscription;
+
constructor(protected router: Router,
protected store: Store,
protected fb: FormBuilder,
@@ -132,6 +149,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
protected dialogService: DialogService,
private telemetryWsService: TelemetryWebsocketService,
private zone: NgZone,
+ private utils: UtilsService,
private cd: ChangeDetectorRef,
public dialog: MatDialog) {
super(store);
@@ -270,6 +288,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
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.combineData();
+ this.generateSubscription();
});
this.inactiveConnectorsDataSource.loadAttributes(this.device, AttributeScope.SHARED_SCOPE, this.pageLink, reload).subscribe(data => {
this.sharedAttributeData = data.data.filter(value => this.activeConnectors.includes(value.key));
@@ -279,7 +298,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
this.inactiveData = data.data.filter(value => this.inactiveConnectors.includes(value.key));
this.combineData();
});
-
}
isConnectorSynced(attribute: AttributeData) {
@@ -457,4 +475,43 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
});
}
+ onDataUpdateError(e: any) {
+ const exceptionData = this.utils.parseException(e);
+ let errorText = exceptionData.name;
+ if (exceptionData.message) {
+ errorText += ': ' + exceptionData.message;
+ }
+ console.error(errorText);
+ }
+
+ onDataUpdated() {
+ this.cd.detectChanges();
+ }
+
+ generateSubscription() {
+ if (this.subscription) {
+ this.subscription.unsubscribe();
+ }
+ if (this.device) {
+ const subscriptionInfo = [{
+ type: DatasourceType.entity,
+ entityType: EntityType.DEVICE,
+ entityId: this.device.id,
+ entityName: "Gateway",
+ timeseries: []
+ }];
+ this.dataSource.data.forEach(value => {
+ subscriptionInfo[0].timeseries.push({name: `${value.key}_ERRORS_COUNT`, label: `${value.key}_ERRORS_COUNT`})
+ })
+ this.ctx.subscriptionApi.createSubscriptionFromInfo(widgetType.latest, subscriptionInfo,this.subscriptionOptions, false, true).subscribe(subscription => {
+ this.subscription = subscription;
+ });
+ }
+ }
+
+ getErrorsCount(attribute) {
+ const connectorName = attribute.key;
+ const connector = this.subscription.data.find(data=>data && data.dataKey.name === `${connectorName}_ERRORS_COUNT`);
+ return (connector && this.activeConnectors.includes(connectorName))? connector.data[0][1]: 'inactive';
+ }
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-logs.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-logs.component.ts
index c4fb8a3534..f724e9dff9 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-logs.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-logs.component.ts
@@ -219,7 +219,7 @@ export class GatewayLogsComponent extends PageComponent implements AfterViewInit
}
changeSubscription() {
- if (this.ctx.datasources[0].entity) {
+ if (this.ctx.datasources && this.ctx.datasources[0].entity && this.ctx.defaultSubscription.options.datasources) {
this.ctx.defaultSubscription.options.datasources[0].dataKeys = [{
name: this.activeLink.key,
type: DataKeyType.timeseries,
diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json
index b9d14eff0e..25969fb9e0 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -2617,7 +2617,7 @@
"connectors-table-enabled": "Enabled",
"connectors-table-name": "Name",
"connectors-table-type": "Type",
- "connectors-table-status": "Sync status",
+ "connectors-table-status": "Status",
"connectors-table-actions": "Actions",
"connectors-table-key": "Key",
"connectors-table-class": "Class",