This is an automated email from the ASF dual-hosted git repository.

rfellows 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 dfd8376a73 NIFI-14637: Preventing the go to action in the local 
changes dialog when the component was removed. (#10028)
dfd8376a73 is described below

commit dfd8376a7341d5bb56ebcec55be2fb6eec79b524
Author: Matt Gilman <[email protected]>
AuthorDate: Wed Jun 25 13:53:26 2025 -0400

    NIFI-14637: Preventing the go to action in the local changes dialog when 
the component was removed. (#10028)
    
    - Fixing routing to modified controller services.
    
    This closes #10028
---
 .../pages/flow-designer/state/flow/flow.effects.ts |  9 ++-
 .../local-changes-table/local-changes-table.html   | 26 +++++----
 .../local-changes-table.spec.ts                    | 65 ++++++++++++++++++++++
 .../local-changes-table/local-changes-table.ts     | 54 +++++++++++++++---
 4 files changed, 133 insertions(+), 21 deletions(-)

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 293649ec4a..c62d0caf4b 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
@@ -2930,10 +2930,15 @@ export class FlowEffects {
                 map((action) => action.request),
                 concatLatestFrom(() => 
this.store.select(selectCurrentProcessGroupId)),
                 tap(([request, currentProcessGroupId]) => {
+                    let type: string = request.type;
+                    if (request.type === ComponentType.ControllerService) {
+                        type = 'controller-services';
+                    }
+
                     if (request.processGroupId) {
-                        this.router.navigate(['/process-groups', 
request.processGroupId, request.type, request.id]);
+                        this.router.navigate(['/process-groups', 
request.processGroupId, type, request.id]);
                     } else {
-                        this.router.navigate(['/process-groups', 
currentProcessGroupId, request.type, request.id]);
+                        this.router.navigate(['/process-groups', 
currentProcessGroupId, type, request.id]);
                     }
                 })
             ),
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.html
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.html
index 1c07af5909..121a245abb 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.html
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.html
@@ -71,19 +71,21 @@
                     <th mat-header-cell *matHeaderCellDef></th>
                     <td mat-cell *matCellDef="let item">
                         <div class="flex items-center justify-end gap-x-2">
-                            <button
-                                mat-icon-button
-                                type="button"
-                                [matMenuTriggerFor]="actionMenu"
-                                class="h-16 w-16 flex items-center 
justify-center icon global-menu">
-                                <i class="fa fa-ellipsis-v"></i>
-                            </button>
-                            <mat-menu #actionMenu="matMenu" xPosition="before">
-                                <button mat-menu-item 
(click)="goToClicked(item)">
-                                    <i class="fa fa-long-arrow-right 
primary-color mr-2"></i>
-                                    Go To
+                            @if (canGoTo(item)) {
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="actionMenu"
+                                    class="h-16 w-16 flex items-center 
justify-center icon global-menu">
+                                    <i class="fa fa-ellipsis-v"></i>
                                 </button>
-                            </mat-menu>
+                                <mat-menu #actionMenu="matMenu" 
xPosition="before">
+                                    <button mat-menu-item 
(click)="goToClicked(item)">
+                                        <i class="fa fa-long-arrow-right 
primary-color mr-2"></i>
+                                        Go To
+                                    </button>
+                                </mat-menu>
+                            }
                         </div>
                     </td>
                 </ng-container>
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.spec.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.spec.ts
index e76dfedffc..105ebf9d26 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.spec.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.spec.ts
@@ -19,6 +19,7 @@ import { ComponentFixture, TestBed } from 
'@angular/core/testing';
 
 import { LocalChangesTable } from './local-changes-table';
 import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { ComponentType } from '@nifi/shared';
 
 describe('LocalChangesTable', () => {
     let component: LocalChangesTable;
@@ -37,4 +38,68 @@ describe('LocalChangesTable', () => {
     it('should create', () => {
         expect(component).toBeTruthy();
     });
+
+    describe('canGoTo', () => {
+        it('should return true if can go to', () => {
+            const localChange = {
+                componentType: 'Processor',
+                componentId: '123',
+                componentName: 'Test Processor',
+                processGroupId: '456',
+                differenceType: 'Component Added',
+                difference: 'Processor was added.'
+            };
+            expect(component.canGoTo(localChange)).toBe(true);
+        });
+
+        it('should return false if cannot go to', () => {
+            const localChange = {
+                componentType: 'Processor',
+                componentId: '123',
+                componentName: 'Test Processor',
+                processGroupId: '456',
+                differenceType: 'Component Removed',
+                difference: 'Processor was removed.'
+            };
+            expect(component.canGoTo(localChange)).toBe(false);
+        });
+    });
+
+    describe('goToClicked', () => {
+        it('should next goToChange event on Processor added', () => {
+            const localChange = {
+                componentType: 'Processor',
+                componentId: '123',
+                componentName: 'Test Processor',
+                processGroupId: '456',
+                differenceType: 'Component Added',
+                difference: 'Processor was added.'
+            };
+            jest.spyOn(component.goToChange, 'next');
+            component.goToClicked(localChange);
+            expect(component.goToChange.next).toHaveBeenCalledWith({
+                id: localChange.componentId,
+                type: ComponentType.Processor,
+                processGroupId: localChange.processGroupId
+            });
+        });
+
+        it('should next goToChange event on Controller Service added', () => {
+            const localChange = {
+                componentType: 'Controller Service',
+                componentId: '123',
+                componentName: 'Test Controller Service',
+                processGroupId: '456',
+                differenceType: 'Component Added',
+                difference: 'Controller Service was added.'
+            };
+            jest.spyOn(component.goToChange, 'next');
+            component.goToClicked(localChange);
+            expect(component.goToChange.next).toHaveBeenCalledWith({
+                id: localChange.componentId,
+                type: ComponentType.ControllerService,
+                processGroupId: localChange.processGroupId
+            });
+        });
+    });
 });
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
index 072d846873..02d9eaef34 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
@@ -29,7 +29,7 @@ import { MatIconButton } from '@angular/material/button';
 import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
 
 interface LocalChange {
-    componentType: ComponentType;
+    componentType: string;
     componentId: string;
     componentName: string;
     processGroupId: string;
@@ -124,6 +124,10 @@ export class LocalChangesTable implements AfterViewInit {
         return item.differenceType;
     }
 
+    canGoTo(item: LocalChange): boolean {
+        return item.differenceType !== 'Component Removed';
+    }
+
     formatDifference(item: LocalChange): string {
         return item.difference;
     }
@@ -158,12 +162,48 @@ export class LocalChangesTable implements AfterViewInit {
     }
 
     goToClicked(item: LocalChange) {
-        const linkMeta: NavigateToComponentRequest = {
-            id: item.componentId,
-            type: item.componentType,
-            processGroupId: item.processGroupId
-        };
-        this.goToChange.next(linkMeta);
+        const type = this.getComponentType(item.componentType);
+        if (type) {
+            const linkMeta: NavigateToComponentRequest = {
+                id: item.componentId,
+                type,
+                processGroupId: item.processGroupId
+            };
+            this.goToChange.next(linkMeta);
+        }
+    }
+
+    private getComponentType(componentType: string): ComponentType | null {
+        switch (componentType) {
+            case 'Connection':
+                return ComponentType.Connection;
+            case 'Processor':
+                return ComponentType.Processor;
+            case 'Output Port':
+                return ComponentType.OutputPort;
+            case 'Input Port':
+                return ComponentType.InputPort;
+            case 'Process Group':
+                return ComponentType.ProcessGroup;
+            case 'Controller Service':
+                return ComponentType.ControllerService;
+            case 'Flow':
+                return ComponentType.Flow;
+            case 'Flow Registry Client':
+                return ComponentType.FlowRegistryClient;
+            case 'Funnel':
+                return ComponentType.Funnel;
+            case 'Label':
+                return ComponentType.Label;
+            case 'Parameter Provider':
+                return ComponentType.ParameterProvider;
+            case 'Remote Process Group':
+                return ComponentType.RemoteProcessGroup;
+            case 'Reporting Task':
+                return ComponentType.ReportingTask;
+            default:
+                return null;
+        }
     }
 
     private explodeDifferences(differences: ComponentDifference[]): 
LocalChange[] {

Reply via email to