Enrichment Rule nodes config UI
This commit is contained in:
parent
9c0f6e9925
commit
c9717f4d1d
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright © 2016-2018 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.rule.engine.data;
|
||||
|
||||
import lombok.Data;
|
||||
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
|
||||
import org.thingsboard.server.common.data.relation.EntityTypeFilter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class RelationsQuery {
|
||||
|
||||
private EntitySearchDirection direction;
|
||||
private int maxLevel = 1;
|
||||
private List<EntityTypeFilter> filters;
|
||||
|
||||
}
|
||||
@ -43,7 +43,9 @@ import static org.thingsboard.server.common.data.DataConstants.*;
|
||||
nodeDetails = "If Attributes enrichment configured, <b>CLIENT/SHARED/SERVER</b> attributes are added into Message metadata " +
|
||||
"with specific prefix: <i>cs/shared/ss</i>. To access those attributes in other nodes this template can be used " +
|
||||
"<code>metadata.cs.temperature</code> or <code>metadata.shared.limit</code> " +
|
||||
"If Latest Telemetry enrichment configured, latest telemetry added into metadata without prefix.")
|
||||
"If Latest Telemetry enrichment configured, latest telemetry added into metadata without prefix.",
|
||||
uiResources = {"static/rulenode/rulenode-core-config.js"},
|
||||
configDirective = "tbEnrichmentNodeOriginatorAttributesConfig")
|
||||
public class TbGetAttributesNode implements TbNode {
|
||||
|
||||
private TbGetAttributesNodeConfiguration config;
|
||||
|
||||
@ -30,7 +30,9 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||
nodeDescription = "Add Originators Customer Attributes or Latest Telemetry into Message Metadata",
|
||||
nodeDetails = "If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
|
||||
"To access those attributes in other nodes this template can be used " +
|
||||
"<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
|
||||
"<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata",
|
||||
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
|
||||
configDirective = "tbEnrichmentNodeCustomerAttributesConfig")
|
||||
public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> {
|
||||
|
||||
@Override
|
||||
|
||||
@ -16,18 +16,19 @@
|
||||
package org.thingsboard.rule.engine.metadata;
|
||||
|
||||
import lombok.Data;
|
||||
import org.thingsboard.rule.engine.api.NodeConfiguration;
|
||||
import org.thingsboard.rule.engine.data.RelationsQuery;
|
||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
|
||||
import org.thingsboard.server.common.data.relation.EntityTypeFilter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class TbGetRelatedAttrNodeConfiguration extends TbGetEntityAttrNodeConfiguration {
|
||||
|
||||
private String relationType;
|
||||
private EntitySearchDirection direction;
|
||||
private RelationsQuery relationsQuery;
|
||||
|
||||
@Override
|
||||
public TbGetRelatedAttrNodeConfiguration defaultConfiguration() {
|
||||
@ -36,8 +37,14 @@ public class TbGetRelatedAttrNodeConfiguration extends TbGetEntityAttrNodeConfig
|
||||
attrMapping.putIfAbsent("temperature", "tempo");
|
||||
configuration.setAttrMapping(attrMapping);
|
||||
configuration.setTelemetry(true);
|
||||
configuration.setRelationType(EntityRelation.CONTAINS_TYPE);
|
||||
configuration.setDirection(EntitySearchDirection.FROM);
|
||||
|
||||
RelationsQuery relationsQuery = new RelationsQuery();
|
||||
relationsQuery.setDirection(EntitySearchDirection.FROM);
|
||||
relationsQuery.setMaxLevel(1);
|
||||
EntityTypeFilter entityTypeFilter = new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.emptyList());
|
||||
relationsQuery.setFilters(Collections.singletonList(entityTypeFilter));
|
||||
configuration.setRelationsQuery(relationsQuery);
|
||||
|
||||
return configuration;
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,10 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||
"If multiple Related Entities are found, only first Entity is used for attributes enrichment, other entities are discarded. " +
|
||||
"If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
|
||||
"To access those attributes in other nodes this template can be used " +
|
||||
"<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
|
||||
"<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata",
|
||||
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
|
||||
configDirective = "tbEnrichmentNodeRelatedAttributesConfig")
|
||||
|
||||
public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> {
|
||||
|
||||
private TbGetRelatedAttrNodeConfiguration config;
|
||||
@ -45,6 +48,6 @@ public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> {
|
||||
|
||||
@Override
|
||||
protected ListenableFuture<EntityId> findEntityAsync(TbContext ctx, EntityId originator) {
|
||||
return EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctx, originator, config.getDirection(), config.getRelationType());
|
||||
return EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctx, originator, config.getRelationsQuery());
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,9 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||
nodeDescription = "Add Originators Tenant Attributes or Latest Telemetry into Message Metadata",
|
||||
nodeDetails = "If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
|
||||
"To access those attributes in other nodes this template can be used " +
|
||||
"<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
|
||||
"<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata",
|
||||
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
|
||||
configDirective = "tbEnrichmentNodeTenantAttributesConfig")
|
||||
public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> {
|
||||
|
||||
@Override
|
||||
|
||||
@ -68,7 +68,7 @@ public class TbChangeOriginatorNode extends TbAbstractTransformNode {
|
||||
case TENANT_SOURCE:
|
||||
return EntitiesTenantIdAsyncLoader.findEntityIdAsync(ctx, original);
|
||||
case RELATED_SOURCE:
|
||||
return EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctx, original, config.getDirection(), config.getRelationType());
|
||||
return EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctx, original, config.getRelationsQuery());
|
||||
default:
|
||||
return Futures.immediateFailedFuture(new IllegalStateException("Unexpected originator source " + config.getOriginatorSource()));
|
||||
}
|
||||
@ -82,9 +82,9 @@ public class TbChangeOriginatorNode extends TbAbstractTransformNode {
|
||||
}
|
||||
|
||||
if (conf.getOriginatorSource().equals(RELATED_SOURCE)) {
|
||||
if (conf.getDirection() == null || StringUtils.isBlank(conf.getRelationType())) {
|
||||
log.error("Related source for TbChangeOriginatorNode should have direction and relationType. Actual [{}] [{}]",
|
||||
conf.getDirection(), conf.getRelationType());
|
||||
if (conf.getRelationsQuery() == null) {
|
||||
log.error("Related source for TbChangeOriginatorNode should have relations query. Actual [{}]",
|
||||
conf.getRelationsQuery());
|
||||
throw new IllegalArgumentException("Wrong config for RElated Source in TbChangeOriginatorNode" + conf.getOriginatorSource());
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,22 +17,32 @@ package org.thingsboard.rule.engine.transform;
|
||||
|
||||
import lombok.Data;
|
||||
import org.thingsboard.rule.engine.api.NodeConfiguration;
|
||||
import org.thingsboard.rule.engine.data.RelationsQuery;
|
||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
|
||||
import org.thingsboard.server.common.data.relation.EntityTypeFilter;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@Data
|
||||
public class TbChangeOriginatorNodeConfiguration extends TbTransformNodeConfiguration implements NodeConfiguration {
|
||||
|
||||
private String originatorSource;
|
||||
private EntitySearchDirection direction;
|
||||
private String relationType;
|
||||
|
||||
private RelationsQuery relationsQuery;
|
||||
|
||||
@Override
|
||||
public TbChangeOriginatorNodeConfiguration defaultConfiguration() {
|
||||
TbChangeOriginatorNodeConfiguration configuration = new TbChangeOriginatorNodeConfiguration();
|
||||
configuration.setOriginatorSource(TbChangeOriginatorNode.CUSTOMER_SOURCE);
|
||||
configuration.setDirection(EntitySearchDirection.FROM);
|
||||
configuration.setRelationType(EntityRelation.CONTAINS_TYPE);
|
||||
|
||||
RelationsQuery relationsQuery = new RelationsQuery();
|
||||
relationsQuery.setDirection(EntitySearchDirection.FROM);
|
||||
relationsQuery.setMaxLevel(1);
|
||||
EntityTypeFilter entityTypeFilter = new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.emptyList());
|
||||
relationsQuery.setFilters(Collections.singletonList(entityTypeFilter));
|
||||
configuration.setRelationsQuery(relationsQuery);
|
||||
|
||||
configuration.setStartNewChain(false);
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@ -20,32 +20,41 @@ import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.thingsboard.rule.engine.api.TbContext;
|
||||
import org.thingsboard.rule.engine.data.RelationsQuery;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||
import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
|
||||
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
|
||||
import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
|
||||
import org.thingsboard.server.dao.relation.RelationService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.thingsboard.server.common.data.relation.RelationTypeGroup.COMMON;
|
||||
|
||||
public class EntitiesRelatedEntityIdAsyncLoader {
|
||||
|
||||
public static ListenableFuture<EntityId> findEntityAsync(TbContext ctx, EntityId originator,
|
||||
EntitySearchDirection direction, String relationType) {
|
||||
RelationsQuery relationsQuery) {
|
||||
RelationService relationService = ctx.getRelationService();
|
||||
if (direction == EntitySearchDirection.FROM) {
|
||||
ListenableFuture<List<EntityRelation>> asyncRelation = relationService.findByFromAndTypeAsync(originator, relationType, COMMON);
|
||||
EntityRelationsQuery query = buildQuery(originator, relationsQuery);
|
||||
ListenableFuture<List<EntityRelation>> asyncRelation = relationService.findByQuery(query);
|
||||
if (relationsQuery.getDirection() == EntitySearchDirection.FROM) {
|
||||
return Futures.transform(asyncRelation, (AsyncFunction<? super List<EntityRelation>, EntityId>)
|
||||
r -> CollectionUtils.isNotEmpty(r) ? Futures.immediateFuture(r.get(0).getTo())
|
||||
: Futures.immediateFailedFuture(new IllegalStateException("Relation not found")));
|
||||
} else if (direction == EntitySearchDirection.TO) {
|
||||
ListenableFuture<List<EntityRelation>> asyncRelation = relationService.findByToAndTypeAsync(originator, relationType, COMMON);
|
||||
} else if (relationsQuery.getDirection() == EntitySearchDirection.TO) {
|
||||
return Futures.transform(asyncRelation, (AsyncFunction<? super List<EntityRelation>, EntityId>)
|
||||
r -> CollectionUtils.isNotEmpty(r) ? Futures.immediateFuture(r.get(0).getFrom())
|
||||
: Futures.immediateFailedFuture(new IllegalStateException("Relation not found")));
|
||||
}
|
||||
|
||||
return Futures.immediateFailedFuture(new IllegalStateException("Unknown direction"));
|
||||
}
|
||||
|
||||
private static EntityRelationsQuery buildQuery(EntityId originator, RelationsQuery relationsQuery) {
|
||||
EntityRelationsQuery query = new EntityRelationsQuery();
|
||||
RelationsSearchParameters parameters = new RelationsSearchParameters(originator,
|
||||
relationsQuery.getDirection(), relationsQuery.getMaxLevel());
|
||||
query.setParameters(parameters);
|
||||
query.setFilters(relationsQuery.getFilters());
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
.tb-message-type-autocomplete .tb-not-found{display:block;line-height:1.5;height:48px}.tb-message-type-autocomplete .tb-not-found .tb-no-entries{line-height:48px}.tb-message-type-autocomplete li{height:auto!important;white-space:normal!important}
|
||||
.tb-message-type-autocomplete .tb-not-found{display:block;line-height:1.5;height:48px}.tb-message-type-autocomplete .tb-not-found .tb-no-entries{line-height:48px}.tb-message-type-autocomplete li{height:auto!important;white-space:normal!important}.tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}.tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:rgba(0,0,0,.54);font-size:12px;font-weight:700;white-space:nowrap}.tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:20px;max-height:300px;overflow:auto}.tb-kv-map-config .body .row{padding-top:5px;max-height:40px}.tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}.tb-kv-map-config .body md-input-container.cell{margin:0;max-height:40px}.tb-kv-map-config .body .md-button{margin:0}
|
||||
/*# sourceMappingURL=rulenode-core-config.css.map*/
|
||||
File diff suppressed because one or more lines are too long
@ -46,6 +46,7 @@ export default function RelationFilters($compile, $templateCache) {
|
||||
ngModelCtrl.$render = function () {
|
||||
if (ngModelCtrl.$viewValue) {
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
scope.relationFilters.length = 0;
|
||||
value.forEach(function (filter) {
|
||||
scope.relationFilters.push(filter);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user