Commit c991ab96f179ec71cb040d5a9dc4040288e1ef0a
Merge branch 'feature/edge' of github.com:volodymyr-babak/thingsboard into feature/edge
Showing
16 changed files
with
171 additions
and
74 deletions
... | ... | @@ -292,7 +292,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { |
292 | 292 | case ADDED: // used only for USER entity |
293 | 293 | case UPDATED: |
294 | 294 | case CREDENTIALS_UPDATED: |
295 | - edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); | |
295 | + edgeIdsFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId); | |
296 | 296 | Futures.addCallback(edgeIdsFuture, new FutureCallback<List<EdgeId>>() { |
297 | 297 | @Override |
298 | 298 | public void onSuccess(@Nullable List<EdgeId> edgeIds) { |
... | ... | @@ -310,7 +310,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { |
310 | 310 | break; |
311 | 311 | case ASSIGNED_TO_CUSTOMER: |
312 | 312 | case UNASSIGNED_FROM_CUSTOMER: |
313 | - edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); | |
313 | + edgeIdsFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId); | |
314 | 314 | Futures.addCallback(edgeIdsFuture, new FutureCallback<List<EdgeId>>() { |
315 | 315 | @Override |
316 | 316 | public void onSuccess(@Nullable List<EdgeId> edgeIds) { |
... | ... | @@ -408,7 +408,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { |
408 | 408 | if (alarm != null) { |
409 | 409 | EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType()); |
410 | 410 | if (edgeEventType != null) { |
411 | - ListenableFuture<List<EdgeId>> relatedEdgeIdsByEntityIdFuture = findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator()); | |
411 | + ListenableFuture<List<EdgeId>> relatedEdgeIdsByEntityIdFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator()); | |
412 | 412 | Futures.transform(relatedEdgeIdsByEntityIdFuture, relatedEdgeIdsByEntityId -> { |
413 | 413 | if (relatedEdgeIdsByEntityId != null) { |
414 | 414 | for (EdgeId edgeId : relatedEdgeIdsByEntityId) { |
... | ... | @@ -433,8 +433,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { |
433 | 433 | if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && |
434 | 434 | !relation.getTo().getEntityType().equals(EntityType.EDGE)) { |
435 | 435 | List<ListenableFuture<List<EdgeId>>> futures = new ArrayList<>(); |
436 | - futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getTo())); | |
437 | - futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom())); | |
436 | + futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getTo())); | |
437 | + futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom())); | |
438 | 438 | ListenableFuture<List<List<EdgeId>>> combinedFuture = Futures.allAsList(futures); |
439 | 439 | Futures.transform(combinedFuture, listOfListsEdgeIds -> { |
440 | 440 | Set<EdgeId> uniqueEdgeIds = new HashSet<>(); |
... | ... | @@ -460,48 +460,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { |
460 | 460 | } |
461 | 461 | } |
462 | 462 | |
463 | - private ListenableFuture<List<EdgeId>> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { | |
464 | - switch (entityId.getEntityType()) { | |
465 | - case DEVICE: | |
466 | - case ASSET: | |
467 | - case ENTITY_VIEW: | |
468 | - ListenableFuture<List<EntityRelation>> originatorEdgeRelationsFuture = | |
469 | - relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); | |
470 | - return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { | |
471 | - if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { | |
472 | - return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); | |
473 | - } else { | |
474 | - return Collections.emptyList(); | |
475 | - } | |
476 | - }, dbCallbackExecutorService); | |
477 | - case DASHBOARD: | |
478 | - return convertToEdgeIds(edgeService.findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); | |
479 | - case RULE_CHAIN: | |
480 | - return convertToEdgeIds(edgeService.findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); | |
481 | - case USER: | |
482 | - User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); | |
483 | - TextPageData<Edge> edges; | |
484 | - if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { | |
485 | - edges = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); | |
486 | - } else { | |
487 | - edges = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); | |
488 | - } | |
489 | - return convertToEdgeIds(Futures.immediateFuture(edges.getData())); | |
490 | - default: | |
491 | - return Futures.immediateFuture(Collections.emptyList()); | |
492 | - } | |
493 | - } | |
494 | - | |
495 | - private ListenableFuture<List<EdgeId>> convertToEdgeIds(ListenableFuture<List<Edge>> future) { | |
496 | - return Futures.transform(future, edges -> { | |
497 | - if (edges != null && !edges.isEmpty()) { | |
498 | - return edges.stream().map(IdBased::getId).collect(Collectors.toList()); | |
499 | - } else { | |
500 | - return Collections.emptyList(); | |
501 | - } | |
502 | - }, dbCallbackExecutorService); | |
503 | - } | |
504 | - | |
505 | 463 | private EdgeEventType getEdgeQueueTypeByEntityType(EntityType entityType) { |
506 | 464 | switch (entityType) { |
507 | 465 | case DEVICE: | ... | ... |
... | ... | @@ -32,6 +32,7 @@ import lombok.Data; |
32 | 32 | import lombok.extern.slf4j.Slf4j; |
33 | 33 | import org.apache.commons.lang.RandomStringUtils; |
34 | 34 | import org.checkerframework.checker.nullness.qual.Nullable; |
35 | +import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | |
35 | 36 | import org.thingsboard.server.common.data.AdminSettings; |
36 | 37 | import org.thingsboard.server.common.data.Customer; |
37 | 38 | import org.thingsboard.server.common.data.Dashboard; |
... | ... | @@ -64,6 +65,7 @@ import org.thingsboard.server.common.data.id.TenantId; |
64 | 65 | import org.thingsboard.server.common.data.id.UserId; |
65 | 66 | import org.thingsboard.server.common.data.id.WidgetTypeId; |
66 | 67 | import org.thingsboard.server.common.data.id.WidgetsBundleId; |
68 | +import org.thingsboard.server.common.data.kv.AttributeKey; | |
67 | 69 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
68 | 70 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
69 | 71 | import org.thingsboard.server.common.data.kv.LongDataEntry; |
... | ... | @@ -87,6 +89,7 @@ import org.thingsboard.server.common.transport.util.JsonUtils; |
87 | 89 | import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; |
88 | 90 | import org.thingsboard.server.gen.edge.AlarmUpdateMsg; |
89 | 91 | import org.thingsboard.server.gen.edge.AssetUpdateMsg; |
92 | +import org.thingsboard.server.gen.edge.AttributeDeleteMsg; | |
90 | 93 | import org.thingsboard.server.gen.edge.AttributesRequestMsg; |
91 | 94 | import org.thingsboard.server.gen.edge.ConnectRequestMsg; |
92 | 95 | import org.thingsboard.server.gen.edge.ConnectResponseCode; |
... | ... | @@ -124,11 +127,12 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
124 | 127 | import org.thingsboard.server.service.edge.EdgeContextComponent; |
125 | 128 | |
126 | 129 | import java.io.Closeable; |
127 | -import java.io.IOException; | |
128 | 130 | import java.util.ArrayList; |
129 | 131 | import java.util.Collections; |
132 | +import java.util.HashSet; | |
130 | 133 | import java.util.List; |
131 | 134 | import java.util.Optional; |
135 | +import java.util.Set; | |
132 | 136 | import java.util.UUID; |
133 | 137 | import java.util.concurrent.CountDownLatch; |
134 | 138 | import java.util.concurrent.ExecutionException; |
... | ... | @@ -387,7 +391,7 @@ public final class EdgeGrpcSession implements Closeable { |
387 | 391 | ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes); |
388 | 392 | } |
389 | 393 | |
390 | - private DownlinkMsg processTelemetryMessage(EdgeEvent edgeEvent) throws IOException { | |
394 | + private DownlinkMsg processTelemetryMessage(EdgeEvent edgeEvent) { | |
391 | 395 | log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent); |
392 | 396 | EntityId entityId = null; |
393 | 397 | switch (edgeEvent.getEdgeEventType()) { |
... | ... | @@ -840,6 +844,9 @@ public final class EdgeGrpcSession implements Closeable { |
840 | 844 | result.add(processPostTelemetry(entityId, entityData.getPostTelemetryMsg(), metaData)); |
841 | 845 | } |
842 | 846 | } |
847 | + if (entityData.hasAttributeDeleteMsg()) { | |
848 | + result.add(processAttributeDeleteMsg(entityId, entityData.getAttributeDeleteMsg(), entityData.getEntityType())); | |
849 | + } | |
843 | 850 | } |
844 | 851 | } |
845 | 852 | |
... | ... | @@ -962,6 +969,7 @@ public final class EdgeGrpcSession implements Closeable { |
962 | 969 | |
963 | 970 | @Override |
964 | 971 | public void onFailure(Throwable t) { |
972 | + log.error("Can't process post telemetry [{}]", msg, t); | |
965 | 973 | futureToSet.setException(t); |
966 | 974 | } |
967 | 975 | }); |
... | ... | @@ -970,11 +978,49 @@ public final class EdgeGrpcSession implements Closeable { |
970 | 978 | } |
971 | 979 | |
972 | 980 | private ListenableFuture<Void> processPostAttributes(EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { |
981 | + SettableFuture<Void> futureToSet = SettableFuture.create(); | |
973 | 982 | JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); |
974 | 983 | TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, metaData, gson.toJson(json)); |
975 | - // TODO: voba - verify that null callback is OK | |
976 | - ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, null); | |
977 | - return Futures.immediateFuture(null); | |
984 | + ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { | |
985 | + @Override | |
986 | + public void onSuccess(TbQueueMsgMetadata metadata) { | |
987 | + futureToSet.set(null); | |
988 | + } | |
989 | + | |
990 | + @Override | |
991 | + public void onFailure(Throwable t) { | |
992 | + log.error("Can't process post attributes [{}]", msg, t); | |
993 | + futureToSet.setException(t); | |
994 | + } | |
995 | + }); | |
996 | + return futureToSet; | |
997 | + } | |
998 | + | |
999 | + private ListenableFuture<Void> processAttributeDeleteMsg(EntityId entityId, AttributeDeleteMsg attributeDeleteMsg, String entityType) { | |
1000 | + SettableFuture<Void> futureToSet = SettableFuture.create(); | |
1001 | + String scope = attributeDeleteMsg.getScope(); | |
1002 | + List<String> attributeNames = attributeDeleteMsg.getAttributeNamesList(); | |
1003 | + ctx.getAttributesService().removeAll(edge.getTenantId(), entityId, scope, attributeNames); | |
1004 | + if (EntityType.DEVICE.name().equals(entityType)) { | |
1005 | + Set<AttributeKey> attributeKeys = new HashSet<>(); | |
1006 | + for (String attributeName : attributeNames) { | |
1007 | + attributeKeys.add(new AttributeKey(scope, attributeName)); | |
1008 | + } | |
1009 | + ctx.getTbClusterService().pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete( | |
1010 | + edge.getTenantId(), (DeviceId) entityId, attributeKeys), new TbQueueCallback() { | |
1011 | + @Override | |
1012 | + public void onSuccess(TbQueueMsgMetadata metadata) { | |
1013 | + futureToSet.set(null); | |
1014 | + } | |
1015 | + | |
1016 | + @Override | |
1017 | + public void onFailure(Throwable t) { | |
1018 | + log.error("Can't process attribute delete msg [{}]", attributeDeleteMsg, t); | |
1019 | + futureToSet.setException(t); | |
1020 | + } | |
1021 | + }); | |
1022 | + } | |
1023 | + return futureToSet; | |
978 | 1024 | } |
979 | 1025 | |
980 | 1026 | private ListenableFuture<Void> onDeviceUpdate(DeviceUpdateMsg deviceUpdateMsg) { | ... | ... |
... | ... | @@ -43,9 +43,11 @@ public class EntityDataMsgConstructor { |
43 | 43 | case TIMESERIES_UPDATED: |
44 | 44 | try { |
45 | 45 | JsonObject data = entityData.getAsJsonObject(); |
46 | - long ts = System.currentTimeMillis(); | |
46 | + long ts; | |
47 | 47 | if (data.get("ts") != null && !data.get("ts").isJsonNull()) { |
48 | - ts = data.getAsJsonObject("ts").getAsLong(); | |
48 | + ts = data.getAsJsonPrimitive("ts").getAsLong(); | |
49 | + } else { | |
50 | + ts = System.currentTimeMillis(); | |
49 | 51 | } |
50 | 52 | builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(data.getAsJsonObject("data"), ts)); |
51 | 53 | } catch (Exception e) { | ... | ... |
... | ... | @@ -68,6 +68,8 @@ public class RuleChainUpdateMsgConstructor { |
68 | 68 | .addAllRuleChainConnections(constructRuleChainConnections(ruleChainMetaData.getRuleChainConnections())); |
69 | 69 | if (ruleChainMetaData.getFirstNodeIndex() != null) { |
70 | 70 | builder.setFirstNodeIndex(ruleChainMetaData.getFirstNodeIndex()); |
71 | + } else { | |
72 | + builder.setFirstNodeIndex(-1); | |
71 | 73 | } |
72 | 74 | builder.setMsgType(msgType); |
73 | 75 | return builder.build(); | ... | ... |
... | ... | @@ -22,12 +22,11 @@ import org.thingsboard.server.common.data.edge.EdgeSearchQuery; |
22 | 22 | import org.thingsboard.server.common.data.id.CustomerId; |
23 | 23 | import org.thingsboard.server.common.data.id.DashboardId; |
24 | 24 | import org.thingsboard.server.common.data.id.EdgeId; |
25 | +import org.thingsboard.server.common.data.id.EntityId; | |
25 | 26 | import org.thingsboard.server.common.data.id.RuleChainId; |
26 | 27 | import org.thingsboard.server.common.data.id.TenantId; |
27 | 28 | import org.thingsboard.server.common.data.page.TextPageData; |
28 | 29 | import org.thingsboard.server.common.data.page.TextPageLink; |
29 | -import org.thingsboard.server.common.data.page.TimePageData; | |
30 | -import org.thingsboard.server.common.data.page.TimePageLink; | |
31 | 30 | |
32 | 31 | import java.util.List; |
33 | 32 | import java.util.Optional; |
... | ... | @@ -75,6 +74,8 @@ public interface EdgeService { |
75 | 74 | ListenableFuture<List<Edge>> findEdgesByTenantIdAndRuleChainId(TenantId tenantId, RuleChainId ruleChainId); |
76 | 75 | |
77 | 76 | ListenableFuture<List<Edge>> findEdgesByTenantIdAndDashboardId(TenantId tenantId, DashboardId dashboardId); |
77 | + | |
78 | + ListenableFuture<List<EdgeId>> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId); | |
78 | 79 | } |
79 | 80 | |
80 | 81 | ... | ... |
... | ... | @@ -31,18 +31,22 @@ import org.thingsboard.server.common.data.Customer; |
31 | 31 | import org.thingsboard.server.common.data.EntitySubtype; |
32 | 32 | import org.thingsboard.server.common.data.EntityType; |
33 | 33 | import org.thingsboard.server.common.data.Tenant; |
34 | +import org.thingsboard.server.common.data.User; | |
34 | 35 | import org.thingsboard.server.common.data.edge.Edge; |
35 | 36 | import org.thingsboard.server.common.data.edge.EdgeSearchQuery; |
36 | 37 | import org.thingsboard.server.common.data.id.CustomerId; |
37 | 38 | import org.thingsboard.server.common.data.id.DashboardId; |
38 | 39 | import org.thingsboard.server.common.data.id.EdgeId; |
39 | 40 | import org.thingsboard.server.common.data.id.EntityId; |
41 | +import org.thingsboard.server.common.data.id.IdBased; | |
40 | 42 | import org.thingsboard.server.common.data.id.RuleChainId; |
41 | 43 | import org.thingsboard.server.common.data.id.TenantId; |
44 | +import org.thingsboard.server.common.data.id.UserId; | |
42 | 45 | import org.thingsboard.server.common.data.page.TextPageData; |
43 | 46 | import org.thingsboard.server.common.data.page.TextPageLink; |
44 | 47 | import org.thingsboard.server.common.data.relation.EntityRelation; |
45 | 48 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
49 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | |
46 | 50 | import org.thingsboard.server.common.data.rule.RuleChain; |
47 | 51 | import org.thingsboard.server.dao.asset.AssetService; |
48 | 52 | import org.thingsboard.server.dao.customer.CustomerDao; |
... | ... | @@ -51,12 +55,14 @@ import org.thingsboard.server.dao.device.DeviceService; |
51 | 55 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
52 | 56 | import org.thingsboard.server.dao.entityview.EntityViewService; |
53 | 57 | import org.thingsboard.server.dao.exception.DataValidationException; |
58 | +import org.thingsboard.server.dao.model.ModelConstants; | |
54 | 59 | import org.thingsboard.server.dao.relation.RelationService; |
55 | 60 | import org.thingsboard.server.dao.rule.RuleChainService; |
56 | 61 | import org.thingsboard.server.dao.service.DataValidator; |
57 | 62 | import org.thingsboard.server.dao.service.PaginatedRemover; |
58 | 63 | import org.thingsboard.server.dao.service.Validator; |
59 | 64 | import org.thingsboard.server.dao.tenant.TenantDao; |
65 | +import org.thingsboard.server.dao.user.UserService; | |
60 | 66 | |
61 | 67 | import javax.annotation.Nullable; |
62 | 68 | import java.util.ArrayList; |
... | ... | @@ -93,6 +99,9 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic |
93 | 99 | private CustomerDao customerDao; |
94 | 100 | |
95 | 101 | @Autowired |
102 | + private UserService userService; | |
103 | + | |
104 | + @Autowired | |
96 | 105 | private CacheManager cacheManager; |
97 | 106 | |
98 | 107 | @Autowired |
... | ... | @@ -430,4 +439,47 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic |
430 | 439 | } |
431 | 440 | }; |
432 | 441 | |
442 | + @Override | |
443 | + public ListenableFuture<List<EdgeId>> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { | |
444 | + switch (entityId.getEntityType()) { | |
445 | + case DEVICE: | |
446 | + case ASSET: | |
447 | + case ENTITY_VIEW: | |
448 | + ListenableFuture<List<EntityRelation>> originatorEdgeRelationsFuture = | |
449 | + relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); | |
450 | + return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { | |
451 | + if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { | |
452 | + return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); | |
453 | + } else { | |
454 | + return Collections.emptyList(); | |
455 | + } | |
456 | + }, MoreExecutors.directExecutor()); | |
457 | + case DASHBOARD: | |
458 | + return convertToEdgeIds(findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); | |
459 | + case RULE_CHAIN: | |
460 | + return convertToEdgeIds(findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); | |
461 | + case USER: | |
462 | + User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); | |
463 | + TextPageData<Edge> edges; | |
464 | + if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { | |
465 | + edges = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); | |
466 | + } else { | |
467 | + edges = findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); | |
468 | + } | |
469 | + return convertToEdgeIds(Futures.immediateFuture(edges.getData())); | |
470 | + default: | |
471 | + return Futures.immediateFuture(Collections.emptyList()); | |
472 | + } | |
473 | + } | |
474 | + | |
475 | + private ListenableFuture<List<EdgeId>> convertToEdgeIds(ListenableFuture<List<Edge>> future) { | |
476 | + return Futures.transform(future, edges -> { | |
477 | + if (edges != null && !edges.isEmpty()) { | |
478 | + return edges.stream().map(IdBased::getId).collect(Collectors.toList()); | |
479 | + } else { | |
480 | + return Collections.emptyList(); | |
481 | + } | |
482 | + }, MoreExecutors.directExecutor()); | |
483 | + } | |
484 | + | |
433 | 485 | } | ... | ... |
... | ... | @@ -232,14 +232,7 @@ public class TbMsgPushToEdgeNode implements TbNode { |
232 | 232 | TextPageData<Edge> edgesByTenantId = ctx.getEdgeService().findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); |
233 | 233 | return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList())); |
234 | 234 | } else { |
235 | - ListenableFuture<List<EntityRelation>> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); | |
236 | - return Futures.transform(future, relations -> { | |
237 | - List<EdgeId> result = new ArrayList<>(); | |
238 | - if (relations != null && relations.size() > 0) { | |
239 | - result.add(new EdgeId(relations.get(0).getFrom().getId())); | |
240 | - } | |
241 | - return result; | |
242 | - }, ctx.getDbCallbackExecutor()); | |
235 | + return ctx.getEdgeService().findRelatedEdgeIdsByEntityId(tenantId, originatorId); | |
243 | 236 | } |
244 | 237 | } |
245 | 238 | ... | ... |
... | ... | @@ -284,13 +284,6 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { |
284 | 284 | } |
285 | 285 | dashboard.assignedCustomersText = assignedCustomersTitles.join(', '); |
286 | 286 | } |
287 | - dashboard.assignedEdgesIds = []; | |
288 | - if (dashboard.assignedEdges && dashboard.assignedEdges.length) { | |
289 | - for (var j = 0; j < dashboard.assignedEdges.length; j++) { | |
290 | - var assignedEdge = dashboard.assignedEdges[j]; | |
291 | - dashboard.assignedEdgesIds.push(assignedEdge.edgeId.id); | |
292 | - } | |
293 | - } | |
294 | 287 | return dashboard; |
295 | 288 | } |
296 | 289 | |
... | ... | @@ -298,7 +291,6 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { |
298 | 291 | delete dashboard.publicCustomerId; |
299 | 292 | delete dashboard.assignedCustomersText; |
300 | 293 | delete dashboard.assignedCustomersIds; |
301 | - delete dashboard.assignedEdgesIds; | |
302 | 294 | return dashboard; |
303 | 295 | } |
304 | 296 | ... | ... |
... | ... | @@ -19,6 +19,7 @@ |
19 | 19 | <md-button ng-click="onManageAssets({event: $event})" ng-show="!isEdit && !isPublic" class="md-raised md-primary">{{ 'customer.manage-assets' | translate }}</md-button> |
20 | 20 | <md-button ng-click="onManageDevices({event: $event})" ng-show="!isEdit" class="md-raised md-primary">{{ 'customer.manage-devices' | translate }}</md-button> |
21 | 21 | <md-button ng-click="onManageDashboards({event: $event})" ng-show="!isEdit" class="md-raised md-primary">{{ 'customer.manage-dashboards' | translate }}</md-button> |
22 | +<md-button ng-click="onManageEdges({event: $event})" ng-show="!isEdit && !isPublic" class="md-raised md-primary">{{ 'customer.manage-edges' | translate }}</md-button> | |
22 | 23 | <md-button ng-click="onDeleteCustomer({event: $event})" ng-show="!isEdit && !isPublic" class="md-raised md-primary">{{ 'customer.delete' | translate }}</md-button> |
23 | 24 | |
24 | 25 | <div layout="row"> | ... | ... |
... | ... | @@ -79,6 +79,20 @@ export default function CustomerController(customerService, $state, $stateParams |
79 | 79 | }, |
80 | 80 | { |
81 | 81 | onAction: function ($event, item) { |
82 | + openCustomerEdges($event, item); | |
83 | + }, | |
84 | + name: function() { return $translate.instant('edge.edges') }, | |
85 | + details: function(customer) { | |
86 | + if (customer && customer.additionalInfo && customer.additionalInfo.isPublic) { | |
87 | + return $translate.instant('customer.manage-public-edges') | |
88 | + } else { | |
89 | + return $translate.instant('customer.manage-customer-edges') | |
90 | + } | |
91 | + }, | |
92 | + icon: "router" | |
93 | + }, | |
94 | + { | |
95 | + onAction: function ($event, item) { | |
82 | 96 | vm.grid.deleteItem($event, item); |
83 | 97 | }, |
84 | 98 | name: function() { return $translate.instant('action.delete') }, |
... | ... | @@ -147,6 +161,7 @@ export default function CustomerController(customerService, $state, $stateParams |
147 | 161 | vm.openCustomerAssets = openCustomerAssets; |
148 | 162 | vm.openCustomerDevices = openCustomerDevices; |
149 | 163 | vm.openCustomerDashboards = openCustomerDashboards; |
164 | + vm.openCustomerEdges = openCustomerEdges; | |
150 | 165 | |
151 | 166 | function deleteCustomerTitle(customer) { |
152 | 167 | return $translate.instant('customer.delete-customer-title', {customerTitle: customer.title}); |
... | ... | @@ -216,4 +231,11 @@ export default function CustomerController(customerService, $state, $stateParams |
216 | 231 | $state.go('home.customers.dashboards', {customerId: customer.id.id}); |
217 | 232 | } |
218 | 233 | |
234 | + function openCustomerEdges($event, customer) { | |
235 | + if ($event) { | |
236 | + $event.stopPropagation(); | |
237 | + } | |
238 | + $state.go('home.customers.edges', {customerId: customer.id.id}); | |
239 | + } | |
240 | + | |
219 | 241 | } | ... | ... |
... | ... | @@ -29,6 +29,7 @@ |
29 | 29 | on-manage-assets="vm.openCustomerAssets(event, vm.grid.detailsConfig.currentItem)" |
30 | 30 | on-manage-devices="vm.openCustomerDevices(event, vm.grid.detailsConfig.currentItem)" |
31 | 31 | on-manage-dashboards="vm.openCustomerDashboards(event, vm.grid.detailsConfig.currentItem)" |
32 | + on-manage-edges="vm.openCustomerEdges(event, vm.grid.detailsConfig.currentItem)" | |
32 | 33 | on-delete-customer="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-customer> |
33 | 34 | </md-tab> |
34 | 35 | <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}"> | ... | ... |
... | ... | @@ -552,7 +552,7 @@ export function EdgeController($rootScope, userService, edgeService, customerSer |
552 | 552 | $event.stopPropagation(); |
553 | 553 | } |
554 | 554 | var pageSize = 10; |
555 | - ruleChainService.getRuleChains({limit: pageSize, textSearch: ''}).then( | |
555 | + ruleChainService.getEdgesRuleChains({limit: pageSize, textSearch: ''}).then( | |
556 | 556 | function success(_ruleChains) { |
557 | 557 | var ruleChains = { |
558 | 558 | pageSize: pageSize, | ... | ... |
... | ... | @@ -161,5 +161,28 @@ export default function EdgeRoutes($stateProvider, types) { |
161 | 161 | ncyBreadcrumb: { |
162 | 162 | label: '{"icon": "dashboard", "label": "{{ vm.dashboard.title }}", "translate": "false"}' |
163 | 163 | } |
164 | + }) | |
165 | + .state('home.customers.edges', { | |
166 | + url: '/:customerId/edges', | |
167 | + params: {'topIndex': 0}, | |
168 | + module: 'private', | |
169 | + auth: ['TENANT_ADMIN'], | |
170 | + views: { | |
171 | + "content@home": { | |
172 | + templateUrl: edgesTemplate, | |
173 | + controllerAs: 'vm', | |
174 | + controller: 'EdgeController' | |
175 | + } | |
176 | + }, | |
177 | + data: { | |
178 | + edgesType: 'customer', | |
179 | + searchEnabled: true, | |
180 | + searchByEntitySubtype: true, | |
181 | + searchEntityType: types.entityType.edge, | |
182 | + pageTitle: 'customer.edges' | |
183 | + }, | |
184 | + ncyBreadcrumb: { | |
185 | + label: '{"icon": "router", "label": "{{ vm.customerEdgesTitle }}", "translate": "false"}' | |
186 | + } | |
164 | 187 | }); |
165 | 188 | } | ... | ... |
... | ... | @@ -53,7 +53,7 @@ export default function SetRootRuleChainToEdgesController(ruleChainService, edge |
53 | 53 | fetchMoreItems_: function () { |
54 | 54 | if (vm.ruleChains.hasNext && !vm.ruleChains.pending) { |
55 | 55 | vm.ruleChains.pending = true; |
56 | - ruleChainService.getRuleChains(vm.ruleChains.nextPageLink).then( | |
56 | + ruleChainService.getEdgesRuleChains(vm.ruleChains.nextPageLink).then( | |
57 | 57 | function success(ruleChains) { |
58 | 58 | vm.ruleChains.data = vm.ruleChains.data.concat(ruleChains.data); |
59 | 59 | vm.ruleChains.nextPageLink = ruleChains.nextPageLink; | ... | ... |
... | ... | @@ -441,6 +441,7 @@ |
441 | 441 | "manage-assets": "Manage assets", |
442 | 442 | "manage-devices": "Manage devices", |
443 | 443 | "manage-dashboards": "Manage dashboards", |
444 | + "manage-edges": "Manage edges", | |
444 | 445 | "title": "Title", |
445 | 446 | "title-required": "Title is required.", |
446 | 447 | "description": "Description", |
... | ... | @@ -812,6 +813,8 @@ |
812 | 813 | "assign-edges-text": "Assign { count, plural, 1 {1 edge} other {# edges} } to customer", |
813 | 814 | "unassign-edge-title": "Are you sure you want to unassign the edge '{{edgeName}}'?", |
814 | 815 | "unassign-edge-text": "After the confirmation the edge will be unassigned and won't be accessible by the customer.", |
816 | + "unassign-edges-title": "Are you sure you want to unassign { count, plural, 1 {1 edge} other {# edges} }?", | |
817 | + "unassign-edges-text": "After the confirmation all selected edges will be unassigned and won't be accessible by the customer.", | |
815 | 818 | "make-public": "Make edge public", |
816 | 819 | "make-public-edge-title": "Are you sure you want to make the edge '{{edgeName}}' public?", |
817 | 820 | "make-public-edge-text": "After the confirmation the edge and all its data will be made public and accessible by others.", | ... | ... |