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 a05146aa003 NIFI-16496: Show disabled Drain on the connector canvas 
with the reason it is unavailable (#11839)
a05146aa003 is described below

commit a05146aa003b13c8dce972acd5bfa9cf2f75149a
Author: Matt Gilman <[email protected]>
AuthorDate: Fri Oct 23 14:54:46 2026 -0400

    NIFI-16496: Show disabled Drain on the connector canvas with the reason it 
is unavailable (#11839)
    
    Keep Drain visible when the user can operate the connector, replace it with 
Cancel Drain while a drain can be cancelled, and surface the server reason on 
hover. Reload the connector entity on every canvas flow load, including polling 
and Refresh, so that reason stays current.
    
    This closes #11839
---
 .../connector-canvas-entity.effects.spec.ts        |  49 +++++-----
 .../connector-canvas-entity.effects.ts             |  12 ++-
 .../connector-canvas-entity.reducer.spec.ts        |  63 ++++++++++++
 .../connector-canvas-entity.reducer.ts             |   7 +-
 .../connector-info-control.component.html          |  48 +++++----
 .../connector-info-control.component.spec.ts       | 108 ++++++++++++++++++---
 .../connector-info-control.component.ts            |  21 +++-
 7 files changed, 248 insertions(+), 60 deletions(-)

diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.spec.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.spec.ts
index e3c0d097d2a..68727394069 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.spec.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.spec.ts
@@ -167,30 +167,33 @@ describe('ConnectorCanvasEntityEffects', () => {
             expect(result).toEqual(loadConnectorEntity({ connectorId: 
'connector-456' }));
         });
 
-        it('should not dispatch loadConnectorEntity when entity already 
matches connector id', () =>
-            new Promise<void>((resolve) => {
-                setup({ existingConnectorEntity: createMockConnectorEntity({ 
id: 'connector-456' }) }).then(
-                    ({ effects, actions$ }) => {
-                        let emissionCount = 0;
-                        const subscription = 
effects.triggerEntityLoad$.subscribe(() => {
-                            emissionCount++;
-                        });
-
-                        actions$.next(
-                            ConnectorCanvasActions.loadConnectorFlow({
-                                connectorId: 'connector-456',
-                                processGroupId: 'pg-789'
-                            })
-                        );
+        it('should dispatch loadConnectorEntity when the stored entity already 
matches, including a repeated refresh', async () => {
+            const { effects, actions$ } = await setup({
+                existingConnectorEntity: createMockConnectorEntity({ id: 
'connector-456' })
+            });
 
-                        queueMicrotask(() => {
-                            expect(emissionCount).toBe(0);
-                            subscription.unsubscribe();
-                            resolve();
-                        });
-                    }
-                );
-            }));
+            const emitted: Action[] = [];
+            const subscription = effects.triggerEntityLoad$.subscribe((action) 
=> emitted.push(action));
+
+            actions$.next(
+                ConnectorCanvasActions.loadConnectorFlow({
+                    connectorId: 'connector-456',
+                    processGroupId: 'pg-789'
+                })
+            );
+            actions$.next(
+                ConnectorCanvasActions.loadConnectorFlow({
+                    connectorId: 'connector-456',
+                    processGroupId: 'pg-789'
+                })
+            );
+
+            expect(emitted).toEqual([
+                loadConnectorEntity({ connectorId: 'connector-456' }),
+                loadConnectorEntity({ connectorId: 'connector-456' })
+            ]);
+            subscription.unsubscribe();
+        });
     });
 
     describe('loadConnectorEntity$', () => {
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.ts
index 20b04f1fd6a..5e4d64de519 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.effects.ts
@@ -29,7 +29,6 @@ import * as ErrorActions from 
'../../../../state/error/error.actions';
 import { ErrorContextKey } from '../../../../state/error';
 import * as ConnectorCanvasActions from 
'../connector-canvas/connector-canvas.actions';
 import { selectConnectorIdFromRoute } from 
'../connector-canvas/connector-canvas.selectors';
-import { selectConnectorCanvasEntity } from 
'./connector-canvas-entity.selectors';
 import {
     loadConnectorEntity,
     loadConnectorEntitySuccess,
@@ -54,12 +53,17 @@ export class ConnectorCanvasEntityEffects {
     private errorHelper = inject(ErrorHelper);
     private dialog = inject(MatDialog);
 
+    /**
+     * Refresh the connector entity alongside every flow load.
+     *
+     * Each `loadConnectorFlow` — the initial mount, a polling tick, 
navigation, and the
+     * canvas Refresh action — dispatches `loadConnectorEntity` so the entity 
stays in
+     * lockstep with the flow.
+     */
     triggerEntityLoad$ = createEffect(() =>
         this.actions$.pipe(
             ofType(ConnectorCanvasActions.loadConnectorFlow),
-            concatLatestFrom(() => 
this.store.select(selectConnectorCanvasEntity)),
-            filter(([action, existingEntity]) => existingEntity == null || 
existingEntity.id !== action.connectorId),
-            map(([action]) => loadConnectorEntity({ connectorId: 
action.connectorId }))
+            map((action) => loadConnectorEntity({ connectorId: 
action.connectorId }))
         )
     );
 
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.spec.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.spec.ts
index 0fc1e965649..ffc0ddde05d 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.spec.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.spec.ts
@@ -98,6 +98,69 @@ describe('connectorCanvasEntityReducer', () => {
             expect(result.loadingStatus).toBe('success');
             expect(result.error).toBeNull();
         });
+
+        it('should preserve the current entity when the loaded revision is 
older', () => {
+            const currentEntity = createMockConnectorEntity({ revision: { 
version: 2 } });
+            const olderEntity = createMockConnectorEntity({
+                revision: { version: 1 },
+                component: { ...currentEntity.component, state: 'RUNNING' }
+            });
+            const priorState: ConnectorCanvasEntityState = {
+                ...initialConnectorCanvasEntityState,
+                connectorEntity: currentEntity,
+                loadingStatus: 'loading',
+                error: 'previous error'
+            };
+
+            const result = connectorCanvasEntityReducer(
+                priorState,
+                loadConnectorEntitySuccess({ connectorEntity: olderEntity })
+            );
+
+            expect(result.connectorEntity).toBe(currentEntity);
+            expect(result.loadingStatus).toBe('success');
+            expect(result.error).toBeNull();
+        });
+
+        it('should apply a loaded entity with an equal revision', () => {
+            const currentEntity = createMockConnectorEntity({ revision: { 
version: 2 } });
+            const equalRevisionEntity = createMockConnectorEntity({
+                revision: { version: 2 },
+                component: { ...currentEntity.component, state: 'RUNNING' }
+            });
+            const priorState: ConnectorCanvasEntityState = {
+                ...initialConnectorCanvasEntityState,
+                connectorEntity: currentEntity,
+                loadingStatus: 'loading'
+            };
+
+            const result = connectorCanvasEntityReducer(
+                priorState,
+                loadConnectorEntitySuccess({ connectorEntity: 
equalRevisionEntity })
+            );
+
+            expect(result.connectorEntity).toBe(equalRevisionEntity);
+        });
+
+        it('should apply a loaded entity with a newer revision', () => {
+            const currentEntity = createMockConnectorEntity({ revision: { 
version: 2 } });
+            const newerEntity = createMockConnectorEntity({
+                revision: { version: 3 },
+                component: { ...currentEntity.component, state: 'RUNNING' }
+            });
+            const priorState: ConnectorCanvasEntityState = {
+                ...initialConnectorCanvasEntityState,
+                connectorEntity: currentEntity,
+                loadingStatus: 'loading'
+            };
+
+            const result = connectorCanvasEntityReducer(
+                priorState,
+                loadConnectorEntitySuccess({ connectorEntity: newerEntity })
+            );
+
+            expect(result.connectorEntity).toBe(newerEntity);
+        });
     });
 
     describe('loadConnectorEntityFailure', () => {
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.ts
index 483e3f326d7..89ab096e4f7 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas-entity/connector-canvas-entity.reducer.ts
@@ -16,6 +16,7 @@
  */
 
 import { createReducer, on } from '@ngrx/store';
+import { ConnectorEntity } from '@nifi/shared';
 import { initialConnectorCanvasEntityState } from './index';
 import {
     loadConnectorEntity,
@@ -33,6 +34,10 @@ import {
     resetConnectorCanvasEntityState
 } from './connector-canvas-entity.actions';
 
+function reconcileConnectorEntity(current: ConnectorEntity | null, incoming: 
ConnectorEntity): ConnectorEntity {
+    return current?.id === incoming.id && incoming.revision.version < 
current.revision.version ? current : incoming;
+}
+
 export const connectorCanvasEntityReducer = createReducer(
     initialConnectorCanvasEntityState,
 
@@ -44,7 +49,7 @@ export const connectorCanvasEntityReducer = createReducer(
 
     on(loadConnectorEntitySuccess, (state, { connectorEntity }) => ({
         ...state,
-        connectorEntity,
+        connectorEntity: reconcileConnectorEntity(state.connectorEntity, 
connectorEntity),
         loadingStatus: 'success' as const,
         error: null
     })),
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.html
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.html
index 6a3b3661315..0e54dbc8c0d 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.html
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.html
@@ -84,24 +84,36 @@
             </div>
             @if (showDrain() || showCancelDrain()) {
                 <div class="flex gap-1 flex-wrap">
-                    @if (showDrain()) {
-                        <button
-                            mat-stroked-button
-                            type="button"
-                            [disabled]="!canDrain()"
-                            data-qa="connector-panel-drain"
-                            (click)="drainConnector()">
-                            Drain
-                        </button>
-                    } @else if (showCancelDrain()) {
-                        <button
-                            mat-stroked-button
-                            type="button"
-                            [disabled]="!canCancelDrain()"
-                            data-qa="connector-panel-cancel-drain"
-                            (click)="cancelDrain()">
-                            Cancel Drain
-                        </button>
+                    @if (showCancelDrain()) {
+                        <span
+                            class="flex"
+                            [matTooltip]="getCancelDrainDisabledReason()"
+                            [matTooltipDisabled]="canCancelDrain()"
+                            data-qa="connector-panel-cancel-drain-tooltip">
+                            <button
+                                mat-stroked-button
+                                type="button"
+                                [disabled]="!canCancelDrain()"
+                                data-qa="connector-panel-cancel-drain"
+                                (click)="cancelDrain()">
+                                Cancel Drain
+                            </button>
+                        </span>
+                    } @else if (showDrain()) {
+                        <span
+                            class="flex"
+                            [matTooltip]="getDrainDisabledReason()"
+                            [matTooltipDisabled]="canDrain()"
+                            data-qa="connector-panel-drain-tooltip">
+                            <button
+                                mat-stroked-button
+                                type="button"
+                                [disabled]="!canDrain()"
+                                data-qa="connector-panel-drain"
+                                (click)="drainConnector()">
+                                Drain
+                            </button>
+                        </span>
                     }
                 </div>
             }
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.spec.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.spec.ts
index 757137e0fa6..949d8985547 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.spec.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.spec.ts
@@ -16,7 +16,9 @@
  */
 
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
 import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { MatTooltip } from '@angular/material/tooltip';
 import { provideMockStore, MockStore } from '@ngrx/store/testing';
 import { ConnectorInfoControl } from './connector-info-control.component';
 import { ConnectorEntity, ConnectorStatus, Storage } from '@nifi/shared';
@@ -260,31 +262,86 @@ describe('ConnectorInfoControl', () => {
             expect(button.textContent).toContain('Drain');
         });
 
-        it('should not show drain button when DRAIN_FLOWFILES is not allowed', 
async () => {
+        it.each(['Connector must be stopped', 'No data is queued'])(
+            'should disable drain and show "%s" when DRAIN_FLOWFILES is not 
allowed',
+            async (reasonNotAllowed) => {
+                const entity = createMockConnectorEntity({
+                    component: {
+                        ...createMockConnectorEntity().component,
+                        availableActions: [
+                            {
+                                name: 'DRAIN_FLOWFILES',
+                                description: 'Drain',
+                                allowed: false,
+                                reasonNotAllowed
+                            },
+                            { name: 'CANCEL_DRAIN_FLOWFILES', description: 
'Cancel', allowed: false },
+                            { name: 'DISCARD_WORKING_CONFIGURATION', 
description: 'Discard', allowed: false },
+                            { name: 'CONFIGURE', description: 'Configure', 
allowed: true }
+                        ]
+                    }
+                });
+                const { fixture } = await setup({ connectorEntity: entity });
+
+                const button = 
fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]');
+                const tooltip = fixture.debugElement
+                    .query(By.css('[data-qa="connector-panel-drain-tooltip"]'))
+                    .injector.get(MatTooltip);
+
+                expect(button).toBeTruthy();
+                expect(button.disabled).toBe(true);
+                expect(tooltip.message).toBe(reasonNotAllowed);
+                expect(tooltip.disabled).toBe(false);
+            }
+        );
+
+        it('should render but disable drain button when entity is saving', 
async () => {
+            const entity = createMockConnectorEntity();
+            const { fixture } = await setup({ connectorEntity: entity, 
entitySaving: true });
+
+            const button = 
fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]');
+            const tooltip = fixture.debugElement
+                .query(By.css('[data-qa="connector-panel-drain-tooltip"]'))
+                .injector.get(MatTooltip);
+
+            expect(button).toBeTruthy();
+            expect(button.disabled).toBe(true);
+            expect(button.textContent).toContain('Drain');
+            expect(tooltip.message).toBe('Request in progress');
+            expect(tooltip.disabled).toBe(false);
+        });
+
+        it('should not dispatch when the disabled drain button is clicked', 
async () => {
             const entity = createMockConnectorEntity({
                 component: {
                     ...createMockConnectorEntity().component,
                     availableActions: [
-                        { name: 'DRAIN_FLOWFILES', description: 'Drain', 
allowed: false },
-                        { name: 'CANCEL_DRAIN_FLOWFILES', description: 
'Cancel', allowed: false },
-                        { name: 'DISCARD_WORKING_CONFIGURATION', description: 
'Discard', allowed: false },
-                        { name: 'CONFIGURE', description: 'Configure', 
allowed: true }
+                        {
+                            name: 'DRAIN_FLOWFILES',
+                            description: 'Drain',
+                            allowed: false,
+                            reasonNotAllowed: 'No data is queued'
+                        },
+                        { name: 'CANCEL_DRAIN_FLOWFILES', description: 
'Cancel', allowed: false }
                     ]
                 }
             });
-            const { fixture } = await setup({ connectorEntity: entity });
+            const { fixture, dispatchSpy } = await setup({ connectorEntity: 
entity });
 
-            const button = 
fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]');
-            expect(button).toBeNull();
+            
fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]').click();
+
+            expect(dispatchSpy).not.toHaveBeenCalled();
         });
 
-        it('should render but disable drain button when entity is saving', 
async () => {
+        it('should disable the tooltip when drain is allowed', async () => {
             const entity = createMockConnectorEntity();
-            const { fixture } = await setup({ connectorEntity: entity, 
entitySaving: true });
+            const { fixture } = await setup({ connectorEntity: entity });
 
-            const button = 
fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]');
-            expect(button).toBeTruthy();
-            expect(button.disabled).toBe(true);
+            const tooltip = fixture.debugElement
+                .query(By.css('[data-qa="connector-panel-drain-tooltip"]'))
+                .injector.get(MatTooltip);
+
+            expect(tooltip.disabled).toBe(true);
         });
 
         it('should dispatch promptDrainConnector when drain button is 
clicked', async () => {
@@ -306,6 +363,21 @@ describe('ConnectorInfoControl', () => {
             expect(component.showDrain()).toBe(true);
         });
 
+        it('showDrain should remain true when DRAIN_FLOWFILES is not allowed', 
async () => {
+            const entity = createMockConnectorEntity({
+                component: {
+                    ...createMockConnectorEntity().component,
+                    availableActions: [
+                        { name: 'DRAIN_FLOWFILES', description: 'Drain', 
allowed: false },
+                        { name: 'CANCEL_DRAIN_FLOWFILES', description: 
'Cancel', allowed: false }
+                    ]
+                }
+            });
+            const { component } = await setup({ connectorEntity: entity });
+
+            expect(component.showDrain()).toBe(true);
+        });
+
         it('canDrain should be false while entity is saving', async () => {
             const entity = createMockConnectorEntity();
             const { component } = await setup({ connectorEntity: entity, 
entitySaving: true });
@@ -332,6 +404,7 @@ describe('ConnectorInfoControl', () => {
             const button = 
fixture.nativeElement.querySelector('[data-qa="connector-panel-cancel-drain"]');
             expect(button).toBeTruthy();
             expect(button.textContent).toContain('Cancel Drain');
+            
expect(fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]')).toBeNull();
         });
 
         it('should not show cancel drain button when CANCEL_DRAIN_FLOWFILES is 
not allowed', async () => {
@@ -359,8 +432,16 @@ describe('ConnectorInfoControl', () => {
             const { fixture } = await setup({ connectorEntity: entity, 
entitySaving: true });
 
             const button = 
fixture.nativeElement.querySelector('[data-qa="connector-panel-cancel-drain"]');
+            const tooltip = fixture.debugElement
+                
.query(By.css('[data-qa="connector-panel-cancel-drain-tooltip"]'))
+                .injector.get(MatTooltip);
+
             expect(button).toBeTruthy();
             expect(button.disabled).toBe(true);
+            expect(button.textContent).toContain('Cancel Drain');
+            expect(tooltip.message).toBe('Request in progress');
+            expect(tooltip.disabled).toBe(false);
+            
expect(fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]')).toBeNull();
         });
 
         it('should dispatch cancelConnectorDrain when cancel drain button is 
clicked', async () => {
@@ -430,6 +511,7 @@ describe('ConnectorInfoControl', () => {
 
             const button = 
fixture.nativeElement.querySelector('[data-qa="connector-panel-drain"]');
             expect(button).toBeNull();
+            
expect(fixture.nativeElement.querySelector('[data-qa="connector-panel-cancel-drain"]')).toBeNull();
         });
 
         it('should not show start/stop buttons when user lacks operate 
permissions', async () => {
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.ts
index 5e25d700778..b00bd91b0fa 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-canvas/graph-controls/connector-info-control/connector-info-control.component.ts
@@ -56,6 +56,7 @@ export class ConnectorInfoControl {
 
     private static readonly CONTROL_VISIBILITY_KEY = 
'graph-control-visibility';
     private static readonly CONNECTOR_KEY = 'connector-info-control';
+    private static readonly REQUEST_IN_PROGRESS_REASON = 'Request in progress';
 
     connectorCollapsed = false;
 
@@ -121,7 +122,7 @@ export class ConnectorInfoControl {
         if (!entity) {
             return false;
         }
-        return canOperateConnector(entity) && isConnectorActionAllowed(entity, 
'DRAIN_FLOWFILES');
+        return canOperateConnector(entity) && 
!isConnectorActionAllowed(entity, 'CANCEL_DRAIN_FLOWFILES');
     }
 
     showCancelDrain(): boolean {
@@ -148,6 +149,24 @@ export class ConnectorInfoControl {
         return canOperateConnector(entity) && isConnectorActionAllowed(entity, 
'CANCEL_DRAIN_FLOWFILES');
     }
 
+    getDrainDisabledReason(): string {
+        if (this.entitySaving()) {
+            return ConnectorInfoControl.REQUEST_IN_PROGRESS_REASON;
+        }
+
+        const entity = this.connectorEntity();
+        return entity ? getConnectorActionDisabledReason(entity, 
'DRAIN_FLOWFILES') : '';
+    }
+
+    getCancelDrainDisabledReason(): string {
+        if (this.entitySaving()) {
+            return ConnectorInfoControl.REQUEST_IN_PROGRESS_REASON;
+        }
+
+        const entity = this.connectorEntity();
+        return entity ? getConnectorActionDisabledReason(entity, 
'CANCEL_DRAIN_FLOWFILES') : '';
+    }
+
     showOperateButtons(): boolean {
         const entity = this.connectorEntity();
         return !!entity && canOperateConnector(entity);

Reply via email to