connector status and new gateway cards
This commit is contained in:
parent
b94a55944c
commit
67031e43da
@ -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 <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,
|
||||
"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>
|
||||
</mat-cell>
|
||||
</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>
|
||||
<mat-header-cell *matHeaderCellDef
|
||||
[ngStyle.gt-md]="{ minWidth: '144px', maxWidth: '144px', width: '144px'}">
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<AttributeData>;
|
||||
|
||||
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<AppState>,
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user