Showing
29 changed files
with
365 additions
and
85 deletions
@@ -55,6 +55,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | @@ -55,6 +55,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | ||
55 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 55 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
56 | import org.thingsboard.server.common.data.rule.RuleChain; | 56 | import org.thingsboard.server.common.data.rule.RuleChain; |
57 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 57 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
58 | +import org.thingsboard.server.common.data.rule.RuleChainType; | ||
58 | import org.thingsboard.server.common.data.rule.RuleNode; | 59 | import org.thingsboard.server.common.data.rule.RuleNode; |
59 | import org.thingsboard.server.common.msg.TbMsg; | 60 | import org.thingsboard.server.common.msg.TbMsg; |
60 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 61 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
@@ -231,13 +232,19 @@ public class RuleChainController extends BaseController { | @@ -231,13 +232,19 @@ public class RuleChainController extends BaseController { | ||
231 | @ResponseBody | 232 | @ResponseBody |
232 | public TextPageData<RuleChain> getRuleChains( | 233 | public TextPageData<RuleChain> getRuleChains( |
233 | @RequestParam int limit, | 234 | @RequestParam int limit, |
235 | + @RequestParam(value = "type", required = false) String typeStr, | ||
234 | @RequestParam(required = false) String textSearch, | 236 | @RequestParam(required = false) String textSearch, |
235 | @RequestParam(required = false) String idOffset, | 237 | @RequestParam(required = false) String idOffset, |
236 | @RequestParam(required = false) String textOffset) throws ThingsboardException { | 238 | @RequestParam(required = false) String textOffset) throws ThingsboardException { |
237 | try { | 239 | try { |
238 | TenantId tenantId = getCurrentUser().getTenantId(); | 240 | TenantId tenantId = getCurrentUser().getTenantId(); |
239 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 241 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
240 | - return checkNotNull(ruleChainService.findTenantRuleChains(tenantId, pageLink)); | 242 | + if (typeStr != null && typeStr.trim().length() > 0) { |
243 | + RuleChainType type = RuleChainType.valueOf(typeStr); | ||
244 | + return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink)); | ||
245 | + } else { | ||
246 | + return checkNotNull(ruleChainService.findTenantRuleChains(tenantId, pageLink)); | ||
247 | + } | ||
241 | } catch (Exception e) { | 248 | } catch (Exception e) { |
242 | throw handleException(e); | 249 | throw handleException(e); |
243 | } | 250 | } |
@@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.alarm.Alarm; | @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.alarm.Alarm; | ||
37 | import org.thingsboard.server.common.data.alarm.AlarmSeverity; | 37 | import org.thingsboard.server.common.data.alarm.AlarmSeverity; |
38 | import org.thingsboard.server.common.data.alarm.AlarmStatus; | 38 | import org.thingsboard.server.common.data.alarm.AlarmStatus; |
39 | import org.thingsboard.server.common.data.asset.Asset; | 39 | import org.thingsboard.server.common.data.asset.Asset; |
40 | +import org.thingsboard.server.common.data.audit.ActionType; | ||
40 | import org.thingsboard.server.common.data.edge.Edge; | 41 | import org.thingsboard.server.common.data.edge.Edge; |
41 | import org.thingsboard.server.common.data.edge.EdgeQueueEntry; | 42 | import org.thingsboard.server.common.data.edge.EdgeQueueEntry; |
42 | import org.thingsboard.server.common.data.id.AssetId; | 43 | import org.thingsboard.server.common.data.id.AssetId; |
@@ -44,10 +45,12 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -44,10 +45,12 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
44 | import org.thingsboard.server.common.data.id.DeviceId; | 45 | import org.thingsboard.server.common.data.id.DeviceId; |
45 | import org.thingsboard.server.common.data.id.EdgeId; | 46 | import org.thingsboard.server.common.data.id.EdgeId; |
46 | import org.thingsboard.server.common.data.id.EntityId; | 47 | import org.thingsboard.server.common.data.id.EntityId; |
48 | +import org.thingsboard.server.common.data.id.EntityIdFactory; | ||
47 | import org.thingsboard.server.common.data.id.EntityViewId; | 49 | import org.thingsboard.server.common.data.id.EntityViewId; |
48 | import org.thingsboard.server.common.data.id.TenantId; | 50 | import org.thingsboard.server.common.data.id.TenantId; |
49 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 51 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
50 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 52 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
53 | +import org.thingsboard.server.common.data.kv.DataType; | ||
51 | import org.thingsboard.server.common.data.kv.LongDataEntry; | 54 | import org.thingsboard.server.common.data.kv.LongDataEntry; |
52 | import org.thingsboard.server.common.data.page.TimePageData; | 55 | import org.thingsboard.server.common.data.page.TimePageData; |
53 | import org.thingsboard.server.common.data.page.TimePageLink; | 56 | import org.thingsboard.server.common.data.page.TimePageLink; |
@@ -59,6 +62,7 @@ import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; | @@ -59,6 +62,7 @@ import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; | ||
59 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 62 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
60 | import org.thingsboard.server.common.data.rule.RuleNode; | 63 | import org.thingsboard.server.common.data.rule.RuleNode; |
61 | import org.thingsboard.server.common.msg.TbMsg; | 64 | import org.thingsboard.server.common.msg.TbMsg; |
65 | +import org.thingsboard.server.common.msg.TbMsgDataType; | ||
62 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 66 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
63 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | 67 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; |
64 | import org.thingsboard.server.common.msg.session.SessionMsgType; | 68 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
@@ -91,6 +95,7 @@ import org.thingsboard.server.gen.edge.UplinkResponseMsg; | @@ -91,6 +95,7 @@ import org.thingsboard.server.gen.edge.UplinkResponseMsg; | ||
91 | import org.thingsboard.server.gen.edge.UserUpdateMsg; | 95 | import org.thingsboard.server.gen.edge.UserUpdateMsg; |
92 | import org.thingsboard.server.service.edge.EdgeContextComponent; | 96 | import org.thingsboard.server.service.edge.EdgeContextComponent; |
93 | 97 | ||
98 | +import javax.swing.text.html.parser.Entity; | ||
94 | import java.io.IOException; | 99 | import java.io.IOException; |
95 | import java.util.ArrayList; | 100 | import java.util.ArrayList; |
96 | import java.util.Collections; | 101 | import java.util.Collections; |
@@ -102,6 +107,9 @@ import java.util.concurrent.locks.ReentrantLock; | @@ -102,6 +107,9 @@ import java.util.concurrent.locks.ReentrantLock; | ||
102 | import java.util.function.BiConsumer; | 107 | import java.util.function.BiConsumer; |
103 | import java.util.function.Consumer; | 108 | import java.util.function.Consumer; |
104 | 109 | ||
110 | +import static org.thingsboard.server.gen.edge.UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE; | ||
111 | +import static org.thingsboard.server.gen.edge.UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; | ||
112 | + | ||
105 | @Slf4j | 113 | @Slf4j |
106 | @Data | 114 | @Data |
107 | public final class EdgeGrpcSession implements Cloneable { | 115 | public final class EdgeGrpcSession implements Cloneable { |
@@ -175,7 +183,9 @@ public final class EdgeGrpcSession implements Cloneable { | @@ -175,7 +183,9 @@ public final class EdgeGrpcSession implements Cloneable { | ||
175 | do { | 183 | do { |
176 | pageData = ctx.getEdgeService().findQueueEvents(edge.getTenantId(), edge.getId(), pageLink); | 184 | pageData = ctx.getEdgeService().findQueueEvents(edge.getTenantId(), edge.getId(), pageLink); |
177 | if (!pageData.getData().isEmpty()) { | 185 | if (!pageData.getData().isEmpty()) { |
186 | + log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); | ||
178 | for (Event event : pageData.getData()) { | 187 | for (Event event : pageData.getData()) { |
188 | + log.trace("[{}] Processing event [{}]", this.sessionId, event); | ||
179 | EdgeQueueEntry entry; | 189 | EdgeQueueEntry entry; |
180 | try { | 190 | try { |
181 | entry = objectMapper.treeToValue(event.getBody(), EdgeQueueEntry.class); | 191 | entry = objectMapper.treeToValue(event.getBody(), EdgeQueueEntry.class); |
@@ -193,6 +203,9 @@ public final class EdgeGrpcSession implements Cloneable { | @@ -193,6 +203,9 @@ public final class EdgeGrpcSession implements Cloneable { | ||
193 | processCustomDownlinkMessage(entry); | 203 | processCustomDownlinkMessage(entry); |
194 | break; | 204 | break; |
195 | } | 205 | } |
206 | + if (ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) { | ||
207 | + pushEntityAttributesToEdge(entry); | ||
208 | + } | ||
196 | } catch (Exception e) { | 209 | } catch (Exception e) { |
197 | log.error("Exception during processing records from queue", e); | 210 | log.error("Exception during processing records from queue", e); |
198 | } | 211 | } |
@@ -215,6 +228,63 @@ public final class EdgeGrpcSession implements Cloneable { | @@ -215,6 +228,63 @@ public final class EdgeGrpcSession implements Cloneable { | ||
215 | } | 228 | } |
216 | } | 229 | } |
217 | 230 | ||
231 | + private void pushEntityAttributesToEdge(EdgeQueueEntry entry) throws IOException { | ||
232 | + EntityId entityId = null; | ||
233 | + String entityName = null; | ||
234 | + switch (entry.getEntityType()) { | ||
235 | + case EDGE: | ||
236 | + entityId = objectMapper.readValue(entry.getData(), Edge.class).getId(); | ||
237 | + break; | ||
238 | + case DEVICE: | ||
239 | + entityId = objectMapper.readValue(entry.getData(), Device.class).getId(); | ||
240 | + break; | ||
241 | + case ASSET: | ||
242 | + entityId = objectMapper.readValue(entry.getData(), Asset.class).getId(); | ||
243 | + break; | ||
244 | + case ENTITY_VIEW: | ||
245 | + entityId = objectMapper.readValue(entry.getData(), EntityView.class).getId(); | ||
246 | + break; | ||
247 | + case DASHBOARD: | ||
248 | + entityId = objectMapper.readValue(entry.getData(), Dashboard.class).getId(); | ||
249 | + break; | ||
250 | + } | ||
251 | + if (entityId != null) { | ||
252 | + ListenableFuture<List<AttributeKvEntry>> ssAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); | ||
253 | + Futures.transform(ssAttrFuture, ssAttributes -> { | ||
254 | + if (ssAttributes != null && !ssAttributes.isEmpty()) { | ||
255 | + try { | ||
256 | + TbMsgMetaData metaData = new TbMsgMetaData(); | ||
257 | + ObjectNode entityNode = objectMapper.createObjectNode(); | ||
258 | + metaData.putValue("scope", DataConstants.SERVER_SCOPE); | ||
259 | + for (AttributeKvEntry attr : ssAttributes) { | ||
260 | + if (attr.getDataType() == DataType.BOOLEAN) { | ||
261 | + entityNode.put(attr.getKey(), attr.getBooleanValue().get()); | ||
262 | + } else if (attr.getDataType() == DataType.DOUBLE) { | ||
263 | + entityNode.put(attr.getKey(), attr.getDoubleValue().get()); | ||
264 | + } else if (attr.getDataType() == DataType.LONG) { | ||
265 | + entityNode.put(attr.getKey(), attr.getLongValue().get()); | ||
266 | + } else { | ||
267 | + entityNode.put(attr.getKey(), attr.getValueAsString()); | ||
268 | + } | ||
269 | + } | ||
270 | + TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), DataConstants.ATTRIBUTES_UPDATED, entityId, metaData, TbMsgDataType.JSON | ||
271 | + , objectMapper.writeValueAsString(entityNode) | ||
272 | + , null, null, 0L); | ||
273 | + log.debug("Sending donwlink entity data msg, entityName [{}], tbMsg [{}]", entityName, tbMsg); | ||
274 | + outputStream.onNext(ResponseMsg.newBuilder() | ||
275 | + .setDownlinkMsg(constructDownlinkEntityDataMsg(entityName, tbMsg)) | ||
276 | + .build()); | ||
277 | + } catch (Exception e) { | ||
278 | + log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); | ||
279 | + } | ||
280 | + } | ||
281 | + return null; | ||
282 | + }); | ||
283 | + ListenableFuture<List<AttributeKvEntry>> shAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); | ||
284 | + ListenableFuture<List<AttributeKvEntry>> clAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); | ||
285 | + } | ||
286 | + } | ||
287 | + | ||
218 | private void processCustomDownlinkMessage(EdgeQueueEntry entry) throws IOException { | 288 | private void processCustomDownlinkMessage(EdgeQueueEntry entry) throws IOException { |
219 | log.trace("Executing processCustomDownlinkMessage, entry [{}]", entry); | 289 | log.trace("Executing processCustomDownlinkMessage, entry [{}]", entry); |
220 | TbMsg tbMsg = objectMapper.readValue(entry.getData(), TbMsg.class); | 290 | TbMsg tbMsg = objectMapper.readValue(entry.getData(), TbMsg.class); |
@@ -411,7 +481,7 @@ public final class EdgeGrpcSession implements Cloneable { | @@ -411,7 +481,7 @@ public final class EdgeGrpcSession implements Cloneable { | ||
411 | return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; | 481 | return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; |
412 | case DataConstants.ENTITY_CREATED: | 482 | case DataConstants.ENTITY_CREATED: |
413 | case DataConstants.ENTITY_ASSIGNED_TO_EDGE: | 483 | case DataConstants.ENTITY_ASSIGNED_TO_EDGE: |
414 | - return UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE; | 484 | + return ENTITY_CREATED_RPC_MESSAGE; |
415 | case DataConstants.ENTITY_DELETED: | 485 | case DataConstants.ENTITY_DELETED: |
416 | case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: | 486 | case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: |
417 | return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE; | 487 | return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE; |
@@ -521,6 +591,8 @@ public final class EdgeGrpcSession implements Cloneable { | @@ -521,6 +591,8 @@ public final class EdgeGrpcSession implements Cloneable { | ||
521 | 591 | ||
522 | private RuleNodeProto constructNode(RuleNode node) throws JsonProcessingException { | 592 | private RuleNodeProto constructNode(RuleNode node) throws JsonProcessingException { |
523 | return RuleNodeProto.newBuilder() | 593 | return RuleNodeProto.newBuilder() |
594 | + .setIdMSB(node.getId().getId().getMostSignificantBits()) | ||
595 | + .setIdLSB(node.getId().getId().getLeastSignificantBits()) | ||
524 | .setType(node.getType()) | 596 | .setType(node.getType()) |
525 | .setName(node.getName()) | 597 | .setName(node.getName()) |
526 | .setDebugMode(node.isDebugMode()) | 598 | .setDebugMode(node.isDebugMode()) |
@@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | ||
27 | import org.thingsboard.server.common.data.relation.EntityRelation; | 27 | import org.thingsboard.server.common.data.relation.EntityRelation; |
28 | import org.thingsboard.server.common.data.rule.RuleChain; | 28 | import org.thingsboard.server.common.data.rule.RuleChain; |
29 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 29 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
30 | +import org.thingsboard.server.common.data.rule.RuleChainType; | ||
30 | import org.thingsboard.server.common.data.rule.RuleNode; | 31 | import org.thingsboard.server.common.data.rule.RuleNode; |
31 | 32 | ||
32 | import java.util.List; | 33 | import java.util.List; |
@@ -62,6 +63,8 @@ public interface RuleChainService { | @@ -62,6 +63,8 @@ public interface RuleChainService { | ||
62 | 63 | ||
63 | TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink); | 64 | TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink); |
64 | 65 | ||
66 | + TextPageData<RuleChain> findTenantRuleChainsByType(TenantId tenantId, RuleChainType type, TextPageLink pageLink); | ||
67 | + | ||
65 | void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId); | 68 | void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId); |
66 | 69 | ||
67 | void deleteRuleChainsByTenantId(TenantId tenantId); | 70 | void deleteRuleChainsByTenantId(TenantId tenantId); |
@@ -125,11 +125,13 @@ message RuleChainMetadataUpdateMsg { | @@ -125,11 +125,13 @@ message RuleChainMetadataUpdateMsg { | ||
125 | } | 125 | } |
126 | 126 | ||
127 | message RuleNodeProto { | 127 | message RuleNodeProto { |
128 | - string type = 1; | ||
129 | - string name = 2; | ||
130 | - bool debugMode = 3; | ||
131 | - string configuration = 4; | ||
132 | - string additionalInfo = 5; | 128 | + int64 idMSB = 1; |
129 | + int64 idLSB = 2; | ||
130 | + string type = 3; | ||
131 | + string name = 4; | ||
132 | + bool debugMode = 5; | ||
133 | + string configuration = 6; | ||
134 | + string additionalInfo = 7; | ||
133 | } | 135 | } |
134 | 136 | ||
135 | message NodeConnectionInfoProto { | 137 | message NodeConnectionInfoProto { |
@@ -113,16 +113,16 @@ public class BaseComponentDescriptorService implements ComponentDescriptorServic | @@ -113,16 +113,16 @@ public class BaseComponentDescriptorService implements ComponentDescriptorServic | ||
113 | @Override | 113 | @Override |
114 | protected void validateDataImpl(TenantId tenantId, ComponentDescriptor plugin) { | 114 | protected void validateDataImpl(TenantId tenantId, ComponentDescriptor plugin) { |
115 | if (plugin.getType() == null) { | 115 | if (plugin.getType() == null) { |
116 | - throw new DataValidationException("Component type should be specified!."); | 116 | + throw new DataValidationException("Component type should be specified!"); |
117 | } | 117 | } |
118 | if (plugin.getScope() == null) { | 118 | if (plugin.getScope() == null) { |
119 | - throw new DataValidationException("Component scope should be specified!."); | 119 | + throw new DataValidationException("Component scope should be specified!"); |
120 | } | 120 | } |
121 | if (StringUtils.isEmpty(plugin.getName())) { | 121 | if (StringUtils.isEmpty(plugin.getName())) { |
122 | - throw new DataValidationException("Component name should be specified!."); | 122 | + throw new DataValidationException("Component name should be specified!"); |
123 | } | 123 | } |
124 | if (StringUtils.isEmpty(plugin.getClazz())) { | 124 | if (StringUtils.isEmpty(plugin.getClazz())) { |
125 | - throw new DataValidationException("Component clazz should be specified!."); | 125 | + throw new DataValidationException("Component clazz should be specified!"); |
126 | } | 126 | } |
127 | } | 127 | } |
128 | }; | 128 | }; |
@@ -54,7 +54,7 @@ public class BaseEventService implements EventService { | @@ -54,7 +54,7 @@ public class BaseEventService implements EventService { | ||
54 | public Optional<Event> saveIfNotExists(Event event) { | 54 | public Optional<Event> saveIfNotExists(Event event) { |
55 | eventValidator.validate(event, Event::getTenantId); | 55 | eventValidator.validate(event, Event::getTenantId); |
56 | if (StringUtils.isEmpty(event.getUid())) { | 56 | if (StringUtils.isEmpty(event.getUid())) { |
57 | - throw new DataValidationException("Event uid should be specified!."); | 57 | + throw new DataValidationException("Event uid should be specified!"); |
58 | } | 58 | } |
59 | return eventDao.saveIfNotExists(event); | 59 | return eventDao.saveIfNotExists(event); |
60 | } | 60 | } |
@@ -62,16 +62,16 @@ public class BaseEventService implements EventService { | @@ -62,16 +62,16 @@ public class BaseEventService implements EventService { | ||
62 | @Override | 62 | @Override |
63 | public Optional<Event> findEvent(TenantId tenantId, EntityId entityId, String eventType, String eventUid) { | 63 | public Optional<Event> findEvent(TenantId tenantId, EntityId entityId, String eventType, String eventUid) { |
64 | if (tenantId == null) { | 64 | if (tenantId == null) { |
65 | - throw new DataValidationException("Tenant id should be specified!."); | 65 | + throw new DataValidationException("Tenant id should be specified!"); |
66 | } | 66 | } |
67 | if (entityId == null) { | 67 | if (entityId == null) { |
68 | - throw new DataValidationException("Entity id should be specified!."); | 68 | + throw new DataValidationException("Entity id should be specified!"); |
69 | } | 69 | } |
70 | if (StringUtils.isEmpty(eventType)) { | 70 | if (StringUtils.isEmpty(eventType)) { |
71 | - throw new DataValidationException("Event type should be specified!."); | 71 | + throw new DataValidationException("Event type should be specified!"); |
72 | } | 72 | } |
73 | if (StringUtils.isEmpty(eventUid)) { | 73 | if (StringUtils.isEmpty(eventUid)) { |
74 | - throw new DataValidationException("Event uid should be specified!."); | 74 | + throw new DataValidationException("Event uid should be specified!"); |
75 | } | 75 | } |
76 | Event event = eventDao.findEvent(tenantId.getId(), entityId, eventType, eventUid); | 76 | Event event = eventDao.findEvent(tenantId.getId(), entityId, eventType, eventUid); |
77 | return event != null ? Optional.of(event) : Optional.empty(); | 77 | return event != null ? Optional.of(event) : Optional.empty(); |
@@ -99,13 +99,13 @@ public class BaseEventService implements EventService { | @@ -99,13 +99,13 @@ public class BaseEventService implements EventService { | ||
99 | @Override | 99 | @Override |
100 | protected void validateDataImpl(TenantId tenantId, Event event) { | 100 | protected void validateDataImpl(TenantId tenantId, Event event) { |
101 | if (event.getEntityId() == null) { | 101 | if (event.getEntityId() == null) { |
102 | - throw new DataValidationException("Entity id should be specified!."); | 102 | + throw new DataValidationException("Entity id should be specified!"); |
103 | } | 103 | } |
104 | if (StringUtils.isEmpty(event.getType())) { | 104 | if (StringUtils.isEmpty(event.getType())) { |
105 | - throw new DataValidationException("Event type should be specified!."); | 105 | + throw new DataValidationException("Event type should be specified!"); |
106 | } | 106 | } |
107 | if (event.getBody() == null) { | 107 | if (event.getBody() == null) { |
108 | - throw new DataValidationException("Event body should be specified!."); | 108 | + throw new DataValidationException("Event body should be specified!"); |
109 | } | 109 | } |
110 | } | 110 | } |
111 | }; | 111 | }; |
@@ -343,6 +343,7 @@ public class ModelConstants { | @@ -343,6 +343,7 @@ public class ModelConstants { | ||
343 | public static final String RULE_CHAIN_ASSIGNED_EDGES_PROPERTY = "assigned_edges"; | 343 | public static final String RULE_CHAIN_ASSIGNED_EDGES_PROPERTY = "assigned_edges"; |
344 | 344 | ||
345 | public static final String RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "rule_chain_by_tenant_and_search_text"; | 345 | public static final String RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "rule_chain_by_tenant_and_search_text"; |
346 | + public static final String RULE_CHAIN_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "rule_chain_by_tenant_by_type_and_search_text"; | ||
346 | 347 | ||
347 | /** | 348 | /** |
348 | * Cassandra rule node constants. | 349 | * Cassandra rule node constants. |
@@ -106,11 +106,7 @@ public class RuleChainEntity implements SearchTextEntity<RuleChain> { | @@ -106,11 +106,7 @@ public class RuleChainEntity implements SearchTextEntity<RuleChain> { | ||
106 | } | 106 | } |
107 | this.tenantId = DaoUtil.getId(ruleChain.getTenantId()); | 107 | this.tenantId = DaoUtil.getId(ruleChain.getTenantId()); |
108 | this.name = ruleChain.getName(); | 108 | this.name = ruleChain.getName(); |
109 | - if (ruleChain.getType() != null) { | ||
110 | - this.type = ruleChain.getType(); | ||
111 | - } else { | ||
112 | - this.type = RuleChainType.SYSTEM; | ||
113 | - } | 109 | + this.type = ruleChain.getType(); |
114 | this.searchText = ruleChain.getName(); | 110 | this.searchText = ruleChain.getName(); |
115 | this.firstRuleNodeId = DaoUtil.getId(ruleChain.getFirstRuleNodeId()); | 111 | this.firstRuleNodeId = DaoUtil.getId(ruleChain.getFirstRuleNodeId()); |
116 | this.root = ruleChain.isRoot(); | 112 | this.root = ruleChain.isRoot(); |
@@ -204,11 +200,7 @@ public class RuleChainEntity implements SearchTextEntity<RuleChain> { | @@ -204,11 +200,7 @@ public class RuleChainEntity implements SearchTextEntity<RuleChain> { | ||
204 | ruleChain.setCreatedTime(UUIDs.unixTimestamp(id)); | 200 | ruleChain.setCreatedTime(UUIDs.unixTimestamp(id)); |
205 | ruleChain.setTenantId(new TenantId(tenantId)); | 201 | ruleChain.setTenantId(new TenantId(tenantId)); |
206 | ruleChain.setName(name); | 202 | ruleChain.setName(name); |
207 | - if (type != null) { | ||
208 | - ruleChain.setType(type); | ||
209 | - } else { | ||
210 | - ruleChain.setType(RuleChainType.SYSTEM); | ||
211 | - } | 203 | + ruleChain.setType(type); |
212 | if (this.firstRuleNodeId != null) { | 204 | if (this.firstRuleNodeId != null) { |
213 | ruleChain.setFirstRuleNodeId(new RuleNodeId(this.firstRuleNodeId)); | 205 | ruleChain.setFirstRuleNodeId(new RuleNodeId(this.firstRuleNodeId)); |
214 | } | 206 | } |
@@ -103,11 +103,7 @@ public class RuleChainEntity extends BaseSqlEntity<RuleChain> implements SearchT | @@ -103,11 +103,7 @@ public class RuleChainEntity extends BaseSqlEntity<RuleChain> implements SearchT | ||
103 | } | 103 | } |
104 | this.tenantId = toString(DaoUtil.getId(ruleChain.getTenantId())); | 104 | this.tenantId = toString(DaoUtil.getId(ruleChain.getTenantId())); |
105 | this.name = ruleChain.getName(); | 105 | this.name = ruleChain.getName(); |
106 | - if (ruleChain.getType() != null) { | ||
107 | - this.type = ruleChain.getType(); | ||
108 | - } else { | ||
109 | - this.type = RuleChainType.SYSTEM; | ||
110 | - } | 106 | + this.type = ruleChain.getType(); |
111 | this.searchText = ruleChain.getName(); | 107 | this.searchText = ruleChain.getName(); |
112 | if (ruleChain.getFirstRuleNodeId() != null) { | 108 | if (ruleChain.getFirstRuleNodeId() != null) { |
113 | this.firstRuleNodeId = UUIDConverter.fromTimeUUID(ruleChain.getFirstRuleNodeId().getId()); | 109 | this.firstRuleNodeId = UUIDConverter.fromTimeUUID(ruleChain.getFirstRuleNodeId().getId()); |
@@ -141,11 +137,7 @@ public class RuleChainEntity extends BaseSqlEntity<RuleChain> implements SearchT | @@ -141,11 +137,7 @@ public class RuleChainEntity extends BaseSqlEntity<RuleChain> implements SearchT | ||
141 | ruleChain.setCreatedTime(UUIDs.unixTimestamp(getId())); | 137 | ruleChain.setCreatedTime(UUIDs.unixTimestamp(getId())); |
142 | ruleChain.setTenantId(new TenantId(toUUID(tenantId))); | 138 | ruleChain.setTenantId(new TenantId(toUUID(tenantId))); |
143 | ruleChain.setName(name); | 139 | ruleChain.setName(name); |
144 | - if (type != null) { | ||
145 | - ruleChain.setType(type); | ||
146 | - } else { | ||
147 | - ruleChain.setType(RuleChainType.SYSTEM); | ||
148 | - } | 140 | + ruleChain.setType(type); |
149 | if (firstRuleNodeId != null) { | 141 | if (firstRuleNodeId != null) { |
150 | ruleChain.setFirstRuleNodeId(new RuleNodeId(UUIDConverter.fromString(firstRuleNodeId))); | 142 | ruleChain.setFirstRuleNodeId(new RuleNodeId(UUIDConverter.fromString(firstRuleNodeId))); |
151 | } | 143 | } |
@@ -63,6 +63,8 @@ import java.util.Map; | @@ -63,6 +63,8 @@ import java.util.Map; | ||
63 | import java.util.concurrent.ExecutionException; | 63 | import java.util.concurrent.ExecutionException; |
64 | import java.util.stream.Collectors; | 64 | import java.util.stream.Collectors; |
65 | 65 | ||
66 | +import static org.thingsboard.server.dao.service.Validator.validateString; | ||
67 | + | ||
66 | /** | 68 | /** |
67 | * Created by igor on 3/12/18. | 69 | * Created by igor on 3/12/18. |
68 | */ | 70 | */ |
@@ -359,6 +361,14 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | @@ -359,6 +361,14 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | ||
359 | } | 361 | } |
360 | 362 | ||
361 | @Override | 363 | @Override |
364 | + public TextPageData<RuleChain> findTenantRuleChainsByType(TenantId tenantId, RuleChainType type, TextPageLink pageLink) { | ||
365 | + Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request."); | ||
366 | + Validator.validatePageLink(pageLink, "Incorrect PageLink object for search rule chain request."); | ||
367 | + List<RuleChain> ruleChains = ruleChainDao.findRuleChainsByTenantIdAndType(tenantId.getId(), type, pageLink); | ||
368 | + return new TextPageData<>(ruleChains, pageLink); | ||
369 | + } | ||
370 | + | ||
371 | + @Override | ||
362 | public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) { | 372 | public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) { |
363 | Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request."); | 373 | Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request."); |
364 | RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId()); | 374 | RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId()); |
@@ -514,7 +524,10 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | @@ -514,7 +524,10 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC | ||
514 | @Override | 524 | @Override |
515 | protected void validateDataImpl(TenantId tenantId, RuleChain ruleChain) { | 525 | protected void validateDataImpl(TenantId tenantId, RuleChain ruleChain) { |
516 | if (StringUtils.isEmpty(ruleChain.getName())) { | 526 | if (StringUtils.isEmpty(ruleChain.getName())) { |
517 | - throw new DataValidationException("Rule chain name should be specified!."); | 527 | + throw new DataValidationException("Rule chain name should be specified!"); |
528 | + } | ||
529 | + if (ruleChain.getType() == null) { | ||
530 | + throw new DataValidationException("Rule chain type should be specified!"); | ||
518 | } | 531 | } |
519 | if (ruleChain.getTenantId() == null || ruleChain.getTenantId().isNullUid()) { | 532 | if (ruleChain.getTenantId() == null || ruleChain.getTenantId().isNullUid()) { |
520 | throw new DataValidationException("Rule chain should be assigned to tenant!"); | 533 | throw new DataValidationException("Rule chain should be assigned to tenant!"); |
@@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | ||
28 | import org.thingsboard.server.common.data.relation.EntityRelation; | 28 | import org.thingsboard.server.common.data.relation.EntityRelation; |
29 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 29 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
30 | import org.thingsboard.server.common.data.rule.RuleChain; | 30 | import org.thingsboard.server.common.data.rule.RuleChain; |
31 | +import org.thingsboard.server.common.data.rule.RuleChainType; | ||
31 | import org.thingsboard.server.dao.DaoUtil; | 32 | import org.thingsboard.server.dao.DaoUtil; |
32 | import org.thingsboard.server.dao.model.nosql.RuleChainEntity; | 33 | import org.thingsboard.server.dao.model.nosql.RuleChainEntity; |
33 | import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; | 34 | import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; |
@@ -35,14 +36,19 @@ import org.thingsboard.server.dao.relation.RelationDao; | @@ -35,14 +36,19 @@ import org.thingsboard.server.dao.relation.RelationDao; | ||
35 | import org.thingsboard.server.dao.util.NoSqlDao; | 36 | import org.thingsboard.server.dao.util.NoSqlDao; |
36 | 37 | ||
37 | import java.util.ArrayList; | 38 | import java.util.ArrayList; |
39 | +import java.util.Arrays; | ||
38 | import java.util.Collections; | 40 | import java.util.Collections; |
39 | import java.util.List; | 41 | import java.util.List; |
40 | import java.util.UUID; | 42 | import java.util.UUID; |
41 | 43 | ||
42 | import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; | 44 | import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; |
45 | +import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TENANT_ID_PROPERTY; | ||
46 | +import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TYPE_PROPERTY; | ||
43 | import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; | 47 | import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; |
48 | +import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; | ||
44 | import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_COLUMN_FAMILY_NAME; | 49 | import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_COLUMN_FAMILY_NAME; |
45 | import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY; | 50 | import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY; |
51 | +import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_TYPE_PROPERTY; | ||
46 | 52 | ||
47 | @Component | 53 | @Component |
48 | @Slf4j | 54 | @Slf4j |
@@ -74,6 +80,17 @@ public class CassandraRuleChainDao extends CassandraAbstractSearchTextDao<RuleCh | @@ -74,6 +80,17 @@ public class CassandraRuleChainDao extends CassandraAbstractSearchTextDao<RuleCh | ||
74 | } | 80 | } |
75 | 81 | ||
76 | @Override | 82 | @Override |
83 | + public List<RuleChain> findRuleChainsByTenantIdAndType(UUID tenantId, RuleChainType type, TextPageLink pageLink) { | ||
84 | + log.debug("Try to find rule chains by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink); | ||
85 | + List<RuleChainEntity> ruleChainEntities = findPageWithTextSearch(new TenantId(tenantId), RULE_CHAIN_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, | ||
86 | + Arrays.asList(eq(RULE_CHAIN_TYPE_PROPERTY, type), | ||
87 | + eq(RULE_CHAIN_TENANT_ID_PROPERTY, tenantId)), | ||
88 | + pageLink); | ||
89 | + log.trace("Found rule chains [{}] by tenantId [{}] and pageLink [{}]", ruleChainEntities, tenantId, pageLink); | ||
90 | + return DaoUtil.convertDataList(ruleChainEntities); | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
77 | public ListenableFuture<List<RuleChain>> findRuleChainsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink) { | 94 | public ListenableFuture<List<RuleChain>> findRuleChainsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink) { |
78 | log.debug("Try to find rule chains by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); | 95 | log.debug("Try to find rule chains by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); |
79 | ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new TenantId(tenantId), new EdgeId(edgeId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE, EntityType.DASHBOARD, pageLink); | 96 | ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new TenantId(tenantId), new EdgeId(edgeId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE, EntityType.DASHBOARD, pageLink); |
@@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
19 | import org.thingsboard.server.common.data.page.TextPageLink; | 19 | import org.thingsboard.server.common.data.page.TextPageLink; |
20 | import org.thingsboard.server.common.data.page.TimePageLink; | 20 | import org.thingsboard.server.common.data.page.TimePageLink; |
21 | import org.thingsboard.server.common.data.rule.RuleChain; | 21 | import org.thingsboard.server.common.data.rule.RuleChain; |
22 | +import org.thingsboard.server.common.data.rule.RuleChainType; | ||
22 | import org.thingsboard.server.dao.Dao; | 23 | import org.thingsboard.server.dao.Dao; |
23 | 24 | ||
24 | import java.util.List; | 25 | import java.util.List; |
@@ -39,6 +40,16 @@ public interface RuleChainDao extends Dao<RuleChain> { | @@ -39,6 +40,16 @@ public interface RuleChainDao extends Dao<RuleChain> { | ||
39 | List<RuleChain> findRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink); | 40 | List<RuleChain> findRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink); |
40 | 41 | ||
41 | /** | 42 | /** |
43 | + * Find rule chains by tenantId, type and page link. | ||
44 | + * | ||
45 | + * @param tenantId the tenantId | ||
46 | + * @param type the type | ||
47 | + * @param pageLink the page link | ||
48 | + * @return the list of rule chain objects | ||
49 | + */ | ||
50 | + List<RuleChain> findRuleChainsByTenantIdAndType(UUID tenantId, RuleChainType type, TextPageLink pageLink); | ||
51 | + | ||
52 | + /** | ||
42 | * Find rule chains by tenantId, edgeId and page link. | 53 | * Find rule chains by tenantId, edgeId and page link. |
43 | * | 54 | * |
44 | * @param tenantId the tenantId | 55 | * @param tenantId the tenantId |
@@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | ||
31 | import org.thingsboard.server.common.data.relation.EntityRelation; | 31 | import org.thingsboard.server.common.data.relation.EntityRelation; |
32 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 32 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
33 | import org.thingsboard.server.common.data.rule.RuleChain; | 33 | import org.thingsboard.server.common.data.rule.RuleChain; |
34 | +import org.thingsboard.server.common.data.rule.RuleChainType; | ||
34 | import org.thingsboard.server.dao.DaoUtil; | 35 | import org.thingsboard.server.dao.DaoUtil; |
35 | import org.thingsboard.server.dao.model.sql.RuleChainEntity; | 36 | import org.thingsboard.server.dao.model.sql.RuleChainEntity; |
36 | import org.thingsboard.server.dao.relation.RelationDao; | 37 | import org.thingsboard.server.dao.relation.RelationDao; |
@@ -68,6 +69,7 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R | @@ -68,6 +69,7 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R | ||
68 | 69 | ||
69 | @Override | 70 | @Override |
70 | public List<RuleChain> findRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) { | 71 | public List<RuleChain> findRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) { |
72 | + log.debug("Try to find rule chains by tenantId [{}] and pageLink [{}]", tenantId, pageLink); | ||
71 | return DaoUtil.convertDataList(ruleChainRepository | 73 | return DaoUtil.convertDataList(ruleChainRepository |
72 | .findByTenantId( | 74 | .findByTenantId( |
73 | UUIDConverter.fromTimeUUID(tenantId), | 75 | UUIDConverter.fromTimeUUID(tenantId), |
@@ -77,6 +79,18 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R | @@ -77,6 +79,18 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R | ||
77 | } | 79 | } |
78 | 80 | ||
79 | @Override | 81 | @Override |
82 | + public List<RuleChain> findRuleChainsByTenantIdAndType(UUID tenantId, RuleChainType type, TextPageLink pageLink) { | ||
83 | + log.debug("Try to find rule chains by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink); | ||
84 | + return DaoUtil.convertDataList(ruleChainRepository | ||
85 | + .findByTenantIdAndType( | ||
86 | + UUIDConverter.fromTimeUUID(tenantId), | ||
87 | + type, | ||
88 | + Objects.toString(pageLink.getTextSearch(), ""), | ||
89 | + pageLink.getIdOffset() == null ? NULL_UUID_STR : UUIDConverter.fromTimeUUID(pageLink.getIdOffset()), | ||
90 | + new PageRequest(0, pageLink.getLimit()))); | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
80 | public ListenableFuture<List<RuleChain>> findRuleChainsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink) { | 94 | public ListenableFuture<List<RuleChain>> findRuleChainsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink) { |
81 | log.debug("Try to find rule chains by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); | 95 | log.debug("Try to find rule chains by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); |
82 | ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new TenantId(tenantId), new EdgeId(edgeId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE, EntityType.RULE_CHAIN, pageLink); | 96 | ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new TenantId(tenantId), new EdgeId(edgeId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE, EntityType.RULE_CHAIN, pageLink); |
@@ -19,6 +19,7 @@ import org.springframework.data.domain.Pageable; | @@ -19,6 +19,7 @@ import org.springframework.data.domain.Pageable; | ||
19 | import org.springframework.data.jpa.repository.Query; | 19 | import org.springframework.data.jpa.repository.Query; |
20 | import org.springframework.data.repository.CrudRepository; | 20 | import org.springframework.data.repository.CrudRepository; |
21 | import org.springframework.data.repository.query.Param; | 21 | import org.springframework.data.repository.query.Param; |
22 | +import org.thingsboard.server.common.data.rule.RuleChainType; | ||
22 | import org.thingsboard.server.dao.model.sql.RuleChainEntity; | 23 | import org.thingsboard.server.dao.model.sql.RuleChainEntity; |
23 | import org.thingsboard.server.dao.util.SqlDao; | 24 | import org.thingsboard.server.dao.util.SqlDao; |
24 | 25 | ||
@@ -35,4 +36,13 @@ public interface RuleChainRepository extends CrudRepository<RuleChainEntity, Str | @@ -35,4 +36,13 @@ public interface RuleChainRepository extends CrudRepository<RuleChainEntity, Str | ||
35 | @Param("idOffset") String idOffset, | 36 | @Param("idOffset") String idOffset, |
36 | Pageable pageable); | 37 | Pageable pageable); |
37 | 38 | ||
39 | + @Query("SELECT rc FROM RuleChainEntity rc WHERE rc.tenantId = :tenantId " + | ||
40 | + "AND rc.type = :type " + | ||
41 | + "AND LOWER(rc.searchText) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
42 | + "AND rc.id > :idOffset ORDER BY rc.id") | ||
43 | + List<RuleChainEntity> findByTenantIdAndType(@Param("tenantId") String tenantId, | ||
44 | + @Param("type") RuleChainType type, | ||
45 | + @Param("searchText") String searchText, | ||
46 | + @Param("idOffset") String idOffset, | ||
47 | + Pageable pageable); | ||
38 | } | 48 | } |
@@ -597,22 +597,30 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_chain ( | @@ -597,22 +597,30 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_chain ( | ||
597 | id uuid, | 597 | id uuid, |
598 | tenant_id uuid, | 598 | tenant_id uuid, |
599 | name text, | 599 | name text, |
600 | + type text, | ||
600 | search_text text, | 601 | search_text text, |
601 | first_rule_node_id uuid, | 602 | first_rule_node_id uuid, |
602 | root boolean, | 603 | root boolean, |
603 | debug_mode boolean, | 604 | debug_mode boolean, |
604 | configuration text, | 605 | configuration text, |
605 | additional_info text, | 606 | additional_info text, |
606 | - PRIMARY KEY (id, tenant_id) | 607 | + PRIMARY KEY (id, tenant_id, type) |
607 | ); | 608 | ); |
608 | 609 | ||
609 | CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.rule_chain_by_tenant_and_search_text AS | 610 | CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.rule_chain_by_tenant_and_search_text AS |
610 | SELECT * | 611 | SELECT * |
611 | from thingsboard.rule_chain | 612 | from thingsboard.rule_chain |
612 | - WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
613 | - PRIMARY KEY ( tenant_id, search_text, id ) | 613 | + WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL AND type IS NOT NULL |
614 | + PRIMARY KEY ( tenant_id, search_text, id, type ) | ||
614 | WITH CLUSTERING ORDER BY ( search_text ASC, id DESC ); | 615 | WITH CLUSTERING ORDER BY ( search_text ASC, id DESC ); |
615 | 616 | ||
617 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.rule_chain_by_tenant_by_type_and_search_text AS | ||
618 | + SELECT * | ||
619 | + from thingsboard.rule_chain | ||
620 | + WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL AND type IS NOT NULL | ||
621 | + PRIMARY KEY ( tenant_id, type, search_text, id ) | ||
622 | + WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC ); | ||
623 | + | ||
616 | CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( | 624 | CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( |
617 | id uuid, | 625 | id uuid, |
618 | rule_chain_id uuid, | 626 | rule_chain_id uuid, |
@@ -277,7 +277,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | @@ -277,7 +277,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | ||
277 | } | 277 | } |
278 | break; | 278 | break; |
279 | case types.entityType.rulechain: | 279 | case types.entityType.rulechain: |
280 | - promise = ruleChainService.getRuleChains(pageLink, config); | 280 | + promise = ruleChainService.getRuleChains(pageLink, config, subType); |
281 | break; | 281 | break; |
282 | case types.entityType.dashboard: | 282 | case types.entityType.dashboard: |
283 | if (user.authority === 'CUSTOMER_USER') { | 283 | if (user.authority === 'CUSTOMER_USER') { |
@@ -46,7 +46,7 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co | @@ -46,7 +46,7 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co | ||
46 | 46 | ||
47 | return service; | 47 | return service; |
48 | 48 | ||
49 | - function getRuleChains (pageLink, config) { | 49 | + function getRuleChains (pageLink, config, type) { |
50 | var deferred = $q.defer(); | 50 | var deferred = $q.defer(); |
51 | var url = '/api/ruleChains?limit=' + pageLink.limit; | 51 | var url = '/api/ruleChains?limit=' + pageLink.limit; |
52 | if (angular.isDefined(pageLink.textSearch)) { | 52 | if (angular.isDefined(pageLink.textSearch)) { |
@@ -58,6 +58,9 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co | @@ -58,6 +58,9 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co | ||
58 | if (angular.isDefined(pageLink.textOffset)) { | 58 | if (angular.isDefined(pageLink.textOffset)) { |
59 | url += '&textOffset=' + pageLink.textOffset; | 59 | url += '&textOffset=' + pageLink.textOffset; |
60 | } | 60 | } |
61 | + if (angular.isDefined(type) && type.length) { | ||
62 | + url += '&type=' + type; | ||
63 | + } | ||
61 | $http.get(url, config).then(function success(response) { | 64 | $http.get(url, config).then(function success(response) { |
62 | deferred.resolve(prepareRuleChains(response.data)); | 65 | deferred.resolve(prepareRuleChains(response.data)); |
63 | }, function fail() { | 66 | }, function fail() { |
@@ -607,7 +607,7 @@ export default angular.module('thingsboard.types', []) | @@ -607,7 +607,7 @@ export default angular.module('thingsboard.types', []) | ||
607 | } | 607 | } |
608 | }, | 608 | }, |
609 | systemRuleChainType: "SYSTEM", | 609 | systemRuleChainType: "SYSTEM", |
610 | - ruleChainTypes: ["SYSTEM", "EDGE"], | 610 | + edgeRuleChainType: "EDGE", |
611 | ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], | 611 | ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], |
612 | ruleChainNodeComponent: { | 612 | ruleChainNodeComponent: { |
613 | type: 'RULE_CHAIN', | 613 | type: 'RULE_CHAIN', |
@@ -1391,10 +1391,11 @@ | @@ -1391,10 +1391,11 @@ | ||
1391 | "rulechain": { | 1391 | "rulechain": { |
1392 | "rulechain": "Rule chain", | 1392 | "rulechain": "Rule chain", |
1393 | "rulechains": "Rule chains", | 1393 | "rulechains": "Rule chains", |
1394 | + "system-rulechains": "System Rule chains", | ||
1395 | + "edge-rulechains": "Edge Rule chains", | ||
1394 | "root": "Root", | 1396 | "root": "Root", |
1395 | "delete": "Delete rule chain", | 1397 | "delete": "Delete rule chain", |
1396 | "name": "Name", | 1398 | "name": "Name", |
1397 | - "type": "Type", | ||
1398 | "name-required": "Name is required.", | 1399 | "name-required": "Name is required.", |
1399 | "description": "Description", | 1400 | "description": "Description", |
1400 | "add": "Add Rule Chain", | 1401 | "add": "Add Rule Chain", |
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | 31 | <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> |
32 | <md-dialog-content> | 32 | <md-dialog-content> |
33 | <div class="md-dialog-content"> | 33 | <div class="md-dialog-content"> |
34 | - <tb-rule-chain rule-chain="vm.item" is-edit="true" rule-chain-scope="'tenant'" the-form="theForm"></tb-rule-chain> | 34 | + <tb-rule-chain rule-chain="vm.item" is-edit="true" the-form="theForm"></tb-rule-chain> |
35 | </div> | 35 | </div> |
36 | </md-dialog-content> | 36 | </md-dialog-content> |
37 | <md-dialog-actions layout="row"> | 37 | <md-dialog-actions layout="row"> |
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | 31 | <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> |
32 | <md-dialog-content> | 32 | <md-dialog-content> |
33 | <div class="md-dialog-content"> | 33 | <div class="md-dialog-content"> |
34 | - <tb-rule-node rule-node="vm.ruleNode" rule-chain-id="vm.ruleChainId" is-edit="true" the-form="theForm"></tb-rule-node> | 34 | + <tb-rule-node rule-node="vm.ruleNode" rule-chain-id="vm.ruleChainId" rule-chain-type="vm.ruleChainType" is-edit="true" the-form="theForm"></tb-rule-node> |
35 | </div> | 35 | </div> |
36 | </md-dialog-content> | 36 | </md-dialog-content> |
37 | <md-dialog-actions layout="row"> | 37 | <md-dialog-actions layout="row"> |
@@ -50,14 +50,6 @@ | @@ -50,14 +50,6 @@ | ||
50 | </div> | 50 | </div> |
51 | </md-input-container> | 51 | </md-input-container> |
52 | <md-input-container class="md-block"> | 52 | <md-input-container class="md-block"> |
53 | - <label translate>rulechain.type</label> | ||
54 | - <md-select ng-disabled="$root.loading || !isEdit || ruleChainScope !== 'tenant' || ruleChain.root === true" name="type" ng-model="ruleChain.type"> | ||
55 | - <md-option ng-repeat="ruleChainType in ruleChainTypes" value="{{ruleChainType}}"> | ||
56 | - {{ruleChainType}} | ||
57 | - </md-option> | ||
58 | - </md-select> | ||
59 | - </md-input-container> | ||
60 | - <md-input-container class="md-block"> | ||
61 | <md-checkbox ng-disabled="$root.loading || !isEdit" aria-label="{{ 'rulechain.debug-mode' | translate }}" | 53 | <md-checkbox ng-disabled="$root.loading || !isEdit" aria-label="{{ 'rulechain.debug-mode' | translate }}" |
62 | ng-model="ruleChain.debugMode">{{ 'rulechain.debug-mode' | translate }} | 54 | ng-model="ruleChain.debugMode">{{ 'rulechain.debug-mode' | translate }} |
63 | </md-checkbox> | 55 | </md-checkbox> |
@@ -1179,6 +1179,9 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | @@ -1179,6 +1179,9 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | ||
1179 | function saveRuleChain() { | 1179 | function saveRuleChain() { |
1180 | var saveRuleChainPromise; | 1180 | var saveRuleChainPromise; |
1181 | if (vm.isImport) { | 1181 | if (vm.isImport) { |
1182 | + if (angular.isUndefined(vm.ruleChain.type)) { | ||
1183 | + vm.ruleChain.type = types.systemRuleChainType; | ||
1184 | + } | ||
1182 | saveRuleChainPromise = ruleChainService.saveRuleChain(vm.ruleChain); | 1185 | saveRuleChainPromise = ruleChainService.saveRuleChain(vm.ruleChain); |
1183 | } else { | 1186 | } else { |
1184 | saveRuleChainPromise = $q.when(vm.ruleChain); | 1187 | saveRuleChainPromise = $q.when(vm.ruleChain); |
@@ -1286,6 +1289,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | @@ -1286,6 +1289,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | ||
1286 | ruleNode.configuration = angular.copy(ruleNode.component.configurationDescriptor.nodeDefinition.defaultConfiguration); | 1289 | ruleNode.configuration = angular.copy(ruleNode.component.configurationDescriptor.nodeDefinition.defaultConfiguration); |
1287 | 1290 | ||
1288 | var ruleChainId = vm.ruleChain.id ? vm.ruleChain.id.id : null; | 1291 | var ruleChainId = vm.ruleChain.id ? vm.ruleChain.id.id : null; |
1292 | + var ruleChainType = vm.ruleChain.type ? vm.ruleChain.type : types.systemRuleChainType; | ||
1289 | 1293 | ||
1290 | vm.enableHotKeys = false; | 1294 | vm.enableHotKeys = false; |
1291 | 1295 | ||
@@ -1294,7 +1298,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | @@ -1294,7 +1298,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | ||
1294 | controllerAs: 'vm', | 1298 | controllerAs: 'vm', |
1295 | templateUrl: addRuleNodeTemplate, | 1299 | templateUrl: addRuleNodeTemplate, |
1296 | parent: angular.element($document[0].body), | 1300 | parent: angular.element($document[0].body), |
1297 | - locals: {ruleNode: ruleNode, ruleChainId: ruleChainId}, | 1301 | + locals: {ruleNode: ruleNode, ruleChainId: ruleChainId, ruleChainType: ruleChainType}, |
1298 | fullscreen: true, | 1302 | fullscreen: true, |
1299 | targetEvent: $event | 1303 | targetEvent: $event |
1300 | }).then(function (ruleNode) { | 1304 | }).then(function (ruleNode) { |
@@ -1365,13 +1369,14 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | @@ -1365,13 +1369,14 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time | ||
1365 | } | 1369 | } |
1366 | 1370 | ||
1367 | /*@ngInject*/ | 1371 | /*@ngInject*/ |
1368 | -export function AddRuleNodeController($scope, $mdDialog, ruleNode, ruleChainId, helpLinks) { | 1372 | +export function AddRuleNodeController($scope, $mdDialog, ruleNode, ruleChainId, ruleChainType, helpLinks) { |
1369 | 1373 | ||
1370 | var vm = this; | 1374 | var vm = this; |
1371 | 1375 | ||
1372 | vm.helpLinks = helpLinks; | 1376 | vm.helpLinks = helpLinks; |
1373 | vm.ruleNode = ruleNode; | 1377 | vm.ruleNode = ruleNode; |
1374 | vm.ruleChainId = ruleChainId; | 1378 | vm.ruleChainId = ruleChainId; |
1379 | + vm.ruleChainType = ruleChainType; | ||
1375 | 1380 | ||
1376 | vm.add = add; | 1381 | vm.add = add; |
1377 | vm.cancel = cancel; | 1382 | vm.cancel = cancel; |
@@ -26,12 +26,6 @@ export default function RuleChainDirective($compile, $templateCache, $mdDialog, | @@ -26,12 +26,6 @@ export default function RuleChainDirective($compile, $templateCache, $mdDialog, | ||
26 | var template = $templateCache.get(ruleChainFieldsetTemplate); | 26 | var template = $templateCache.get(ruleChainFieldsetTemplate); |
27 | element.html(template); | 27 | element.html(template); |
28 | 28 | ||
29 | - scope.ruleChainTypes = types.ruleChainTypes; | ||
30 | - | ||
31 | - if (angular.isDefined(scope.ruleChain) && scope.ruleChain != null && angular.isUndefined(scope.ruleChain.type)) { | ||
32 | - scope.ruleChain.type = types.systemRuleChainType; | ||
33 | - } | ||
34 | - | ||
35 | scope.onRuleChainIdCopied = function() { | 29 | scope.onRuleChainIdCopied = function() { |
36 | toast.showSuccess($translate.instant('rulechain.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left'); | 30 | toast.showSuccess($translate.instant('rulechain.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left'); |
37 | }; | 31 | }; |
@@ -44,7 +38,6 @@ export default function RuleChainDirective($compile, $templateCache, $mdDialog, | @@ -44,7 +38,6 @@ export default function RuleChainDirective($compile, $templateCache, $mdDialog, | ||
44 | scope: { | 38 | scope: { |
45 | ruleChain: '=', | 39 | ruleChain: '=', |
46 | isEdit: '=', | 40 | isEdit: '=', |
47 | - ruleChainScope: '=', | ||
48 | isReadOnly: '=', | 41 | isReadOnly: '=', |
49 | theForm: '=', | 42 | theForm: '=', |
50 | onSetRootRuleChain: '&', | 43 | onSetRootRuleChain: '&', |
@@ -29,6 +29,15 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | @@ -29,6 +29,15 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | ||
29 | $stateProvider | 29 | $stateProvider |
30 | .state('home.ruleChains', { | 30 | .state('home.ruleChains', { |
31 | url: '/ruleChains', | 31 | url: '/ruleChains', |
32 | + module: 'private', | ||
33 | + auth: ['SYS_ADMIN', 'TENANT_ADMIN'], | ||
34 | + redirectTo: 'home.ruleChains.system', | ||
35 | + ncyBreadcrumb: { | ||
36 | + label: '{"icon": "settings_ethernet", "label": "rulechain.rulechains"}' | ||
37 | + } | ||
38 | + }) | ||
39 | + .state('home.ruleChains.system', { | ||
40 | + url: '/ruleChains/system', | ||
32 | params: {'topIndex': 0}, | 41 | params: {'topIndex': 0}, |
33 | module: 'private', | 42 | module: 'private', |
34 | auth: ['SYS_ADMIN', 'TENANT_ADMIN'], | 43 | auth: ['SYS_ADMIN', 'TENANT_ADMIN'], |
@@ -41,11 +50,11 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | @@ -41,11 +50,11 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | ||
41 | }, | 50 | }, |
42 | data: { | 51 | data: { |
43 | searchEnabled: true, | 52 | searchEnabled: true, |
44 | - pageTitle: 'rulechain.rulechains', | 53 | + pageTitle: 'rulechain.system-rulechains', |
45 | ruleChainsType: 'tenant' | 54 | ruleChainsType: 'tenant' |
46 | }, | 55 | }, |
47 | ncyBreadcrumb: { | 56 | ncyBreadcrumb: { |
48 | - label: '{"icon": "settings_ethernet", "label": "rulechain.rulechains"}' | 57 | + label: '{"icon": "settings_ethernet", "label": "rulechain.system-rulechains"}' |
49 | } | 58 | } |
50 | }).state('home.ruleChains.ruleChain', { | 59 | }).state('home.ruleChains.ruleChain', { |
51 | url: '/:ruleChainId', | 60 | url: '/:ruleChainId', |
@@ -124,8 +133,64 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | @@ -124,8 +133,64 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | ||
124 | ncyBreadcrumb: { | 133 | ncyBreadcrumb: { |
125 | label: '{"icon": "settings_ethernet", "label": "{{ (\'rulechain.import\' | translate) + \': \'+ vm.ruleChain.name }}", "translate": "false"}' | 134 | label: '{"icon": "settings_ethernet", "label": "{{ (\'rulechain.import\' | translate) + \': \'+ vm.ruleChain.name }}", "translate": "false"}' |
126 | } | 135 | } |
127 | - }) | ||
128 | - .state('home.edges.ruleChains', { | 136 | + }).state('home.ruleChains.edge', { |
137 | + url: '/ruleChains/edge', | ||
138 | + params: {'topIndex': 0}, | ||
139 | + module: 'private', | ||
140 | + auth: ['TENANT_ADMIN'], | ||
141 | + views: { | ||
142 | + "content@home": { | ||
143 | + templateUrl: ruleChainsTemplate, | ||
144 | + controllerAs: 'vm', | ||
145 | + controller: 'RuleChainsController' | ||
146 | + } | ||
147 | + }, | ||
148 | + data: { | ||
149 | + searchEnabled: true, | ||
150 | + pageTitle: 'rulechain.edge-rulechains', | ||
151 | + ruleChainsType: 'edges' | ||
152 | + }, | ||
153 | + ncyBreadcrumb: { | ||
154 | + label: '{"icon": "settings_ethernet", "label": "rulechain.edge-rulechains"}' | ||
155 | + } | ||
156 | + }).state('home.ruleChains.edge.ruleChain', { | ||
157 | + url: '/:ruleChainId', | ||
158 | + reloadOnSearch: false, | ||
159 | + module: 'private', | ||
160 | + auth: ['SYS_ADMIN', 'TENANT_ADMIN'], | ||
161 | + views: { | ||
162 | + "content@home": { | ||
163 | + templateUrl: ruleChainTemplate, | ||
164 | + controller: 'RuleChainController', | ||
165 | + controllerAs: 'vm' | ||
166 | + } | ||
167 | + }, | ||
168 | + resolve: { | ||
169 | + ruleChain: | ||
170 | + /*@ngInject*/ | ||
171 | + function($stateParams, ruleChainService) { | ||
172 | + return ruleChainService.getRuleChain($stateParams.ruleChainId); | ||
173 | + }, | ||
174 | + ruleChainMetaData: | ||
175 | + /*@ngInject*/ | ||
176 | + function($stateParams, ruleChainService) { | ||
177 | + return ruleChainService.getRuleChainMetaData($stateParams.ruleChainId); | ||
178 | + }, | ||
179 | + ruleNodeComponents: | ||
180 | + /*@ngInject*/ | ||
181 | + function($stateParams, ruleChainService) { | ||
182 | + return ruleChainService.getRuleNodeComponents(); | ||
183 | + } | ||
184 | + }, | ||
185 | + data: { | ||
186 | + import: false, | ||
187 | + searchEnabled: false, | ||
188 | + pageTitle: 'edge.rulechain' | ||
189 | + }, | ||
190 | + ncyBreadcrumb: { | ||
191 | + label: '{"icon": "settings_ethernet", "label": "{{ vm.ruleChain.name }}", "translate": "false"}' | ||
192 | + } | ||
193 | + }).state('home.edges.ruleChains', { | ||
129 | url: '/:edgeId/ruleChains', | 194 | url: '/:edgeId/ruleChains', |
130 | params: {'topIndex': 0}, | 195 | params: {'topIndex': 0}, |
131 | module: 'private', | 196 | module: 'private', |
@@ -138,15 +203,14 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | @@ -138,15 +203,14 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | ||
138 | } | 203 | } |
139 | }, | 204 | }, |
140 | data: { | 205 | data: { |
141 | - ruleChainsType: 'edge', | ||
142 | searchEnabled: true, | 206 | searchEnabled: true, |
143 | - pageTitle: 'edge.rulechains' | 207 | + pageTitle: 'edge.rulechains', |
208 | + ruleChainsType: 'edge' | ||
144 | }, | 209 | }, |
145 | ncyBreadcrumb: { | 210 | ncyBreadcrumb: { |
146 | label: '{"icon": "settings_ethernet", "label": "{{ vm.edgeRuleChainsTitle }}", "translate": "false"}' | 211 | label: '{"icon": "settings_ethernet", "label": "{{ vm.edgeRuleChainsTitle }}", "translate": "false"}' |
147 | } | 212 | } |
148 | - }) | ||
149 | - .state('home.edges.ruleChains.ruleChain', { | 213 | + }).state('home.edges.ruleChains.ruleChain', { |
150 | url: '/:ruleChainId', | 214 | url: '/:ruleChainId', |
151 | reloadOnSearch: false, | 215 | reloadOnSearch: false, |
152 | module: 'private', | 216 | module: 'private', |
@@ -181,7 +245,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | @@ -181,7 +245,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | ||
181 | pageTitle: 'edge.rulechain' | 245 | pageTitle: 'edge.rulechain' |
182 | }, | 246 | }, |
183 | ncyBreadcrumb: { | 247 | ncyBreadcrumb: { |
184 | - label: '{"icon": "settings_ethernet", "label": "edge.rulechain"}' | 248 | + label: '{"icon": "settings_ethernet", "label": "{{ vm.ruleChain.name }}", "translate": "false"}' |
185 | } | 249 | } |
186 | }); | 250 | }); |
187 | } | 251 | } |
@@ -116,7 +116,7 @@ export default function RuleChainsController(ruleChainService, userService, edge | @@ -116,7 +116,7 @@ export default function RuleChainsController(ruleChainService, userService, edge | ||
116 | 116 | ||
117 | if (vm.ruleChainsScope === 'tenant') { | 117 | if (vm.ruleChainsScope === 'tenant') { |
118 | fetchRuleChainsFunction = function (pageLink) { | 118 | fetchRuleChainsFunction = function (pageLink) { |
119 | - return fetchRuleChains(pageLink); | 119 | + return fetchRuleChains(pageLink, 'SYSTEM'); |
120 | }; | 120 | }; |
121 | deleteRuleChainFunction = function (ruleChainId) { | 121 | deleteRuleChainFunction = function (ruleChainId) { |
122 | return deleteRuleChain(ruleChainId); | 122 | return deleteRuleChain(ruleChainId); |
@@ -134,6 +134,57 @@ export default function RuleChainsController(ruleChainService, userService, edge | @@ -134,6 +134,57 @@ export default function RuleChainsController(ruleChainService, userService, edge | ||
134 | 134 | ||
135 | ruleChainActionsList.push({ | 135 | ruleChainActionsList.push({ |
136 | onAction: function ($event, item) { | 136 | onAction: function ($event, item) { |
137 | + vm.grid.deleteItem($event, item); | ||
138 | + }, | ||
139 | + name: function() { return $translate.instant('action.delete') }, | ||
140 | + details: function() { return $translate.instant('rulechain.delete') }, | ||
141 | + icon: "delete", | ||
142 | + isEnabled: isNonRootRuleChain | ||
143 | + }); | ||
144 | + | ||
145 | + ruleChainGroupActionsList.push( | ||
146 | + { | ||
147 | + onAction: function ($event) { | ||
148 | + vm.grid.deleteItems($event); | ||
149 | + }, | ||
150 | + name: function() { return $translate.instant('rulechain.delete-rulechains') }, | ||
151 | + details: deleteRuleChainsActionTitle, | ||
152 | + icon: "delete" | ||
153 | + } | ||
154 | + ); | ||
155 | + | ||
156 | + vm.ruleChainGridConfig.addItemActions = []; | ||
157 | + vm.ruleChainGridConfig.addItemActions.push({ | ||
158 | + onAction: function ($event) { | ||
159 | + vm.grid.addItem($event); | ||
160 | + }, | ||
161 | + name: function() { return $translate.instant('action.create') }, | ||
162 | + details: function() { return $translate.instant('rulechain.create-new-rulechain') }, | ||
163 | + icon: "insert_drive_file" | ||
164 | + }); | ||
165 | + vm.ruleChainGridConfig.addItemActions.push({ | ||
166 | + onAction: function ($event) { | ||
167 | + importExport.importRuleChain($event).then( | ||
168 | + function(ruleChainImport) { | ||
169 | + $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport}); | ||
170 | + } | ||
171 | + ); | ||
172 | + }, | ||
173 | + name: function() { return $translate.instant('action.import') }, | ||
174 | + details: function() { return $translate.instant('rulechain.import') }, | ||
175 | + icon: "file_upload" | ||
176 | + }); | ||
177 | + | ||
178 | + } else if (vm.ruleChainsScope === 'edges') { | ||
179 | + fetchRuleChainsFunction = function (pageLink) { | ||
180 | + return fetchRuleChains(pageLink, 'EDGE'); | ||
181 | + }; | ||
182 | + deleteRuleChainFunction = function (ruleChainId) { | ||
183 | + return deleteRuleChain(ruleChainId); | ||
184 | + }; | ||
185 | + | ||
186 | + ruleChainActionsList.push({ | ||
187 | + onAction: function ($event, item) { | ||
137 | manageAssignedEdges($event, item); | 188 | manageAssignedEdges($event, item); |
138 | }, | 189 | }, |
139 | name: function() { return $translate.instant('action.assign') }, | 190 | name: function() { return $translate.instant('action.assign') }, |
@@ -209,7 +260,6 @@ export default function RuleChainsController(ruleChainService, userService, edge | @@ -209,7 +260,6 @@ export default function RuleChainsController(ruleChainService, userService, edge | ||
209 | details: function() { return $translate.instant('rulechain.import') }, | 260 | details: function() { return $translate.instant('rulechain.import') }, |
210 | icon: "file_upload" | 261 | icon: "file_upload" |
211 | }); | 262 | }); |
212 | - | ||
213 | } else if (vm.ruleChainsScope === 'edge') { | 263 | } else if (vm.ruleChainsScope === 'edge') { |
214 | fetchRuleChainsFunction = function (pageLink) { | 264 | fetchRuleChainsFunction = function (pageLink) { |
215 | return ruleChainService.getEdgeRuleChains(edgeId, pageLink); | 265 | return ruleChainService.getEdgeRuleChains(edgeId, pageLink); |
@@ -291,11 +341,18 @@ export default function RuleChainsController(ruleChainService, userService, edge | @@ -291,11 +341,18 @@ export default function RuleChainsController(ruleChainService, userService, edge | ||
291 | vm.grid = grid; | 341 | vm.grid = grid; |
292 | } | 342 | } |
293 | 343 | ||
294 | - function fetchRuleChains(pageLink) { | ||
295 | - return ruleChainService.getRuleChains(pageLink); | 344 | + function fetchRuleChains(pageLink, type) { |
345 | + return ruleChainService.getRuleChains(pageLink, null, type); | ||
296 | } | 346 | } |
297 | 347 | ||
298 | function saveRuleChain(ruleChain) { | 348 | function saveRuleChain(ruleChain) { |
349 | + if (angular.isUndefined(ruleChain.type)) { | ||
350 | + if (vm.ruleChainsScope === 'edges') { | ||
351 | + ruleChain.type = types.edgeRuleChainType; | ||
352 | + } else { | ||
353 | + ruleChain.type = types.systemRuleChainType; | ||
354 | + } | ||
355 | + } | ||
299 | return ruleChainService.saveRuleChain(ruleChain); | 356 | return ruleChainService.saveRuleChain(ruleChain); |
300 | } | 357 | } |
301 | 358 | ||
@@ -303,10 +360,11 @@ export default function RuleChainsController(ruleChainService, userService, edge | @@ -303,10 +360,11 @@ export default function RuleChainsController(ruleChainService, userService, edge | ||
303 | if ($event) { | 360 | if ($event) { |
304 | $event.stopPropagation(); | 361 | $event.stopPropagation(); |
305 | } | 362 | } |
363 | + | ||
306 | if (vm.ruleChainsScope === 'edge') { | 364 | if (vm.ruleChainsScope === 'edge') { |
307 | - $state.go('home.edges.ruleChains.ruleChain', { | ||
308 | - ruleChainId: ruleChain.id.id | ||
309 | - }); | 365 | + $state.go('home.edges.ruleChains.ruleChain', {ruleChainId: ruleChain.id.id, edgeId: vm.edge.id.id}); |
366 | + } else if (vm.ruleChainsScope === 'edges') { | ||
367 | + $state.go('home.ruleChains.edge.ruleChain', {ruleChainId: ruleChain.id.id}); | ||
310 | } else { | 368 | } else { |
311 | $state.go('home.ruleChains.ruleChain', {ruleChainId: ruleChain.id.id}); | 369 | $state.go('home.ruleChains.ruleChain', {ruleChainId: ruleChain.id.id}); |
312 | } | 370 | } |
@@ -53,6 +53,7 @@ | @@ -53,6 +53,7 @@ | ||
53 | tb-required="true" | 53 | tb-required="true" |
54 | exclude-entity-ids="[ruleChainId]" | 54 | exclude-entity-ids="[ruleChainId]" |
55 | entity-type="types.entityType.rulechain" | 55 | entity-type="types.entityType.rulechain" |
56 | + entity-subtype="ruleChainType" | ||
56 | ng-model="params.targetRuleChainId"> | 57 | ng-model="params.targetRuleChainId"> |
57 | </tb-entity-autocomplete> | 58 | </tb-entity-autocomplete> |
58 | <md-input-container class="md-block"> | 59 | <md-input-container class="md-block"> |
@@ -70,6 +70,7 @@ export default function RuleNodeDirective($compile, $templateCache, ruleChainSer | @@ -70,6 +70,7 @@ export default function RuleNodeDirective($compile, $templateCache, ruleChainSer | ||
70 | link: linker, | 70 | link: linker, |
71 | scope: { | 71 | scope: { |
72 | ruleChainId: '=', | 72 | ruleChainId: '=', |
73 | + ruleChainType: '=', | ||
73 | ruleNode: '=', | 74 | ruleNode: '=', |
74 | isEdit: '=', | 75 | isEdit: '=', |
75 | isReadOnly: '=', | 76 | isReadOnly: '=', |
@@ -156,9 +156,24 @@ function Menu(userService, $state, $rootScope) { | @@ -156,9 +156,24 @@ function Menu(userService, $state, $rootScope) { | ||
156 | }, | 156 | }, |
157 | { | 157 | { |
158 | name: 'rulechain.rulechains', | 158 | name: 'rulechain.rulechains', |
159 | - type: 'link', | 159 | + type: 'toggle', |
160 | state: 'home.ruleChains', | 160 | state: 'home.ruleChains', |
161 | - icon: 'settings_ethernet' | 161 | + height: '80px', |
162 | + icon: 'settings_ethernet', | ||
163 | + pages: [ | ||
164 | + { | ||
165 | + name: 'rulechain.system-rulechains', | ||
166 | + type: 'link', | ||
167 | + state: 'home.ruleChains.system', | ||
168 | + icon: 'settings_ethernet' | ||
169 | + }, | ||
170 | + { | ||
171 | + name: 'rulechain.edge-rulechains', | ||
172 | + type: 'link', | ||
173 | + state: 'home.ruleChains.edge', | ||
174 | + icon: 'router' | ||
175 | + } | ||
176 | + ] | ||
162 | }, | 177 | }, |
163 | { | 178 | { |
164 | name: 'customer.customers', | 179 | name: 'customer.customers', |
@@ -214,9 +229,14 @@ function Menu(userService, $state, $rootScope) { | @@ -214,9 +229,14 @@ function Menu(userService, $state, $rootScope) { | ||
214 | name: 'rulechain.management', | 229 | name: 'rulechain.management', |
215 | places: [ | 230 | places: [ |
216 | { | 231 | { |
217 | - name: 'rulechain.rulechains', | 232 | + name: 'rulechain.system-rulechains', |
218 | icon: 'settings_ethernet', | 233 | icon: 'settings_ethernet', |
219 | state: 'home.ruleChains' | 234 | state: 'home.ruleChains' |
235 | + }, | ||
236 | + { | ||
237 | + name: 'rulechain.edge-rulechains', | ||
238 | + icon: 'router', | ||
239 | + state: 'home.edgesRuleChains' | ||
220 | } | 240 | } |
221 | ] | 241 | ] |
222 | }, | 242 | }, |