From f0e1cdcb22f1fdeef804a005813edc0c09929d87 Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Tue, 28 May 2024 15:57:16 -0400 Subject: [PATCH] NIFI-12967: Introducing Back action (#8859) * NIFI-12967: - Adding support for navigating back to the users previous location in certain circumstances like going to a Controller Service, managing access policies, going to parameters, viewing documentation, opening advanced UIs, and viewing data provenance. - Cleaning unnecessary instances of postUpdateNavigation. * NIFI-12967: - Updating the implementation to leverage router events and router state to simplify needed changes. * NIFI-12967: - Conditionally resetting or popping back navigation history because on routing context. * NIFI-12967: - Adding support for navigating back from queue listing and provenance. * NIFI-12967: - Conditionally applying the back navigation following a component update. * NIFI-12967: - Adding back from CS service listing. * NIFI-12967: - Adding back from Go To CS. - Restoring some space in the context menu. * NIFI-12967: - Prevent duplicate entries in the back navigation stack. * NIFI-12967: - Not executing pop through navigation extras because it can result in multiple pops if the user uses their back/forward browser buttons. Instead, always popping until we encounter a back navigation that is still within a route boundary. --- .../main/nifi/src/app/app.component.spec.ts | 12 +- .../src/main/nifi/src/app/app.component.ts | 58 ++- .../component-access-policies.component.ts | 3 + .../service/canvas-actions.service.ts | 13 +- .../service/canvas-context-menu.service.ts | 45 ++- .../controller-services.actions.ts | 10 + .../controller-services.effects.ts | 149 +++++++- .../state/controller-services/index.ts | 2 + .../flow-designer/state/flow/flow.actions.ts | 6 +- .../flow-designer/state/flow/flow.effects.ts | 186 +++++++--- .../pages/flow-designer/state/flow/index.ts | 12 +- .../ui/canvas/header/header.component.spec.ts | 11 +- .../edit-processor.component.ts | 8 +- .../controller-services.component.html | 2 + .../controller-services.component.ts | 48 ++- .../parameter-context-listing.actions.ts | 5 + .../parameter-context-listing.effects.ts | 22 ++ .../parameter-context-listing.component.html | 3 +- .../parameter-context-listing.component.ts | 9 + .../parameter-context-table.component.html | 5 +- .../parameter-context-table.component.ts | 9 +- .../pages/queue/state/queue-listing/index.ts | 8 +- .../queue-listing/queue-listing.effects.ts | 2 + .../queue-listing/queue-listing.reducer.ts | 7 +- .../queue-listing/queue-listing.selectors.ts | 4 +- .../flowfile-table.component.html | 13 +- .../flowfile-table.component.ts | 4 +- .../queue-listing.component.html | 2 +- .../queue-listing/queue-listing.component.ts | 4 +- .../flow-analysis-rules.effects.ts | 97 ++--- .../state/flow-analysis-rules/index.ts | 5 +- .../management-controller-services/index.ts | 2 + .../management-controller-services.actions.ts | 7 +- .../management-controller-services.effects.ts | 96 ++++- .../state/parameter-providers/index.ts | 3 + .../parameter-providers.actions.ts | 5 + .../parameter-providers.effects.ts | 87 ++++- .../settings/state/registry-clients/index.ts | 2 + .../registry-clients.effects.ts | 43 ++- .../settings/state/reporting-tasks/index.ts | 10 +- .../reporting-tasks.actions.ts | 5 + .../reporting-tasks.effects.ts | 91 ++++- .../edit-flow-analysis-rule.component.ts | 5 +- .../flow-analysis-rules.component.ts | 17 +- ...agement-controller-services.component.html | 1 + ...anagement-controller-services.component.ts | 26 +- .../edit-parameter-provider.component.ts | 5 +- .../parameter-providers-table.component.html | 5 +- .../parameter-providers-table.component.ts | 4 +- .../parameter-providers.component.html | 1 + .../parameter-providers.component.ts | 25 +- .../edit-registry-client.component.ts | 5 +- .../edit-reporting-task.component.ts | 5 +- .../reporting-task-table.component.html | 5 +- .../reporting-task-table.component.ts | 5 +- .../reporting-tasks.component.html | 1 + .../reporting-tasks.component.ts | 26 +- .../documentation/documentation.actions.ts | 4 +- .../documentation/documentation.effects.ts | 11 +- .../documentation/documentation.reducer.ts | 4 +- .../nifi/src/app/state/documentation/index.ts | 7 + .../src/main/nifi/src/app/state/index.ts | 4 + .../nifi/src/app/state/navigation/index.ts | 28 ++ .../state/navigation/navigation.actions.ts | 26 ++ .../state/navigation/navigation.reducer.ts | 70 ++++ .../state/navigation/navigation.selectors.ts | 29 ++ .../main/nifi/src/app/state/shared/index.ts | 1 + .../advanced-ui/advanced-ui.component.spec.ts | 9 +- .../context-menu/context-menu.component.html | 8 +- .../controller-service-table.component.html | 7 +- .../controller-service-table.component.ts | 19 +- .../edit-controller-service.component.ts | 5 +- .../navigation/navigation.component.html | 330 +++++++++--------- .../navigation/navigation.component.spec.ts | 9 +- .../common/navigation/navigation.component.ts | 3 + 75 files changed, 1382 insertions(+), 443 deletions(-) create mode 100644 nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/index.ts create mode 100644 nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.actions.ts create mode 100644 nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.reducer.ts create mode 100644 nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.selectors.ts diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.spec.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.spec.ts index 9a3ec4ccda..000b355e5b 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.spec.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.spec.ts @@ -19,12 +19,22 @@ import { TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { provideMockStore } from '@ngrx/store/testing'; +import { navigationFeatureKey } from './state/navigation'; +import * as fromNavigation from './state/navigation/navigation.reducer'; describe('AppComponent', () => { beforeEach(() => TestBed.configureTestingModule({ imports: [RouterTestingModule, MatProgressSpinnerModule], - declarations: [AppComponent] + declarations: [AppComponent], + providers: [ + provideMockStore({ + initialState: { + [navigationFeatureKey]: fromNavigation.initialState + } + }) + ] }) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.ts index 671f251744..91acb5f16e 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.component.ts @@ -16,11 +16,18 @@ */ import { Component } from '@angular/core'; -import { GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationStart, Router } from '@angular/router'; +import { GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationStart, NavigationEnd, Router } from '@angular/router'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { Storage } from './service/storage.service'; import { ThemingService } from './service/theming.service'; import { MatDialog } from '@angular/material/dialog'; +import { NiFiState } from './state'; +import { Store } from '@ngrx/store'; +import { BackNavigation } from './state/navigation'; +import { popBackNavigation, pushBackNavigation } from './state/navigation/navigation.actions'; +import { filter, map, tap } from 'rxjs'; +import { concatLatestFrom } from '@ngrx/operators'; +import { selectBackNavigation } from './state/navigation/navigation.selectors'; @Component({ selector: 'nifi', @@ -35,19 +42,44 @@ export class AppComponent { private router: Router, private storage: Storage, private themingService: ThemingService, - private dialog: MatDialog + private dialog: MatDialog, + private store: Store ) { - this.router.events.pipe(takeUntilDestroyed()).subscribe((event) => { - if (event instanceof NavigationStart) { - this.dialog.openDialogs.forEach((dialog) => dialog.close('ROUTED')); - } - if (event instanceof GuardsCheckStart) { - this.guardLoading = true; - } - if (event instanceof GuardsCheckEnd || event instanceof NavigationCancel) { - this.guardLoading = false; - } - }); + this.router.events + .pipe( + takeUntilDestroyed(), + tap((event) => { + if (event instanceof NavigationStart) { + this.dialog.openDialogs.forEach((dialog) => dialog.close('ROUTED')); + } + if (event instanceof GuardsCheckStart) { + this.guardLoading = true; + } + if (event instanceof GuardsCheckEnd || event instanceof NavigationCancel) { + this.guardLoading = false; + } + }), + filter((e) => e instanceof NavigationEnd), + map((e) => e as NavigationEnd), + concatLatestFrom(() => this.store.select(selectBackNavigation)) + ) + .subscribe(([event, previousBackNavigation]) => { + const extras = this.router.getCurrentNavigation()?.extras; + if (extras?.state?.['backNavigation']) { + const backNavigation: BackNavigation = extras?.state?.['backNavigation']; + this.store.dispatch( + pushBackNavigation({ + backNavigation + }) + ); + } else if (previousBackNavigation) { + this.store.dispatch( + popBackNavigation({ + url: event.url + }) + ); + } + }); let theme = this.storage.getItem('theme'); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts index df7df0a606..76ccb589d5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts @@ -331,6 +331,7 @@ export class ComponentAccessPolicies implements OnInit, OnDestroy { return 'icon-group-remote'; case 'parameter-providers': case 'parameter-contexts': + case 'reporting-tasks': return 'icon-drop'; } @@ -353,6 +354,8 @@ export class ComponentAccessPolicies implements OnInit, OnDestroy { return ComponentType.RemoteProcessGroup; case 'parameter-contexts': return 'Parameter Context'; + case 'reporting-tasks': + return 'Reporting Task'; case 'parameter-providers': return ComponentType.ParameterProvider; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-actions.service.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-actions.service.ts index e07a0af6fa..5c56d1d0a3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-actions.service.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-actions.service.ts @@ -229,7 +229,8 @@ export class CanvasActionsService { navigateToManageComponentPolicies({ request: { resource: 'process-groups', - id: extraArgs.processGroupId + id: extraArgs.processGroupId, + backNavigationContext: 'Process Group' } }) ); @@ -239,24 +240,31 @@ export class CanvasActionsService { const componentType: ComponentType = selectionData.type; let resource = 'process-groups'; + let backNavigationContext = 'Process Group'; switch (componentType) { case ComponentType.Processor: resource = 'processors'; + backNavigationContext = 'Processor'; break; case ComponentType.InputPort: resource = 'input-ports'; + backNavigationContext = 'Input Port'; break; case ComponentType.OutputPort: resource = 'output-ports'; + backNavigationContext = 'Output Port'; break; case ComponentType.Funnel: resource = 'funnels'; + backNavigationContext = 'Funnel'; break; case ComponentType.Label: resource = 'labels'; + backNavigationContext = 'Label'; break; case ComponentType.RemoteProcessGroup: resource = 'remote-process-groups'; + backNavigationContext = 'Remote Process Group'; break; } @@ -264,7 +272,8 @@ export class CanvasActionsService { navigateToManageComponentPolicies({ request: { resource, - id: selectionData.id + id: selectionData.id, + backNavigationContext } }) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts index fad65e0d90..3e9281376d 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts @@ -72,6 +72,7 @@ import { CanvasView } from './canvas-view.service'; import { CanvasActionsService } from './canvas-actions.service'; import * as FlowActions from '../state/flow/flow.actions'; import { DraggableBehavior } from './behavior/draggable-behavior.service'; +import { BackNavigation } from '../../../state/navigation'; @Injectable({ providedIn: 'root' }) export class CanvasContextMenu implements ContextMenuDefinitionProvider { @@ -660,18 +661,37 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider { text: 'Parameters', action: (selection: d3.Selection) => { let id; + let backNavigation; if (selection.empty()) { id = this.canvasUtils.getParameterContextId(); + + backNavigation = { + route: ['/process-groups', this.canvasUtils.getProcessGroupId()], + routeBoundary: ['/parameter-contexts'], + context: 'Process Group' + } as BackNavigation; } else { const selectionData = selection.datum(); id = selectionData.parameterContext.id; + + backNavigation = { + route: [ + '/process-groups', + this.canvasUtils.getProcessGroupId(), + ComponentType.ProcessGroup, + selectionData.id + ], + routeBoundary: ['/parameter-contexts'], + context: 'Process Group' + } as BackNavigation; } if (id) { this.store.dispatch( navigateToParameterContext({ request: { - id + id, + backNavigation } }) ); @@ -941,14 +961,27 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider { clazz: 'fa fa-book', text: 'View Documentation', action: (selection: any) => { + const processGroupId = this.canvasUtils.getProcessGroupId(); const selectionData = selection.datum(); this.store.dispatch( navigateToComponentDocumentation({ - params: { - select: selectionData.component.type, - group: selectionData.component.bundle.group, - artifact: selectionData.component.bundle.artifact, - version: selectionData.component.bundle.version + request: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + ComponentType.Processor, + selectionData.id + ], + routeBoundary: ['/documentation'], + context: 'Processor' + } as BackNavigation, + parameters: { + select: selectionData.component.type, + group: selectionData.component.bundle.group, + artifact: selectionData.component.bundle.artifact, + version: selectionData.component.bundle.version + } } }) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts index 840e5a6845..c920c92764 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts @@ -68,6 +68,11 @@ export const inlineCreateControllerServiceSuccess = createAction( props<{ response: CreateControllerServiceSuccess }>() ); +export const navigateToService = createAction( + '[Controller Services] Navigate To Service', + props<{ request: SelectControllerServiceRequest }>() +); + export const navigateToEditService = createAction( '[Controller Services] Navigate To Edit Service', props<{ id: string }>() @@ -78,6 +83,11 @@ export const navigateToAdvancedServiceUi = createAction( props<{ id: string }>() ); +export const navigateToManageComponentPolicies = createAction( + '[Controller Services] Navigate To Manage Component Policies', + props<{ id: string }>() +); + export const openConfigureControllerServiceDialog = createAction( '[Controller Services] Open Configure Controller Service Dialog', props<{ request: EditControllerServiceDialogRequest }>() diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts index aa0c00ca62..dd8bbea594 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts @@ -63,6 +63,7 @@ import { selectPropertyVerificationStatus } from '../../../../state/property-verification/property-verification.selectors'; import { VerifyPropertiesRequestContext } from '../../../../state/property-verification'; +import { BackNavigation } from '../../../../state/navigation'; @Injectable() export class ControllerServicesEffects { @@ -204,7 +205,66 @@ export class ControllerServicesEffects { map((action) => action.id), concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), tap(([id, processGroupId]) => { - this.router.navigate(['/process-groups', processGroupId, 'controller-services', id, 'advanced']); + const routeBoundary: string[] = [ + '/process-groups', + processGroupId, + 'controller-services', + id, + 'advanced' + ]; + this.router.navigate([...routeBoundary], { + state: { + backNavigation: { + route: ['/process-groups', processGroupId, 'controller-services', id], + routeBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + }) + ), + { dispatch: false } + ); + + navigateToManageComponentPolicies$ = createEffect( + () => + this.actions$.pipe( + ofType(ControllerServicesActions.navigateToManageComponentPolicies), + map((action) => action.id), + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([id, processGroupId]) => { + const routeBoundary: string[] = ['/access-policies']; + this.router.navigate([...routeBoundary, 'read', 'component', 'controller-services', id], { + state: { + backNavigation: { + route: ['/process-groups', processGroupId, 'controller-services', id], + routeBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + }) + ), + { dispatch: false } + ); + + navigateToService$ = createEffect( + () => + this.actions$.pipe( + ofType(ControllerServicesActions.navigateToService), + map((action) => action.request), + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([request, processGroupId]) => { + const routeBoundary: string[] = ['/process-groups', request.processGroupId, 'controller-services']; + this.router.navigate([...routeBoundary, request.id], { + state: { + backNavigation: { + route: ['/process-groups', processGroupId, 'controller-services', request.id], + routeBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -306,7 +366,7 @@ export class ControllerServicesEffects { selectPropertyVerificationStatus ); - const goTo = (commands: string[], destination: string): void => { + const goTo = (commands: string[], destination: string, commandBoundary?: string[]): void => { if (editDialogReference.componentInstance.editControllerServiceForm.dirty) { const saveChangesDialogReference = this.dialog.open(YesNoDialog, { ...SMALL_DIALOG, @@ -317,14 +377,50 @@ export class ControllerServicesEffects { }); saveChangesDialogReference.componentInstance.yes.pipe(take(1)).subscribe(() => { - editDialogReference.componentInstance.submitForm(commands); + editDialogReference.componentInstance.submitForm(commands, commandBoundary); }); saveChangesDialogReference.componentInstance.no.pipe(take(1)).subscribe(() => { - this.router.navigate(commands); + if (commandBoundary) { + this.router.navigate(commands, { + state: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + 'controller-services', + serviceId, + 'edit' + ], + routeBoundary: commandBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + } else { + this.router.navigate(commands); + } }); } else { - this.router.navigate(commands); + if (commandBoundary) { + this.router.navigate(commands, { + state: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + 'controller-services', + serviceId, + 'edit' + ], + routeBoundary: commandBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + } else { + this.router.navigate(commands); + } } }; @@ -338,8 +434,9 @@ export class ControllerServicesEffects { if (parameterContext != null) { editDialogReference.componentInstance.parameterContext = parameterContext; editDialogReference.componentInstance.goToParameter = () => { - const commands: string[] = ['/parameter-contexts', parameterContext.id]; - goTo(commands, 'Parameter'); + const commandBoundary: string[] = ['/parameter-contexts']; + const commands: string[] = [...commandBoundary, parameterContext.id, 'edit']; + goTo(commands, 'Parameter', commandBoundary); }; editDialogReference.componentInstance.convertToParameter = @@ -349,13 +446,13 @@ export class ControllerServicesEffects { editDialogReference.componentInstance.goToService = (serviceId: string) => { this.controllerServiceService.getControllerService(serviceId).subscribe({ next: (serviceEntity) => { - const commands: string[] = [ + const commandBoundary: string[] = [ '/process-groups', serviceEntity.component.parentGroupId, - 'controller-services', - serviceEntity.id + 'controller-services' ]; - goTo(commands, 'Controller Service'); + const commands: string[] = [...commandBoundary, serviceEntity.id]; + goTo(commands, 'Controller Service', commandBoundary); }, error: (errorResponse: HttpErrorResponse) => { this.store.dispatch( @@ -392,7 +489,9 @@ export class ControllerServicesEffects { id: request.controllerService.id, uri: request.controllerService.uri, payload: updateControllerServiceRequest.payload, - postUpdateNavigation: updateControllerServiceRequest.postUpdateNavigation + postUpdateNavigation: updateControllerServiceRequest.postUpdateNavigation, + postUpdateNavigationBoundary: + updateControllerServiceRequest.postUpdateNavigationBoundary } }) ); @@ -429,7 +528,8 @@ export class ControllerServicesEffects { response: { id: request.id, controllerService: response, - postUpdateNavigation: request.postUpdateNavigation + postUpdateNavigation: request.postUpdateNavigation, + postUpdateNavigationBoundary: request.postUpdateNavigationBoundary } }) ), @@ -462,9 +562,28 @@ export class ControllerServicesEffects { this.actions$.pipe( ofType(ControllerServicesActions.configureControllerServiceSuccess), map((action) => action.response), - tap((response) => { + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([response, processGroupId]) => { if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); + if (response.postUpdateNavigationBoundary) { + this.router.navigate(response.postUpdateNavigation, { + state: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + 'controller-services', + response.id, + 'edit' + ], + routeBoundary: response.postUpdateNavigationBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + } else { + this.router.navigate(response.postUpdateNavigation); + } } else { this.dialog.closeAll(); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts index 2362424bc1..9bf4fd460d 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts @@ -41,12 +41,14 @@ export interface ConfigureControllerServiceRequest { uri: string; payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface ConfigureControllerServiceSuccess { id: string; controllerService: ControllerServiceEntity; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface DeleteControllerServiceRequest { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts index 4d349b1494..9a41e2cb9d 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts @@ -106,6 +106,8 @@ import { UpdateConnectionRequest, UpdateConnectionSuccess, UpdatePositionsRequest, + UpdateProcessorRequest, + UpdateProcessorResponse, UploadProcessGroupRequest, VersionControlInformationEntity } from './index'; @@ -460,12 +462,12 @@ export const updateComponentFailure = createAction( export const updateProcessor = createAction( `${CANVAS_PREFIX} Update Processor`, - props<{ request: UpdateComponentRequest }>() + props<{ request: UpdateProcessorRequest }>() ); export const updateProcessorSuccess = createAction( `${CANVAS_PREFIX} Update Processor Success`, - props<{ response: UpdateComponentResponse }>() + props<{ response: UpdateProcessorResponse }>() ); export const updateConnection = createAction( diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts index 750807930e..74f7ca8eee 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts @@ -60,6 +60,7 @@ import { UpdateComponentResponse, UpdateConnectionSuccess, UpdateProcessorRequest, + UpdateProcessorResponse, VersionControlInformationEntity } from './index'; import { Action, Store } from '@ngrx/store'; @@ -145,6 +146,7 @@ import { selectPropertyVerificationStatus } from '../../../../state/property-verification/property-verification.selectors'; import { VerifyPropertiesRequestContext } from '../../../../state/property-verification'; +import { BackNavigation } from '../../../../state/navigation'; @Injectable() export class FlowEffects { @@ -1008,7 +1010,16 @@ export class FlowEffects { map((action) => action.id), concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), tap(([id, processGroupId]) => { - this.router.navigate(['/process-groups', processGroupId, ComponentType.Processor, id, 'advanced']); + const routeBoundary = ['/process-groups', processGroupId, ComponentType.Processor, id, 'advanced']; + this.router.navigate([...routeBoundary], { + state: { + backNavigation: { + route: ['/process-groups', processGroupId, ComponentType.Processor, id], + routeBoundary, + context: 'Processor' + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -1020,7 +1031,11 @@ export class FlowEffects { ofType(FlowActions.navigateToParameterContext), map((action) => action.request), tap((request) => { - this.router.navigate(['/parameter-contexts', request.id]); + this.router.navigate(['/parameter-contexts', request.id], { + state: { + backNavigation: request.backNavigation + } + }); }) ), { dispatch: false } @@ -1043,8 +1058,18 @@ export class FlowEffects { this.actions$.pipe( ofType(FlowActions.navigateToManageComponentPolicies), map((action) => action.request), - tap((request) => { - this.router.navigate(['/access-policies', 'read', 'component', request.resource, request.id]); + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([request, processGroupId]) => { + const routeBoundary: string[] = ['/access-policies']; + this.router.navigate([...routeBoundary, 'read', 'component', request.resource, request.id], { + state: { + backNavigation: { + route: ['/process-groups', processGroupId, request.resource, request.id], + routeBoundary, + context: request.backNavigationContext + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -1055,8 +1080,23 @@ export class FlowEffects { this.actions$.pipe( ofType(FlowActions.navigateToQueueListing), map((action) => action.request), - tap((request) => { - this.router.navigate(['/queue', request.connectionId]); + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([request, processGroupId]) => { + const routeBoundary: string[] = ['/queue', request.connectionId]; + this.router.navigate([...routeBoundary], { + state: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + ComponentType.Connection, + request.connectionId + ], + routeBoundary, + context: 'Connection' + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -1110,8 +1150,25 @@ export class FlowEffects { this.actions$.pipe( ofType(FlowActions.navigateToControllerServicesForProcessGroup), map((action) => action.request), - tap((request) => { - this.router.navigate(['/process-groups', request.id, 'controller-services']); + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([request, processGroupId]) => { + let route: string[]; + if (processGroupId == request.id) { + route = ['/process-groups', processGroupId]; + } else { + route = ['/process-groups', processGroupId, ComponentType.ProcessGroup, request.id]; + } + + const routeBoundary: string[] = ['/process-groups', request.id, 'controller-services']; + this.router.navigate([...routeBoundary], { + state: { + backNavigation: { + route, + routeBoundary, + context: 'Process Group' + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -1327,7 +1384,7 @@ export class FlowEffects { selectPropertyVerificationStatus ); - const goTo = (commands: string[], destination: string): void => { + const goTo = (commands: string[], commandBoundary: string[], destination: string): void => { if (editDialogReference.componentInstance.editProcessorForm.dirty) { const saveChangesDialogReference = this.dialog.open(YesNoDialog, { ...SMALL_DIALOG, @@ -1338,22 +1395,51 @@ export class FlowEffects { }); saveChangesDialogReference.componentInstance.yes.pipe(take(1)).subscribe(() => { - editDialogReference.componentInstance.submitForm(commands); + editDialogReference.componentInstance.submitForm(commands, commandBoundary); }); saveChangesDialogReference.componentInstance.no.pipe(take(1)).subscribe(() => { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + ComponentType.Processor, + processorId, + 'edit' + ], + routeBoundary: commandBoundary, + context: 'Processor' + } as BackNavigation + } + }); }); } else { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + ComponentType.Processor, + processorId, + 'edit' + ], + routeBoundary: commandBoundary, + context: 'Processor' + } as BackNavigation + } + }); } }; if (parameterContext != null) { editDialogReference.componentInstance.parameterContext = parameterContext; editDialogReference.componentInstance.goToParameter = () => { - const commands: string[] = ['/parameter-contexts', parameterContext.id]; - goTo(commands, 'Parameter'); + const commandBoundary: string[] = ['/parameter-contexts']; + const commands: string[] = [...commandBoundary, parameterContext.id, 'edit']; + goTo(commands, commandBoundary, 'Parameter'); }; editDialogReference.componentInstance.convertToParameter = @@ -1363,13 +1449,13 @@ export class FlowEffects { editDialogReference.componentInstance.goToService = (serviceId: string) => { this.controllerServiceService.getControllerService(serviceId).subscribe({ next: (serviceEntity) => { - const commands: string[] = [ + const commandBoundary: string[] = [ '/process-groups', serviceEntity.component.parentGroupId, - 'controller-services', - serviceEntity.id + 'controller-services' ]; - goTo(commands, 'Controller Service'); + const commands: string[] = [...commandBoundary, serviceEntity.id]; + goTo(commands, commandBoundary, 'Controller Service'); }, error: (errorResponse: HttpErrorResponse) => { this.store.dispatch(this.snackBarOrFullScreenError(errorResponse)); @@ -1390,14 +1476,7 @@ export class FlowEffects { .subscribe((updateProcessorRequest: UpdateProcessorRequest) => { this.store.dispatch( FlowActions.updateProcessor({ - request: { - id: processorId, - uri: request.uri, - type: request.type, - payload: updateProcessorRequest.payload, - errorStrategy: 'banner', - postUpdateNavigation: updateProcessorRequest.postUpdateNavigation - } + request: updateProcessorRequest }) ); }); @@ -1636,7 +1715,6 @@ export class FlowEffects { requestId: request.requestId, id: request.id, type: request.type, - postUpdateNavigation: request.postUpdateNavigation, response }; return FlowActions.updateComponentSuccess({ response: updateComponentResponse }); @@ -1661,12 +1739,8 @@ export class FlowEffects { this.actions$.pipe( ofType(FlowActions.updateComponentSuccess), map((action) => action.response), - tap((response) => { - if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); - } else { - this.dialog.closeAll(); - } + tap(() => { + this.dialog.closeAll(); }) ), { dispatch: false } @@ -1693,14 +1767,15 @@ export class FlowEffects { mergeMap((request) => from(this.flowService.updateComponent(request)).pipe( map((response) => { - const updateComponentResponse: UpdateComponentResponse = { + const updateProcessorResponse: UpdateProcessorResponse = { requestId: request.requestId, id: request.id, type: request.type, postUpdateNavigation: request.postUpdateNavigation, + postUpdateNavigationBoundary: request.postUpdateNavigationBoundary, response }; - return FlowActions.updateProcessorSuccess({ response: updateComponentResponse }); + return FlowActions.updateProcessorSuccess({ response: updateProcessorResponse }); }), catchError((errorResponse: HttpErrorResponse) => { const updateComponentFailure: UpdateComponentFailure = { @@ -1721,15 +1796,34 @@ export class FlowEffects { this.actions$.pipe( ofType(FlowActions.updateProcessorSuccess), map((action) => action.response), - tap((response) => { + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([response, processGroupId]) => { if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); + if (response.postUpdateNavigationBoundary) { + this.router.navigate(response.postUpdateNavigation, { + state: { + backNavigation: { + route: [ + '/process-groups', + processGroupId, + ComponentType.Processor, + response.id, + 'edit' + ], + routeBoundary: response.postUpdateNavigationBoundary, + context: 'Processor' + } as BackNavigation + } + }); + } else { + this.router.navigate(response.postUpdateNavigation); + } } else { this.dialog.closeAll(); } }), - filter((response) => response.postUpdateNavigation == null), - switchMap((response) => of(FlowActions.loadConnectionsForComponent({ id: response.id }))) + filter(([response]) => response.postUpdateNavigation == null), + switchMap(([response]) => of(FlowActions.loadConnectionsForComponent({ id: response.id }))) ) ); @@ -2466,8 +2560,18 @@ export class FlowEffects { this.actions$.pipe( ofType(FlowActions.navigateToProvenanceForComponent), map((action) => action.id), - tap((componentId) => { - this.router.navigate(['/provenance'], { queryParams: { componentId } }); + concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), + tap(([componentId, processGroupId]) => { + this.router.navigate(['/provenance'], { + queryParams: { componentId }, + state: { + backNavigation: { + route: ['/process-groups', processGroupId, ComponentType.Processor, componentId], + routeBoundary: ['/provenance'], + context: 'Processor' + } as BackNavigation + } + }); }) ), { dispatch: false } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts index f4e862d45d..75a3dd3a66 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts @@ -32,6 +32,7 @@ import { VersionedFlowSnapshotMetadataEntity } from '../../../../state/shared'; import { HttpErrorResponse } from '@angular/common/http'; +import { BackNavigation } from '../../../../state/navigation'; export const flowFeatureKey = 'flowState'; @@ -346,6 +347,7 @@ export interface OpenComponentDialogRequest { export interface NavigateToManageComponentPoliciesRequest { resource: string; id: string; + backNavigationContext: string; } export interface EditComponentDialogRequest { @@ -373,6 +375,7 @@ export interface NavigateToQueueListing { export interface NavigateToParameterContext { id: string; + backNavigation: BackNavigation; } export interface EditCurrentProcessGroupRequest { @@ -388,9 +391,9 @@ export interface EditConnectionDialogRequest extends EditComponentDialogRequest }; } -export interface UpdateProcessorRequest { - payload: any; +export interface UpdateProcessorRequest extends UpdateComponentRequest { postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface UpdateComponentRequest { @@ -401,7 +404,6 @@ export interface UpdateComponentRequest { payload: any; errorStrategy: 'snackbar' | 'banner'; restoreOnFailure?: any; - postUpdateNavigation?: string[]; } export interface UpdateComponentResponse { @@ -409,7 +411,11 @@ export interface UpdateComponentResponse { id: string; type: ComponentType; response: any; +} + +export interface UpdateProcessorResponse extends UpdateComponentResponse { postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface UpdateComponentFailure { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/header/header.component.spec.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/header/header.component.spec.ts index 450b2e1be4..0dc1d78a81 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/header/header.component.spec.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/header/header.component.spec.ts @@ -19,13 +19,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HeaderComponent } from './header.component'; import { provideMockStore } from '@ngrx/store/testing'; -import { initialState } from '../../../state/flow/flow.reducer'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { NewCanvasItem } from './new-canvas-item/new-canvas-item.component'; import { MatMenuModule } from '@angular/material/menu'; import { MatDividerModule } from '@angular/material/divider'; import { selectControllerBulletins, selectControllerStatus } from '../../../state/flow/flow.selectors'; -import { ControllerStatus } from '../../../state/flow'; +import { ControllerStatus, flowFeatureKey } from '../../../state/flow'; import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Component } from '@angular/core'; @@ -34,10 +33,13 @@ import { ClusterSummary } from '../../../../../state/cluster-summary'; import { selectClusterSummary } from '../../../../../state/cluster-summary/cluster-summary.selectors'; import { selectCurrentUser } from '../../../../../state/current-user/current-user.selectors'; import * as fromUser from '../../../../../state/current-user/current-user.reducer'; +import * as fromNavigation from '../../../../../state/navigation/navigation.reducer'; +import * as fromFlow from '../../../state/flow/flow.reducer'; import { selectFlowConfiguration } from '../../../../../state/flow-configuration/flow-configuration.selectors'; import * as fromFlowConfiguration from '../../../../../state/flow-configuration/flow-configuration.reducer'; import { selectLoginConfiguration } from '../../../../../state/login-configuration/login-configuration.selectors'; import * as fromLoginConfiguration from '../../../../../state/login-configuration/login-configuration.reducer'; +import { navigationFeatureKey } from '../../../../../state/navigation'; describe('HeaderComponent', () => { let component: HeaderComponent; @@ -101,7 +103,10 @@ describe('HeaderComponent', () => { ], providers: [ provideMockStore({ - initialState, + initialState: { + [flowFeatureKey]: fromFlow.initialState, + [navigationFeatureKey]: fromNavigation.initialState + }, selectors: [ { selector: selectClusterSummary, diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/processor/edit-processor/edit-processor.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/processor/edit-processor/edit-processor.component.ts index b024d1ef8a..b435ecc61b 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/processor/edit-processor/edit-processor.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/processor/edit-processor/edit-processor.component.ts @@ -27,6 +27,7 @@ import { MatOptionModule } from '@angular/material/core'; import { MatSelectModule } from '@angular/material/select'; import { Observable, of } from 'rxjs'; import { + ComponentType, InlineServiceCreationRequest, InlineServiceCreationResponse, ParameterContextEntity, @@ -300,7 +301,7 @@ export class EditProcessor extends TabbedDialog { ); } - submitForm(postUpdateNavigation?: string[]) { + submitForm(postUpdateNavigation?: string[], postUpdateNavigationBoundary?: string[]) { const relationshipConfiguration: RelationshipConfiguration = this.editProcessorForm.get('relationshipConfiguration')?.value; const autoTerminated: string[] = relationshipConfiguration.relationships @@ -351,7 +352,12 @@ export class EditProcessor extends TabbedDialog { } this.editProcessor.next({ + id: this.request.entity.id, + uri: this.request.entity.uri, + type: ComponentType.Processor, + errorStrategy: 'banner', postUpdateNavigation, + postUpdateNavigationBoundary, payload }); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html index ff63ae537c..b397322891 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html @@ -50,10 +50,12 @@ (viewControllerServiceDocumentation)="viewControllerServiceDocumentation($event)" (configureControllerService)="configureControllerService($event)" (openAdvancedUi)="openAdvancedUi($event)" + (manageAccessPolicies)="navigateToManageComponentPolicies($event)" (enableControllerService)="enableControllerService($event)" (disableControllerService)="disableControllerService($event)" (viewStateControllerService)="viewStateControllerService($event)" (changeControllerServiceVersion)="changeControllerServiceVersion($event)" + (goToControllerService)="navigateToControllerService($event)" (deleteControllerService)="deleteControllerService($event)"> } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts index 5a6204577d..4b22aaa37c 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts @@ -31,6 +31,8 @@ import { loadControllerServices, navigateToAdvancedServiceUi, navigateToEditService, + navigateToManageComponentPolicies, + navigateToService, openChangeControllerServiceVersionDialog, openConfigureControllerServiceDialog, openDisableControllerServiceDialog, @@ -49,6 +51,7 @@ import { NiFiState } from '../../../../state'; import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions'; import { navigateToComponentDocumentation } from '../../../../state/documentation/documentation.actions'; import { FlowConfiguration } from '../../../../state/flow-configuration'; +import { DocumentationRequest } from '../../../../state/documentation'; @Component({ selector: 'controller-services', @@ -162,14 +165,26 @@ export class ControllerServices implements OnDestroy { } viewControllerServiceDocumentation(entity: ControllerServiceEntity): void { + const request: DocumentationRequest = { + parameters: { + select: entity.component.type, + group: entity.component.bundle.group, + artifact: entity.component.bundle.artifact, + version: entity.component.bundle.version + } + }; + + if (entity.parentGroupId) { + request.backNavigation = { + route: ['/process-groups', entity.parentGroupId, 'controller-services', entity.id], + routeBoundary: ['/documentation'], + context: 'Controller Service' + }; + } + this.store.dispatch( navigateToComponentDocumentation({ - params: { - select: entity.component.type, - group: entity.component.bundle.group, - artifact: entity.component.bundle.artifact, - version: entity.component.bundle.version - } + request }) ); } @@ -190,6 +205,27 @@ export class ControllerServices implements OnDestroy { ); } + navigateToControllerService(entity: ControllerServiceEntity): void { + if (entity.parentGroupId) { + this.store.dispatch( + navigateToService({ + request: { + id: entity.id, + processGroupId: entity.parentGroupId + } + }) + ); + } + } + + navigateToManageComponentPolicies(entity: ControllerServiceEntity): void { + this.store.dispatch( + navigateToManageComponentPolicies({ + id: entity.id + }) + ); + } + enableControllerService(entity: ControllerServiceEntity): void { this.store.dispatch( openEnableControllerServiceDialog({ diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.actions.ts index 8642ca7944..f39b99e196 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.actions.ts @@ -64,6 +64,11 @@ export const navigateToEditParameterContext = createAction( props<{ id: string }>() ); +export const navigateToManageComponentPolicies = createAction( + '[Parameter Context Listing] Navigate To Manage Component Policies', + props<{ id: string }>() +); + export const getEffectiveParameterContextAndOpenDialog = createAction( '[Parameter Context Listing] Get Effective Parameter Context Open Dialog', props<{ request: GetEffectiveParameterContext }>() diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts index 6318c282a8..caac35bdd2 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts @@ -59,6 +59,7 @@ import { OkDialog } from '../../../../ui/common/ok-dialog/ok-dialog.component'; import { ErrorHelper } from '../../../../service/error-helper.service'; import { HttpErrorResponse } from '@angular/common/http'; import { MEDIUM_DIALOG, SMALL_DIALOG, XL_DIALOG } from '../../../../index'; +import { BackNavigation } from '../../../../state/navigation'; @Injectable() export class ParameterContextListingEffects { @@ -201,6 +202,27 @@ export class ParameterContextListingEffects { ) ); + navigateToManageComponentPolicies$ = createEffect( + () => + this.actions$.pipe( + ofType(ParameterContextListingActions.navigateToManageComponentPolicies), + map((action) => action.id), + tap((id) => { + const routeBoundary: string[] = ['/access-policies']; + this.router.navigate([...routeBoundary, 'read', 'component', 'parameter-contexts', id], { + state: { + backNavigation: { + route: ['/parameter-contexts', id], + routeBoundary, + context: 'Parameter Context' + } as BackNavigation + } + }); + }) + ), + { dispatch: false } + ); + navigateToEditService$ = createEffect( () => this.actions$.pipe( diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.html index 3cc3c8261c..f59e0af84f 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.html @@ -35,7 +35,8 @@ [flowConfiguration]="(flowConfiguration$ | async)!" (selectParameterContext)="selectParameterContext($event)" (editParameterContext)="editParameterContext($event)" - (deleteParameterContext)="deleteParameterContext($event)"> + (deleteParameterContext)="deleteParameterContext($event)" + (manageAccessPolicies)="navigateToManageComponentPolicies($event)">
diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.ts index fe88993e3c..3d0d471a3e 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.component.ts @@ -28,6 +28,7 @@ import { getEffectiveParameterContextAndOpenDialog, loadParameterContexts, navigateToEditParameterContext, + navigateToManageComponentPolicies, openNewParameterContextDialog, promptParameterContextDeletion, selectParameterContext @@ -120,4 +121,12 @@ export class ParameterContextListing implements OnInit { }) ); } + + navigateToManageComponentPolicies(entity: ParameterContextEntity): void { + this.store.dispatch( + navigateToManageComponentPolicies({ + id: entity.id + }) + ); + } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.html index ac36f25031..f346d0d228 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.html @@ -86,10 +86,7 @@ } @if (canManageAccessPolicies()) { - diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts index 7bd4886d4b..0c65284d47 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts @@ -47,6 +47,7 @@ export class ParameterContextTable { @Output() selectParameterContext: EventEmitter = new EventEmitter(); @Output() editParameterContext: EventEmitter = new EventEmitter(); @Output() deleteParameterContext: EventEmitter = new EventEmitter(); + @Output() manageAccessPolicies: EventEmitter = new EventEmitter(); displayedColumns: string[] = ['name', 'provider', 'description', 'actions']; dataSource: MatTableDataSource = new MatTableDataSource(); @@ -99,6 +100,10 @@ export class ParameterContextTable { return this.flowConfiguration?.supportsManagedAuthorizer && this.currentUser.tenantsPermissions.canRead; } + manageAccessPoliciesClicked(entity: ParameterContextEntity): void { + this.manageAccessPolicies.next(entity); + } + canGoToParameterProvider(entity: ParameterContextEntity): boolean { if (!this.canRead(entity)) { return false; @@ -113,10 +118,6 @@ export class ParameterContextTable { return ['/settings', 'parameter-providers', entity.component.parameterProviderConfiguration.id]; } - getPolicyLink(entity: ParameterContextEntity): string[] { - return ['/access-policies', 'read', 'component', 'parameter-contexts', entity.id]; - } - select(entity: ParameterContextEntity): void { this.selectParameterContext.next(entity); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/index.ts index cdf7097041..373384072b 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/index.ts @@ -73,6 +73,7 @@ export interface LoadConnectionLabelRequest { } export interface LoadConnectionLabelResponse { + connectionId: string; connectionLabel: string; } @@ -103,10 +104,15 @@ export interface FlowFileDialogRequest { clusterNodeId?: string; } +export interface SelectedConnection { + id: string; + label: string; +} + export interface QueueListingState { activeListingRequest: ListingRequest | null; completedListingRequest: ListingRequest; - connectionLabel: string; + selectedConnection: SelectedConnection | null; loadedTimestamp: string; status: 'pending' | 'loading' | 'error' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.effects.ts index aca3719b0e..ec4f5843cd 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.effects.ts @@ -66,6 +66,7 @@ export class QueueListingEffects { return QueueListingActions.loadConnectionLabelSuccess({ response: { + connectionId: request.connectionId, connectionLabel } }); @@ -74,6 +75,7 @@ export class QueueListingEffects { of( QueueListingActions.loadConnectionLabelSuccess({ response: { + connectionId: request.connectionId, connectionLabel: 'Connection' } }) diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.reducer.ts index 6c58a85b14..7a6a15486a 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.reducer.ts @@ -48,7 +48,7 @@ export const initialState: QueueListingState = { }, flowFileSummaries: [] }, - connectionLabel: 'Connection', + selectedConnection: null, loadedTimestamp: 'N/A', status: 'pending' }; @@ -57,7 +57,10 @@ export const queueListingReducer = createReducer( initialState, on(loadConnectionLabelSuccess, (state, { response }) => ({ ...state, - connectionLabel: response.connectionLabel + selectedConnection: { + id: response.connectionId, + label: response.connectionLabel + } })), on(submitQueueListingRequest, (state) => ({ ...state, diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.selectors.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.selectors.ts index a43fe859e0..b3bd917a85 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.selectors.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/state/queue-listing/queue-listing.selectors.ts @@ -37,9 +37,9 @@ export const selectCompletedListingRequest = createSelector( export const selectStatus = createSelector(selectQueueListingState, (state: QueueListingState) => state.status); -export const selectConnectionLabel = createSelector( +export const selectSelectedConnection = createSelector( selectQueueListingState, - (state: QueueListingState) => state.connectionLabel + (state: QueueListingState) => state.selectedConnection ); export const selectLoadedTimestamp = createSelector( diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.html index 3561167340..dfd0ef29f9 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.html @@ -16,7 +16,7 @@ -->
-

{{ connectionLabel }}

+

{{ selectedConnection?.label }}

@@ -151,11 +151,18 @@ View content } - @if (currentUser.provenancePermissions.canRead) { + @if (selectedConnection && currentUser.provenancePermissions.canRead) { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.ts index e6b6a47a44..14eab8cc45 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/flowfile-table/flowfile-table.component.ts @@ -23,7 +23,7 @@ import { ValidationErrorsTip } from '../../../../../ui/common/tooltips/validatio import { NiFiCommon } from '../../../../../service/nifi-common.service'; import { RouterLink } from '@angular/router'; -import { FlowFileSummary, ListingRequest } from '../../../state/queue-listing'; +import { FlowFileSummary, ListingRequest, SelectedConnection } from '../../../state/queue-listing'; import { CurrentUser } from '../../../../../state/current-user'; import { ErrorBanner } from '../../../../../ui/common/error-banner/error-banner.component'; import { ClusterSummary } from '../../../../../state/cluster-summary'; @@ -38,7 +38,7 @@ import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu'; styleUrls: ['./flowfile-table.component.scss'] }) export class FlowFileTable { - @Input() connectionLabel!: string; + @Input() selectedConnection: SelectedConnection | null = null; @Input() set listingRequest(listingRequest: ListingRequest) { if (listingRequest.flowFileSummaries) { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/queue-listing.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/queue-listing.component.html index d1a01c9799..0d9e95a3ac 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/queue-listing.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/ui/queue-listing/queue-listing.component.html @@ -21,7 +21,7 @@ @if (listingRequest$ | async; as listingRequest) { @if (about$ | async; as about) { { + const goTo = (commands: string[], destination: string, commandBoundary: string[]): void => { if (editDialogReference.componentInstance.editFlowAnalysisRuleForm.dirty) { const saveChangesDialogReference = this.dialog.open(YesNoDialog, { ...SMALL_DIALOG, @@ -301,20 +306,37 @@ export class FlowAnalysisRulesEffects { }); saveChangesDialogReference.componentInstance.yes.pipe(take(1)).subscribe(() => { - editDialogReference.componentInstance.submitForm(commands); + editDialogReference.componentInstance.submitForm(commands, commandBoundary); }); saveChangesDialogReference.componentInstance.no.pipe(take(1)).subscribe(() => { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'flow-analysis-rules', ruleId, 'edit'], + routeBoundary: commandBoundary, + context: 'Flow Analysis Rule' + } as BackNavigation + } + }); }); } else { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'flow-analysis-rules', ruleId, 'edit'], + routeBoundary: commandBoundary, + context: 'Flow Analysis Rule' + } as BackNavigation + } + }); } }; editDialogReference.componentInstance.goToService = (serviceId: string) => { - const commands: string[] = ['/settings', 'management-controller-services', serviceId]; - goTo(commands, 'Controller Service'); + const commandBoundary: string[] = ['/settings', 'management-controller-services']; + const commands: string[] = [...commandBoundary, serviceId]; + goTo(commands, 'Controller Service', commandBoundary); }; editDialogReference.componentInstance.createNewService = @@ -326,14 +348,16 @@ export class FlowAnalysisRulesEffects { editDialogReference.componentInstance.editFlowAnalysisRule .pipe(takeUntil(editDialogReference.afterClosed())) - .subscribe((updateControllerServiceRequest: UpdateControllerServiceRequest) => { + .subscribe((updateFlowAnalysisRuleRequest: UpdateFlowAnalysisRuleRequest) => { this.store.dispatch( FlowAnalysisRuleActions.configureFlowAnalysisRule({ request: { id: request.flowAnalysisRule.id, uri: request.flowAnalysisRule.uri, - payload: updateControllerServiceRequest.payload, - postUpdateNavigation: updateControllerServiceRequest.postUpdateNavigation + payload: updateFlowAnalysisRuleRequest.payload, + postUpdateNavigation: updateFlowAnalysisRuleRequest.postUpdateNavigation, + postUpdateNavigationBoundary: + updateFlowAnalysisRuleRequest.postUpdateNavigationBoundary } }) ); @@ -369,7 +393,8 @@ export class FlowAnalysisRulesEffects { response: { id: request.id, flowAnalysisRule: response, - postUpdateNavigation: request.postUpdateNavigation + postUpdateNavigation: request.postUpdateNavigation, + postUpdateNavigationBoundary: request.postUpdateNavigationBoundary } }) ), @@ -392,7 +417,19 @@ export class FlowAnalysisRulesEffects { map((action) => action.response), tap((response) => { if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); + if (response.postUpdateNavigationBoundary) { + this.router.navigate(response.postUpdateNavigation, { + state: { + backNavigation: { + route: ['/settings', 'flow-analysis-rules', response.id, 'edit'], + routeBoundary: response.postUpdateNavigationBoundary, + context: 'Flow Analysis Rule' + } as BackNavigation + } + }); + } else { + this.router.navigate(response.postUpdateNavigation); + } } else { this.dialog.closeAll(); } @@ -423,8 +460,7 @@ export class FlowAnalysisRulesEffects { FlowAnalysisRuleActions.enableFlowAnalysisRuleSuccess({ response: { id: request.id, - flowAnalysisRule: response, - postUpdateNavigation: response.postUpdateNavigation + flowAnalysisRule: response } }) ), @@ -440,20 +476,6 @@ export class FlowAnalysisRulesEffects { ) ); - enableFlowAnalysisRuleSuccess$ = createEffect( - () => - this.actions$.pipe( - ofType(FlowAnalysisRuleActions.enableFlowAnalysisRuleSuccess), - map((action) => action.response), - tap((response) => { - if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); - } - }) - ), - { dispatch: false } - ); - disableFlowAnalysisRule$ = createEffect(() => this.actions$.pipe( ofType(FlowAnalysisRuleActions.disableFlowAnalysisRule), @@ -464,8 +486,7 @@ export class FlowAnalysisRulesEffects { FlowAnalysisRuleActions.disableFlowAnalysisRuleSuccess({ response: { id: request.id, - flowAnalysisRule: response, - postUpdateNavigation: response.postUpdateNavigation + flowAnalysisRule: response } }) ), @@ -481,20 +502,6 @@ export class FlowAnalysisRulesEffects { ) ); - disableFlowAnalysisRuleSuccess$ = createEffect( - () => - this.actions$.pipe( - ofType(FlowAnalysisRuleActions.disableFlowAnalysisRuleSuccess), - map((action) => action.response), - tap((response) => { - if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); - } - }) - ), - { dispatch: false } - ); - openChangeFlowAnalysisRuleVersionDialog$ = createEffect( () => this.actions$.pipe( diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/index.ts index a22639b86a..0124769ac6 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/index.ts @@ -50,29 +50,30 @@ export interface ConfigureFlowAnalysisRuleRequest { uri: string; payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface ConfigureFlowAnalysisRuleSuccess { id: string; flowAnalysisRule: FlowAnalysisRuleEntity; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface UpdateFlowAnalysisRuleRequest { payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface EnableFlowAnalysisRuleSuccess { id: string; flowAnalysisRule: FlowAnalysisRuleEntity; - postUpdateNavigation?: string[]; } export interface DisableFlowAnalysisRuleSuccess { id: string; flowAnalysisRule: FlowAnalysisRuleEntity; - postUpdateNavigation?: string[]; } export interface EnableFlowAnalysisRuleRequest { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts index 3fbbd08aa5..4c48285a43 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts @@ -33,12 +33,14 @@ export interface ConfigureControllerServiceRequest { uri: string; payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface ConfigureControllerServiceSuccess { id: string; controllerService: ControllerServiceEntity; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface DeleteControllerServiceRequest { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts index 42f1958e6e..9e470b13d6 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts @@ -81,7 +81,12 @@ export const navigateToEditService = createAction( ); export const navigateToAdvancedServiceUi = createAction( - '[Controller Services] Navigate To Advanced Service UI', + '[Management Controller Services] Navigate To Advanced Service UI', + props<{ id: string }>() +); + +export const navigateToManageComponentPolicies = createAction( + '[Management Controller Services] Navigate To Manage Component Policies', props<{ id: string }>() ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts index a41bd4f7ba..f34102a6b7 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts @@ -56,6 +56,7 @@ import { selectPropertyVerificationStatus } from '../../../../state/property-verification/property-verification.selectors'; import { VerifyPropertiesRequestContext } from '../../../../state/property-verification'; +import { BackNavigation } from '../../../../state/navigation'; @Injectable() export class ManagementControllerServicesEffects { @@ -191,7 +192,37 @@ export class ManagementControllerServicesEffects { ofType(ManagementControllerServicesActions.navigateToAdvancedServiceUi), map((action) => action.id), tap((id) => { - this.router.navigate(['/settings', 'management-controller-services', id, 'advanced']); + const routeBoundary: string[] = ['/settings', 'management-controller-services', id, 'advanced']; + this.router.navigate([...routeBoundary], { + state: { + backNavigation: { + route: ['/settings', 'management-controller-services', id], + routeBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + }) + ), + { dispatch: false } + ); + + navigateToManageComponentPolicies$ = createEffect( + () => + this.actions$.pipe( + ofType(ManagementControllerServicesActions.navigateToManageComponentPolicies), + map((action) => action.id), + tap((id) => { + const routeBoundary: string[] = ['/access-policies']; + this.router.navigate([...routeBoundary, 'read', 'component', 'controller-services', id], { + state: { + backNavigation: { + route: ['/settings', 'management-controller-services', id], + routeBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -263,7 +294,7 @@ export class ManagementControllerServicesEffects { selectPropertyVerificationStatus ); - const goTo = (commands: string[], destination: string): void => { + const goTo = (commands: string[], destination: string, commandBoundary?: string[]): void => { if (editDialogReference.componentInstance.editControllerServiceForm.dirty) { const saveChangesDialogReference = this.dialog.open(YesNoDialog, { ...SMALL_DIALOG, @@ -274,20 +305,50 @@ export class ManagementControllerServicesEffects { }); saveChangesDialogReference.componentInstance.yes.pipe(take(1)).subscribe(() => { - editDialogReference.componentInstance.submitForm(commands); + editDialogReference.componentInstance.submitForm(commands, commandBoundary); }); saveChangesDialogReference.componentInstance.no.pipe(take(1)).subscribe(() => { - this.router.navigate(commands); + if (commandBoundary) { + this.router.navigate(commands, { + state: { + backNavigation: { + route: [ + '/settings', + 'management-controller-services', + serviceId, + 'edit' + ], + routeBoundary: commandBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + } else { + this.router.navigate(commands); + } }); } else { - this.router.navigate(commands); + if (commandBoundary) { + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'management-controller-services', serviceId, 'edit'], + routeBoundary: commandBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + } else { + this.router.navigate(commands); + } } }; editDialogReference.componentInstance.goToService = (serviceId: string) => { - const commands: string[] = ['/settings', 'management-controller-services', serviceId]; - goTo(commands, 'Controller Service'); + const commandBoundary: string[] = ['/settings', 'management-controller-services']; + const commands: string[] = [...commandBoundary, serviceId]; + goTo(commands, 'Controller Service', commandBoundary); }; editDialogReference.componentInstance.goToReferencingComponent = ( @@ -322,7 +383,9 @@ export class ManagementControllerServicesEffects { id: request.controllerService.id, uri: request.controllerService.uri, payload: updateControllerServiceRequest.payload, - postUpdateNavigation: updateControllerServiceRequest.postUpdateNavigation + postUpdateNavigation: updateControllerServiceRequest.postUpdateNavigation, + postUpdateNavigationBoundary: + updateControllerServiceRequest.postUpdateNavigationBoundary } }) ); @@ -358,7 +421,8 @@ export class ManagementControllerServicesEffects { response: { id: request.id, controllerService: response, - postUpdateNavigation: request.postUpdateNavigation + postUpdateNavigation: request.postUpdateNavigation, + postUpdateNavigationBoundary: request.postUpdateNavigationBoundary } }) ), @@ -401,7 +465,19 @@ export class ManagementControllerServicesEffects { map((action) => action.response), tap((response) => { if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); + if (response.postUpdateNavigationBoundary) { + this.router.navigate(response.postUpdateNavigation, { + state: { + backNavigation: { + route: ['/settings', 'management-controller-services', response.id, 'edit'], + routeBoundary: response.postUpdateNavigationBoundary, + context: 'Controller Service' + } as BackNavigation + } + }); + } else { + this.router.navigate(response.postUpdateNavigation); + } } else { this.dialog.closeAll(); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/index.ts index 41504a6543..f8bdceefa7 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/index.ts @@ -167,17 +167,20 @@ export interface ConfigureParameterProviderRequest { uri: string; payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface ConfigureParameterProviderSuccess { id: string; parameterProvider: ParameterProviderEntity; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface UpdateParameterProviderRequest { payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface FetchParameterProviderParametersRequest { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.actions.ts index 7c123eca33..80faf24305 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.actions.ts @@ -92,6 +92,11 @@ export const navigateToAdvancedParameterProviderUi = createAction( props<{ id: string }>() ); +export const navigateToManageAccessPolicies = createAction( + `${PARAMETER_PROVIDERS_PREFIX} Navigate To Manage Access Policies`, + props<{ id: string }>() +); + export const navigateToFetchParameterProvider = createAction( `${PARAMETER_PROVIDERS_PREFIX} Navigate To Fetch Parameter Provider`, props<{ id: string }>() diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts index c87b5bae21..1e40c8f72c 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts @@ -66,6 +66,7 @@ import { selectPropertyVerificationStatus } from '../../../../state/property-verification/property-verification.selectors'; import { VerifyPropertiesRequestContext } from '../../../../state/property-verification'; +import { BackNavigation } from '../../../../state/navigation'; @Injectable() export class ParameterProvidersEffects { @@ -257,7 +258,37 @@ export class ParameterProvidersEffects { ofType(ParameterProviderActions.navigateToAdvancedParameterProviderUi), map((action) => action.id), tap((id) => { - this.router.navigate(['settings', 'parameter-providers', id, 'advanced']); + const routeBoundary: string[] = ['/settings', 'parameter-providers', id, 'advanced']; + this.router.navigate([...routeBoundary], { + state: { + backNavigation: { + route: ['/settings', 'parameter-providers', id], + routeBoundary, + context: 'Parameter Provider' + } as BackNavigation + } + }); + }) + ), + { dispatch: false } + ); + + navigateToManageAccessPolicies$ = createEffect( + () => + this.actions$.pipe( + ofType(ParameterProviderActions.navigateToManageAccessPolicies), + map((action) => action.id), + tap((id) => { + const routeBoundary: string[] = ['/access-policies']; + this.router.navigate([...routeBoundary, 'read', 'component', 'parameter-providers', id], { + state: { + backNavigation: { + route: ['/settings', 'parameter-providers', id], + routeBoundary, + context: 'Parameter Provider' + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -333,7 +364,7 @@ export class ParameterProvidersEffects { selectPropertyVerificationStatus ); - const goTo = (commands: string[], destination: string) => { + const goTo = (commands: string[], destination: string, commandBoundary: string[]) => { // confirm navigating away while changes are unsaved if (editDialogReference.componentInstance.editParameterProviderForm.dirty) { const promptSaveDialogRef = this.dialog.open(YesNoDialog, { @@ -345,25 +376,43 @@ export class ParameterProvidersEffects { }); promptSaveDialogRef.componentInstance.yes.pipe(take(1)).subscribe(() => { - editDialogReference.componentInstance.submitForm(commands); + editDialogReference.componentInstance.submitForm(commands, commandBoundary); }); promptSaveDialogRef.componentInstance.no.pipe(take(1)).subscribe(() => { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'parameter-providers', id, 'edit'], + routeBoundary: commandBoundary, + context: 'Parameter Provider' + } as BackNavigation + } + }); }); } else { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'parameter-providers', id, 'edit'], + routeBoundary: commandBoundary, + context: 'Parameter Provider' + } as BackNavigation + } + }); } }; editDialogReference.componentInstance.goToReferencingParameterContext = (id: string) => { - const commands: string[] = ['parameter-contexts', id]; - goTo(commands, 'Parameter Context'); + const commandBoundary: string[] = ['/parameter-contexts']; + const commands: string[] = [...commandBoundary, id]; + goTo(commands, 'Parameter Context', commandBoundary); }; editDialogReference.componentInstance.goToService = (serviceId: string) => { - const commands: string[] = ['/settings', 'management-controller-services', serviceId]; - goTo(commands, 'Controller Service'); + const commandBoundary: string[] = ['/settings', 'management-controller-services']; + const commands: string[] = [...commandBoundary, serviceId]; + goTo(commands, 'Controller Service', commandBoundary); }; editDialogReference.componentInstance.createNewProperty = @@ -385,7 +434,8 @@ export class ParameterProvidersEffects { id: request.parameterProvider.id, uri: request.parameterProvider.uri, payload: updateRequest.payload, - postUpdateNavigation: updateRequest.postUpdateNavigation + postUpdateNavigation: updateRequest.postUpdateNavigation, + postUpdateNavigationBoundary: updateRequest.postUpdateNavigationBoundary } }) ); @@ -421,7 +471,8 @@ export class ParameterProvidersEffects { response: { id: request.id, parameterProvider: response, - postUpdateNavigation: request.postUpdateNavigation + postUpdateNavigation: request.postUpdateNavigation, + postUpdateNavigationBoundary: request.postUpdateNavigationBoundary } }) ), @@ -448,7 +499,19 @@ export class ParameterProvidersEffects { map((action) => action.response), tap((response) => { if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); + if (response.postUpdateNavigationBoundary) { + this.router.navigate(response.postUpdateNavigation, { + state: { + backNavigation: { + route: ['/settings', 'parameter-providers', response.id, 'edit'], + routeBoundary: response.postUpdateNavigationBoundary, + context: 'Parameter Provider' + } as BackNavigation + } + }); + } else { + this.router.navigate(response.postUpdateNavigation); + } } else { this.dialog.closeAll(); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/index.ts index d4d7473855..73d8ce0c0d 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/index.ts @@ -51,12 +51,14 @@ export interface EditRegistryClientRequest { uri: string; payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface EditRegistryClientRequestSuccess { id: string; registryClient: RegistryClientEntity; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface DeleteRegistryClientRequest { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts index caa9f448b3..df859ebce6 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts @@ -37,6 +37,7 @@ import * as ErrorActions from '../../../../state/error/error.actions'; import { ErrorHelper } from '../../../../service/error-helper.service'; import { HttpErrorResponse } from '@angular/common/http'; import { LARGE_DIALOG, MEDIUM_DIALOG, SMALL_DIALOG } from '../../../../index'; +import { BackNavigation } from '../../../../state/navigation'; @Injectable() export class RegistryClientsEffects { @@ -193,7 +194,8 @@ export class RegistryClientsEffects { this.propertyTableHelperService.createNewProperty(registryClientId, this.registryClientService); editDialogReference.componentInstance.goToService = (serviceId: string) => { - const commands: string[] = ['/settings', 'management-controller-services', serviceId]; + const commandBoundary: string[] = ['/settings', 'management-controller-services']; + const commands: string[] = [...commandBoundary, serviceId]; if (editDialogReference.componentInstance.editRegistryClientForm.dirty) { const saveChangesDialogReference = this.dialog.open(YesNoDialog, { @@ -205,14 +207,30 @@ export class RegistryClientsEffects { }); saveChangesDialogReference.componentInstance.yes.pipe(take(1)).subscribe(() => { - editDialogReference.componentInstance.submitForm(commands); + editDialogReference.componentInstance.submitForm(commands, commandBoundary); }); saveChangesDialogReference.componentInstance.no.pipe(take(1)).subscribe(() => { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'registry-clients', registryClientId, 'edit'], + routeBoundary: commandBoundary, + context: 'Registry Client' + } as BackNavigation + } + }); }); } else { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'registry-clients', registryClientId, 'edit'], + routeBoundary: commandBoundary, + context: 'Registry Client' + } as BackNavigation + } + }); } }; @@ -262,7 +280,8 @@ export class RegistryClientsEffects { response: { id: request.id, registryClient: response, - postUpdateNavigation: request.postUpdateNavigation + postUpdateNavigation: request.postUpdateNavigation, + postUpdateNavigationBoundary: request.postUpdateNavigationBoundary } }) ), @@ -285,7 +304,19 @@ export class RegistryClientsEffects { map((action) => action.response), tap((response) => { if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); + if (response.postUpdateNavigationBoundary) { + this.router.navigate(response.postUpdateNavigation, { + state: { + backNavigation: { + route: ['/settings', 'registry-clients', response.id, 'edit'], + routeBoundary: response.postUpdateNavigationBoundary, + context: 'Registry Client' + } as BackNavigation + } + }); + } else { + this.router.navigate(response.postUpdateNavigation); + } } else { this.dialog.closeAll(); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/index.ts index 5371471e44..33abaa4c99 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/index.ts @@ -50,24 +50,20 @@ export interface ConfigureReportingTaskRequest { uri: string; payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface ConfigureReportingTaskSuccess { id: string; reportingTask: ReportingTaskEntity; postUpdateNavigation?: string[]; -} - -export interface ConfigureReportingTaskRequest { - id: string; - uri: string; - payload: any; - postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface UpdateReportingTaskRequest { payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface EditReportingTaskDialogRequest { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.actions.ts index 88cb5c7493..746baf6136 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.actions.ts @@ -89,6 +89,11 @@ export const navigateToAdvancedReportingTaskUi = createAction( props<{ id: string }>() ); +export const navigateToManageAccessPolicies = createAction( + '[Reporting Tasks] Navigate To Manage Access Policies', + props<{ id: string }>() +); + export const startReportingTask = createAction( '[Reporting Tasks] Start Reporting Task', props<{ request: StartReportingTaskRequest }>() diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts index 2568798665..e73369f4e4 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts @@ -29,9 +29,9 @@ import { ReportingTaskService } from '../../service/reporting-task.service'; import { CreateReportingTask } from '../../ui/reporting-tasks/create-reporting-task/create-reporting-task.component'; import { Router } from '@angular/router'; import { selectSaving } from '../management-controller-services/management-controller-services.selectors'; -import { OpenChangeComponentVersionDialogRequest, UpdateControllerServiceRequest } from '../../../../state/shared'; +import { OpenChangeComponentVersionDialogRequest } from '../../../../state/shared'; import { EditReportingTask } from '../../ui/reporting-tasks/edit-reporting-task/edit-reporting-task.component'; -import { CreateReportingTaskSuccess, EditReportingTaskDialogRequest } from './index'; +import { CreateReportingTaskSuccess, EditReportingTaskDialogRequest, UpdateReportingTaskRequest } from './index'; import { ManagementControllerServiceService } from '../../service/management-controller-service.service'; import { PropertyTableHelperService } from '../../../../service/property-table-helper.service'; import * as ErrorActions from '../../../../state/error/error.actions'; @@ -50,6 +50,7 @@ import { selectPropertyVerificationStatus } from '../../../../state/property-verification/property-verification.selectors'; import { VerifyPropertiesRequestContext } from '../../../../state/property-verification'; +import { BackNavigation } from '../../../../state/navigation'; @Injectable() export class ReportingTasksEffects { @@ -234,7 +235,37 @@ export class ReportingTasksEffects { ofType(ReportingTaskActions.navigateToAdvancedReportingTaskUi), map((action) => action.id), tap((id) => { - this.router.navigate(['/settings', 'reporting-tasks', id, 'advanced']); + const routeBoundary: string[] = ['/settings', 'reporting-tasks', id, 'advanced']; + this.router.navigate([...routeBoundary], { + state: { + backNavigation: { + route: ['/settings', 'reporting-tasks', id], + routeBoundary, + context: 'Reporting Task' + } as BackNavigation + } + }); + }) + ), + { dispatch: false } + ); + + navigateToManageAccessPolicies$ = createEffect( + () => + this.actions$.pipe( + ofType(ReportingTaskActions.navigateToManageAccessPolicies), + map((action) => action.id), + tap((id) => { + const routeBoundary = ['/access-policies']; + this.router.navigate([...routeBoundary, 'read', 'component', 'reporting-tasks', id], { + state: { + backNavigation: { + route: ['/settings', 'reporting-tasks', id], + routeBoundary, + context: 'Reporting Task' + } as BackNavigation + } + }); }) ), { dispatch: false } @@ -302,7 +333,7 @@ export class ReportingTasksEffects { selectPropertyVerificationStatus ); - const goTo = (commands: string[], destination: string): void => { + const goTo = (commands: string[], destination: string, commandBoundary: string[]): void => { if (editDialogReference.componentInstance.editReportingTaskForm.dirty) { const saveChangesDialogReference = this.dialog.open(YesNoDialog, { ...SMALL_DIALOG, @@ -313,20 +344,37 @@ export class ReportingTasksEffects { }); saveChangesDialogReference.componentInstance.yes.pipe(take(1)).subscribe(() => { - editDialogReference.componentInstance.submitForm(commands); + editDialogReference.componentInstance.submitForm(commands, commandBoundary); }); saveChangesDialogReference.componentInstance.no.pipe(take(1)).subscribe(() => { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'reporting-tasks', taskId, 'edit'], + routeBoundary: commandBoundary, + context: 'Reporting Task' + } as BackNavigation + } + }); }); } else { - this.router.navigate(commands); + this.router.navigate(commands, { + state: { + backNavigation: { + route: ['/settings', 'reporting-tasks', taskId, 'edit'], + routeBoundary: commandBoundary, + context: 'Reporting Task' + } as BackNavigation + } + }); } }; editDialogReference.componentInstance.goToService = (serviceId: string) => { - const commands: string[] = ['/settings', 'management-controller-services', serviceId]; - goTo(commands, 'Controller Service'); + const commandBoundary: string[] = ['/settings', 'management-controller-services']; + const commands: string[] = [...commandBoundary, serviceId]; + goTo(commands, 'Controller Service', commandBoundary); }; editDialogReference.componentInstance.createNewService = @@ -338,14 +386,16 @@ export class ReportingTasksEffects { editDialogReference.componentInstance.editReportingTask .pipe(takeUntil(editDialogReference.afterClosed())) - .subscribe((updateControllerServiceRequest: UpdateControllerServiceRequest) => { + .subscribe((updateReportingTaskRequest: UpdateReportingTaskRequest) => { this.store.dispatch( ReportingTaskActions.configureReportingTask({ request: { id: request.reportingTask.id, uri: request.reportingTask.uri, - payload: updateControllerServiceRequest.payload, - postUpdateNavigation: updateControllerServiceRequest.postUpdateNavigation + payload: updateReportingTaskRequest.payload, + postUpdateNavigation: updateReportingTaskRequest.postUpdateNavigation, + postUpdateNavigationBoundary: + updateReportingTaskRequest.postUpdateNavigationBoundary } }) ); @@ -381,7 +431,8 @@ export class ReportingTasksEffects { response: { id: request.id, reportingTask: response, - postUpdateNavigation: request.postUpdateNavigation + postUpdateNavigation: request.postUpdateNavigation, + postUpdateNavigationBoundary: request.postUpdateNavigationBoundary } }) ), @@ -404,7 +455,19 @@ export class ReportingTasksEffects { map((action) => action.response), tap((response) => { if (response.postUpdateNavigation) { - this.router.navigate(response.postUpdateNavigation); + if (response.postUpdateNavigationBoundary) { + this.router.navigate(response.postUpdateNavigation, { + state: { + backNavigation: { + route: ['/settings', 'reporting-tasks', response.id, 'edit'], + routeBoundary: response.postUpdateNavigationBoundary, + context: 'Reporting Task' + } as BackNavigation + } + }); + } else { + this.router.navigate(response.postUpdateNavigation); + } } else { this.dialog.closeAll(); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/edit-flow-analysis-rule/edit-flow-analysis-rule.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/edit-flow-analysis-rule/edit-flow-analysis-rule.component.ts index 4c79199568..f563f11b71 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/edit-flow-analysis-rule/edit-flow-analysis-rule.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/edit-flow-analysis-rule/edit-flow-analysis-rule.component.ts @@ -140,7 +140,7 @@ export class EditFlowAnalysisRule extends TabbedDialog { return this.nifiCommon.formatBundle(entity.component.bundle); } - submitForm(postUpdateNavigation?: string[]) { + submitForm(postUpdateNavigation?: string[], postUpdateNavigationBoundary?: string[]) { const payload: any = { revision: this.client.getRevision(this.request.flowAnalysisRule), disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), @@ -164,7 +164,8 @@ export class EditFlowAnalysisRule extends TabbedDialog { this.editFlowAnalysisRule.next({ payload, - postUpdateNavigation + postUpdateNavigation, + postUpdateNavigationBoundary }); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/flow-analysis-rules.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/flow-analysis-rules.component.ts index 38e97d6ff6..dfdb4c8431 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/flow-analysis-rules.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/flow-analysis-rules/flow-analysis-rules.component.ts @@ -111,11 +111,18 @@ export class FlowAnalysisRules implements OnInit, OnDestroy { viewFlowAnalysisRuleDocumentation(entity: FlowAnalysisRuleEntity): void { this.store.dispatch( navigateToComponentDocumentation({ - params: { - select: entity.component.type, - group: entity.component.bundle.group, - artifact: entity.component.bundle.artifact, - version: entity.component.bundle.version + request: { + backNavigation: { + route: ['/settings', 'flow-analysis-rules', entity.id], + routeBoundary: ['/documentation'], + context: 'Flow Analysis Rule' + }, + parameters: { + select: entity.component.type, + group: entity.component.bundle.group, + artifact: entity.component.bundle.artifact, + version: entity.component.bundle.version + } } }) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html index b3a177d0c7..431f03e206 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html @@ -42,6 +42,7 @@ (selectControllerService)="selectControllerService($event)" (viewControllerServiceDocumentation)="viewControllerServiceDocumentation($event)" (configureControllerService)="configureControllerService($event)" + (manageAccessPolicies)="navigateToManageComponentPolicies($event)" (openAdvancedUi)="openAdvancedUi($event)" (enableControllerService)="enableControllerService($event)" (disableControllerService)="disableControllerService($event)" diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts index c5de03c853..a79d364b46 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts @@ -28,6 +28,7 @@ import { loadManagementControllerServices, navigateToAdvancedServiceUi, navigateToEditService, + navigateToManageComponentPolicies, openChangeMgtControllerServiceVersionDialog, openConfigureControllerServiceDialog, openDisableControllerServiceDialog, @@ -114,11 +115,18 @@ export class ManagementControllerServices implements OnInit, OnDestroy { viewControllerServiceDocumentation(entity: ControllerServiceEntity): void { this.store.dispatch( navigateToComponentDocumentation({ - params: { - select: entity.component.type, - group: entity.component.bundle.group, - artifact: entity.component.bundle.artifact, - version: entity.component.bundle.version + request: { + backNavigation: { + route: ['/settings', 'management-controller-services', entity.id], + routeBoundary: ['/documentation'], + context: 'Controller Service' + }, + parameters: { + select: entity.component.type, + group: entity.component.bundle.group, + artifact: entity.component.bundle.artifact, + version: entity.component.bundle.version + } } }) ); @@ -132,6 +140,14 @@ export class ManagementControllerServices implements OnInit, OnDestroy { ); } + navigateToManageComponentPolicies(entity: ControllerServiceEntity): void { + this.store.dispatch( + navigateToManageComponentPolicies({ + id: entity.id + }) + ); + } + openAdvancedUi(entity: ControllerServiceEntity): void { this.store.dispatch( navigateToAdvancedServiceUi({ diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.ts index 189522726c..7b89543776 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.ts @@ -129,7 +129,7 @@ export class EditParameterProvider extends TabbedDialog { return this.nifiCommon.formatBundle(entity.component.bundle); } - submitForm(postUpdateNavigation?: string[]) { + submitForm(postUpdateNavigation?: string[], postUpdateNavigationBoundary?: string[]) { const payload: any = { revision: this.client.getRevision(this.request.parameterProvider), disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), @@ -151,7 +151,8 @@ export class EditParameterProvider extends TabbedDialog { this.editParameterProvider.next({ payload, - postUpdateNavigation + postUpdateNavigation, + postUpdateNavigationBoundary }); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.html index f142cc9613..1d8c8546a5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.html @@ -134,10 +134,7 @@ } @if (canManageAccessPolicies()) { - diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.ts index 6a02aab588..31ede01de8 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.ts @@ -212,7 +212,7 @@ export class ParameterProvidersTable { this.deleteParameterProvider.next(entity); } - getPolicyLink(entity: ParameterProviderEntity): string[] { - return ['/access-policies', 'read', 'component', 'parameter-providers', entity.id]; + manageAccessPoliciesClicked(entity: ParameterProviderEntity) { + this.manageAccessPolicies.next(entity); } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html index 3350d21c42..aac9cbe6ba 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html @@ -43,6 +43,7 @@ (deleteParameterProvider)="deleteParameterProvider($event)" (configureParameterProvider)="openConfigureParameterProviderDialog($event)" (openAdvancedUi)="openAdvancedUi($event)" + (manageAccessPolicies)="navigateToManageAccessPolicies($event)" (fetchParameterProvider)="fetchParameterProviderParameters($event)" (viewParameterProviderDocumentation)="viewParameterProviderDocumentation($event)" (selectParameterProvider)="selectParameterProvider($event)"> diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts index 37f71bed8a..af86fce04c 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts @@ -137,14 +137,29 @@ export class ParameterProviders implements OnInit, OnDestroy { ); } + navigateToManageAccessPolicies(parameterProvider: ParameterProviderEntity) { + this.store.dispatch( + ParameterProviderActions.navigateToManageAccessPolicies({ + id: parameterProvider.id + }) + ); + } + viewParameterProviderDocumentation(parameterProvider: ParameterProviderEntity): void { this.store.dispatch( navigateToComponentDocumentation({ - params: { - select: parameterProvider.component.type, - group: parameterProvider.component.bundle.group, - artifact: parameterProvider.component.bundle.artifact, - version: parameterProvider.component.bundle.version + request: { + backNavigation: { + route: ['/settings', 'parameter-providers', parameterProvider.id], + routeBoundary: ['/documentation'], + context: 'Parameter Provider' + }, + parameters: { + select: parameterProvider.component.type, + group: parameterProvider.component.bundle.group, + artifact: parameterProvider.component.bundle.artifact, + version: parameterProvider.component.bundle.version + } } }) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/registry-clients/edit-registry-client/edit-registry-client.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/registry-clients/edit-registry-client/edit-registry-client.component.ts index 042cc4bae1..f922ec1c24 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/registry-clients/edit-registry-client/edit-registry-client.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/registry-clients/edit-registry-client/edit-registry-client.component.ts @@ -105,7 +105,7 @@ export class EditRegistryClient extends TabbedDialog { return this.nifiCommon.formatType(entity.component); } - submitForm(postUpdateNavigation?: string[]) { + submitForm(postUpdateNavigation?: string[], postUpdateNavigationBoundary?: string[]) { const payload: any = { revision: this.client.getRevision(this.request.registryClient), disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), @@ -132,7 +132,8 @@ export class EditRegistryClient extends TabbedDialog { id: this.request.registryClient.id, uri: this.request.registryClient.uri, payload, - postUpdateNavigation + postUpdateNavigation, + postUpdateNavigationBoundary }); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/edit-reporting-task/edit-reporting-task.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/edit-reporting-task/edit-reporting-task.component.ts index a27f72d7e2..5192cd5cbd 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/edit-reporting-task/edit-reporting-task.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/edit-reporting-task/edit-reporting-task.component.ts @@ -179,7 +179,7 @@ export class EditReportingTask extends TabbedDialog { return this.nifiCommon.formatBundle(entity.component.bundle); } - submitForm(postUpdateNavigation?: string[]) { + submitForm(postUpdateNavigation?: string[], postUpdateNavigationBoundary?: string[]) { const payload: any = { revision: this.client.getRevision(this.request.reportingTask), disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), @@ -204,7 +204,8 @@ export class EditReportingTask extends TabbedDialog { this.editReportingTask.next({ payload, - postUpdateNavigation + postUpdateNavigation, + postUpdateNavigationBoundary }); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.html index bdd6d687c4..3a074603a2 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.html @@ -160,10 +160,7 @@ } @if (canManageAccessPolicies()) { - diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts index 870a072bb1..7a179142a6 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts @@ -55,6 +55,7 @@ export class ReportingTaskTable { @Output() startReportingTask: EventEmitter = new EventEmitter(); @Output() configureReportingTask: EventEmitter = new EventEmitter(); @Output() openAdvancedUi: EventEmitter = new EventEmitter(); + @Output() manageAccessPolicies: EventEmitter = new EventEmitter(); @Output() viewStateReportingTask: EventEmitter = new EventEmitter(); @Output() stopReportingTask: EventEmitter = new EventEmitter(); @Output() changeReportingTaskVersion: EventEmitter = new EventEmitter(); @@ -253,8 +254,8 @@ export class ReportingTaskTable { return this.flowConfiguration.supportsManagedAuthorizer && this.currentUser.tenantsPermissions.canRead; } - getPolicyLink(entity: ReportingTaskEntity): string[] { - return ['/access-policies', 'read', 'component', 'reporting-tasks', entity.id]; + managedAccessPoliciesClicked(entity: ReportingTaskEntity): void { + this.manageAccessPolicies.next(entity); } select(entity: ReportingTaskEntity): void { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.html index f4a148e7b6..ceec68bea8 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.html @@ -38,6 +38,7 @@ [flowConfiguration]="(flowConfiguration$ | async)!" (configureReportingTask)="configureReportingTask($event)" (openAdvancedUi)="openAdvancedUi($event)" + (manageAccessPolicies)="navigateToManageAccessPolicies($event)" (viewStateReportingTask)="viewStateReportingTask($event)" (selectReportingTask)="selectReportingTask($event)" (viewReportingTaskDocumentation)="viewReportingTaskDocumentation($event)" diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.ts index b8ceed7ad2..041675863f 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-tasks.component.ts @@ -30,6 +30,7 @@ import { loadReportingTasks, navigateToAdvancedReportingTaskUi, navigateToEditReportingTask, + navigateToManageAccessPolicies, openChangeReportingTaskVersionDialog, openConfigureReportingTaskDialog, openNewReportingTaskDialog, @@ -119,14 +120,29 @@ export class ReportingTasks implements OnInit, OnDestroy { ); } + navigateToManageAccessPolicies(entity: ReportingTaskEntity): void { + this.store.dispatch( + navigateToManageAccessPolicies({ + id: entity.id + }) + ); + } + viewReportingTaskDocumentation(entity: ReportingTaskEntity): void { this.store.dispatch( navigateToComponentDocumentation({ - params: { - select: entity.component.type, - group: entity.component.bundle.group, - artifact: entity.component.bundle.artifact, - version: entity.component.bundle.version + request: { + backNavigation: { + route: ['/settings', 'reporting-tasks', entity.id], + routeBoundary: ['/documentation'], + context: 'Reporting Task' + }, + parameters: { + select: entity.component.type, + group: entity.component.bundle.group, + artifact: entity.component.bundle.artifact, + version: entity.component.bundle.version + } } }) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.actions.ts index 4c3389d027..742dbb53d6 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.actions.ts @@ -16,12 +16,12 @@ */ import { createAction, props } from '@ngrx/store'; -import { DocumentationParameters } from './index'; +import { DocumentationRequest } from './index'; export const navigateToComponentDocumentation = createAction( '[Documentation] Navigate To Component Documentation', props<{ - params: DocumentationParameters; + request: DocumentationRequest; }>() ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.effects.ts index 945f8a0edd..2335a5d4fb 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.effects.ts @@ -18,7 +18,7 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import * as DocumentationActions from './documentation.actions'; -import { tap } from 'rxjs'; +import { map, tap } from 'rxjs'; import { Router } from '@angular/router'; @Injectable() @@ -32,8 +32,13 @@ export class DocumentationEffects { () => this.actions$.pipe( ofType(DocumentationActions.navigateToComponentDocumentation), - tap(() => { - this.router.navigate(['/documentation']); + map((action) => action.request), + tap((request) => { + this.router.navigate(['/documentation'], { + state: { + backNavigation: request.backNavigation + } + }); }) ), { dispatch: false } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.reducer.ts index 9b3e379fef..db16d153ad 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/documentation.reducer.ts @@ -25,9 +25,9 @@ export const initialState: DocumentationState = { export const documentationReducer = createReducer( initialState, - on(navigateToComponentDocumentation, (state, { params }) => ({ + on(navigateToComponentDocumentation, (state, { request }) => ({ ...state, - documentationParameters: params + documentationParameters: request.parameters })), on(clearDocumentationParameters, (state) => ({ ...state, diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/index.ts index cd3d311d41..4458515be3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/documentation/index.ts @@ -15,8 +15,15 @@ * limitations under the License. */ +import { BackNavigation } from '../navigation'; + export const documentationFeatureKey = 'documentation'; +export interface DocumentationRequest { + backNavigation?: BackNavigation; + parameters: DocumentationParameters; +} + export interface DocumentationParameters { [key: string]: string; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/index.ts index d0ac31c01a..3ed20f96e0 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/index.ts @@ -43,6 +43,8 @@ import { loginConfigurationFeatureKey, LoginConfigurationState } from './login-c import { loginConfigurationReducer } from './login-configuration/login-configuration.reducer'; import { propertyVerificationFeatureKey, PropertyVerificationState } from './property-verification'; import { propertyVerificationReducer } from './property-verification/property-verification.reducer'; +import { navigationFeatureKey, NavigationState } from './navigation'; +import { navigationReducer } from './navigation/navigation.reducer'; export interface NiFiState { [DEFAULT_ROUTER_FEATURENAME]: RouterReducerState; @@ -50,6 +52,7 @@ export interface NiFiState { [currentUserFeatureKey]: CurrentUserState; [extensionTypesFeatureKey]: ExtensionTypesState; [aboutFeatureKey]: AboutState; + [navigationFeatureKey]: NavigationState; [flowConfigurationFeatureKey]: FlowConfigurationState; [loginConfigurationFeatureKey]: LoginConfigurationState; [statusHistoryFeatureKey]: StatusHistoryState; @@ -67,6 +70,7 @@ export const rootReducers: ActionReducerMap = { [currentUserFeatureKey]: currentUserReducer, [extensionTypesFeatureKey]: extensionTypesReducer, [aboutFeatureKey]: aboutReducer, + [navigationFeatureKey]: navigationReducer, [flowConfigurationFeatureKey]: flowConfigurationReducer, [loginConfigurationFeatureKey]: loginConfigurationReducer, [statusHistoryFeatureKey]: statusHistoryReducer, diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/index.ts new file mode 100644 index 0000000000..3739106269 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/index.ts @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const navigationFeatureKey = 'navigation'; + +export interface BackNavigation { + route: string[]; + routeBoundary: string[]; + context: string; +} + +export interface NavigationState { + backNavigations: BackNavigation[]; +} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.actions.ts new file mode 100644 index 0000000000..065d3766e2 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.actions.ts @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createAction, props } from '@ngrx/store'; +import { BackNavigation } from './index'; + +export const pushBackNavigation = createAction( + '[Navigation] Push Back Navigation', + props<{ backNavigation: BackNavigation }>() +); + +export const popBackNavigation = createAction('[Navigation] Pop Back Navigation', props<{ url: string }>()); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.reducer.ts new file mode 100644 index 0000000000..ec982fa2b9 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.reducer.ts @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createReducer, on } from '@ngrx/store'; +import { NavigationState } from './index'; +import { popBackNavigation, pushBackNavigation } from './navigation.actions'; +import { produce } from 'immer'; + +export const initialState: NavigationState = { + backNavigations: [] +}; + +export const navigationReducer = createReducer( + initialState, + on(pushBackNavigation, (state, { backNavigation }) => { + return produce(state, (draftState) => { + if (draftState.backNavigations.length > 0) { + const currentBackNavigation = draftState.backNavigations[draftState.backNavigations.length - 1]; + + // don't push multiple back navigations going to the same route + if (routesNotEqual(currentBackNavigation.route, backNavigation.route)) { + draftState.backNavigations.push(backNavigation); + } + } else { + draftState.backNavigations.push(backNavigation); + } + }); + }), + on(popBackNavigation, (state, { url }) => { + return produce(state, (draftState) => { + // pop any back navigation that is outside the bounds of the current url + while (draftState.backNavigations.length > 0) { + const lastBackNavigation = draftState.backNavigations[draftState.backNavigations.length - 1]; + if (!url.startsWith(lastBackNavigation.routeBoundary.join('/'))) { + draftState.backNavigations.pop(); + } else { + break; + } + } + }); + }) +); + +function routesNotEqual(route1: string[], route2: string[]) { + if (route1.length !== route2.length) { + return true; + } + + for (let i = 0; i < route1.length; i++) { + if (route1[i] !== route2[i]) { + return true; + } + } + + return false; +} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.selectors.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.selectors.ts new file mode 100644 index 0000000000..5b25996f98 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/navigation/navigation.selectors.ts @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createFeatureSelector, createSelector } from '@ngrx/store'; +import { navigationFeatureKey, NavigationState } from './index'; + +export const selectNavigationState = createFeatureSelector(navigationFeatureKey); + +export const selectBackNavigation = createSelector(selectNavigationState, (state: NavigationState) => { + if (state.backNavigations.length > 0) { + return state.backNavigations[state.backNavigations.length - 1]; + } + + return null; +}); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts index cf9c0109a0..0e87a45e22 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts @@ -135,6 +135,7 @@ export interface EditControllerServiceDialogRequest { export interface UpdateControllerServiceRequest { payload: any; postUpdateNavigation?: string[]; + postUpdateNavigationBoundary?: string[]; } export interface SetEnableControllerServiceDialogRequest { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/advanced-ui/advanced-ui.component.spec.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/advanced-ui/advanced-ui.component.spec.ts index 8291b351ab..69458d6c9a 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/advanced-ui/advanced-ui.component.spec.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/advanced-ui/advanced-ui.component.spec.ts @@ -21,16 +21,18 @@ import { AdvancedUi } from './advanced-ui.component'; import { RouterTestingModule } from '@angular/router/testing'; import { Component } from '@angular/core'; import { provideMockStore } from '@ngrx/store/testing'; -import { initialState } from '../../../state/documentation/documentation.reducer'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { selectCurrentUser } from '../../../state/current-user/current-user.selectors'; import * as fromUser from '../../../state/current-user/current-user.reducer'; +import * as fromNavigation from '../../../state/navigation/navigation.reducer'; import { selectClusterSummary } from '../../../state/cluster-summary/cluster-summary.selectors'; import * as fromClusterSummary from '../../../state/cluster-summary/cluster-summary.reducer'; import { selectFlowConfiguration } from '../../../state/flow-configuration/flow-configuration.selectors'; import * as fromFlowConfiguration from '../../../state/flow-configuration/flow-configuration.reducer'; import { selectLoginConfiguration } from '../../../state/login-configuration/login-configuration.selectors'; import * as fromLoginConfiguration from '../../../state/login-configuration/login-configuration.reducer'; +import { currentUserFeatureKey } from '../../../state/current-user'; +import { navigationFeatureKey } from '../../../state/navigation'; describe('AdvancedUi', () => { let component: AdvancedUi; @@ -48,7 +50,10 @@ describe('AdvancedUi', () => { imports: [AdvancedUi, HttpClientTestingModule, RouterTestingModule, MockNavigation], providers: [ provideMockStore({ - initialState, + initialState: { + [currentUserFeatureKey]: fromUser.initialState, + [navigationFeatureKey]: fromNavigation.initialState + }, selectors: [ { selector: selectCurrentUser, diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/context-menu/context-menu.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/context-menu/context-menu.component.html index d7226b23ec..f8e15ee9cf 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/context-menu/context-menu.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/context-menu/context-menu.component.html @@ -28,8 +28,10 @@ @if (hasSubMenu(item)) { @if (menuComponent.menu; as subMenu) { } @@ -42,7 +44,7 @@ class="context-menu-item pl-1 pr-1 pt-2 pb-2 flex justify-between" (click)="menuItemClicked(item, $event)" cdkMenuItem> -
+
{{ item.text }}
diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.html index f154d35e5d..2e898623c3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.html @@ -167,16 +167,13 @@ } @if (canManageAccessPolicies()) { - } } @else { - diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts index b6a69c0a48..a7af8ea592 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts @@ -77,6 +77,7 @@ export class ControllerServiceTable { new EventEmitter(); @Output() configureControllerService: EventEmitter = new EventEmitter(); + @Output() manageAccessPolicies: EventEmitter = new EventEmitter(); @Output() openAdvancedUi: EventEmitter = new EventEmitter(); @Output() enableControllerService: EventEmitter = new EventEmitter(); @@ -86,6 +87,8 @@ export class ControllerServiceTable { new EventEmitter(); @Output() changeControllerServiceVersion: EventEmitter = new EventEmitter(); + @Output() goToControllerService: EventEmitter = + new EventEmitter(); protected readonly TextTip = TextTip; protected readonly BulletinsTip = BulletinsTip; @@ -191,12 +194,8 @@ export class ControllerServiceTable { return this.canRead(entity) ? this.nifiCommon.formatBundle(entity.component.bundle) : ''; } - getServiceLink(entity: ControllerServiceEntity): string[] { - if (entity.parentGroupId == null) { - return ['/settings', 'management-controller-services', entity.id]; - } else { - return ['/process-groups', entity.parentGroupId, 'controller-services', entity.id]; - } + goToControllerServiceClicked(entity: ControllerServiceEntity): void { + this.goToControllerService.next(entity); } isDisabled(entity: ControllerServiceEntity): boolean { @@ -259,6 +258,10 @@ export class ControllerServiceTable { this.deleteControllerService.next(entity); } + manageAccessPoliciesClicked(entity: ControllerServiceEntity): void { + this.manageAccessPolicies.next(entity); + } + changeVersionClicked(entity: ControllerServiceEntity) { this.changeControllerServiceVersion.next(entity); } @@ -275,10 +278,6 @@ export class ControllerServiceTable { return this.flowConfiguration.supportsManagedAuthorizer && this.currentUser.tenantsPermissions.canRead; } - getPolicyLink(entity: ControllerServiceEntity): string[] { - return ['/access-policies', 'read', 'component', 'controller-services', entity.id]; - } - select(entity: ControllerServiceEntity): void { this.selectControllerService.next(entity); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/edit-controller-service/edit-controller-service.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/edit-controller-service/edit-controller-service.component.ts index 9975a9ff6b..80ef04fb75 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/edit-controller-service/edit-controller-service.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/edit-controller-service/edit-controller-service.component.ts @@ -166,7 +166,7 @@ export class EditControllerService extends TabbedDialog { return this.nifiCommon.formatBundle(entity.component.bundle); } - submitForm(postUpdateNavigation?: string[]) { + submitForm(postUpdateNavigation?: string[], postUpdateNavigationBoundary?: string[]) { const payload: any = { revision: this.client.getRevision(this.request.controllerService), disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), @@ -188,7 +188,8 @@ export class EditControllerService extends TabbedDialog { this.editControllerService.next({ payload, - postUpdateNavigation + postUpdateNavigation, + postUpdateNavigationBoundary }); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.html index b37870f0e6..300ea6afe1 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.html @@ -15,178 +15,188 @@ ~ limitations under the License. --> - + @if (backNavigation(); as navigation) { + + } +
diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.spec.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.spec.ts index 175914c37f..3c27ca23e8 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.spec.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.spec.ts @@ -19,17 +19,19 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Navigation } from './navigation.component'; import { provideMockStore } from '@ngrx/store/testing'; -import { initialState } from '../../../state/current-user/current-user.reducer'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { selectCurrentUser } from '../../../state/current-user/current-user.selectors'; import * as fromUser from '../../../state/current-user/current-user.reducer'; +import * as fromNavigation from '../../../state/navigation/navigation.reducer'; import { selectClusterSummary } from '../../../state/cluster-summary/cluster-summary.selectors'; import * as fromClusterSummary from '../../../state/cluster-summary/cluster-summary.reducer'; import { selectFlowConfiguration } from '../../../state/flow-configuration/flow-configuration.selectors'; import * as fromFlowConfiguration from '../../../state/flow-configuration/flow-configuration.reducer'; import { selectLoginConfiguration } from '../../../state/login-configuration/login-configuration.selectors'; import * as fromLoginConfiguration from '../../../state/login-configuration/login-configuration.reducer'; +import { currentUserFeatureKey } from '../../../state/current-user'; +import { navigationFeatureKey } from '../../../state/navigation'; describe('Navigation', () => { let component: Navigation; @@ -40,7 +42,10 @@ describe('Navigation', () => { imports: [Navigation, HttpClientTestingModule, RouterTestingModule], providers: [ provideMockStore({ - initialState, + initialState: { + [currentUserFeatureKey]: fromUser.initialState, + [navigationFeatureKey]: fromNavigation.initialState + }, selectors: [ { selector: selectCurrentUser, diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.ts index 8abc3014a8..32e7174e50 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/navigation/navigation.component.ts @@ -46,6 +46,7 @@ import { } from '../../../state/cluster-summary/cluster-summary.actions'; import { selectClusterSummary } from '../../../state/cluster-summary/cluster-summary.selectors'; import { selectLoginConfiguration } from '../../../state/login-configuration/login-configuration.selectors'; +import { selectBackNavigation } from '../../../state/navigation/navigation.selectors'; @Component({ selector: 'navigation', @@ -70,10 +71,12 @@ export class Navigation implements OnInit, OnDestroy { LIGHT_THEME: string = LIGHT_THEME; DARK_THEME: string = DARK_THEME; OS_SETTING: string = OS_SETTING; + currentUser = this.store.selectSignal(selectCurrentUser); flowConfiguration = this.store.selectSignal(selectFlowConfiguration); loginConfiguration = this.store.selectSignal(selectLoginConfiguration); clusterSummary = this.store.selectSignal(selectClusterSummary); + backNavigation = this.store.selectSignal(selectBackNavigation); constructor( private store: Store,