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..fa283f99c5 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 @@ -171,12 +171,27 @@ .fc-edit { .fc-nodeedit, - .fc-nodedelete { + .fc-nodedelete, + .fc-nodeopen { box-sizing: content-box; border: solid 2px #fff; background: #f83e05; outline: none; } + + .fc-nodeopen{ + top: 30px; + right: -14px; + + mat-icon{ + width: 20px; + min-width: 20px; + height: 20px; + min-height: 20px; + font-size: 18px; + line-height: 18px; + } + } } .fc-arrow-marker { 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..6a558edc11 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,100 @@ 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.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() { 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..ec7eb61cc7 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.scss b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.scss index f95da40ebc..51729d6066 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.scss +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.scss @@ -40,7 +40,8 @@ :host-context(.fc-edit) { .fc-nodeedit, - .fc-nodedelete { + .fc-nodedelete, + .fc-nodeopen { box-sizing: content-box; border: solid 2px #fff; background: #f83e05; 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}`); + } + } }