Browse Source

Introduce Flow rule node type. Add rile node UIs for RuleChain input/output. Remove rule chain connection metadata.

pull/5673/head
Igor Kulikov 5 years ago
parent
commit
d6e18d05cd
  1. 27
      application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java
  2. 2
      common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentType.java
  3. 1
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NodeDefinition.java
  4. 2
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java
  5. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java
  6. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java
  7. 8
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java
  8. 6
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java
  9. 96
      rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js
  10. 83
      ui-ngx/src/app/core/http/rule-chain.service.ts
  11. 9
      ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts
  12. 8
      ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts
  13. 3
      ui-ngx/src/app/modules/home/pages/rulechain/add-rule-node-link-dialog.component.html
  14. 74
      ui-ngx/src/app/modules/home/pages/rulechain/link-labels.component.ts
  15. 2
      ui-ngx/src/app/modules/home/pages/rulechain/rule-node-colors.scss
  16. 9
      ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts
  17. 20
      ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html
  18. 62
      ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts
  19. 1
      ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.html
  20. 3
      ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.ts
  21. 3
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html
  22. 2
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss
  23. 147
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts
  24. 12
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts
  25. 4
      ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.html
  26. 43
      ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts
  27. 3
      ui-ngx/src/app/shared/models/component-descriptor.models.ts
  28. 33
      ui-ngx/src/app/shared/models/rule-chain.models.ts
  29. 23
      ui-ngx/src/app/shared/models/rule-node.models.ts
  30. 2
      ui-ngx/src/assets/locale/locale.constant-en_US.json

27
application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java

@ -152,24 +152,14 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
try {
scannedComponent.setType(type);
Class<?> clazz = Class.forName(clazzName);
switch (type) {
case ENRICHMENT:
case FILTER:
case TRANSFORMATION:
case ACTION:
case EXTERNAL:
RuleNode ruleNodeAnnotation = clazz.getAnnotation(RuleNode.class);
scannedComponent.setName(ruleNodeAnnotation.name());
scannedComponent.setScope(ruleNodeAnnotation.scope());
NodeDefinition nodeDefinition = prepareNodeDefinition(ruleNodeAnnotation);
ObjectNode configurationDescriptor = mapper.createObjectNode();
JsonNode node = mapper.valueToTree(nodeDefinition);
configurationDescriptor.set("nodeDefinition", node);
scannedComponent.setConfigurationDescriptor(configurationDescriptor);
break;
default:
throw new RuntimeException(type + " is not supported yet!");
}
RuleNode ruleNodeAnnotation = clazz.getAnnotation(RuleNode.class);
scannedComponent.setName(ruleNodeAnnotation.name());
scannedComponent.setScope(ruleNodeAnnotation.scope());
NodeDefinition nodeDefinition = prepareNodeDefinition(ruleNodeAnnotation);
ObjectNode configurationDescriptor = mapper.createObjectNode();
JsonNode node = mapper.valueToTree(nodeDefinition);
configurationDescriptor.set("nodeDefinition", node);
scannedComponent.setConfigurationDescriptor(configurationDescriptor);
scannedComponent.setClazz(clazzName);
log.info("Processing scanned component: {}", scannedComponent);
} catch (Exception e) {
@ -200,6 +190,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
nodeDefinition.setOutEnabled(nodeAnnotation.outEnabled());
nodeDefinition.setRelationTypes(getRelationTypesWithFailureRelation(nodeAnnotation));
nodeDefinition.setCustomRelations(nodeAnnotation.customRelations());
nodeDefinition.setRuleChainNode(nodeAnnotation.ruleChainNode());
Class<? extends NodeConfiguration> configClazz = nodeAnnotation.configClazz();
NodeConfiguration config = configClazz.getDeclaredConstructor().newInstance();
NodeConfiguration defaultConfiguration = config.defaultConfiguration();

2
common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentType.java

@ -20,6 +20,6 @@ package org.thingsboard.server.common.data.plugin;
*/
public enum ComponentType {
ENRICHMENT, FILTER, TRANSFORMATION, ACTION, EXTERNAL
ENRICHMENT, FILTER, TRANSFORMATION, ACTION, EXTERNAL, FLOW
}

1
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NodeDefinition.java

@ -27,6 +27,7 @@ public class NodeDefinition {
private boolean outEnabled;
String[] relationTypes;
boolean customRelations;
boolean ruleChainNode;
JsonNode defaultConfiguration;
String[] uiResources;
String configDirective;

2
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java

@ -58,6 +58,8 @@ public @interface RuleNode {
boolean customRelations() default false;
boolean ruleChainNode() default false;
RuleChainType[] ruleChainTypes() default {RuleChainType.CORE, RuleChainType.EDGE};
}

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java

@ -28,7 +28,7 @@ import org.thingsboard.server.common.msg.TbMsg;
@Slf4j
@RuleNode(
type = ComponentType.ACTION,
type = ComponentType.FLOW,
name = "acknowledge",
configClazz = EmptyNodeConfiguration.class,
nodeDescription = "Acknowledges the incoming message",

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java

@ -31,7 +31,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
@Slf4j
@RuleNode(
type = ComponentType.ACTION,
type = ComponentType.FLOW,
name = "checkpoint",
configClazz = TbCheckpointNodeConfiguration.class,
nodeDescription = "transfers the message to another queue",

8
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java

@ -33,14 +33,18 @@ import java.util.UUID;
@Slf4j
@RuleNode(
type = ComponentType.ACTION,
name = "rule chain input",
type = ComponentType.FLOW,
name = "rule chain",
configClazz = TbRuleChainInputNodeConfiguration.class,
nodeDescription = "transfers the message to another rule chain",
nodeDetails = "Allows to nest the rule chain similar to single rule node. " +
"The incoming message is forwarded to the input node of the specified target rule chain. " +
"The target rule chain may produce multiple labeled outputs. " +
"You may use the outputs to forward the results of processing to other rule nodes.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFlowNodeRuleChainInputConfig",
relationTypes = {},
ruleChainNode = true,
customRelations = true
)
public class TbRuleChainInputNode implements TbNode {

6
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java

@ -28,14 +28,16 @@ import org.thingsboard.server.common.msg.TbMsg;
@Slf4j
@RuleNode(
type = ComponentType.ACTION,
name = "rule chain output",
type = ComponentType.FLOW,
name = "output",
configClazz = TbRuleChainOutputNodeConfiguration.class,
nodeDescription = "transfers the message to the caller rule chain",
nodeDetails = "Produces output of the rule chain processing. " +
"The output is forwarded to the caller rule chain, as an output of the corresponding \"input\" rule node. " +
"The rule node configuration contains the \"label\" parameter. " +
"This parameter corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain. ",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFlowNodeRuleChainOutputConfig",
outEnabled = false
)
public class TbRuleChainOutputNode implements TbNode {

96
rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js

@ -3691,6 +3691,91 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImpo
}]
}] });
class RuleChainInputComponent extends RuleNodeConfigurationComponent {
constructor(store, fb) {
super(store);
this.store = store;
this.fb = fb;
this.entityType = EntityType;
}
configForm() {
return this.ruleChainInputConfigForm;
}
onConfigurationSet(configuration) {
this.ruleChainInputConfigForm = this.fb.group({
ruleChainId: [configuration ? configuration.ruleChainId : null, [Validators.required]]
});
}
}
RuleChainInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleChainInputComponent, deps: [{ token: i1.Store }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
RuleChainInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.14", type: RuleChainInputComponent, selector: "tb-flow-node-rule-chain-input-config", usesInheritance: true, ngImport: i0, template: "<section [formGroup]=\"ruleChainInputConfigForm\" fxLayout=\"column\">\n <tb-entity-autocomplete required\n [excludeEntityIds]=\"[ruleChainId]\"\n [entityType]=\"entityType.RULE_CHAIN\"\n [entitySubtype]=\"ruleChainType\"\n formControlName=\"ruleChainId\">\n </tb-entity-autocomplete>\n</section>\n", components: [{ type: i8$3.EntityAutocompleteComponent, selector: "tb-entity-autocomplete", inputs: ["entityType", "entitySubtype", "excludeEntityIds", "labelText", "requiredText", "required", "disabled"], outputs: ["entityChanged"] }], directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleChainInputComponent, decorators: [{
type: Component,
args: [{
selector: 'tb-flow-node-rule-chain-input-config',
templateUrl: './rule-chain-input.component.html',
styleUrls: []
}]
}], ctorParameters: function () { return [{ type: i1.Store }, { type: i2.FormBuilder }]; } });
class RuleChainOutputComponent extends RuleNodeConfigurationComponent {
constructor(store, fb) {
super(store);
this.store = store;
this.fb = fb;
}
configForm() {
return this.ruleChainOutputConfigForm;
}
onConfigurationSet(configuration) {
this.ruleChainOutputConfigForm = this.fb.group({
label: [configuration ? configuration.label : null, [Validators.required]]
});
}
}
RuleChainOutputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleChainOutputComponent, deps: [{ token: i1.Store }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
RuleChainOutputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.14", type: RuleChainOutputComponent, selector: "tb-flow-node-rule-chain-output-config", usesInheritance: true, ngImport: i0, template: "<section [formGroup]=\"ruleChainOutputConfigForm\" fxLayout=\"column\">\n <mat-form-field class=\"mat-block\">\n <mat-label translate>tb.rulenode.label</mat-label>\n <input required matInput formControlName=\"label\">\n <mat-error *ngIf=\"ruleChainOutputConfigForm.get('label').hasError('required')\">\n {{ 'tb.rulenode.label-required' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n", components: [{ type: i3.MatFormField, selector: "mat-form-field", inputs: ["color", "floatLabel", "appearance", "hideRequiredMarker", "hintLabel"], exportAs: ["matFormField"] }], directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.MatLabel, selector: "mat-label" }, { type: i4.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["id", "disabled", "required", "type", "value", "readonly", "placeholder", "errorStateMatcher", "aria-describedby"], exportAs: ["matInput"] }, { type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i10.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.MatError, selector: "mat-error", inputs: ["id"] }], pipes: { "translate": i4.TranslatePipe } });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleChainOutputComponent, decorators: [{
type: Component,
args: [{
selector: 'tb-flow-node-rule-chain-output-config',
templateUrl: './rule-chain-output.component.html',
styleUrls: []
}]
}], ctorParameters: function () { return [{ type: i1.Store }, { type: i2.FormBuilder }]; } });
class RuleNodeCoreConfigFlowModule {
}
RuleNodeCoreConfigFlowModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleNodeCoreConfigFlowModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
RuleNodeCoreConfigFlowModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleNodeCoreConfigFlowModule, declarations: [RuleChainInputComponent,
RuleChainOutputComponent], imports: [CommonModule,
SharedModule,
RulenodeCoreConfigCommonModule], exports: [RuleChainInputComponent,
RuleChainOutputComponent] });
RuleNodeCoreConfigFlowModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleNodeCoreConfigFlowModule, imports: [[
CommonModule,
SharedModule,
RulenodeCoreConfigCommonModule
]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleNodeCoreConfigFlowModule, decorators: [{
type: NgModule,
args: [{
declarations: [
RuleChainInputComponent,
RuleChainOutputComponent
],
imports: [
CommonModule,
SharedModule,
RulenodeCoreConfigCommonModule
],
exports: [
RuleChainInputComponent,
RuleChainOutputComponent
]
}]
}] });
function addRuleNodeCoreLocaleEnglish(translate) {
const enUS = {
tb: {
@ -4105,7 +4190,9 @@ function addRuleNodeCoreLocaleEnglish(translate) {
'for value from message body',
'alarm-severity-pattern-hint': 'Hint: use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> ' +
'for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> ' +
'for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)'
'for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)',
label: 'Label',
'label-required': 'Label is required'
},
'key-val': {
key: 'Key',
@ -4134,6 +4221,7 @@ RuleNodeCoreConfigModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0"
RuleNodeCoreConfigFilterModule,
RulenodeCoreConfigEnrichmentModule,
RulenodeCoreConfigTransformModule,
RuleNodeCoreConfigFlowModule,
EmptyConfigComponent] });
RuleNodeCoreConfigModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleNodeCoreConfigModule, imports: [[
CommonModule,
@ -4141,7 +4229,8 @@ RuleNodeCoreConfigModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0"
], RuleNodeCoreConfigActionModule,
RuleNodeCoreConfigFilterModule,
RulenodeCoreConfigEnrichmentModule,
RulenodeCoreConfigTransformModule] });
RulenodeCoreConfigTransformModule,
RuleNodeCoreConfigFlowModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleNodeCoreConfigModule, decorators: [{
type: NgModule,
args: [{
@ -4157,6 +4246,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImpo
RuleNodeCoreConfigFilterModule,
RulenodeCoreConfigEnrichmentModule,
RulenodeCoreConfigTransformModule,
RuleNodeCoreConfigFlowModule,
EmptyConfigComponent
]
}]
@ -4170,5 +4260,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImpo
* Generated bundle index. Do not edit.
*/
export { AssignCustomerConfigComponent, AttributesConfigComponent, AzureIotHubConfigComponent, CalculateDeltaConfigComponent, ChangeOriginatorConfigComponent, CheckAlarmStatusComponent, CheckMessageConfigComponent, CheckPointConfigComponent, CheckRelationConfigComponent, ClearAlarmConfigComponent, CreateAlarmConfigComponent, CreateRelationConfigComponent, CredentialsConfigComponent, CustomerAttributesConfigComponent, DeleteRelationConfigComponent, DeviceAttributesConfigComponent, DeviceProfileConfigComponent, DeviceRelationsQueryConfigComponent, EmptyConfigComponent, EntityDetailsConfigComponent, GeneratorConfigComponent, GetTelemetryFromDatabaseConfigComponent, GpsGeoActionConfigComponent, GpsGeoFilterConfigComponent, KafkaConfigComponent, KvMapConfigComponent, LogConfigComponent, MessageTypeConfigComponent, MessageTypesConfigComponent, MqttConfigComponent, MsgCountConfigComponent, MsgDelayConfigComponent, OriginatorAttributesConfigComponent, OriginatorFieldsConfigComponent, OriginatorTypeConfigComponent, PubSubConfigComponent, PushToCloudConfigComponent, PushToEdgeConfigComponent, RabbitMqConfigComponent, RelatedAttributesConfigComponent, RelationsQueryConfigComponent, RestApiCallConfigComponent, RpcReplyConfigComponent, RpcRequestConfigComponent, RuleNodeCoreConfigActionModule, RuleNodeCoreConfigFilterModule, RuleNodeCoreConfigModule, RulenodeCoreConfigCommonModule, RulenodeCoreConfigEnrichmentModule, RulenodeCoreConfigTransformModule, SafeHtmlPipe, SaveToCustomTableConfigComponent, ScriptConfigComponent, SendEmailConfigComponent, SendSmsConfigComponent, SnsConfigComponent, SqsConfigComponent, SwitchConfigComponent, TenantAttributesConfigComponent, TimeseriesConfigComponent, ToEmailConfigComponent, TransformScriptConfigComponent, UnassignCustomerConfigComponent };
export { AssignCustomerConfigComponent, AttributesConfigComponent, AzureIotHubConfigComponent, CalculateDeltaConfigComponent, ChangeOriginatorConfigComponent, CheckAlarmStatusComponent, CheckMessageConfigComponent, CheckPointConfigComponent, CheckRelationConfigComponent, ClearAlarmConfigComponent, CreateAlarmConfigComponent, CreateRelationConfigComponent, CredentialsConfigComponent, CustomerAttributesConfigComponent, DeleteRelationConfigComponent, DeviceAttributesConfigComponent, DeviceProfileConfigComponent, DeviceRelationsQueryConfigComponent, EmptyConfigComponent, EntityDetailsConfigComponent, GeneratorConfigComponent, GetTelemetryFromDatabaseConfigComponent, GpsGeoActionConfigComponent, GpsGeoFilterConfigComponent, KafkaConfigComponent, KvMapConfigComponent, LogConfigComponent, MessageTypeConfigComponent, MessageTypesConfigComponent, MqttConfigComponent, MsgCountConfigComponent, MsgDelayConfigComponent, OriginatorAttributesConfigComponent, OriginatorFieldsConfigComponent, OriginatorTypeConfigComponent, PubSubConfigComponent, PushToCloudConfigComponent, PushToEdgeConfigComponent, RabbitMqConfigComponent, RelatedAttributesConfigComponent, RelationsQueryConfigComponent, RestApiCallConfigComponent, RpcReplyConfigComponent, RpcRequestConfigComponent, RuleChainInputComponent, RuleChainOutputComponent, RuleNodeCoreConfigActionModule, RuleNodeCoreConfigFilterModule, RuleNodeCoreConfigFlowModule, RuleNodeCoreConfigModule, RulenodeCoreConfigCommonModule, RulenodeCoreConfigEnrichmentModule, RulenodeCoreConfigTransformModule, SafeHtmlPipe, SaveToCustomTableConfigComponent, ScriptConfigComponent, SendEmailConfigComponent, SendSmsConfigComponent, SnsConfigComponent, SqsConfigComponent, SwitchConfigComponent, TenantAttributesConfigComponent, TimeseriesConfigComponent, ToEmailConfigComponent, TransformScriptConfigComponent, UnassignCustomerConfigComponent };
//# sourceMappingURL=rulenode-core-config.js.map

83
ui-ngx/src/app/core/http/rule-chain.service.ts

@ -21,11 +21,8 @@ import { HttpClient } from '@angular/common/http';
import { PageLink } from '@shared/models/page/page-link';
import { PageData } from '@shared/models/page/page-data';
import {
ResolvedRuleChainMetaData,
RuleChain,
RuleChainConnectionInfo,
RuleChainMetaData,
ruleChainNodeComponent,
RuleChainType,
ruleNodeTypeComponentTypes,
unknownNodeComponent
@ -34,14 +31,13 @@ import { ComponentDescriptorService } from './component-descriptor.service';
import {
IRuleNodeConfigurationComponent,
LinkLabel,
RuleNodeComponentDescriptor,
RuleNodeComponentDescriptor, RuleNodeConfiguration,
TestScriptInputParams,
TestScriptResult
} from '@app/shared/models/rule-node.models';
import { ResourcesService } from '../services/resources.service';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { EntityType } from '@shared/models/entity-type.models';
import { deepClone, snakeCase } from '@core/utils';
import { DebugRuleNodeEventBody } from '@app/shared/models/event.models';
import { Edge } from '@shared/models/edge.models';
@ -63,7 +59,8 @@ export class RuleChainService {
private translate: TranslateService
) { }
public getRuleChains(pageLink: PageLink, type: RuleChainType = RuleChainType.CORE, config?: RequestConfig): Observable<PageData<RuleChain>> {
public getRuleChains(pageLink: PageLink, type: RuleChainType = RuleChainType.CORE,
config?: RequestConfig): Observable<PageData<RuleChain>> {
return this.http.get<PageData<RuleChain>>(`/api/ruleChains${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config));
}
@ -72,6 +69,10 @@ export class RuleChainService {
return this.http.get<RuleChain>(`/api/ruleChain/${ruleChainId}`, defaultHttpOptionsFromConfig(config));
}
public getRuleChainOutputLabels(ruleChainId: string, config?: RequestConfig): Observable<Array<string>> {
return this.http.get<Array<string>>(`/api/ruleChain/${ruleChainId}/output/labels`, defaultHttpOptionsFromConfig(config));
}
public createDefaultRuleChain(ruleChainName: string, config?: RequestConfig): Observable<RuleChain> {
return this.http.post<RuleChain>('/api/ruleChain/device/default', {
name: ruleChainName
@ -94,32 +95,10 @@ export class RuleChainService {
return this.http.get<RuleChainMetaData>(`/api/ruleChain/${ruleChainId}/metadata`, defaultHttpOptionsFromConfig(config));
}
public getResolvedRuleChainMetadata(ruleChainId: string, config?: RequestConfig): Observable<ResolvedRuleChainMetaData> {
return this.getRuleChainMetadata(ruleChainId, config).pipe(
mergeMap((ruleChainMetaData) => this.resolveRuleChainMetadata(ruleChainMetaData))
);
}
public saveRuleChainMetadata(ruleChainMetaData: RuleChainMetaData, config?: RequestConfig): Observable<RuleChainMetaData> {
return this.http.post<RuleChainMetaData>('/api/ruleChain/metadata', ruleChainMetaData, defaultHttpOptionsFromConfig(config));
}
public saveAndGetResolvedRuleChainMetadata(ruleChainMetaData: RuleChainMetaData,
config?: RequestConfig): Observable<ResolvedRuleChainMetaData> {
return this.saveRuleChainMetadata(ruleChainMetaData, config).pipe(
mergeMap((savedRuleChainMetaData) => this.resolveRuleChainMetadata(savedRuleChainMetaData))
);
}
public resolveRuleChainMetadata(ruleChainMetaData: RuleChainMetaData): Observable<ResolvedRuleChainMetaData> {
return this.resolveTargetRuleChains(ruleChainMetaData.ruleChainConnections).pipe(
map((targetRuleChainsMap) => {
const resolvedRuleChainMetadata: ResolvedRuleChainMetaData = {...ruleChainMetaData, targetRuleChainsMap};
return resolvedRuleChainMetadata;
})
);
}
public getRuleNodeComponents(modulesMap: IModulesMap, ruleChainType: RuleChainType, config?: RequestConfig):
Observable<Array<RuleNodeComponentDescriptor>> {
if (this.ruleNodeComponentsMap.get(ruleChainType)) {
@ -130,7 +109,6 @@ export class RuleChainService {
return this.resolveRuleNodeComponentsUiResources(components, modulesMap).pipe(
map((ruleNodeComponents) => {
this.ruleNodeComponentsMap.set(ruleChainType, ruleNodeComponents);
this.ruleNodeComponentsMap.get(ruleChainType).push(ruleChainNodeComponent);
this.ruleNodeComponentsMap.get(ruleChainType).sort(
(comp1, comp2) => {
let result = comp1.type.toString().localeCompare(comp2.type.toString());
@ -180,6 +158,14 @@ export class RuleChainService {
return component.configurationDescriptor.nodeDefinition.customRelations;
}
public ruleNodeSourceRuleChainId(component: RuleNodeComponentDescriptor, config: RuleNodeConfiguration): string {
if (component.configurationDescriptor.nodeDefinition.ruleChainNode) {
return config?.ruleChainId;
} else {
return null;
}
}
public getLatestRuleNodeDebugInput(ruleNodeId: string, config?: RequestConfig): Observable<DebugRuleNodeEventBody> {
return this.http.get<DebugRuleNodeEventBody>(`/api/ruleNode/${ruleNodeId}/debugIn`, defaultHttpOptionsFromConfig(config));
}
@ -188,26 +174,6 @@ export class RuleChainService {
return this.http.post<TestScriptResult>('/api/ruleChain/testScript', inputParams, defaultHttpOptionsFromConfig(config));
}
private resolveTargetRuleChains(ruleChainConnections: Array<RuleChainConnectionInfo>): Observable<{[ruleChainId: string]: RuleChain}> {
if (ruleChainConnections && ruleChainConnections.length) {
const tasks: Observable<RuleChain>[] = [];
ruleChainConnections.forEach((connection) => {
tasks.push(this.resolveRuleChain(connection.targetRuleChainId.id));
});
return forkJoin(tasks).pipe(
map((ruleChains) => {
const ruleChainsMap: {[ruleChainId: string]: RuleChain} = {};
ruleChains.forEach((ruleChain) => {
ruleChainsMap[ruleChain.id.id] = ruleChain;
});
return ruleChainsMap;
})
);
} else {
return of({} as {[ruleChainId: string]: RuleChain});
}
}
private loadRuleNodeComponents(ruleChainType: RuleChainType, config?: RequestConfig): Observable<Array<RuleNodeComponentDescriptor>> {
return this.componentDescriptorService.getComponentDescriptorsByTypes(ruleNodeTypeComponentTypes, ruleChainType, config).pipe(
map((components) => {
@ -228,7 +194,7 @@ export class RuleChainService {
tasks.push(this.resolveRuleNodeComponentUiResources(component, modulesMap));
});
return forkJoin(tasks).pipe(
catchError((err) => {
catchError(() => {
return of(components);
})
);
@ -268,7 +234,7 @@ export class RuleChainService {
));
}
return forkJoin(tasks).pipe(
map((res) => {
map(() => {
return component;
}),
catchError(() => {
@ -281,21 +247,6 @@ export class RuleChainService {
}
}
private resolveRuleChain(ruleChainId: string): Observable<RuleChain> {
return this.getRuleChain(ruleChainId, {ignoreErrors: true}).pipe(
map(ruleChain => ruleChain),
catchError((err) => {
const ruleChain = {
id: {
entityType: EntityType.RULE_CHAIN,
id: ruleChainId
}
} as RuleChain;
return of(ruleChain);
})
);
}
public getEdgeRuleChains(edgeId: string, pageLink: PageLink, config?: RequestConfig): Observable<PageData<RuleChain>> {
return this.http.get<PageData<RuleChain>>(`/api/edge/${edgeId}/ruleChains${pageLink.toQuery()}`,
defaultHttpOptionsFromConfig(config));

9
ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts

@ -423,7 +423,7 @@ export class ImportExportService {
public importRuleChain(expectedRuleChainType: RuleChainType): Observable<RuleChainImport> {
return this.openImportDialog('rulechain.import', 'rulechain.rulechain-file').pipe(
mergeMap((ruleChainImport: RuleChainImport) => {
map((ruleChainImport: RuleChainImport) => {
if (!this.validateImportedRuleChain(ruleChainImport)) {
this.store.dispatch(new ActionNotificationShow(
{message: this.translate.instant('rulechain.invalid-rulechain-file-error'),
@ -435,12 +435,7 @@ export class ImportExportService {
type: 'error'}));
throw new Error('Invalid rule chain type');
} else {
return this.ruleChainService.resolveRuleChainMetadata(ruleChainImport.metadata).pipe(
map((resolvedMetadata) => {
ruleChainImport.resolvedMetadata = resolvedMetadata;
return ruleChainImport;
})
);
return ruleChainImport;
}
}),
catchError((err) => {

8
ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts

@ -18,7 +18,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
import { Authority } from '@shared/models/authority.enum';
import { EdgesTableConfigResolver } from '@home/pages/edge/edges-table-config.resolver'
import { EdgesTableConfigResolver } from '@home/pages/edge/edges-table-config.resolver';
import { AssetsTableConfigResolver } from '@home/pages/asset/assets-table-config.resolver';
import { DevicesTableConfigResolver } from '@home/pages/device/devices-table-config.resolver';
import { EntityViewsTableConfigResolver } from '@home/pages/entity-view/entity-views-table-config.resolver';
@ -32,7 +32,7 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { RuleChainType } from '@shared/models/rule-chain.models';
import {
importRuleChainBreadcumbLabelFunction,
ResolvedRuleChainMetaDataResolver,
RuleChainMetaDataResolver,
ruleChainBreadcumbLabelFunction,
RuleChainImportGuard,
RuleChainResolver,
@ -181,7 +181,7 @@ const routes: Routes = [
},
resolve: {
ruleChain: RuleChainResolver,
ruleChainMetaData: ResolvedRuleChainMetaDataResolver,
ruleChainMetaData: RuleChainMetaDataResolver,
ruleNodeComponents: RuleNodeComponentsResolver,
tooltipster: TooltipsterResolver
}
@ -243,7 +243,7 @@ const routes: Routes = [
},
resolve: {
ruleChain: RuleChainResolver,
ruleChainMetaData: ResolvedRuleChainMetaDataResolver,
ruleChainMetaData: RuleChainMetaDataResolver,
ruleNodeComponents: RuleNodeComponentsResolver,
tooltipster: TooltipsterResolver
}

3
ui-ngx/src/app/modules/home/pages/rulechain/add-rule-node-link-dialog.component.html

@ -34,7 +34,8 @@
required
formControlName="link"
[allowedLabels]="labels"
[allowCustom]="allowCustomLabels">
[allowCustom]="allowCustomLabels"
[sourceRuleChainId]="sourceRuleChainId">
</tb-rule-node-link>
</fieldset>
</div>

74
ui-ngx/src/app/modules/home/pages/rulechain/link-labels.component.ts

@ -25,7 +25,8 @@ import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material
import { MatChipInputEvent, MatChipList } from '@angular/material/chips';
import { TranslateService } from '@ngx-translate/core';
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
import { map, mergeMap, share, startWith } from 'rxjs/operators';
import { catchError, map, mergeMap, share, startWith } from 'rxjs/operators';
import { RuleChainService } from '@core/http/rule-chain.service';
@Component({
selector: 'tb-link-labels',
@ -68,6 +69,9 @@ export class LinkLabelsComponent implements ControlValueAccessor, OnInit, OnChan
@Input()
allowedLabels: {[label: string]: LinkLabel};
@Input()
sourceRuleChainId: string;
linksFormGroup: FormGroup;
modelValue: Array<string>;
@ -86,7 +90,8 @@ export class LinkLabelsComponent implements ControlValueAccessor, OnInit, OnChan
constructor(private fb: FormBuilder,
public truncate: TruncatePipe,
public translate: TranslateService) {
public translate: TranslateService,
private ruleChainService: RuleChainService) {
this.linksFormGroup = this.fb.group({
label: [null]
});
@ -115,7 +120,7 @@ export class LinkLabelsComponent implements ControlValueAccessor, OnInit, OnChan
for (const propName of Object.keys(changes)) {
const change = changes[propName];
if (change.currentValue !== change.previousValue) {
if (['allowCustom', 'allowedLabels'].includes(propName)) {
if (['allowCustom', 'allowedLabels', 'sourceRuleChainId'].includes(propName)) {
reloadLabels = true;
}
}
@ -139,25 +144,50 @@ export class LinkLabelsComponent implements ControlValueAccessor, OnInit, OnChan
this.labelsList.length = 0;
this.labels.length = 0;
this.modelValue = value;
for (const label of Object.keys(this.allowedLabels)) {
this.labelsList.push({name: this.allowedLabels[label].name, value: this.allowedLabels[label].value});
}
if (value) {
value.forEach((label) => {
if (this.allowedLabels[label]) {
this.labels.push(deepClone(this.allowedLabels[label]));
} else {
this.labels.push({
name: label,
value: label
});
}
});
}
if (this.chipList && this.required) {
this.chipList.errorState = this.labels.length ? false : true;
this.prepareLabelsList().subscribe((labelsList) => {
this.labelsList = labelsList;
if (value) {
value.forEach((label) => {
if (this.allowedLabels[label]) {
this.labels.push(deepClone(this.allowedLabels[label]));
} else {
this.labels.push({
name: label,
value: label
});
}
});
}
if (this.chipList && this.required) {
this.chipList.errorState = !this.labels.length;
}
this.linksFormGroup.get('label').patchValue('', {emitEvent: true});
});
}
prepareLabelsList(): Observable<Array<LinkLabel>> {
const labelsList: Array<LinkLabel> = [];
if (this.sourceRuleChainId) {
return this.ruleChainService.getRuleChainOutputLabels(this.sourceRuleChainId, {ignoreErrors: true}).pipe(
map((labels) => {
for (const label of labels) {
labelsList.push({
name: label,
value: label
});
}
return labelsList;
}),
catchError(() => {
return of(labelsList);
})
);
} else {
for (const label of Object.keys(this.allowedLabels)) {
labelsList.push({name: this.allowedLabels[label].name, value: this.allowedLabels[label].value});
}
return of(labelsList);
}
this.linksFormGroup.get('label').patchValue('', {emitEvent: true});
}
displayLabelFn(label?: LinkLabel): string | undefined {
@ -165,7 +195,7 @@ export class LinkLabelsComponent implements ControlValueAccessor, OnInit, OnChan
}
textIsNotEmpty(text: string): boolean {
return (text && text != null && text.length > 0) ? true : false;
return (text && text.length > 0);
}
createLinkLabel($event: Event, value: string) {

2
ui-ngx/src/app/modules/home/pages/rulechain/rule-node-colors.scss

@ -34,7 +34,7 @@
background-color: #fbc766;
}
&.tb-rule-chain-type {
&.tb-flow-type {
background-color: #d6c4f1;
}

9
ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts

@ -37,6 +37,7 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { TranslateService } from '@ngx-translate/core';
import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component';
import { deepClone } from '@core/utils';
import { RuleChainType } from '@shared/models/rule-chain.models';
@Component({
selector: 'tb-rule-node-config',
@ -69,6 +70,12 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On
@Input()
ruleNodeId: string;
@Input()
ruleChainId: string;
@Input()
ruleChainType: RuleChainType;
nodeDefinitionValue: RuleNodeDefinition;
@Input()
@ -186,6 +193,8 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On
this.definedConfigComponentRef = this.definedConfigContainer.createComponent(factory);
this.definedConfigComponent = this.definedConfigComponentRef.instance;
this.definedConfigComponent.ruleNodeId = this.ruleNodeId;
this.definedConfigComponent.ruleChainId = this.ruleChainId;
this.definedConfigComponent.ruleChainType = this.ruleChainType;
this.definedConfigComponent.configuration = this.configuration;
this.changeSubscription = this.definedConfigComponent.configurationChanged.subscribe((configuration) => {
this.updateModel(configuration);

20
ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html

@ -15,7 +15,7 @@
limitations under the License.
-->
<div class="tb-details-buttons" *ngIf="!isAdd && ruleNode.component.type === ruleNodeType.RULE_CHAIN">
<div class="tb-details-buttons" *ngIf="!isAdd && ruleNode.component?.configurationDescriptor?.nodeDefinition?.ruleChainNode">
<button mat-raised-button color="primary"
(click)="openRuleChain($event)">
{{'rulechain.open-rulechain' | translate }}
@ -23,7 +23,7 @@
</div>
<form [formGroup]="ruleNodeFormGroup" class="mat-padding">
<fieldset [disabled]="(isLoading$ | async) || !isEdit || isReadOnly">
<section *ngIf="ruleNode.component.type !== ruleNodeType.RULE_CHAIN">
<section>
<section fxLayout="column" fxLayout.gt-sm="row">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>rulenode.name</mat-label>
@ -43,6 +43,8 @@
<tb-rule-node-config #ruleNodeConfigComponent
formControlName="configuration"
[ruleNodeId]="ruleNode.ruleNodeId?.id"
[ruleChainId]="ruleChainId"
[ruleChainType]="ruleChainType"
[nodeDefinition]="ruleNode.component.configurationDescriptor.nodeDefinition">
</tb-rule-node-config>
<div formGroupName="additionalInfo" fxLayout="column">
@ -52,19 +54,5 @@
</mat-form-field>
</div>
</section>
<section *ngIf="ruleNode.component.type === ruleNodeType.RULE_CHAIN">
<tb-entity-autocomplete required
[excludeEntityIds]="[ruleChainId]"
[entityType]="entityType.RULE_CHAIN"
[entitySubtype]="ruleChainType"
formControlName="targetRuleChainId">
</tb-entity-autocomplete>
<div formGroupName="additionalInfo" fxLayout="column">
<mat-form-field class="mat-block">
<mat-label translate>rulenode.description</mat-label>
<textarea matInput formControlName="description" rows="2"></textarea>
</mat-form-field>
</div>
</section>
</fieldset>
</form>

62
ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts

@ -75,28 +75,16 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
this.ruleNodeFormSubscription = null;
}
if (this.ruleNode) {
if (this.ruleNode.component.type !== RuleNodeType.RULE_CHAIN) {
this.ruleNodeFormGroup = this.fb.group({
name: [this.ruleNode.name, [Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*'), Validators.maxLength(255)]],
debugMode: [this.ruleNode.debugMode, []],
configuration: [this.ruleNode.configuration, [Validators.required]],
additionalInfo: this.fb.group(
{
description: [this.ruleNode.additionalInfo ? this.ruleNode.additionalInfo.description : ''],
}
)
});
} else {
this.ruleNodeFormGroup = this.fb.group({
targetRuleChainId: [this.ruleNode.targetRuleChainId, [Validators.required]],
additionalInfo: this.fb.group(
{
description: [this.ruleNode.additionalInfo ? this.ruleNode.additionalInfo.description : ''],
}
)
});
}
this.ruleNodeFormGroup = this.fb.group({
name: [this.ruleNode.name, [Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*'), Validators.maxLength(255)]],
debugMode: [this.ruleNode.debugMode, []],
configuration: [this.ruleNode.configuration, [Validators.required]],
additionalInfo: this.fb.group(
{
description: [this.ruleNode.additionalInfo ? this.ruleNode.additionalInfo.description : ''],
}
)
});
this.ruleNodeFormSubscription = this.ruleNodeFormGroup.valueChanges.subscribe(() => {
this.updateRuleNode();
});
@ -107,23 +95,8 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
private updateRuleNode() {
const formValue = this.ruleNodeFormGroup.value || {};
if (this.ruleNode.component.type === RuleNodeType.RULE_CHAIN) {
const targetRuleChainId: string = formValue.targetRuleChainId;
if (this.ruleNode.targetRuleChainId !== targetRuleChainId && targetRuleChainId) {
this.ruleChainService.getRuleChain(targetRuleChainId).subscribe(
(ruleChain) => {
this.ruleNode.name = ruleChain.name;
Object.assign(this.ruleNode, formValue);
}
);
} else {
Object.assign(this.ruleNode, formValue);
}
} else {
formValue.name = formValue.name.trim();
Object.assign(this.ruleNode, formValue);
}
formValue.name = formValue.name.trim();
Object.assign(this.ruleNode, formValue);
}
ngOnInit(): void {
@ -141,20 +114,19 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
}
validate() {
if (this.ruleNode.component.type !== RuleNodeType.RULE_CHAIN) {
this.ruleNodeConfigComponent.validate();
}
this.ruleNodeConfigComponent.validate();
}
openRuleChain($event: Event) {
if ($event) {
$event.stopPropagation();
}
if (this.ruleNode.targetRuleChainId) {
const ruleChainId = this.ruleNodeFormGroup.get('configuration')?.value?.ruleChainId;
if (ruleChainId) {
if (this.ruleChainType === RuleChainType.EDGE) {
this.router.navigateByUrl(`/edgeManagement/ruleChains/${this.ruleNode.targetRuleChainId}`);
this.router.navigateByUrl(`/edgeManagement/ruleChains/${ruleChainId}`);
} else {
this.router.navigateByUrl(`/ruleChains/${this.ruleNode.targetRuleChainId}`);
this.router.navigateByUrl(`/ruleChains/${ruleChainId}`);
}
}
}

1
ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.html

@ -22,6 +22,7 @@
formControlName="labels"
[allowedLabels]="allowedLabels"
[allowCustom]="allowCustom"
[sourceRuleChainId]="sourceRuleChainId"
></tb-link-labels>
</form>
</div>

3
ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.ts

@ -57,6 +57,9 @@ export class RuleNodeLinkComponent implements ControlValueAccessor, OnInit {
@Input()
allowedLabels: {[label: string]: LinkLabel};
@Input()
sourceRuleChainId: string;
ruleNodeLinkFormGroup: FormGroup;
modelValue: FcRuleEdge;

3
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html

@ -158,7 +158,8 @@
#tbRuleNodeLink
[(ngModel)]="editingRuleNodeLink"
[allowedLabels]="editingRuleNodeLinkLabels"
[allowCustom]="editingRuleNodeAllowCustomLabels">
[allowCustom]="editingRuleNodeAllowCustomLabels"
[sourceRuleChainId]="editingRuleNodeSourceRuleChainId">
</tb-rule-node-link>
</tb-details-panel>
</mat-drawer>

2
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss

@ -184,7 +184,7 @@
display: block;
position: absolute;
top: 11px;
right: -12px;
right: 10px;
border: 1px solid #FFFFFF;
border-radius: 4px;
line-height: 18px;

147
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts

@ -43,12 +43,10 @@ import { ActivatedRoute, Router } from '@angular/router';
import {
inputNodeComponent,
NodeConnectionInfo,
ResolvedRuleChainMetaData,
RuleChain,
RuleChainConnectionInfo,
RuleChainImport,
RuleChainMetaData,
ruleChainNodeComponent, RuleChainType
RuleChainType
} from '@shared/models/rule-chain.models';
import { FcItemInfo, FlowchartConstants, NgxFlowchartComponent, UserCallbacks } from 'ngx-flowchart';
import {
@ -75,7 +73,6 @@ import { DialogComponent } from '@shared/components/dialog.component';
import { MatMenuTrigger } from '@angular/material/menu';
import { ItemBufferService, RuleNodeConnection } from '@core/services/item-buffer.service';
import { Hotkey } from 'angular2-hotkeys';
import { EntityType } from '@shared/models/entity-type.models';
import { DebugEventType, EventType } from '@shared/models/event.models';
import Timeout = NodeJS.Timeout;
@ -130,6 +127,7 @@ export class RuleChainPageComponent extends PageComponent
editingRuleNodeIndex = -1;
editingRuleNodeAllowCustomLabels = false;
editingRuleNodeLinkLabels: {[label: string]: LinkLabel};
editingRuleNodeSourceRuleChainId: string;
@ViewChild('tbRuleNode') ruleNodeComponent: RuleNodeDetailsComponent;
@ViewChild('tbRuleNodeLink') ruleNodeLinkComponent: RuleNodeLinkComponent;
@ -147,7 +145,7 @@ export class RuleChainPageComponent extends PageComponent
ruleNodeTypeSearch = '';
ruleChain: RuleChain;
ruleChainMetaData: ResolvedRuleChainMetaData;
ruleChainMetaData: RuleChainMetaData;
ruleChainModel: FcRuleNodeModel = {
nodes: [],
@ -179,16 +177,11 @@ export class RuleChainPageComponent extends PageComponent
createEdge: (event, edge: FcRuleEdge) => {
const sourceNode = this.ruleChainCanvas.modelService.nodes.getNodeByConnectorId(edge.source) as FcRuleNode;
if (sourceNode.component.type === RuleNodeType.INPUT) {
const destNode = this.ruleChainCanvas.modelService.nodes.getNodeByConnectorId(edge.destination) as FcRuleNode;
if (destNode.component.type === RuleNodeType.RULE_CHAIN) {
return NEVER;
} else {
const found = this.ruleChainModel.edges.find(theEdge => theEdge.source === (this.inputConnectorId + ''));
if (found) {
this.ruleChainCanvas.modelService.edges.delete(found);
}
return of(edge);
const found = this.ruleChainModel.edges.find(theEdge => theEdge.source === (this.inputConnectorId + ''));
if (found) {
this.ruleChainCanvas.modelService.edges.delete(found);
}
return of(edge);
} else {
if (edge.label) {
if (!edge.labels) {
@ -198,8 +191,9 @@ export class RuleChainPageComponent extends PageComponent
} else {
const labels = this.ruleChainService.getRuleNodeSupportedLinks(sourceNode.component);
const allowCustomLabels = this.ruleChainService.ruleNodeAllowCustomLinks(sourceNode.component);
const sourceRuleChainId = this.ruleChainService.ruleNodeSourceRuleChainId(sourceNode.component, sourceNode.configuration);
this.enableHotKeys = false;
return this.addRuleNodeLink(edge, labels, allowCustomLabels).pipe(
return this.addRuleNodeLink(edge, labels, allowCustomLabels, sourceRuleChainId).pipe(
tap(() => {
this.enableHotKeys = true;
}),
@ -294,7 +288,7 @@ export class RuleChainPageComponent extends PageComponent
if (this.isImport) {
const ruleChainImport: RuleChainImport = this.itembuffer.getRuleChainImport();
this.ruleChain = ruleChainImport.ruleChain;
this.ruleChainMetaData = ruleChainImport.resolvedMetadata;
this.ruleChainMetaData = ruleChainImport.metadata;
} else {
this.ruleChain = this.route.snapshot.data.ruleChain;
this.ruleChainMetaData = this.route.snapshot.data.ruleChainMetaData;
@ -601,63 +595,6 @@ export class RuleChainPageComponent extends PageComponent
}
});
}
if (this.ruleChainMetaData.ruleChainConnections) {
const ruleChainsMap = this.ruleChainMetaData.targetRuleChainsMap;
const ruleChainNodesMap: {[ruleChainNodeId: string]: FcRuleNode} = {};
const ruleChainEdgeMap: {[edgeKey: string]: FcRuleEdge} = {};
this.ruleChainMetaData.ruleChainConnections.forEach((ruleChainConnection) => {
const ruleChain = ruleChainsMap[ruleChainConnection.targetRuleChainId.id];
if (ruleChainConnection.additionalInfo && ruleChainConnection.additionalInfo.ruleChainNodeId) {
let ruleChainNode = ruleChainNodesMap[ruleChainConnection.additionalInfo.ruleChainNodeId];
if (!ruleChainNode) {
ruleChainNode = {
id: 'rule-chain-node-' + this.nextNodeID++,
name: ruleChain.name ? ruleChain.name : 'Unresolved',
targetRuleChainId: ruleChain.name ? ruleChainConnection.targetRuleChainId.id : null,
error: ruleChain.name ? undefined : this.translate.instant('rulenode.invalid-target-rulechain'),
additionalInfo: ruleChainConnection.additionalInfo,
x: Math.round(ruleChainConnection.additionalInfo.layoutX),
y: Math.round(ruleChainConnection.additionalInfo.layoutY),
component: ruleChainNodeComponent,
nodeClass: ruleNodeTypeDescriptors.get(RuleNodeType.RULE_CHAIN).nodeClass,
icon: ruleNodeTypeDescriptors.get(RuleNodeType.RULE_CHAIN).icon,
connectors: [
{
type: FlowchartConstants.leftConnectorType,
id: (this.nextConnectorID++) + ''
}
],
ruleChainType: this.ruleChainType
};
ruleChainNodesMap[ruleChainConnection.additionalInfo.ruleChainNodeId] = ruleChainNode;
this.ruleChainModel.nodes.push(ruleChainNode);
}
const sourceNode = nodes[ruleChainConnection.fromIndex];
if (sourceNode) {
const connectors = sourceNode.connectors.filter(connector => connector.type === FlowchartConstants.rightConnectorType);
if (connectors && connectors.length) {
const sourceId = connectors[0].id;
const destId = ruleChainNode.connectors[0].id;
const edgeKey = sourceId + '_' + destId;
let ruleChainEdge = ruleChainEdgeMap[edgeKey];
if (!ruleChainEdge) {
ruleChainEdge = {
source: sourceId,
destination: destId,
label: ruleChainConnection.type,
labels: [ruleChainConnection.type]
};
ruleChainEdgeMap[edgeKey] = ruleChainEdge;
this.ruleChainModel.edges.push(ruleChainEdge);
} else {
ruleChainEdge.label += ' / ' + ruleChainConnection.type;
ruleChainEdge.labels.push(ruleChainConnection.type);
}
}
}
}
});
}
if (this.ruleChainCanvas) {
this.ruleChainCanvas.adjustCanvasSize(true);
}
@ -918,6 +855,8 @@ export class RuleChainPageComponent extends PageComponent
this.editingRuleNode = null;
this.editingRuleNodeLinkLabels = this.ruleChainService.getRuleNodeSupportedLinks(sourceNode.component);
this.editingRuleNodeAllowCustomLabels = this.ruleChainService.ruleNodeAllowCustomLinks(sourceNode.component);
this.editingRuleNodeSourceRuleChainId =
this.ruleChainService.ruleNodeSourceRuleChainId(sourceNode.component, sourceNode.configuration);
this.isEditingRuleNodeLink = true;
this.editingRuleNodeLinkIndex = this.ruleChainModel.edges.indexOf(edge);
this.editingRuleNodeLink = deepClone(edge);
@ -1093,7 +1032,7 @@ export class RuleChainPageComponent extends PageComponent
const type = ruleNodeTypeDescriptors.get(ruleNodeType);
this.displayTooltip(event,
'<div class="tb-rule-node-tooltip tb-lib-tooltip">' +
'<div id="tb-node-content" layout="column">' +
'<div id="tb-node-content">' +
'<div class="tb-node-title">' + this.translate.instant(type.name) + '</div>' +
'<div class="tb-node-details">' + this.translate.instant(type.details) + '</div>' +
'</div>' +
@ -1104,7 +1043,7 @@ export class RuleChainPageComponent extends PageComponent
displayLibNodeDescriptionTooltip(event: MouseEvent, node: FcRuleNodeType) {
this.displayTooltip(event,
'<div class="tb-rule-node-tooltip tb-lib-tooltip">' +
'<div id="tb-node-content" layout="column">' +
'<div id="tb-node-content">' +
'<div class="tb-node-title">' + node.component.name + '</div>' +
'<div class="tb-node-description">' + node.component.configurationDescriptor.nodeDefinition.description + '</div>' +
'<div class="tb-node-details">' + node.component.configurationDescriptor.nodeDefinition.details + '</div>' +
@ -1129,7 +1068,7 @@ export class RuleChainPageComponent extends PageComponent
}
}
let tooltipContent = '<div class="tb-rule-node-tooltip">' +
'<div id="tb-node-content" layout="column">' +
'<div id="tb-node-content">' +
'<div class="tb-node-title">' + name + '</div>' +
'<div class="tb-node-description">' + desc + '</div>';
if (details) {
@ -1189,7 +1128,7 @@ export class RuleChainPageComponent extends PageComponent
resetDebugModeInAllNodes() {
let changed = false;
this.ruleChainModel.nodes.forEach((node) => {
if (node.component.type !== RuleNodeType.INPUT && node.component.type !== RuleNodeType.RULE_CHAIN) {
if (node.component.type !== RuleNodeType.INPUT) {
changed = changed || node.debugMode;
node.debugMode = false;
}
@ -1223,12 +1162,11 @@ export class RuleChainPageComponent extends PageComponent
const ruleChainMetaData: RuleChainMetaData = {
ruleChainId: this.ruleChain.id,
nodes: [],
connections: [],
ruleChainConnections: []
connections: []
};
const nodes: FcRuleNode[] = [];
this.ruleChainModel.nodes.forEach((node) => {
if (node.component.type !== RuleNodeType.INPUT && node.component.type !== RuleNodeType.RULE_CHAIN) {
if (node.component.type !== RuleNodeType.INPUT) {
const ruleNode: RuleNode = {
id: node.ruleNodeId,
type: node.component.clazz,
@ -1253,35 +1191,19 @@ export class RuleChainPageComponent extends PageComponent
const destNode = this.ruleChainCanvas.modelService.nodes.getNodeByConnectorId(edge.destination);
if (sourceNode.component.type !== RuleNodeType.INPUT) {
const fromIndex = nodes.indexOf(sourceNode);
if (destNode.component.type === RuleNodeType.RULE_CHAIN) {
const ruleChainConnection = {
fromIndex,
targetRuleChainId: {entityType: EntityType.RULE_CHAIN, id: destNode.targetRuleChainId},
additionalInfo: destNode.additionalInfo ? destNode.additionalInfo : {}
} as RuleChainConnectionInfo;
ruleChainConnection.additionalInfo.layoutX = Math.round(destNode.x);
ruleChainConnection.additionalInfo.layoutY = Math.round(destNode.y);
ruleChainConnection.additionalInfo.ruleChainNodeId = destNode.id;
edge.labels.forEach((label) => {
const newRuleChainConnection = deepClone(ruleChainConnection);
newRuleChainConnection.type = label;
ruleChainMetaData.ruleChainConnections.push(newRuleChainConnection);
});
} else {
const toIndex = nodes.indexOf(destNode);
const nodeConnection = {
fromIndex,
toIndex
} as NodeConnectionInfo;
edge.labels.forEach((label) => {
const newNodeConnection = deepClone(nodeConnection);
newNodeConnection.type = label;
ruleChainMetaData.connections.push(newNodeConnection);
});
}
const toIndex = nodes.indexOf(destNode);
const nodeConnection = {
fromIndex,
toIndex
} as NodeConnectionInfo;
edge.labels.forEach((label) => {
const newNodeConnection = deepClone(nodeConnection);
newNodeConnection.type = label;
ruleChainMetaData.connections.push(newNodeConnection);
});
}
});
this.ruleChainService.saveAndGetResolvedRuleChainMetadata(ruleChainMetaData).subscribe((savedRuleChainMetaData) => {
this.ruleChainService.saveRuleChainMetadata(ruleChainMetaData).subscribe((savedRuleChainMetaData) => {
this.ruleChainMetaData = savedRuleChainMetaData;
if (this.isImport) {
this.isDirtyValue = false;
@ -1346,7 +1268,8 @@ export class RuleChainPageComponent extends PageComponent
);
}
addRuleNodeLink(link: FcRuleEdge, labels: {[label: string]: LinkLabel}, allowCustomLabels: boolean): Observable<FcRuleEdge> {
addRuleNodeLink(link: FcRuleEdge, labels: {[label: string]: LinkLabel},
allowCustomLabels: boolean, sourceRuleChainId: string): Observable<FcRuleEdge> {
return this.dialog.open<AddRuleNodeLinkDialogComponent, AddRuleNodeLinkDialogData,
FcRuleEdge>(AddRuleNodeLinkDialogComponent, {
disableClose: true,
@ -1354,7 +1277,8 @@ export class RuleChainPageComponent extends PageComponent
data: {
link,
labels,
allowCustomLabels
allowCustomLabels,
sourceRuleChainId
}
}).afterClosed();
}
@ -1384,7 +1308,7 @@ export class RuleChainPageComponent extends PageComponent
}
);
const content = '<div class="tb-rule-node-error-tooltip">' +
'<div id="tooltip-content" layout="column">' +
'<div id="tooltip-content">' +
'<div class="tb-node-details">' + node.error + '</div>' +
'</div>' +
'</div>';
@ -1452,6 +1376,7 @@ export interface AddRuleNodeLinkDialogData {
link: FcRuleEdge;
labels: {[label: string]: LinkLabel};
allowCustomLabels: boolean;
sourceRuleChainId: string;
}
@Component({
@ -1468,6 +1393,7 @@ export class AddRuleNodeLinkDialogComponent extends DialogComponent<AddRuleNodeL
link: FcRuleEdge;
labels: {[label: string]: LinkLabel};
allowCustomLabels: boolean;
sourceRuleChainId: string;
submitted = false;
@ -1482,6 +1408,7 @@ export class AddRuleNodeLinkDialogComponent extends DialogComponent<AddRuleNodeL
this.link = this.data.link;
this.labels = this.data.labels;
this.allowCustomLabels = this.data.allowCustomLabels;
this.sourceRuleChainId = this.data.sourceRuleChainId;
this.ruleNodeLinkFormGroup = this.fb.group({
link: [deepClone(this.link), [Validators.required]]

12
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts

@ -32,7 +32,7 @@ import { RuleChainsTableConfigResolver } from '@modules/home/pages/rulechain/rul
import { from, Observable } from 'rxjs';
import { BreadCrumbConfig, BreadCrumbLabelFunction } from '@shared/components/breadcrumb';
import {
ResolvedRuleChainMetaData,
RuleChainMetaData,
RuleChain, RuleChainType
} from '@shared/models/rule-chain.models';
import { RuleChainService } from '@core/http/rule-chain.service';
@ -56,14 +56,14 @@ export class RuleChainResolver implements Resolve<RuleChain> {
}
@Injectable()
export class ResolvedRuleChainMetaDataResolver implements Resolve<ResolvedRuleChainMetaData> {
export class RuleChainMetaDataResolver implements Resolve<RuleChainMetaData> {
constructor(private ruleChainService: RuleChainService) {
}
resolve(route: ActivatedRouteSnapshot): Observable<ResolvedRuleChainMetaData> {
resolve(route: ActivatedRouteSnapshot): Observable<RuleChainMetaData> {
const ruleChainId = route.params.ruleChainId;
return this.ruleChainService.getResolvedRuleChainMetadata(ruleChainId);
return this.ruleChainService.getRuleChainMetadata(ruleChainId);
}
}
@ -160,7 +160,7 @@ const routes: Routes = [
},
resolve: {
ruleChain: RuleChainResolver,
ruleChainMetaData: ResolvedRuleChainMetaDataResolver,
ruleChainMetaData: RuleChainMetaDataResolver,
ruleNodeComponents: RuleNodeComponentsResolver,
tooltipster: TooltipsterResolver
}
@ -196,7 +196,7 @@ const routes: Routes = [
providers: [
RuleChainsTableConfigResolver,
RuleChainResolver,
ResolvedRuleChainMetaDataResolver,
RuleChainMetaDataResolver,
RuleNodeComponentsResolver,
TooltipsterResolver,
RuleChainImportGuard

4
ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.html

@ -59,8 +59,8 @@
&times;
</div>
</section>
<section *ngIf="node.component.type === RuleNodeType.RULE_CHAIN && modelservice.isEditable()">
<div class="fc-nodeopen" (click)="openRuleChain($event, node)">
<section *ngIf="node.component?.configurationDescriptor?.nodeDefinition?.ruleChainNode && modelservice.isEditable()">
<div class="fc-nodeopen" (click)="openRuleChain($event, node)" (mouseenter)="displayOpenRuleChainTooltip($event, node)">
<mat-icon class="material-icons" svgIcon="mdi:login"></mat-icon>
</div>
</section>

43
ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts

@ -20,6 +20,7 @@ import { FcNodeComponent } from 'ngx-flowchart';
import { FcRuleNode, RuleNodeType } from '@shared/models/rule-node.models';
import { Router } from '@angular/router';
import { RuleChainType } from '@app/shared/models/rule-chain.models';
import { TranslateService } from '@ngx-translate/core';
@Component({
// tslint:disable-next-line:component-selector
@ -33,6 +34,7 @@ export class RuleNodeComponent extends FcNodeComponent implements OnInit {
RuleNodeType = RuleNodeType;
constructor(private sanitizer: DomSanitizer,
private translate: TranslateService,
private router: Router) {
super();
}
@ -48,13 +50,48 @@ export class RuleNodeComponent extends FcNodeComponent implements OnInit {
if ($event) {
$event.stopPropagation();
}
if (node.targetRuleChainId) {
if (node.configuration?.ruleChainId) {
if (node.ruleChainType === RuleChainType.EDGE) {
this.router.navigateByUrl(`/edgeManagement/ruleChains/${node.targetRuleChainId}`);
this.router.navigateByUrl(`/edgeManagement/ruleChains/${node.configuration?.ruleChainId}`);
} else {
this.router.navigateByUrl(`/ruleChains/${node.targetRuleChainId}`);
this.router.navigateByUrl(`/ruleChains/${node.configuration?.ruleChainId}`);
}
}
}
displayOpenRuleChainTooltip($event: MouseEvent, node: FcRuleNode) {
if ($event) {
$event.stopPropagation();
}
this.userNodeCallbacks.mouseLeave($event, node);
const tooltipContent = '<div class="tb-rule-node-tooltip">' +
'<div id="tb-node-content">' +
'<div class="tb-node-description">' + this.translate.instant('rulechain.open-rulechain') + '</div></div></div>';
const element = $($event.target);
element.tooltipster(
{
theme: 'tooltipster-shadow',
delay: 100,
trigger: 'custom',
triggerOpen: {
click: false,
tap: false
},
triggerClose: {
click: true,
tap: true,
scroll: true,
mouseleave: true
},
side: 'top',
distance: 12,
trackOrigin: true
}
);
const tooltip = element.tooltipster('instance');
const contentElement = $(tooltipContent);
tooltip.content(contentElement);
tooltip.open();
}
}

3
ui-ngx/src/app/shared/models/component-descriptor.models.ts

@ -21,7 +21,8 @@ export enum ComponentType {
FILTER = 'FILTER',
TRANSFORMATION = 'TRANSFORMATION',
ACTION = 'ACTION',
EXTERNAL = 'EXTERNAL'
EXTERNAL = 'EXTERNAL',
FLOW = 'FLOW'
}
export enum ComponentScope {

33
ui-ngx/src/app/shared/models/rule-chain.models.ts

@ -38,17 +38,11 @@ export interface RuleChainMetaData {
firstNodeIndex?: number;
nodes: Array<RuleNode>;
connections: Array<NodeConnectionInfo>;
ruleChainConnections: Array<RuleChainConnectionInfo>;
}
export interface ResolvedRuleChainMetaData extends RuleChainMetaData {
targetRuleChainsMap: {[ruleChainId: string]: RuleChain};
}
export interface RuleChainImport {
ruleChain: RuleChain;
metadata: RuleChainMetaData;
resolvedMetadata?: ResolvedRuleChainMetaData;
}
export interface NodeConnectionInfo {
@ -57,39 +51,16 @@ export interface NodeConnectionInfo {
type: string;
}
export interface RuleChainConnectionInfo {
fromIndex: number;
targetRuleChainId: RuleChainId;
additionalInfo: any;
type: string;
}
export const ruleNodeTypeComponentTypes: ComponentType[] =
[
ComponentType.FILTER,
ComponentType.ENRICHMENT,
ComponentType.TRANSFORMATION,
ComponentType.ACTION,
ComponentType.EXTERNAL
ComponentType.EXTERNAL,
ComponentType.FLOW
];
export const ruleChainNodeComponent: RuleNodeComponentDescriptor = {
type: RuleNodeType.RULE_CHAIN,
name: 'rule chain',
clazz: 'tb.internal.RuleChain',
configurationDescriptor: {
nodeDefinition: {
description: '',
details: 'Forwards incoming messages to specified Rule Chain',
inEnabled: true,
outEnabled: false,
relationTypes: [],
customRelations: false,
defaultConfiguration: {}
}
}
};
export const unknownNodeComponent: RuleNodeComponentDescriptor = {
type: RuleNodeType.UNKNOWN,
name: 'unknown',

23
ui-ngx/src/app/shared/models/rule-node.models.ts

@ -52,6 +52,7 @@ export interface RuleNodeDefinition {
outEnabled: boolean;
relationTypes: string[];
customRelations: boolean;
ruleChainNode?: boolean;
defaultConfiguration: RuleNodeConfiguration;
icon?: string;
iconUrl?: string;
@ -67,6 +68,8 @@ export interface RuleNodeConfigurationDescriptor {
export interface IRuleNodeConfigurationComponent {
ruleNodeId: string;
ruleChainId: string;
ruleChainType: RuleChainType;
configuration: RuleNodeConfiguration;
configurationChanged: Observable<RuleNodeConfiguration>;
validate();
@ -74,11 +77,16 @@ export interface IRuleNodeConfigurationComponent {
}
@Directive()
// tslint:disable-next-line:directive-class-suffix
export abstract class RuleNodeConfigurationComponent extends PageComponent implements
IRuleNodeConfigurationComponent, OnInit, AfterViewInit {
ruleNodeId: string;
ruleChainId: string;
ruleChainType: RuleChainType;
configurationValue: RuleNodeConfiguration;
private configurationSet = false;
@ -184,7 +192,7 @@ export enum RuleNodeType {
TRANSFORMATION = 'TRANSFORMATION',
ACTION = 'ACTION',
EXTERNAL = 'EXTERNAL',
RULE_CHAIN = 'RULE_CHAIN',
FLOW = 'FLOW',
UNKNOWN = 'UNKNOWN',
INPUT = 'INPUT'
}
@ -195,7 +203,7 @@ export const ruleNodeTypesLibrary = [
RuleNodeType.TRANSFORMATION,
RuleNodeType.ACTION,
RuleNodeType.EXTERNAL,
RuleNodeType.RULE_CHAIN,
RuleNodeType.FLOW,
];
export interface RuleNodeTypeDescriptor {
@ -260,12 +268,12 @@ export const ruleNodeTypeDescriptors = new Map<RuleNodeType, RuleNodeTypeDescrip
}
],
[
RuleNodeType.RULE_CHAIN,
RuleNodeType.FLOW,
{
value: RuleNodeType.RULE_CHAIN,
name: 'rulenode.type-rule-chain',
details: 'rulenode.type-rule-chain-details',
nodeClass: 'tb-rule-chain-type',
value: RuleNodeType.FLOW,
name: 'rulenode.type-flow',
details: 'rulenode.type-flow-details',
nodeClass: 'tb-flow-type',
icon: 'settings_ethernet'
}
],
@ -310,7 +318,6 @@ export interface FcRuleNode extends FcRuleNodeType {
additionalInfo?: any;
configuration?: RuleNodeConfiguration;
debugMode?: boolean;
targetRuleChainId?: string;
error?: string;
highlighted?: boolean;
componentClazz?: string;

2
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -2617,6 +2617,8 @@
"type-external-details": "Interacts with external system",
"type-rule-chain": "Rule Chain",
"type-rule-chain-details": "Forwards incoming messages to specified Rule Chain",
"type-flow": "Flow",
"type-flow-details": "Organizes message flow",
"type-input": "Input",
"type-input-details": "Logical input of Rule Chain, forwards incoming messages to next related Rule Node",
"type-unknown": "Unknown",

Loading…
Cancel
Save