diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/add-rule-node-dialog.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/add-rule-node-dialog.component.html index 999ac5c199..e8df333ecd 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/add-rule-node-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/add-rule-node-dialog.component.html @@ -34,6 +34,7 @@ [ruleNode]="ruleNode" [ruleChainId]="ruleChainId" [isEdit]="true" + [isAdd]="true" [isReadOnly]="false"> diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html index 259196d1a6..e87f7158d0 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html @@ -15,6 +15,12 @@ limitations under the License. --> +
+ +
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts index 29312725b5..c19fe98348 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts @@ -24,6 +24,7 @@ import { EntityType } from '@shared/models/entity-type.models'; import { Subscription } from 'rxjs'; import { RuleChainService } from '@core/http/rule-chain.service'; import { RuleNodeConfigComponent } from './rule-node-config.component'; +import { Router } from '@angular/router'; @Component({ selector: 'tb-rule-node', @@ -46,6 +47,9 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O @Input() isReadOnly: boolean; + @Input() + isAdd = false; + ruleNodeType = RuleNodeType; entityType = EntityType; @@ -55,7 +59,8 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O constructor(protected store: Store, private fb: FormBuilder, - private ruleChainService: RuleChainService) { + private ruleChainService: RuleChainService, + private router: Router) { super(store); this.ruleNodeFormGroup = this.fb.group({}); } @@ -133,4 +138,13 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O this.ruleNodeConfigComponent.validate(); } } + + openRuleChain($event: Event) { + if ($event) { + $event.stopPropagation(); + } + if (this.ruleNode.targetRuleChainId) { + this.router.navigateByUrl(`/ruleChains/${this.ruleNode.targetRuleChainId}`); + } + } } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss index 8d034392c6..b4a9a85a08 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss @@ -179,6 +179,35 @@ } } + .fc-nodeopen{ + display: block; + position: absolute; + top: 11px; + right: -12px; + border: 1px solid #FFFFFF; + border-radius: 4px; + line-height: 18px; + height: 22px; + width: 22px; + background: #886CB1; + color: #fff; + text-align: center; + cursor: pointer; + box-sizing: border-box; + + mat-icon{ + width: 16px; + min-width: 16px; + height: 16px; + min-height: 16px; + font-size: 16px; + } + + &:hover{ + background-color: #4E2D7E; + } + } + .fc-arrow-marker { polygon { fill: #808080; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index cd305ed81a..2c8ecc9419 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -20,6 +20,7 @@ import { ElementRef, HostBinding, Inject, + OnDestroy, OnInit, QueryList, SkipSelf, @@ -64,7 +65,7 @@ import { } from '@shared/models/rule-node.models'; import { FcRuleNodeModel, FcRuleNodeTypeModel, RuleChainMenuContextInfo } from './rulechain-page.models'; import { RuleChainService } from '@core/http/rule-chain.service'; -import { fromEvent, NEVER, Observable, of } from 'rxjs'; +import { fromEvent, NEVER, Observable, of, Subscription } from 'rxjs'; import { debounceTime, distinctUntilChanged, mergeMap, tap } from 'rxjs/operators'; import { ISearchableComponent } from '../../models/searchable-component.models'; import { deepClone } from '@core/utils'; @@ -85,7 +86,7 @@ import Timeout = NodeJS.Timeout; encapsulation: ViewEncapsulation.None }) export class RuleChainPageComponent extends PageComponent - implements AfterViewInit, OnInit, HasDirtyFlag, ISearchableComponent { + implements AfterViewInit, OnInit, OnDestroy, HasDirtyFlag, ISearchableComponent { get isDirty(): boolean { return this.isDirtyValue || this.isImport; @@ -234,6 +235,8 @@ export class RuleChainPageComponent extends PageComponent flowchartConstants = FlowchartConstants; + private rxSubscription: Subscription; + private tooltipTimeout: Timeout; constructor(protected store: Store, @@ -247,7 +250,13 @@ export class RuleChainPageComponent extends PageComponent public dialogService: DialogService, public fb: FormBuilder) { super(store); - this.init(); + + this.rxSubscription = this.route.data.subscribe( + () => { + this.reset(); + this.init(); + } + ); } ngOnInit() { @@ -266,6 +275,11 @@ export class RuleChainPageComponent extends PageComponent this.ruleChainCanvas.adjustCanvasSize(true); } + ngOnDestroy() { + super.ngOnDestroy(); + this.rxSubscription.unsubscribe(); + } + onSearchTextUpdated(searchText: string) { this.ruleNodeSearch = searchText; this.updateRuleNodesHighlight(); @@ -299,87 +313,102 @@ export class RuleChainPageComponent extends PageComponent this.createRuleChainModel(); } + private reset(): void { + this.selectedObjects = []; + this.ruleChainModel.nodes = []; + this.ruleChainModel.edges = []; + this.ruleNodeTypesModel = {}; + if (this.ruleChainCanvas) { + this.ruleChainCanvas.adjustCanvasSize(true); + } + this.isEditingRuleNode = false; + this.isEditingRuleNodeLink = false; + this.updateRuleNodesHighlight(); + } + private initHotKeys(): void { - this.hotKeys.push( - new Hotkey('ctrl+a', (event: KeyboardEvent) => { - if (this.enableHotKeys) { - event.preventDefault(); - this.ruleChainCanvas.modelService.selectAll(); - return false; - } - return true; - }, ['INPUT', 'SELECT', 'TEXTAREA'], - this.translate.instant('rulenode.select-all-objects')) - ); - this.hotKeys.push( - new Hotkey('ctrl+c', (event: KeyboardEvent) => { - if (this.enableHotKeys) { - event.preventDefault(); - this.copyRuleNodes(); - return false; - } - return true; - }, ['INPUT', 'SELECT', 'TEXTAREA'], - this.translate.instant('rulenode.copy-selected')) - ); - this.hotKeys.push( - new Hotkey('ctrl+v', (event: KeyboardEvent) => { - if (this.enableHotKeys) { - event.preventDefault(); - if (this.itembuffer.hasRuleNodes()) { - this.pasteRuleNodes(); + if (!this.hotKeys.length) { + this.hotKeys.push( + new Hotkey('ctrl+a', (event: KeyboardEvent) => { + if (this.enableHotKeys) { + event.preventDefault(); + this.ruleChainCanvas.modelService.selectAll(); + return false; } - return false; - } - return true; - }, ['INPUT', 'SELECT', 'TEXTAREA'], - this.translate.instant('action.paste')) - ); - this.hotKeys.push( - new Hotkey('esc', (event: KeyboardEvent) => { - if (this.enableHotKeys) { - event.preventDefault(); - event.stopPropagation(); - this.ruleChainCanvas.modelService.deselectAll(); - return false; - } - return true; - }, ['INPUT', 'SELECT', 'TEXTAREA'], - this.translate.instant('rulenode.deselect-all-objects')) - ); - this.hotKeys.push( - new Hotkey('ctrl+s', (event: KeyboardEvent) => { - if (this.enableHotKeys) { - event.preventDefault(); - this.saveRuleChain(); - return false; - } - return true; - }, ['INPUT', 'SELECT', 'TEXTAREA'], - this.translate.instant('action.apply')) - ); - this.hotKeys.push( - new Hotkey('ctrl+z', (event: KeyboardEvent) => { - if (this.enableHotKeys) { - event.preventDefault(); - this.revertRuleChain(); - return false; - } - return true; - }, ['INPUT', 'SELECT', 'TEXTAREA'], - this.translate.instant('action.decline-changes')) - ); - this.hotKeys.push( - new Hotkey('del', (event: KeyboardEvent) => { - if (this.enableHotKeys) { - event.preventDefault(); - this.ruleChainCanvas.modelService.deleteSelected(); - return false; - } - return true; - }, ['INPUT', 'SELECT', 'TEXTAREA'], - this.translate.instant('rulenode.delete-selected-objects')) - ); + return true; + }, ['INPUT', 'SELECT', 'TEXTAREA'], + this.translate.instant('rulenode.select-all-objects')) + ); + this.hotKeys.push( + new Hotkey('ctrl+c', (event: KeyboardEvent) => { + if (this.enableHotKeys) { + event.preventDefault(); + this.copyRuleNodes(); + return false; + } + return true; + }, ['INPUT', 'SELECT', 'TEXTAREA'], + this.translate.instant('rulenode.copy-selected')) + ); + this.hotKeys.push( + new Hotkey('ctrl+v', (event: KeyboardEvent) => { + if (this.enableHotKeys) { + event.preventDefault(); + if (this.itembuffer.hasRuleNodes()) { + this.pasteRuleNodes(); + } + return false; + } + return true; + }, ['INPUT', 'SELECT', 'TEXTAREA'], + this.translate.instant('action.paste')) + ); + this.hotKeys.push( + new Hotkey('esc', (event: KeyboardEvent) => { + if (this.enableHotKeys) { + event.preventDefault(); + event.stopPropagation(); + this.ruleChainCanvas.modelService.deselectAll(); + return false; + } + return true; + }, ['INPUT', 'SELECT', 'TEXTAREA'], + this.translate.instant('rulenode.deselect-all-objects')) + ); + this.hotKeys.push( + new Hotkey('ctrl+s', (event: KeyboardEvent) => { + if (this.enableHotKeys) { + event.preventDefault(); + this.saveRuleChain(); + return false; + } + return true; + }, ['INPUT', 'SELECT', 'TEXTAREA'], + this.translate.instant('action.apply')) + ); + this.hotKeys.push( + new Hotkey('ctrl+z', (event: KeyboardEvent) => { + if (this.enableHotKeys) { + event.preventDefault(); + this.revertRuleChain(); + return false; + } + return true; + }, ['INPUT', 'SELECT', 'TEXTAREA'], + this.translate.instant('action.decline-changes')) + ); + this.hotKeys.push( + new Hotkey('del', (event: KeyboardEvent) => { + if (this.enableHotKeys) { + event.preventDefault(); + this.ruleChainCanvas.modelService.deleteSelected(); + return false; + } + return true; + }, ['INPUT', 'SELECT', 'TEXTAREA'], + this.translate.instant('rulenode.delete-selected-objects')) + ); + } } updateRuleChainLibrary() { @@ -1396,6 +1425,7 @@ export class RuleChainPageComponent extends PageComponent scroll: true }, side: 'right', + distance: 12, trackOrigin: true } ); diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.html index 51fda8dd02..bc4632f817 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.html @@ -59,4 +59,9 @@ ×
+
+
+ +
+
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts index 1fac4e6c18..2d057565e2 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts @@ -17,6 +17,8 @@ import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Component, OnInit } from '@angular/core'; import { FcNodeComponent } from 'ngx-flowchart/dist/ngx-flowchart'; +import { FcRuleNode, RuleNodeType } from '@shared/models/rule-node.models'; +import { Router } from '@angular/router'; @Component({ // tslint:disable-next-line:component-selector @@ -27,8 +29,10 @@ import { FcNodeComponent } from 'ngx-flowchart/dist/ngx-flowchart'; export class RuleNodeComponent extends FcNodeComponent implements OnInit { iconUrl: SafeResourceUrl; + RuleNodeType = RuleNodeType; - constructor(private sanitizer: DomSanitizer) { + constructor(private sanitizer: DomSanitizer, + private router: Router) { super(); } @@ -39,4 +43,12 @@ export class RuleNodeComponent extends FcNodeComponent implements OnInit { } } + openRuleChain($event: Event, node: FcRuleNode) { + if ($event) { + $event.stopPropagation(); + } + if (node.targetRuleChainId) { + this.router.navigateByUrl(`/ruleChains/${node.targetRuleChainId}`); + } + } }