UI: Added queue for rule node

This commit is contained in:
Artem Dzhereleiko 2024-01-05 11:36:01 +02:00
parent f799194c44
commit 1727728439
6 changed files with 85 additions and 20 deletions

View File

@ -38,7 +38,7 @@
<mat-slide-toggle formControlName="debugMode"> <mat-slide-toggle formControlName="debugMode">
{{ 'rulenode.debug-mode' | translate }} {{ 'rulenode.debug-mode' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle *ngIf="isSingletonEditAllowed()" formControlName="singletonMode"> <mat-slide-toggle *ngIf="isSingleton()" formControlName="singletonMode">
{{ 'rulenode.singleton-mode' | translate }} {{ 'rulenode.singleton-mode' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
@ -52,10 +52,20 @@
(initRuleNode)="initRuleNode.emit($event)" (initRuleNode)="initRuleNode.emit($event)"
(changeScript)="changeScript.emit($event)"> (changeScript)="changeScript.emit($event)">
</tb-rule-node-config> </tb-rule-node-config>
<div formGroupName="additionalInfo" fxLayout="column" class="description-block">
<mat-form-field class="mat-block"> <div class="description-block">
<mat-label translate>rulenode.rule-node-description</mat-label> <tb-queue-autocomplete
<textarea matInput formControlName="description" rows="1"></textarea> *ngIf="isAddQueue()"
</mat-form-field> [queueType]="serviceType"
subscriptSizing="dynamic"
[autocompleteHint]="isSingleton() ? 'rulenode.queue-singleton-hint' : 'rulenode.queue-hint'"
formControlName="queueName">
</tb-queue-autocomplete>
<div formGroupName="additionalInfo">
<mat-form-field class="mat-block">
<mat-label translate>rulenode.rule-node-description</mat-label>
<textarea matInput formControlName="description" rows="1"></textarea>
</mat-form-field>
</div>
</div> </div>
</form> </form>

View File

@ -14,26 +14,38 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; import {
Component,
EventEmitter,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
ViewChild
} from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { FcRuleNode, RuleNodeType } from '@shared/models/rule-node.models'; import { FcRuleNode, RuleNodeType } from '@shared/models/rule-node.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { Subscription } from 'rxjs'; import { Subject } from 'rxjs';
import { RuleNodeConfigComponent } from './rule-node-config.component'; import { RuleNodeConfigComponent } from './rule-node-config.component';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { RuleChainType } from '@app/shared/models/rule-chain.models'; import { RuleChainType } from '@app/shared/models/rule-chain.models';
import { ComponentClusteringMode } from '@shared/models/component-descriptor.models'; import { ComponentClusteringMode } from '@shared/models/component-descriptor.models';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean } from '@shared/decorators/coercion';
import { ServiceType } from '@shared/models/queue.models';
import { takeUntil } from 'rxjs/operators';
@Component({ @Component({
selector: 'tb-rule-node', selector: 'tb-rule-node',
templateUrl: './rule-node-details.component.html', templateUrl: './rule-node-details.component.html',
styleUrls: ['./rule-node-details.component.scss'] styleUrls: ['./rule-node-details.component.scss']
}) })
export class RuleNodeDetailsComponent extends PageComponent implements OnInit, OnChanges { export class RuleNodeDetailsComponent extends PageComponent implements OnInit, OnChanges, OnDestroy {
@ViewChild('ruleNodeConfigComponent') ruleNodeConfigComponent: RuleNodeConfigComponent; @ViewChild('ruleNodeConfigComponent') ruleNodeConfigComponent: RuleNodeConfigComponent;
@ -63,9 +75,11 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
ruleNodeType = RuleNodeType; ruleNodeType = RuleNodeType;
entityType = EntityType; entityType = EntityType;
serviceType = ServiceType.TB_RULE_ENGINE;
ruleNodeFormGroup: UntypedFormGroup; ruleNodeFormGroup: UntypedFormGroup;
private ruleNodeFormSubscription: Subscription; private destroy$ = new Subject<void>();
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
private fb: UntypedFormBuilder, private fb: UntypedFormBuilder,
@ -75,10 +89,6 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
} }
private buildForm() { private buildForm() {
if (this.ruleNodeFormSubscription) {
this.ruleNodeFormSubscription.unsubscribe();
this.ruleNodeFormSubscription = null;
}
if (this.ruleNode) { if (this.ruleNode) {
this.ruleNodeFormGroup = this.fb.group({ this.ruleNodeFormGroup = this.fb.group({
name: [this.ruleNode.name, [Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*'), Validators.maxLength(255)]], name: [this.ruleNode.name, [Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*'), Validators.maxLength(255)]],
@ -91,9 +101,32 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
} }
) )
}); });
this.ruleNodeFormSubscription = this.ruleNodeFormGroup.valueChanges.subscribe(() => {
this.updateRuleNode(); if (this.isAddQueue()) {
}); this.ruleNodeFormGroup.addControl('queueName', this.fb.control(this.ruleNode?.queueName ? this.ruleNode.queueName : null));
if (this.isSingleton()) {
if (!this.isSingletonEditAllowed()) {
this.ruleNodeFormGroup.get('singletonMode').disable({emitEvent: false});
}
if (!this.ruleNodeFormGroup.get('singletonMode').value) {
this.ruleNodeFormGroup.get('queueName').disable({emitEvent: false});
}
this.ruleNodeFormGroup.get('singletonMode').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(value => {
if (value) {
this.ruleNodeFormGroup.get('queueName').enable({emitEvent: false});
} else {
this.ruleNodeFormGroup.get('queueName').disable({emitEvent: false});
}
});
}
}
this.ruleNodeFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateRuleNode());
} else { } else {
this.ruleNodeFormGroup = this.fb.group({}); this.ruleNodeFormGroup = this.fb.group({});
} }
@ -114,6 +147,11 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
} }
} }
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
for (const propName of Object.keys(changes)) { for (const propName of Object.keys(changes)) {
const change = changes[propName]; const change = changes[propName];
@ -143,6 +181,15 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
} }
} }
isAddQueue() {
return this.isSingleton() || this.ruleNode.component.hasQueueName;
}
isSingleton() {
return this.ruleNode.component.clusteringMode === ComponentClusteringMode.SINGLETON ||
this.ruleNode.component.clusteringMode === ComponentClusteringMode.USER_PREFERENCE;
}
isSingletonEditAllowed() { isSingletonEditAllowed() {
return this.ruleNode.component.clusteringMode === ComponentClusteringMode.USER_PREFERENCE; return this.ruleNode.component.clusteringMode === ComponentClusteringMode.USER_PREFERENCE;
} }

View File

@ -575,6 +575,7 @@ export class RuleChainPageComponent extends PageComponent
configurationVersion: isDefinedAndNotNull(ruleNode.configurationVersion) ? ruleNode.configurationVersion : 0, configurationVersion: isDefinedAndNotNull(ruleNode.configurationVersion) ? ruleNode.configurationVersion : 0,
debugMode: ruleNode.debugMode, debugMode: ruleNode.debugMode,
singletonMode: ruleNode.singletonMode, singletonMode: ruleNode.singletonMode,
queueName: ruleNode.queueName,
x: Math.round(ruleNode.additionalInfo.layoutX), x: Math.round(ruleNode.additionalInfo.layoutX),
y: Math.round(ruleNode.additionalInfo.layoutY), y: Math.round(ruleNode.additionalInfo.layoutY),
component, component,
@ -934,7 +935,8 @@ export class RuleChainPageComponent extends PageComponent
configuration: deepClone(node.configuration), configuration: deepClone(node.configuration),
additionalInfo: node.additionalInfo ? deepClone(node.additionalInfo) : {}, additionalInfo: node.additionalInfo ? deepClone(node.additionalInfo) : {},
debugMode: node.debugMode, debugMode: node.debugMode,
singletonMode: node.singletonMode singletonMode: node.singletonMode,
queueName: node.queueName
}; };
if (minX === null) { if (minX === null) {
minX = node.x; minX = node.x;
@ -1467,7 +1469,8 @@ export class RuleChainPageComponent extends PageComponent
configuration: node.configuration, configuration: node.configuration,
additionalInfo: node.additionalInfo ? node.additionalInfo : {}, additionalInfo: node.additionalInfo ? node.additionalInfo : {},
debugMode: node.debugMode, debugMode: node.debugMode,
singletonMode: node.singletonMode singletonMode: node.singletonMode,
queueName: node.queueName
}; };
ruleNode.additionalInfo.layoutX = Math.round(node.x); ruleNode.additionalInfo.layoutX = Math.round(node.x);
ruleNode.additionalInfo.layoutY = Math.round(node.y); ruleNode.additionalInfo.layoutY = Math.round(node.y);

View File

@ -40,6 +40,7 @@ export interface ComponentDescriptor {
type: ComponentType | RuleNodeType; type: ComponentType | RuleNodeType;
scope?: ComponentScope; scope?: ComponentScope;
clusteringMode: ComponentClusteringMode; clusteringMode: ComponentClusteringMode;
hasQueueName?: boolean;
name: string; name: string;
clazz: string; clazz: string;
configurationDescriptor?: any; configurationDescriptor?: any;

View File

@ -39,6 +39,7 @@ export interface RuleNode extends BaseData<RuleNodeId> {
name: string; name: string;
debugMode: boolean; debugMode: boolean;
singletonMode: boolean; singletonMode: boolean;
queueName?: string;
configurationVersion?: number; configurationVersion?: number;
configuration: RuleNodeConfiguration; configuration: RuleNodeConfiguration;
additionalInfo?: any; additionalInfo?: any;
@ -334,6 +335,7 @@ export interface RuleNodeComponentDescriptor extends ComponentDescriptor {
export interface FcRuleNodeType extends FcNode { export interface FcRuleNodeType extends FcNode {
component?: RuleNodeComponentDescriptor; component?: RuleNodeComponentDescriptor;
singletonMode?: boolean; singletonMode?: boolean;
queueName?: string;
nodeClass?: string; nodeClass?: string;
icon?: string; icon?: string;
iconUrl?: string; iconUrl?: string;

View File

@ -3841,7 +3841,9 @@
"test": "Test", "test": "Test",
"help": "Help", "help": "Help",
"reset-debug-mode": "Reset debug mode in all nodes", "reset-debug-mode": "Reset debug mode in all nodes",
"test-with-this-message": "{{test}} with this message" "test-with-this-message": "{{test}} with this message",
"queue-hint": "Select a queue for message forwarding to another queue. 'Main' queue is used by default.",
"queue-singleton-hint": "Select a queue for message forwarding in multi-instance environments. 'Main' queue is used by default."
}, },
"timezone": { "timezone": {
"timezone": "Timezone", "timezone": "Timezone",