Merge pull request #23 from deaflynx/feature/edge

EdgeEvents with Status, "Manage edge..." buttons in fieldset
This commit is contained in:
VoBa 2020-07-30 18:25:58 +03:00 committed by GitHub
commit e01d59f533
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 164 additions and 32 deletions

View File

@ -56,7 +56,7 @@ function EdgeService($http, $q, customerService) {
deferred.reject();
});
return deferred.promise;
} // TODO: deaflynx: check usage in UI
}
function getEdgesByIds(edgeIds, config) {
var deferred = $q.defer();

View File

@ -389,6 +389,25 @@ export default angular.module('thingsboard.types', [])
customer: "CUSTOMER",
relation: "RELATION"
},
edgeEventAction: {
updated: "UPDATED",
added: "ADDED",
assignedToEdge: "ASSIGNED_TO_EDGE",
deleted: "DELETED",
unassignedFromEdge: "UNASSIGNED_FROM_EDGE",
alarmAck: "ALARM_ACK",
alarmClear: "ALARM_CLEAR",
credentialsUpdated: "CREDENTIALS_UPDATED",
attributesUpdated: "ATTRIBUTES_UPDATED",
attributesDeleted: "ATTRIBUTES_DELETED",
timeseriesUpdated: "TIMESERIES_UPDATED"
},
edgeAttributeKeys: {
active: "active",
lastConnectTime: "lastConnectTime",
lastDisconnectTime: "lastDisconnectTime",
queueStartTs: "queueStartTs"
},
importEntityColumnType: {
name: {
name: 'import.column-type.name',

View File

@ -21,6 +21,21 @@
<md-button ng-click="onUnassignFromCustomer({event: $event, isPublic: isPublic})"
ng-show="!isEdit && (edgeScope === 'customer' || edgeScope === 'tenant') && isAssignedToCustomer"
class="md-raised md-primary">{{ isPublic ? 'edge.make-private' : 'edge.unassign-from-customer' | translate }}</md-button>
<md-button ng-click="onManageEdgeAssets({event: $event})"
ng-show="!isEdit && edgeScope === 'tenant'"
class="md-raised md-primary">{{ 'edge.manage-edge-assets' | translate }}</md-button>
<md-button ng-click="onManageEdgeDevices({event: $event})"
ng-show="!isEdit && edgeScope === 'tenant'"
class="md-raised md-primary">{{ 'edge.manage-edge-devices' | translate }}</md-button>
<md-button ng-click="onManageEdgeEntityViews({event: $event})"
ng-show="!isEdit && edgeScope === 'tenant'"
class="md-raised md-primary">{{ 'edge.manage-edge-entity-views' | translate }}</md-button>
<md-button ng-click="onManageEdgeDashboards({event: $event})"
ng-show="!isEdit && edgeScope === 'tenant'"
class="md-raised md-primary">{{ 'edge.manage-edge-dashboards' | translate }}</md-button>
<md-button ng-click="onManageEdgeRuleChains({event: $event})"
ng-show="!isEdit && edgeScope === 'tenant'"
class="md-raised md-primary">{{ 'edge.manage-edge-rulechains' | translate }}</md-button>
<md-button ng-click="onDeleteEdge({event: $event})"
ng-show="!isEdit && edgeScope === 'tenant'"
class="md-raised md-primary">{{ 'edge.delete' | translate }}</md-button>

View File

@ -129,6 +129,11 @@ export function EdgeController($rootScope, userService, edgeService, customerSer
vm.assignToCustomer = assignToCustomer;
vm.makePublic = makePublic;
vm.unassignFromCustomer = unassignFromCustomer;
vm.openEdgeAssets = openEdgeAssets;
vm.openEdgeDevices = openEdgeDevices;
vm.openEdgeEntityViews = openEdgeEntityViews;
vm.openEdgeDashboards = openEdgeDashboards;
vm.openEdgeRuleChains = openEdgeRuleChains;
initController();

View File

@ -96,6 +96,11 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD
onAssignToCustomer: '&',
onMakePublic: '&',
onUnassignFromCustomer: '&',
onManageEdgeAssets: '&',
onManageEdgeDevices: '&',
onManageEdgeEntityViews: '&',
onManageEdgeDashboards: '&',
onManageEdgeRuleChains: '&',
onDeleteEdge: '&'
}
};

View File

@ -29,6 +29,11 @@
on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])"
on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)"
on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, isPublic)"
on-manage-edge-assets="vm.openEdgeAssets(event, vm.grid.detailsConfig.currentItem)"
on-manage-edge-devices="vm.openEdgeDevices(event, vm.grid.detailsConfig.currentItem)"
on-manage-edge-entity-views="vm.openEdgeEntityViews(event, vm.grid.detailsConfig.currentItem)"
on-manage-edge-dashboards="vm.openEdgeDashboards(event, vm.grid.detailsConfig.currentItem)"
on-manage-edge-rule-chains="vm.openEdgeRuleChains(event, vm.grid.detailsConfig.currentItem)"
on-delete-edge="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-edge>
</md-tab>
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}">

View File

@ -17,6 +17,7 @@
-->
<div translate class="tb-cell" flex="20">event.event-time</div>
<div translate class="tb-cell" flex="20">event.event-type</div>
<div translate class="tb-cell" flex="20">edge.event-action</div>
<div translate class="tb-cell" flex="30">edge.entity-id</div>
<div translate class="tb-cell" flex="20">edge.entity-info</div>
<div translate class="tb-cell" flex="40">edge.event-action</div>
<div translate class="tb-cell" flex="20">edge.entity-id</div>
<div translate class="tb-cell" flex="15">edge.status</div>
<div translate class="tb-cell" flex="10">edge.entity-info</div>

View File

@ -15,11 +15,12 @@
limitations under the License.
-->
<div class="tb-cell" flex="20">{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}</div>
<div class="tb-cell" flex="20">{{event.edgeEventType}}</div>
<div class="tb-cell" flex="20">{{event.edgeEventAction}}</div>
<div class="tb-cell" flex="30">{{event.entityId}}</div>
<div class="tb-cell" flex="20">
<div class="tb-cell" flex="20">{{ event.createdTime | date : 'yyyy-MM-dd HH:mm:ss' }}</div>
<div class="tb-cell" flex="20">{{ event.edgeEventType }}</div>
<div class="tb-cell" flex="40">{{ event.edgeEventAction }}</div>
<div class="tb-cell" flex="20">{{ event.entityId }}</div>
<div class="tb-cell" flex="15" ng-style="isPending ? {'color': 'rgba(0, 0, 0, .38)'} : {'color': '#000'}">{{ updateStatus(event.createdTime) | translate }}</div>
<div class="tb-cell" flex="10">
<md-button class="md-icon-button md-primary"
ng-click="showEdgeEntityContent($event, 'edge.entity-info', 'JSON')"
aria-label="{{ 'action.view' | translate }}">
@ -33,3 +34,4 @@
</md-button>
</div>

View File

@ -102,37 +102,45 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $
switch(scope.event.edgeEventType) {
case types.edgeEventType.relation:
content = angular.toJson(scope.event.entityBody);
showDialog();
break;
case types.edgeEventType.ruleChainMetaData:
content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {}).then(
content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {ignoreErrors: true}).then(
function success(info) {
showDialog();
return angular.toJson(info);
}, function fail() {
toast.showError($translate.instant('edge.load-entity-error'));
showError();
});
break;
default:
content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {}).then(
content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {ignoreErrors: true}).then(
function success(info) {
showDialog();
return angular.toJson(info);
}, function fail() {
toast.showError($translate.instant('edge.load-entity-error'));
showError();
});
break;
}
$mdDialog.show({
controller: 'EventContentDialogController',
controllerAs: 'vm',
templateUrl: eventErrorDialogTemplate,
locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback},
parent: angular.element($document[0].body),
fullscreen: true,
targetEvent: $event,
multiple: true,
onShowing: function(scope, element) {
onShowingCallback.onShowing(scope, element);
}
});
function showDialog() {
$mdDialog.show({
controller: 'EventContentDialogController',
controllerAs: 'vm',
templateUrl: eventErrorDialogTemplate,
locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback},
parent: angular.element($document[0].body),
fullscreen: true,
targetEvent: $event,
multiple: true,
onShowing: function(scope, element) {
onShowingCallback.onShowing(scope, element);
}
});
}
function showError() {
toast.showError($translate.instant('edge.load-entity-error'));
}
}
scope.checkTooltip = function($event) {
@ -144,6 +152,20 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $
}
$compile(element.contents())(scope);
scope.updateStatus = function(eventCreatedTime) {
if (scope.queueStartTs) {
var status;
if (eventCreatedTime < scope.queueStartTs) {
status = $translate.instant('edge.success');
scope.isPending = false;
} else {
status = $translate.instant('edge.failed');
scope.isPending = true;
}
return status;
}
}
}
return {

View File

@ -22,7 +22,8 @@ import eventTableTemplate from './event-table.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
export default function EventTableDirective($compile, $templateCache, $rootScope, types, eventService, edgeService) {
export default function EventTableDirective($compile, $templateCache, $rootScope, types,
eventService, edgeService, attributeService) {
var linker = function (scope, element, attrs) {
@ -30,11 +31,16 @@ export default function EventTableDirective($compile, $templateCache, $rootScope
element.html(template);
scope.eventTypeScope = angular.copy(types.eventType);
if (scope.entityType !== types.entityType.edge) {
delete scope.eventTypeScope.edgeEvent;
}
if (attrs.disabledEventTypes) {
var disabledEventTypes = attrs.disabledEventTypes.split(',');
scope.eventTypes = {};
for (var type in types.eventType) {
var eventType = types.eventType[type];
for (var type in scope.eventTypeScope) {
var eventType = scope.eventTypeScope[type];
var enabled = true;
for (var i=0;i<disabledEventTypes.length;i++) {
if (eventType.value === disabledEventTypes[i]) {
@ -47,7 +53,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope
}
}
} else {
scope.eventTypes = angular.copy(types.eventType);
scope.eventTypes = angular.copy(scope.eventTypeScope);
}
if (attrs.debugEventTypes) {
@ -106,6 +112,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope
scope.eventType, scope.tenantId, scope.events.nextPageLink);
} else {
promise = edgeService.getEdgeEvents(scope.entityId, scope.events.nextPageLink);
scope.loadEdgeInfo();
}
if (promise) {
scope.events.pending = true;
@ -135,6 +142,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope
scope.$watch("entityId", function(newVal, prevVal) {
if (newVal && !angular.equals(newVal, prevVal)) {
scope.loadEdgeInfo();
scope.resetFilter();
scope.reload();
}
@ -212,6 +220,53 @@ export default function EventTableDirective($compile, $templateCache, $rootScope
return false;
}
scope.subscriptionId = null;
scope.queueStartTs;
scope.loadEdgeInfo = function() {
attributeService.getEntityAttributesValues(scope.entityType, scope.entityId, types.attributesScope.server.value,
types.edgeAttributeKeys.queueStartTs, {})
.then(function success(attributes) {
scope.onUpdate(attributes);
});
scope.checkSubscription();
attributeService.getEntityAttributes(scope.entityType, scope.entityId, types.attributesScope.server.value, {order: '', limit: 1, page: 1, search: ''},
function (attributes) {
if (attributes && attributes.data) {
scope.onUpdate(attributes.data);
}
});
}
scope.onUpdate = function(attributes) {
let edge = attributes.reduce(function (map, attribute) {
map[attribute.key] = attribute;
return map;
}, {});
if (edge.queueStartTs) {
scope.queueStartTs = edge.queueStartTs.lastUpdateTs;
}
}
scope.checkSubscription = function() {
var newSubscriptionId = null;
if (scope.entityId && scope.entityType && types.attributesScope.server.value) {
newSubscriptionId = attributeService.subscribeForEntityAttributes(scope.entityType, scope.entityId, types.attributesScope.server.value);
}
if (scope.subscriptionId && scope.subscriptionId != newSubscriptionId) {
attributeService.unsubscribeForEntityAttributes(scope.subscriptionId);
}
scope.subscriptionId = newSubscriptionId;
}
scope.$on('$destroy', function () {
if (scope.subscriptionId) {
attributeService.unsubscribeForEntityAttributes(scope.subscriptionId);
}
});
scope.reload();
$compile(element.contents())(scope);

View File

@ -821,7 +821,7 @@
"make-private-edge-text": "After the confirmation the edge and all its data will be made private and won't be accessible by others.",
"import": "Import edge",
"label": "Label",
"load-entity-error": "Could not load entity info",
"load-entity-error": "Entity not found. Failed to load info",
"assign-new-edge": "Assign new edge",
"manage-edge-dashboards": "Manage edge dashboards",
"unassign-from-edge": "Unassign from edge",
@ -843,7 +843,10 @@
"entity-views": "Edge entity views",
"set-root-rule-chain-text": "Please select root rule chain for edge(s)",
"set-root-rule-chain-to-edges": "Set root rule chain for Edge(s)",
"set-root-rule-chain-to-edges-text": "Set root rule chain for { count, plural, 1 {1 edge} other {# edges} }"
"set-root-rule-chain-to-edges-text": "Set root rule chain for { count, plural, 1 {1 edge} other {# edges} }",
"status": "Received by edge",
"success": "Deployed",
"failed": "Pending"
},
"error": {
"unable-to-connect": "Unable to connect to the server! Please check your internet connection.",