This is an automated email from the ASF dual-hosted git repository.
rfellows pushed a commit to branch NIFI-15258
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/NIFI-15258 by this push:
new 2ee0178e5d NIFI-15577: Including connector id in provenance event dto.
(#10883)
2ee0178e5d is described below
commit 2ee0178e5dee706b52acc0efe8686f9392f6b8b7
Author: Matt Gilman <[email protected]>
AuthorDate: Wed Feb 11 17:28:56 2026 -0500
NIFI-15577: Including connector id in provenance event dto. (#10883)
* NIFI-15577: Including connector id in provenance event dto.
- Fixing go to routing logic in the provenance event table.
* NIFI-15577: Fixing back navigation context when navigating to provenance
from the flow designer.
This closes #10883
---
.../web/api/dto/provenance/ProvenanceEventDTO.java | 14 +++
.../nifi/web/controller/ControllerFacade.java | 16 ++-
.../nifi/web/controller/ControllerFacadeTest.java | 115 +++++++++++++++++++++
.../flow-designer/feature/flow-designer.module.ts | 4 +-
.../service/canvas-context-menu.service.ts | 3 +-
.../pages/flow-designer/state/flow/flow.actions.ts | 3 +-
.../flow-designer/state/flow/flow.effects.spec.ts | 104 ++++++++++++++++++-
.../pages/flow-designer/state/flow/flow.effects.ts | 10 +-
.../state/provenance-event-listing/index.ts | 1 +
.../provenance-event-listing.effects.ts | 18 +++-
.../provenance-event-table.component.ts | 3 +-
11 files changed, 274 insertions(+), 17 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/provenance/ProvenanceEventDTO.java
b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/provenance/ProvenanceEventDTO.java
index 071ccf01be..4ce0514514 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/provenance/ProvenanceEventDTO.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/provenance/ProvenanceEventDTO.java
@@ -49,6 +49,7 @@ public class ProvenanceEventDTO {
private String clusterNodeAddress; // include when clustered
private String groupId;
+ private String connectorId;
private String componentId;
private String componentType;
private String componentName;
@@ -217,6 +218,19 @@ public class ProvenanceEventDTO {
this.groupId = groupId;
}
+ /**
+ * @return id of the Connector that manages the component that generated
this event, or {@code null} if the component is not managed by a Connector
+ */
+ @Schema(description = "The id of the connector that manages the component
that generated the event. If the component is not managed by a connector, this
will not be set."
+ )
+ public String getConnectorId() {
+ return connectorId;
+ }
+
+ public void setConnectorId(String connectorId) {
+ this.connectorId = connectorId;
+ }
+
/**
* @return id of the component that generated this event
*/
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 924b7ca3e6..68e73d88b7 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -1864,7 +1864,9 @@ public class ControllerFacade implements Authorizable {
final Connectable connectable =
findLocalConnectable(dto.getComponentId());
if (connectable != null) {
- dto.setGroupId(connectable.getProcessGroup().getIdentifier());
+ final ProcessGroup connectableGroup =
connectable.getProcessGroup();
+ dto.setGroupId(connectableGroup.getIdentifier());
+
connectableGroup.getConnectorIdentifier().ifPresent(dto::setConnectorId);
// if the user is approved for this component policy, provide
additional details, otherwise override/redact as necessary
if
(Result.Approved.equals(connectable.checkAuthorization(authorizer,
RequestAction.READ, user).getResult())) {
@@ -1880,7 +1882,13 @@ public class ControllerFacade implements Authorizable {
final RemoteGroupPort remoteGroupPort =
root.findRemoteGroupPort(dto.getComponentId());
if (remoteGroupPort != null) {
- dto.setGroupId(remoteGroupPort.getProcessGroupIdentifier());
+ final String remoteGroupPortGroupId =
remoteGroupPort.getProcessGroupIdentifier();
+ dto.setGroupId(remoteGroupPortGroupId);
+
+ final ProcessGroup remotePortGroup =
root.findProcessGroup(remoteGroupPortGroupId);
+ if (remotePortGroup != null) {
+
remotePortGroup.getConnectorIdentifier().ifPresent(dto::setConnectorId);
+ }
// if the user is approved for this component policy, provide
additional details, otherwise override/redact as necessary
if
(Result.Approved.equals(remoteGroupPort.checkAuthorization(authorizer,
RequestAction.READ, user).getResult())) {
@@ -1895,7 +1903,9 @@ public class ControllerFacade implements Authorizable {
final Connection connection =
root.findConnection(dto.getComponentId());
if (connection != null) {
- dto.setGroupId(connection.getProcessGroup().getIdentifier());
+ final ProcessGroup connectionGroup = connection.getProcessGroup();
+ dto.setGroupId(connectionGroup.getIdentifier());
+
connectionGroup.getConnectorIdentifier().ifPresent(dto::setConnectorId);
// if the user is approved for this component policy, provide
additional details, otherwise override/redact as necessary
if
(Result.Approved.equals(connection.checkAuthorization(authorizer,
RequestAction.READ, user).getResult())) {
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerFacadeTest.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerFacadeTest.java
index 5dad329baf..eb43ece3ea 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerFacadeTest.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerFacadeTest.java
@@ -16,6 +16,10 @@
*/
package org.apache.nifi.web.controller;
+import org.apache.nifi.authorization.AuthorizationResult;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserDetails;
import org.apache.nifi.authorization.user.StandardNiFiUser;
@@ -23,8 +27,16 @@ import org.apache.nifi.c2.protocol.component.api.Bundle;
import org.apache.nifi.c2.protocol.component.api.ComponentManifest;
import org.apache.nifi.c2.protocol.component.api.ConnectorDefinition;
import org.apache.nifi.c2.protocol.component.api.RuntimeManifest;
+import org.apache.nifi.connectable.Connectable;
+import org.apache.nifi.controller.FlowController;
+import org.apache.nifi.controller.flow.FlowManager;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.manifest.RuntimeManifestService;
+import org.apache.nifi.provenance.ProvenanceAuthorizableFactory;
+import org.apache.nifi.provenance.ProvenanceEventRecord;
+import org.apache.nifi.provenance.ProvenanceEventType;
+import org.apache.nifi.provenance.ProvenanceRepository;
+import org.apache.nifi.web.api.dto.provenance.ProvenanceEventDTO;
import org.apache.nifi.web.api.dto.search.SearchResultsDTO;
import org.apache.nifi.web.search.query.SearchQuery;
import org.apache.nifi.web.search.query.SearchQueryParser;
@@ -36,14 +48,18 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.core.context.SecurityContextHolder;
+import java.io.IOException;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -186,5 +202,104 @@ public class ControllerFacadeTest {
assertNull(result);
}
+
+ @Test
+ public void
testGetProvenanceEventSetsConnectorIdWhenComponentBelongsToConnector() throws
IOException {
+ final String componentId = "test-component-id";
+ final String groupId = "test-group-id";
+ final String connectorId = "test-connector-id";
+
+ final ControllerFacade facade = createProvenanceFacade(componentId,
groupId, Optional.of(connectorId));
+
+ final ProvenanceEventDTO result = facade.getProvenanceEvent(1L);
+
+ assertNotNull(result);
+ assertEquals(connectorId, result.getConnectorId());
+ assertEquals(groupId, result.getGroupId());
+ assertEquals(componentId, result.getComponentId());
+ }
+
+ @Test
+ public void
testGetProvenanceEventConnectorIdIsNullWhenComponentNotManagedByConnector()
throws IOException {
+ final String componentId = "test-component-id";
+ final String groupId = "test-group-id";
+
+ final ControllerFacade facade = createProvenanceFacade(componentId,
groupId, Optional.empty());
+
+ final ProvenanceEventDTO result = facade.getProvenanceEvent(1L);
+
+ assertNotNull(result);
+ assertNull(result.getConnectorId());
+ assertEquals(groupId, result.getGroupId());
+ assertEquals(componentId, result.getComponentId());
+ }
+
+ /**
+ * Creates a ControllerFacade wired with mocks sufficient to test
provenance event creation
+ * through the connectable branch of setComponentDetails.
+ */
+ private ControllerFacade createProvenanceFacade(final String componentId,
final String groupId,
+ final Optional<String>
connectorIdentifier) throws IOException {
+ // Mock the ProvenanceEventRecord
+ final ProvenanceEventRecord event = mock(ProvenanceEventRecord.class);
+ when(event.getEventId()).thenReturn(1L);
+ when(event.getEventTime()).thenReturn(System.currentTimeMillis());
+ when(event.getEventType()).thenReturn(ProvenanceEventType.CREATE);
+ when(event.getFlowFileUuid()).thenReturn("test-flowfile-uuid");
+ when(event.getFileSize()).thenReturn(1024L);
+ when(event.getComponentId()).thenReturn(componentId);
+ when(event.getComponentType()).thenReturn("TestProcessor");
+ when(event.getUpdatedAttributes()).thenReturn(Map.of());
+ when(event.getPreviousAttributes()).thenReturn(Map.of());
+ when(event.getParentUuids()).thenReturn(List.of());
+ when(event.getChildUuids()).thenReturn(List.of());
+ when(event.getEventDuration()).thenReturn(-1L);
+ when(event.getLineageStartDate()).thenReturn(0L);
+
+ // Mock the ProcessGroup that the connectable belongs to
+ final ProcessGroup processGroup = mock(ProcessGroup.class);
+ when(processGroup.getIdentifier()).thenReturn(groupId);
+
when(processGroup.getConnectorIdentifier()).thenReturn(connectorIdentifier);
+
+ // Mock a Connectable found in the flow
+ final Connectable connectable = mock(Connectable.class);
+ when(connectable.getProcessGroup()).thenReturn(processGroup);
+ when(connectable.getName()).thenReturn("Test Component");
+ when(connectable.checkAuthorization(any(), any(),
any())).thenReturn(AuthorizationResult.approved());
+
+ // Mock FlowManager
+ final FlowManager flowManager = mock(FlowManager.class);
+ when(flowManager.findConnectable(componentId)).thenReturn(connectable);
+ when(flowManager.getRootGroup()).thenReturn(mock(ProcessGroup.class));
+
+ // Mock ProvenanceRepository
+ final ProvenanceRepository provenanceRepository =
mock(ProvenanceRepository.class);
+ when(provenanceRepository.getEvent(eq(1L),
any(NiFiUser.class))).thenReturn(event);
+
+ // Mock data authorization as not approved so we skip content
availability logic
+ final Authorizable dataAuthorizable = mock(Authorizable.class);
+ when(dataAuthorizable.checkAuthorization(any(),
eq(RequestAction.READ), any(NiFiUser.class), any()))
+ .thenReturn(AuthorizationResult.denied("test"));
+
+ // Mock ProvenanceAuthorizableFactory
+ final ProvenanceAuthorizableFactory provenanceAuthorizableFactory =
mock(ProvenanceAuthorizableFactory.class);
+
when(provenanceAuthorizableFactory.createLocalDataAuthorizable(componentId)).thenReturn(dataAuthorizable);
+
+ // Mock FlowController
+ final FlowController flowController = mock(FlowController.class);
+ when(flowController.getFlowManager()).thenReturn(flowManager);
+
when(flowController.getProvenanceRepository()).thenReturn(provenanceRepository);
+
when(flowController.getProvenanceAuthorizableFactory()).thenReturn(provenanceAuthorizableFactory);
+
+ // Mock Authorizer
+ final Authorizer authorizer = mock(Authorizer.class);
+
+ // Build the ControllerFacade
+ final ControllerFacade facade = new ControllerFacade();
+ facade.setFlowController(flowController);
+ facade.setAuthorizer(authorizer);
+
+ return facade;
+ }
}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/feature/flow-designer.module.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/feature/flow-designer.module.ts
index d68b3c9f75..bb3e63033a 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/feature/flow-designer.module.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/feature/flow-designer.module.ts
@@ -30,6 +30,7 @@ import { ParameterEffects } from
'../state/parameter/parameter.effects';
import { QueueEffects } from '../state/queue/queue.effects';
import { BannerText } from
'../../../ui/common/banner-text/banner-text.component';
import { FlowAnalysisEffects } from
'../state/flow-analysis/flow-analysis.effects';
+import { ComponentTypeNamePipe } from '@nifi/shared';
@NgModule({
declarations: [FlowDesigner],
@@ -49,6 +50,7 @@ import { FlowAnalysisEffects } from
'../state/flow-analysis/flow-analysis.effect
NgOptimizedImage,
MatDialogModule,
BannerText
- ]
+ ],
+ providers: [ComponentTypeNamePipe]
})
export class FlowDesignerModule {}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts
index ab7cdbe04b..2e8baea059 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/canvas-context-menu.service.ts
@@ -887,7 +887,8 @@ export class CanvasContextMenu implements
ContextMenuDefinitionProvider {
const selectionData = selection.datum();
this.store.dispatch(
navigateToProvenanceForComponent({
- id: selectionData.id
+ id: selectionData.id,
+ componentType: selectionData.type
})
);
}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts
index 32614579b6..efb96845ed 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.actions.ts
@@ -120,6 +120,7 @@ import {
} from '../../../../state/shared';
import { ErrorContext } from '../../../../state/error';
import { CopyResponseContext, CopyResponseEntity } from
'../../../../state/copy';
+import { ComponentType } from '@nifi/shared';
const CANVAS_PREFIX = '[Canvas]';
@@ -608,7 +609,7 @@ export const renderConnectionsForComponent = createAction(
export const navigateToProvenanceForComponent = createAction(
`${CANVAS_PREFIX} Navigate To Provenance For Component`,
- props<{ id: string }>()
+ props<{ id: string; componentType: ComponentType }>()
);
export const replayLastProvenanceEvent = createAction(
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.spec.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.spec.ts
index ba287885d7..70cf7bcc71 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.spec.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.spec.ts
@@ -58,9 +58,10 @@ import { CopyPasteService } from
'../../service/copy-paste.service';
import { CanvasView } from '../../service/canvas-view.service';
import { BirdseyeView } from '../../service/birdseye-view.service';
import { selectDisconnectionAcknowledged } from
'../../../../state/cluster-summary/cluster-summary.selectors';
-import { ComponentType } from '@nifi/shared';
+import { ComponentType, ComponentTypeNamePipe } from '@nifi/shared';
import { ParameterContextService } from
'../../../parameter-contexts/service/parameter-contexts.service';
import { HttpErrorResponse } from '@angular/common/http';
+import { provideRouter, Router } from '@angular/router';
import { ErrorHelper } from '../../../../service/error-helper.service';
import { selectConnectedStateChanged } from
'../../../../state/cluster-summary/cluster-summary.selectors';
@@ -775,6 +776,8 @@ describe('FlowEffects', () => {
imports: [],
providers: [
FlowEffects,
+ ComponentTypeNamePipe,
+ provideRouter([]),
provideMockActions(() => action$),
provideMockStore({
selectors: [
@@ -1182,4 +1185,103 @@ describe('FlowEffects', () => {
);
});
});
+
+ describe('navigateToProvenanceForComponent$', () => {
+ let router: Router;
+
+ beforeEach(() => {
+ router = TestBed.inject(Router);
+ jest.spyOn(router, 'navigate').mockImplementation(() =>
Promise.resolve(true));
+ store.overrideSelector(selectCurrentProcessGroupId, 'pg-123');
+ store.refreshState();
+ });
+
+ it('should navigate to provenance with Processor type in back
navigation route and context', () => {
+ effects.navigateToProvenanceForComponent$.subscribe();
+
+ action$.next(
+ FlowActions.navigateToProvenanceForComponent({
+ id: 'comp-1',
+ componentType: ComponentType.Processor
+ })
+ );
+
+ expect(router.navigate).toHaveBeenCalledWith(['/provenance'], {
+ queryParams: { componentId: 'comp-1' },
+ state: {
+ backNavigation: {
+ route: ['/process-groups', 'pg-123',
ComponentType.Processor, 'comp-1'],
+ routeBoundary: ['/provenance'],
+ context: 'Processor'
+ }
+ }
+ });
+ });
+
+ it('should navigate to provenance with Funnel type in back navigation
route and context', () => {
+ effects.navigateToProvenanceForComponent$.subscribe();
+
+ action$.next(
+ FlowActions.navigateToProvenanceForComponent({
+ id: 'funnel-1',
+ componentType: ComponentType.Funnel
+ })
+ );
+
+ expect(router.navigate).toHaveBeenCalledWith(['/provenance'], {
+ queryParams: { componentId: 'funnel-1' },
+ state: {
+ backNavigation: {
+ route: ['/process-groups', 'pg-123',
ComponentType.Funnel, 'funnel-1'],
+ routeBoundary: ['/provenance'],
+ context: 'Funnel'
+ }
+ }
+ });
+ });
+
+ it('should navigate to provenance with InputPort type in back
navigation route and context', () => {
+ effects.navigateToProvenanceForComponent$.subscribe();
+
+ action$.next(
+ FlowActions.navigateToProvenanceForComponent({
+ id: 'port-1',
+ componentType: ComponentType.InputPort
+ })
+ );
+
+ expect(router.navigate).toHaveBeenCalledWith(['/provenance'], {
+ queryParams: { componentId: 'port-1' },
+ state: {
+ backNavigation: {
+ route: ['/process-groups', 'pg-123',
ComponentType.InputPort, 'port-1'],
+ routeBoundary: ['/provenance'],
+ context: 'Input Port'
+ }
+ }
+ });
+ });
+
+ it('should navigate to provenance with OutputPort type in back
navigation route and context', () => {
+ effects.navigateToProvenanceForComponent$.subscribe();
+
+ action$.next(
+ FlowActions.navigateToProvenanceForComponent({
+ id: 'port-2',
+ componentType: ComponentType.OutputPort
+ })
+ );
+
+ expect(router.navigate).toHaveBeenCalledWith(['/provenance'], {
+ queryParams: { componentId: 'port-2' },
+ state: {
+ backNavigation: {
+ route: ['/process-groups', 'pg-123',
ComponentType.OutputPort, 'port-2'],
+ routeBoundary: ['/provenance'],
+ context: 'Output Port'
+ }
+ }
+ });
+ });
+ });
});
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts
index 94553f29f7..bef4fb79ab 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts
@@ -128,6 +128,7 @@ import { EditProcessGroup } from
'../../ui/canvas/items/process-group/edit-proce
import { ControllerServiceService } from
'../../service/controller-service.service';
import {
ComponentType,
+ ComponentTypeNamePipe,
isDefinedAndNotNull,
LARGE_DIALOG,
MEDIUM_DIALOG,
@@ -200,6 +201,7 @@ export class FlowEffects {
private parameterContextService = inject(ParameterContextService);
private extensionTypesService = inject(ExtensionTypesService);
private errorHelper = inject(ErrorHelper);
+ private componentTypeNamePipe = inject(ComponentTypeNamePipe);
private copyPasteService = inject(CopyPasteService);
private createProcessGroupDialogRef: MatDialogRef<CreateProcessGroup, any>
| undefined;
@@ -2968,16 +2970,16 @@ export class FlowEffects {
() =>
this.actions$.pipe(
ofType(FlowActions.navigateToProvenanceForComponent),
- map((action) => action.id),
+ map((action) => ({ id: action.id, componentType:
action.componentType })),
concatLatestFrom(() =>
this.store.select(selectCurrentProcessGroupId)),
- tap(([componentId, processGroupId]) => {
+ tap(([{ id: componentId, componentType }, processGroupId]) => {
this.router.navigate(['/provenance'], {
queryParams: { componentId },
state: {
backNavigation: {
- route: ['/process-groups', processGroupId,
ComponentType.Processor, componentId],
+ route: ['/process-groups', processGroupId,
componentType, componentId],
routeBoundary: ['/provenance'],
- context: 'Processor'
+ context:
this.componentTypeNamePipe.transform(componentType)
} as BackNavigation
}
});
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/index.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/index.ts
index 8cb87708e5..f8d95b4fba 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/index.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/index.ts
@@ -41,6 +41,7 @@ export interface ProvenanceEventRequest {
export interface GoToProvenanceEventSourceRequest {
eventId?: number;
componentId?: string;
+ componentType?: string;
groupId?: string;
clusterNodeId?: string;
}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/provenance-event-listing.effects.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/provenance-event-listing.effects.ts
index 46cb2e7915..9ff84a4d93 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/provenance-event-listing.effects.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/state/provenance-event-listing/provenance-event-listing.effects.ts
@@ -444,7 +444,9 @@ export class ProvenanceEventListingEffects {
this.provenanceService.getProvenanceEvent(request.eventId,
request.clusterNodeId).subscribe({
next: (response) => {
const event: any = response.provenanceEvent;
-
this.router.navigate(this.getEventComponentLink(event.groupId,
event.componentId));
+ this.router.navigate(
+ this.getEventComponentLink(event.groupId,
event.componentId, event.componentType)
+ );
},
error: (errorResponse: HttpErrorResponse) => {
this.store.dispatch(
@@ -455,7 +457,9 @@ export class ProvenanceEventListingEffects {
}
});
} else if (request.groupId && request.componentId) {
-
this.router.navigate(this.getEventComponentLink(request.groupId,
request.componentId));
+ this.router.navigate(
+ this.getEventComponentLink(request.groupId,
request.componentId, request.componentType)
+ );
}
})
),
@@ -495,15 +499,19 @@ export class ProvenanceEventListingEffects {
{ dispatch: false }
);
- private getEventComponentLink(groupId: string, componentId: string):
string[] {
+ private getEventComponentLink(groupId: string, componentId: string,
componentType?: string): string[] {
let link: string[];
if (groupId == componentId) {
link = ['/process-groups', componentId];
- } else if (componentId === 'Connection' || componentId === 'Load
Balanced Connection') {
+ } else if (componentType === 'Connection' || componentType === 'Load
Balanced Connection') {
link = ['/process-groups', groupId, 'Connection', componentId];
- } else if (componentId === 'Output Port') {
+ } else if (componentType === 'Output Port') {
link = ['/process-groups', groupId, 'OutputPort', componentId];
+ } else if (componentType === 'Input Port') {
+ link = ['/process-groups', groupId, 'InputPort', componentId];
+ } else if (componentType === 'Funnel') {
+ link = ['/process-groups', groupId, 'Funnel', componentId];
} else {
link = ['/process-groups', groupId, 'Processor', componentId];
}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/ui/provenance-event-listing/provenance-event-table/provenance-event-table.component.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/ui/provenance-event-listing/provenance-event-table/provenance-event-table.component.ts
index e2df47bb35..adb6266130 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/ui/provenance-event-listing/provenance-event-table/provenance-event-table.component.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/provenance/ui/provenance-event-listing/provenance-event-table/provenance-event-table.component.ts
@@ -338,12 +338,13 @@ export class ProvenanceEventTable implements
AfterViewInit {
return false;
}
- return !(event.componentId === 'Remote Output Port' ||
event.componentId === 'Remote Input Port');
+ return !(event.componentType === 'Remote Output Port' ||
event.componentType === 'Remote Input Port');
}
goToClicked(event: ProvenanceEventSummary): void {
this.goToEventSource({
componentId: event.componentId,
+ componentType: event.componentType,
groupId: event.groupId
});
}