This is an automated email from the ASF dual-hosted git repository.
turcsanyip pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 7418e2eba6d NIFI-16042 Make rule violation "Go to component" link to
work for more component types. (#11365)
7418e2eba6d is described below
commit 7418e2eba6d3030bef7d80c982156c6a0d5eebe3
Author: tpalfy <[email protected]>
AuthorDate: Wed Jun 24 20:07:39 2026 +0200
NIFI-16042 Make rule violation "Go to component" link to work for more
component types. (#11365)
Signed-off-by: Peter Turcsanyi <[email protected]>
---
.../nifi/flowanalysis/StandardFlowAnalyzer.java | 5 +-
.../flow-analysis-drawer.component.html | 4 +-
.../flow-analysis-drawer.component.spec.ts | 58 +++++++++++++++++++++-
.../flow-analysis-drawer.component.ts | 31 +++++++++++-
4 files changed, 92 insertions(+), 6 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/flowanalysis/StandardFlowAnalyzer.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/flowanalysis/StandardFlowAnalyzer.java
index ce0beac1ad9..74f23d9409f 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/flowanalysis/StandardFlowAnalyzer.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/flowanalysis/StandardFlowAnalyzer.java
@@ -27,6 +27,7 @@ import org.apache.nifi.flow.ComponentType;
import org.apache.nifi.flow.VersionedComponent;
import org.apache.nifi.flow.VersionedConnection;
import org.apache.nifi.flow.VersionedControllerService;
+import org.apache.nifi.flow.VersionedFunnel;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.flow.VersionedProcessor;
import org.apache.nifi.nar.ExtensionManager;
@@ -256,7 +257,9 @@ public class StandardFlowAnalyzer implements FlowAnalyzer {
private String getDisplayName(VersionedComponent component) {
final String displayName;
- if (component instanceof VersionedConnection) {
+ if (component instanceof VersionedFunnel) {
+ displayName = "Funnel";
+ } else if (component instanceof VersionedConnection) {
VersionedConnection connection = (VersionedConnection) component;
displayName = connection.getSource().getName() + " > " +
connection.getSelectedRelationships().stream().collect(Collectors.joining(","));
} else {
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html
index 6a44bd57e7d..36aefe3965b 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html
@@ -261,8 +261,8 @@
[disabled]="!violation?.subjectPermissionDto?.canRead">
<i class="fa fa-info-circle mr-2 primary-color"></i>Violation
details
</button>
- @if (violation?.subjectComponentType === 'PROCESSOR' &&
violation?.subjectPermissionDto?.canRead) {
- <button mat-menu-item [routerLink]="getProcessorLink(violation)">
+ @if (violation?.subjectPermissionDto?.canRead &&
getComponentLink(violation); as componentLink) {
+ <button mat-menu-item [routerLink]="componentLink">
<i class="fa mr-2 fa-long-arrow-right primary-color"></i>Go to
component
</button>
}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.spec.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.spec.ts
index 5627cdf2303..a789a6af95d 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.spec.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.spec.ts
@@ -22,9 +22,10 @@ import { NoopAnimationsModule } from
'@angular/platform-browser/animations';
import { initialState as initialErrorState } from
'../../../../../../state/error/error.reducer';
import { errorFeatureKey } from '../../../../../../state/error';
import { initialState as initialFlowAnalysisState } from
'../../../../state/flow-analysis/flow-analysis.reducer';
-import { flowAnalysisFeatureKey } from '../../../../state/flow-analysis';
+import { flowAnalysisFeatureKey, FlowAnalysisRuleViolation } from
'../../../../state/flow-analysis';
import { initialState as initialFlowState } from
'../../../../state/flow/flow.reducer';
import { flowFeatureKey } from '../../../../state/flow';
+import { ComponentType } from '@nifi/shared';
describe('FlowAnalysisDrawerComponent', () => {
let component: FlowAnalysisDrawerComponent;
@@ -54,4 +55,59 @@ describe('FlowAnalysisDrawerComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ const supportedComponentTypes: [string, ComponentType][] = [
+ ['PROCESSOR', ComponentType.Processor],
+ ['PROCESS_GROUP', ComponentType.ProcessGroup],
+ ['REMOTE_PROCESS_GROUP', ComponentType.RemoteProcessGroup],
+ ['INPUT_PORT', ComponentType.InputPort],
+ ['OUTPUT_PORT', ComponentType.OutputPort],
+ ['FUNNEL', ComponentType.Funnel],
+ ['CONNECTION', ComponentType.Connection]
+ ];
+
+ it.each(supportedComponentTypes)(
+ 'should get a component link for %s violations',
+ (subjectComponentType: string, componentType: ComponentType) => {
+ const violation = createViolation(subjectComponentType);
+
+ expect(component.getComponentLink(violation)).toEqual([
+ '/process-groups',
+ 'group-id',
+ componentType,
+ 'subject-id'
+ ]);
+ }
+ );
+
+ it('should not get a component link for unsupported subject types', () => {
+ const violation = createViolation('CONTROLLER_SERVICE');
+
+ expect(component.getComponentLink(violation)).toBeNull();
+ });
+
+ it('should not get a component link for label violations', () => {
+ const violation = createViolation('LABEL');
+
+ expect(component.getComponentLink(violation)).toBeNull();
+ });
+
+ function createViolation(subjectComponentType: string):
FlowAnalysisRuleViolation {
+ return {
+ enforcementPolicy: 'WARN',
+ scope: 'scope',
+ subjectId: 'subject-id',
+ subjectDisplayName: 'Subject',
+ groupId: 'group-id',
+ ruleId: 'rule-id',
+ issueId: 'issue-id',
+ violationMessage: 'Violation message',
+ subjectComponentType,
+ subjectPermissionDto: {
+ canRead: true,
+ canWrite: true
+ },
+ enabled: true
+ };
+ }
});
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.ts
index 57c8a80d121..3d64723f171 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.ts
@@ -155,8 +155,35 @@ export class FlowAnalysisDrawerComponent {
this.store.dispatch(openRuleDetailsDialog({ violation, rule: ruleTest
}));
}
- getProcessorLink(violation: FlowAnalysisRuleViolation): string[] {
- return ['/process-groups', violation.groupId,
violation.subjectComponentType, violation.subjectId];
+ getComponentLink(violation: FlowAnalysisRuleViolation): string[] | null {
+ const componentType =
this.getComponentType(violation.subjectComponentType);
+
+ if (componentType && violation.groupId) {
+ return ['/process-groups', violation.groupId, componentType,
violation.subjectId];
+ }
+
+ return null;
+ }
+
+ private getComponentType(subjectComponentType: string): ComponentType |
null {
+ switch (subjectComponentType) {
+ case 'PROCESSOR':
+ return ComponentType.Processor;
+ case 'PROCESS_GROUP':
+ return ComponentType.ProcessGroup;
+ case 'REMOTE_PROCESS_GROUP':
+ return ComponentType.RemoteProcessGroup;
+ case 'INPUT_PORT':
+ return ComponentType.InputPort;
+ case 'OUTPUT_PORT':
+ return ComponentType.OutputPort;
+ case 'FUNNEL':
+ return ComponentType.Funnel;
+ case 'CONNECTION':
+ return ComponentType.Connection;
+ default:
+ return null;
+ }
}
getRuleName(id: string) {