connector status and new gateway cards
This commit is contained in:
parent
b94a55944c
commit
67031e43da
@ -479,6 +479,14 @@
|
|||||||
"funcBody": null,
|
"funcBody": null,
|
||||||
"usePostProcessing": true,
|
"usePostProcessing": true,
|
||||||
"postFuncBody": "var newValue = value == 'true' ? \"Active\" : \"Inactive\";\nreturn newValue;"
|
"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": {
|
"alarmFilterConfig": {
|
||||||
@ -550,7 +558,7 @@
|
|||||||
"padding": "8px",
|
"padding": "8px",
|
||||||
"settings": {
|
"settings": {
|
||||||
"useMarkdownTextFunction": true,
|
"useMarkdownTextFunction": true,
|
||||||
"markdownTextFunction": "var blockData = '';\nfunction createDataBlock(value, label, dividerStyle, mobile) {\n blockData += `\n <mat-card style=\"flex-grow: 1; width: ${mobile? '100%': 'auto'}; min-height: ${mobile? 'auto': '57px'}\" class=\" ${dividerStyle}\">\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].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 `<div fxLayout=\"row wrap\" fxLayoutGap=\"8px\" class=\"cards-container\">${blockData}</div>`;",
|
"markdownTextFunction": "var blockData = '';\nfunction createDataBlock(value, label, dividerStyle, mobile) {\n blockData += `\n <mat-card style=\"flex-grow: 1; width: ${mobile? '100%': 'auto'}; min-height: ${mobile? 'auto': '57px'}\" class=\" ${dividerStyle}\">\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].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 `<span style=\"color:rgb(25,128,56)\">${(data[1]?data[1].count:0)} </span>`\n + \" | \" + \n `<span style=\"color:rgb(203,37,48)\">${(data[2]?data[2][\"count 2\"]:0)} </span>`\n , \"Devices\", '');\ncreateDataBlock(\n `<span style=\"color:rgb(25,128,56)\">${(data[0].active_connectors?JSON.parse(data[0].active_connectors).length:0)} </span>`\n + \" | \" + \n `<span style=\"color:rgb(203,37,48)\">${(data[0].inactive_connectors?JSON.parse(data[0].inactive_connectors).length:0)} </span>`\n , \"Connectors\", '');\ncreateDataBlock(data[0].ALL_ERRORS_COUNT || 0, \"Errors\", (data[0].ALL_ERRORS_COUNT || 0) === 0 ? 'divider-green' : 'divider-red');\nreturn `<div fxLayout=\"row wrap\" fxLayoutGap=\"8px\" class=\"cards-container\">${blockData}</div>`;",
|
||||||
"applyDefaultMarkdownStyle": false,
|
"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}"
|
"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}"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -69,6 +69,20 @@
|
|||||||
}">{{isConnectorSynced(attribute)?'sync' : 'out of sync'}}</div>
|
}">{{isConnectorSynced(attribute)?'sync' : 'out of sync'}}</div>
|
||||||
</mat-cell>
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="errors">
|
||||||
|
<mat-header-cell *matHeaderCellDef mat-sort-header style="width: 30%">
|
||||||
|
{{ 'gateway.connectors-table-status' | translate }}
|
||||||
|
</mat-header-cell>
|
||||||
|
<mat-cell *matCellDef="let attribute" style="text-transform: uppercase">
|
||||||
|
<span class="dot"
|
||||||
|
matTooltip="{{getErrorsCount(attribute)}}"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
[ngClass]="{
|
||||||
|
'hasErrors': +getErrorsCount(attribute) > 0,
|
||||||
|
'noErrors': +getErrorsCount(attribute) == 0 || getErrorsCount(attribute) == ''
|
||||||
|
}"></span>
|
||||||
|
</mat-cell>
|
||||||
|
</ng-container>
|
||||||
<ng-container matColumnDef="actions" stickyEnd>
|
<ng-container matColumnDef="actions" stickyEnd>
|
||||||
<mat-header-cell *matHeaderCellDef
|
<mat-header-cell *matHeaderCellDef
|
||||||
[ngStyle.gt-md]="{ minWidth: '144px', maxWidth: '144px', width: '144px'}">
|
[ngStyle.gt-md]="{ minWidth: '144px', maxWidth: '144px', width: '144px'}">
|
||||||
|
|||||||
@ -90,6 +90,22 @@
|
|||||||
mat-row {
|
mat-row {
|
||||||
cursor: pointer;
|
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 {
|
:host ::ng-deep tb-json-object-edit > div {
|
||||||
|
|||||||
@ -39,6 +39,10 @@ import { DialogService } from '@core/services/dialog.service';
|
|||||||
import { WidgetContext } from '@home/models/widget-component.models';
|
import { WidgetContext } from '@home/models/widget-component.models';
|
||||||
import { deepClone } from '@core/utils';
|
import { deepClone } from '@core/utils';
|
||||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
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 {
|
export interface gatewayConnector {
|
||||||
@ -88,7 +92,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
|
|
||||||
dataSource: MatTableDataSource<AttributeData>;
|
dataSource: MatTableDataSource<AttributeData>;
|
||||||
|
|
||||||
displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'actions'];
|
displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions'];
|
||||||
|
|
||||||
gatewayConnectorDefaultTypes = GatewayConnectorDefaultTypesTranslates;
|
gatewayConnectorDefaultTypes = GatewayConnectorDefaultTypesTranslates;
|
||||||
|
|
||||||
@ -123,6 +127,19 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
|
|
||||||
initialConnector: gatewayConnector;
|
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,
|
constructor(protected router: Router,
|
||||||
protected store: Store<AppState>,
|
protected store: Store<AppState>,
|
||||||
protected fb: FormBuilder,
|
protected fb: FormBuilder,
|
||||||
@ -132,6 +149,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
protected dialogService: DialogService,
|
protected dialogService: DialogService,
|
||||||
private telemetryWsService: TelemetryWebsocketService,
|
private telemetryWsService: TelemetryWebsocketService,
|
||||||
private zone: NgZone,
|
private zone: NgZone,
|
||||||
|
private utils: UtilsService,
|
||||||
private cd: ChangeDetectorRef,
|
private cd: ChangeDetectorRef,
|
||||||
public dialog: MatDialog) {
|
public dialog: MatDialog) {
|
||||||
super(store);
|
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.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.generateSubscription();
|
||||||
});
|
});
|
||||||
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.sharedAttributeData = data.data.filter(value => this.activeConnectors.includes(value.key));
|
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.inactiveData = data.data.filter(value => this.inactiveConnectors.includes(value.key));
|
||||||
this.combineData();
|
this.combineData();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isConnectorSynced(attribute: AttributeData) {
|
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';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -219,7 +219,7 @@ export class GatewayLogsComponent extends PageComponent implements AfterViewInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
changeSubscription() {
|
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 = [{
|
this.ctx.defaultSubscription.options.datasources[0].dataKeys = [{
|
||||||
name: this.activeLink.key,
|
name: this.activeLink.key,
|
||||||
type: DataKeyType.timeseries,
|
type: DataKeyType.timeseries,
|
||||||
|
|||||||
@ -2617,7 +2617,7 @@
|
|||||||
"connectors-table-enabled": "Enabled",
|
"connectors-table-enabled": "Enabled",
|
||||||
"connectors-table-name": "Name",
|
"connectors-table-name": "Name",
|
||||||
"connectors-table-type": "Type",
|
"connectors-table-type": "Type",
|
||||||
"connectors-table-status": "Sync status",
|
"connectors-table-status": "Status",
|
||||||
"connectors-table-actions": "Actions",
|
"connectors-table-actions": "Actions",
|
||||||
"connectors-table-key": "Key",
|
"connectors-table-key": "Key",
|
||||||
"connectors-table-class": "Class",
|
"connectors-table-class": "Class",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user