From 5c8da8bfe8f5383ab22cce3f07da9f9d35cca042 Mon Sep 17 00:00:00 2001 From: Freedom9339 Date: Tue, 10 Mar 2026 16:26:40 +0000 Subject: [PATCH 1/2] NIFI-14191: Add the Reference Process Group to the URL when navigating to the Parent --- .../flow-designer/state/flow/flow.actions.ts | 5 ++++ .../flow-designer/state/flow/flow.effects.ts | 15 ++++++++--- .../flow-designer/state/flow/flow.reducer.ts | 6 +++++ .../state/flow/flow.selectors.ts | 5 ++++ .../pages/flow-designer/state/flow/index.ts | 1 + .../ui/canvas/canvas.component.ts | 26 +++++++++++++++++-- 6 files changed, 53 insertions(+), 5 deletions(-) diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts index a7fdc481555b..9b8275ff8379 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts @@ -554,6 +554,11 @@ export const setSkipTransform = createAction( props<{ skipTransform: boolean }>() ); +export const setLeavingProcessGroupId = createAction( + `${CANVAS_PREFIX} Set Leaving Process Group Id`, + props<{ leavingProcessGroupId: string | null }>() +); + /** * allowTransition is a flag that can be set that indicates if a transition should be used when applying a transform. * By default, restoring the viewport or selecting/centering components will not use a transition unless explicitly diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts index 658b630af5d3..b96c4d00d639 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts @@ -2823,9 +2823,18 @@ export class FlowEffects { () => this.actions$.pipe( ofType(FlowActions.leaveProcessGroup), - concatLatestFrom(() => this.store.select(selectParentProcessGroupId)), - filter(([, parentProcessGroupId]) => parentProcessGroupId != null), - tap(([, parentProcessGroupId]) => { + concatLatestFrom(() => [ + this.store.select(selectParentProcessGroupId), + this.store.select(selectCurrentProcessGroupId) + ]), + filter( + ([, parentProcessGroupId, currentProcessGroupId]) => + parentProcessGroupId != null && currentProcessGroupId != null + ), + tap(([, parentProcessGroupId, currentProcessGroupId]) => { + this.store.dispatch( + FlowActions.setLeavingProcessGroupId({ leavingProcessGroupId: currentProcessGroupId }) + ); this.router.navigate(['/process-groups', parentProcessGroupId]); }) ), diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts index f9d0122704c1..35b72c599f21 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts @@ -64,6 +64,7 @@ import { setAllowTransition, setDragging, setFlowAnalysisOpen, + setLeavingProcessGroupId, setNavigationCollapsed, setOperationCollapsed, setRegistryClients, @@ -172,6 +173,7 @@ export const initialState: FlowState = { versionSaving: false, transitionRequired: false, skipTransform: false, + leavingProcessGroupId: null, allowTransition: false, navigationCollapsed: false, operationCollapsed: false, @@ -558,6 +560,10 @@ export const flowReducer = createReducer( ...state, skipTransform: true })), + on(setLeavingProcessGroupId, (state, { leavingProcessGroupId }) => ({ + ...state, + leavingProcessGroupId + })), on(setNavigationCollapsed, (state, { navigationCollapsed }) => ({ ...state, navigationCollapsed diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts index 27b84bddbb0a..ba534fbd38df 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts @@ -170,6 +170,11 @@ export const selectDragging = createSelector(selectFlowState, (state: FlowState) export const selectSkipTransform = createSelector(selectFlowState, (state: FlowState) => state.skipTransform); +export const selectLeavingProcessGroupId = createSelector( + selectFlowState, + (state: FlowState) => state.leavingProcessGroupId +); + export const selectAllowTransition = createSelector(selectFlowState, (state: FlowState) => state.allowTransition); export const selectFunnels = createSelector( diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts index fd9ac29d306e..19ebcf883bf6 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts @@ -666,6 +666,7 @@ export interface FlowState { dragging: boolean; transitionRequired: boolean; skipTransform: boolean; + leavingProcessGroupId: string | null; allowTransition: boolean; saving: boolean; navigationCollapsed: boolean; diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts index 7459bb905801..25fa8f7e7d27 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts @@ -26,10 +26,12 @@ import { editCurrentProcessGroup, loadProcessGroup, navigateToComponents, + navigateWithoutTransform, paste, resetFlowState, selectComponents, setAllowTransition, + setLeavingProcessGroupId, setSkipTransform, startProcessGroupPolling, stopProcessGroupPolling @@ -51,6 +53,7 @@ import { selectFunnel, selectInputPort, selectLabel, + selectLeavingProcessGroupId, selectOutputPort, selectProcessGroup, selectProcessGroupIdFromRoute, @@ -156,15 +159,34 @@ export class Canvas implements OnInit, OnDestroy { distinctUntilChanged(), switchMap(() => this.store.select(selectProcessGroupRoute)), filter((processGroupRoute) => processGroupRoute != null), - concatLatestFrom(() => this.store.select(selectSkipTransform)), + concatLatestFrom(() => [ + this.store.select(selectSkipTransform), + this.store.select(selectCurrentProcessGroupId), + this.store.select(selectLeavingProcessGroupId) + ]), takeUntilDestroyed() ) - .subscribe(([, skipTransform]) => { + .subscribe(([, skipTransform, currentProcessGroupId, leavingProcessGroupId]) => { if (skipTransform) { this.store.dispatch(setSkipTransform({ skipTransform: false })); } else { this.store.dispatch(restoreViewport()); } + + // If leaving process group, select it after parent PG has loaded + if (leavingProcessGroupId && currentProcessGroupId != leavingProcessGroupId) { + this.store.dispatch(setLeavingProcessGroupId({ leavingProcessGroupId: null })); + this.store.dispatch( + navigateWithoutTransform({ + url: [ + '/process-groups', + currentProcessGroupId, + ComponentType.ProcessGroup, + leavingProcessGroupId + ] + }) + ); + } }); // handle single component selection From 1a74ede44b4bd3a0fefbcd2cbf53a47f1918a049 Mon Sep 17 00:00:00 2001 From: Freedom9339 Date: Fri, 13 Mar 2026 12:53:02 +0000 Subject: [PATCH 2/2] NIFI-14191: Fixed restoreViewport being called twice. Removed leavingProcessGroupId from the store. --- .../flow-designer/state/flow/flow.actions.ts | 5 -- .../flow-designer/state/flow/flow.effects.ts | 48 +++++++++++-------- .../flow-designer/state/flow/flow.reducer.ts | 6 --- .../state/flow/flow.selectors.ts | 5 -- .../pages/flow-designer/state/flow/index.ts | 1 - .../ui/canvas/canvas.component.ts | 34 ++++--------- 6 files changed, 37 insertions(+), 62 deletions(-) diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts index 9b8275ff8379..a7fdc481555b 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts @@ -554,11 +554,6 @@ export const setSkipTransform = createAction( props<{ skipTransform: boolean }>() ); -export const setLeavingProcessGroupId = createAction( - `${CANVAS_PREFIX} Set Leaving Process Group Id`, - props<{ leavingProcessGroupId: string | null }>() -); - /** * allowTransition is a flag that can be set that indicates if a transition should be used when applying a transform. * By default, restoring the viewport or selecting/centering components will not use a transition unless explicitly diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts index b96c4d00d639..4523342af89c 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts @@ -2819,26 +2819,36 @@ export class FlowEffects { { dispatch: false } ); - leaveProcessGroup$ = createEffect( - () => - this.actions$.pipe( - ofType(FlowActions.leaveProcessGroup), - concatLatestFrom(() => [ - this.store.select(selectParentProcessGroupId), - this.store.select(selectCurrentProcessGroupId) - ]), - filter( - ([, parentProcessGroupId, currentProcessGroupId]) => - parentProcessGroupId != null && currentProcessGroupId != null - ), - tap(([, parentProcessGroupId, currentProcessGroupId]) => { - this.store.dispatch( - FlowActions.setLeavingProcessGroupId({ leavingProcessGroupId: currentProcessGroupId }) - ); - this.router.navigate(['/process-groups', parentProcessGroupId]); - }) + leaveProcessGroup$ = createEffect(() => + this.actions$.pipe( + ofType(FlowActions.leaveProcessGroup), + concatLatestFrom(() => [ + this.store.select(selectParentProcessGroupId), + this.store.select(selectCurrentProcessGroupId) + ]), + filter( + ([, parentProcessGroupId, currentProcessGroupId]) => + parentProcessGroupId != null && currentProcessGroupId != null ), - { dispatch: false } + switchMap(([, parentProcessGroupId, currentProcessGroupId]) => { + this.router.navigate(['/process-groups', parentProcessGroupId]); + + return this.actions$.pipe( + ofType(FlowActions.loadProcessGroupComplete), + take(1), + map(() => + FlowActions.navigateWithoutTransform({ + url: [ + '/process-groups', + parentProcessGroupId!, + ComponentType.ProcessGroup, + currentProcessGroupId! + ] + }) + ) + ); + }) + ) ); addSelectedComponents$ = createEffect(() => diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts index 35b72c599f21..f9d0122704c1 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts @@ -64,7 +64,6 @@ import { setAllowTransition, setDragging, setFlowAnalysisOpen, - setLeavingProcessGroupId, setNavigationCollapsed, setOperationCollapsed, setRegistryClients, @@ -173,7 +172,6 @@ export const initialState: FlowState = { versionSaving: false, transitionRequired: false, skipTransform: false, - leavingProcessGroupId: null, allowTransition: false, navigationCollapsed: false, operationCollapsed: false, @@ -560,10 +558,6 @@ export const flowReducer = createReducer( ...state, skipTransform: true })), - on(setLeavingProcessGroupId, (state, { leavingProcessGroupId }) => ({ - ...state, - leavingProcessGroupId - })), on(setNavigationCollapsed, (state, { navigationCollapsed }) => ({ ...state, navigationCollapsed diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts index ba534fbd38df..27b84bddbb0a 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.selectors.ts @@ -170,11 +170,6 @@ export const selectDragging = createSelector(selectFlowState, (state: FlowState) export const selectSkipTransform = createSelector(selectFlowState, (state: FlowState) => state.skipTransform); -export const selectLeavingProcessGroupId = createSelector( - selectFlowState, - (state: FlowState) => state.leavingProcessGroupId -); - export const selectAllowTransition = createSelector(selectFlowState, (state: FlowState) => state.allowTransition); export const selectFunnels = createSelector( diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts index 19ebcf883bf6..fd9ac29d306e 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/index.ts @@ -666,7 +666,6 @@ export interface FlowState { dragging: boolean; transitionRequired: boolean; skipTransform: boolean; - leavingProcessGroupId: string | null; allowTransition: boolean; saving: boolean; navigationCollapsed: boolean; diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts index 25fa8f7e7d27..29919261dc5e 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/canvas.component.ts @@ -26,12 +26,10 @@ import { editCurrentProcessGroup, loadProcessGroup, navigateToComponents, - navigateWithoutTransform, paste, resetFlowState, selectComponents, setAllowTransition, - setLeavingProcessGroupId, setSkipTransform, startProcessGroupPolling, stopProcessGroupPolling @@ -53,7 +51,6 @@ import { selectFunnel, selectInputPort, selectLabel, - selectLeavingProcessGroupId, selectOutputPort, selectProcessGroup, selectProcessGroupIdFromRoute, @@ -157,36 +154,21 @@ export class Canvas implements OnInit, OnDestroy { filter((status) => status === 'complete'), switchMap(() => this.store.select(selectCurrentProcessGroupId)), distinctUntilChanged(), - switchMap(() => this.store.select(selectProcessGroupRoute)), - filter((processGroupRoute) => processGroupRoute != null), - concatLatestFrom(() => [ - this.store.select(selectSkipTransform), - this.store.select(selectCurrentProcessGroupId), - this.store.select(selectLeavingProcessGroupId) - ]), + switchMap(() => + this.store.select(selectProcessGroupRoute).pipe( + filter((processGroupRoute) => processGroupRoute != null), + take(1) + ) + ), + concatLatestFrom(() => [this.store.select(selectSkipTransform)]), takeUntilDestroyed() ) - .subscribe(([, skipTransform, currentProcessGroupId, leavingProcessGroupId]) => { + .subscribe(([, skipTransform]) => { if (skipTransform) { this.store.dispatch(setSkipTransform({ skipTransform: false })); } else { this.store.dispatch(restoreViewport()); } - - // If leaving process group, select it after parent PG has loaded - if (leavingProcessGroupId && currentProcessGroupId != leavingProcessGroupId) { - this.store.dispatch(setLeavingProcessGroupId({ leavingProcessGroupId: null })); - this.store.dispatch( - navigateWithoutTransform({ - url: [ - '/process-groups', - currentProcessGroupId, - ComponentType.ProcessGroup, - leavingProcessGroupId - ] - }) - ); - } }); // handle single component selection