Skip to content

Conversation

@rhamilto
Copy link
Member

@rhamilto rhamilto commented Jan 21, 2026

Summary

Continues the migration of modals from the legacy createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook. This PR migrates 4 additional modals and removes 1 orphaned modal.

Note: This PR builds on #15932.

Changes

Modals Migrated (4 total)

All modals now follow the OverlayComponent pattern with consistent implementation:

  1. ConfigureUpdateStrategyModal (public/components/modals/configure-update-strategy-modal.tsx)

    • Wrapped with ConfigureUpdateStrategyModalProvider: OverlayComponent
    • Exported as LazyConfigureUpdateStrategyModalProvider with lazy loading
    • Updated in useDeploymentActions hook
  2. ConfigureNamespacePullSecretModal (public/components/modals/configure-ns-pull-secret-modal.tsx)

    • Wrapped with ConfigureNamespacePullSecretModalProvider: OverlayComponent
    • Updated in namespace.jsx to use useOverlay() hook
  3. ConfigureClusterUpstreamModal (public/components/modals/configure-cluster-upstream-modal.tsx)

    • Wrapped with ConfigureClusterUpstreamModalProvider: OverlayComponent
    • Updated in details-page.tsx to use useOverlay() hook
    • Fixed react-modal accessibility warnings with proper app element setup
  4. ManagedResourceSaveModal (public/components/modals/managed-resource-save-modal.tsx)

    • Wrapped with ManagedResourceSaveModalProvider: OverlayComponent
    • Updated in edit-yaml.tsx to use useOverlay() hook
    • Removed unnecessary 'kind' prop from modal invocation

Cleanup

  1. RemoveUserModal (public/components/modals/remove-user-modal.tsx)
    • Deleted orphaned modal that was already replaced by useWarningModal in group.tsx
    • Removed LazyRemoveUserModalProvider export from index.ts

Pattern Example

// Modal file
export const ConfigureUpdateStrategyModalProvider: OverlayComponent<ConfigureUpdateStrategyModalProps> = (props) => {
  return (
    <ModalWrapper blocking onClose={props.closeOverlay}>
      <ConfigureUpdateStrategyModal cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
    </ModalWrapper>
  );
};

export default ConfigureUpdateStrategyModalProvider;
// index.ts
export const LazyConfigureUpdateStrategyModalProvider = lazy(() =>
  import('./configure-update-strategy-modal').then((m) => ({ default: m.default })),
);
// Usage in action hook
const launchModal = useOverlay();

return useMemo(
  () => ({
    id: 'edit-update-strategy',
    label: t('public~Edit update strategy'),
    cta: () => launchModal(LazyConfigureUpdateStrategyModalProvider, { deployment }),
  }),
  [t, deployment], // launchModal intentionally omitted
);

Benefits

  • ✅ Consistent pattern across all modals
  • ✅ Better code splitting with lazy loading
  • ✅ Proper React hooks integration
  • ✅ Maintains backward compatibility with default exports
  • ✅ Improved maintainability
  • ✅ Fixed react-modal accessibility warnings

Testing

  • All 4 modals open and close correctly
  • Configure update strategy modal works for Deployments
  • Configure namespace pull secret modal works
  • Configure cluster upstream modal works
  • Managed resource save modal works in YAML editor
  • No console errors or infinite loops
  • Lazy loading works correctly (check Network tab for separate chunks)

Related

🤖 Generated with Claude Code

@openshift-ci-robot
Copy link
Contributor

@rhamilto: No Jira issue with key CONSOLE-5212 exists in the tracker at https://issues.redhat.com/.
Once a valid jira issue is referenced in the title of this pull request, request a refresh with /jira refresh.

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jan 21, 2026
@openshift-ci-robot
Copy link
Contributor

@rhamilto: No Jira issue with key CONSOLE-5212 exists in the tracker at https://issues.redhat.com/.
Once a valid jira issue is referenced in the title of this pull request, request a refresh with /jira refresh.

Details

In response to this:

Includes changes from #15932, which should merge first.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot requested review from cajieh and spadgett January 21, 2026 16:22
@openshift-ci openshift-ci bot added component/core Related to console core functionality approved Indicates a PR has been approved by an approver from all required OWNERS files. component/dev-console Related to dev-console component/knative Related to knative-plugin component/sdk Related to console-plugin-sdk labels Jan 21, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 21, 2026

@rhamilto: No Jira issue with key CONSOLE-5212 exists in the tracker at https://issues.redhat.com/.
Once a valid jira issue is referenced in the title of this pull request, request a refresh with /jira refresh.

Details

In response to this:

Summary

This PR continues the migration of legacy modals from the createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook.

Note: This PR builds on #15932, which should merge first.

Changes Included

Modal Migrations

  1. configure-update-strategy-modal (aa2e2d3)
  • Migrated to OverlayComponent pattern
  • Updated usages in Deployment and DaemonSet actions
  1. configure-ns-pull-secret-modal (a9ab259)
  • Migrated to OverlayComponent pattern
  • Updated usage in namespace actions
  1. configure-cluster-upstream-modal (1359e50)
  • Migrated to OverlayComponent pattern
  • Updated usage in ClusterVersion details page
  • Fixed react-modal accessibility warnings
  1. managed-resource-save-modal (b468570)
  • Migrated to OverlayComponent pattern
  • Updated usage in edit-yaml.tsx to use useOverlay hook
  1. rollback-modal (aebae95)
  • Migrated to OverlayComponent pattern
  • Updated useReplicationControllerActions hook
  • Updated useReplicaSetActions hook

Cleanup

  1. remove-user-modal (a3bc91d)
  • Removed orphaned modal (functionality replaced by useWarningModal in group.tsx)

Pattern Used

All migrations follow the same pattern:

  • Export [ModalName]Provider as an OverlayComponent
  • Add lazy-loaded export in modals/index.ts as Lazy[ModalName]Provider
  • Update all usages to call launchModal(Lazy[ModalName]Provider, props) instead of the old modal launcher
  • Remove createModalLauncher usage

Testing

Each modal can be tested via:

  • configure-update-strategy-modal: Deployment/DaemonSet actions → "Edit update strategy"
  • configure-ns-pull-secret-modal: Namespace actions → "Edit pull secret"
  • configure-cluster-upstream-modal: ClusterVersion details page → "Channel" pencil icon
  • managed-resource-save-modal: Edit YAML of operator-managed resource → Save
  • rollback-modal: ReplicaSet/ReplicationController actions → "Rollback"

Related

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

1 similar comment
@openshift-ci-robot
Copy link
Contributor

@rhamilto: No Jira issue with key CONSOLE-5212 exists in the tracker at https://issues.redhat.com/.
Once a valid jira issue is referenced in the title of this pull request, request a refresh with /jira refresh.

Details

In response to this:

Summary

This PR continues the migration of legacy modals from the createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook.

Note: This PR builds on #15932, which should merge first.

Changes Included

Modal Migrations

  1. configure-update-strategy-modal (aa2e2d3)
  • Migrated to OverlayComponent pattern
  • Updated usages in Deployment and DaemonSet actions
  1. configure-ns-pull-secret-modal (a9ab259)
  • Migrated to OverlayComponent pattern
  • Updated usage in namespace actions
  1. configure-cluster-upstream-modal (1359e50)
  • Migrated to OverlayComponent pattern
  • Updated usage in ClusterVersion details page
  • Fixed react-modal accessibility warnings
  1. managed-resource-save-modal (b468570)
  • Migrated to OverlayComponent pattern
  • Updated usage in edit-yaml.tsx to use useOverlay hook
  1. rollback-modal (aebae95)
  • Migrated to OverlayComponent pattern
  • Updated useReplicationControllerActions hook
  • Updated useReplicaSetActions hook

Cleanup

  1. remove-user-modal (a3bc91d)
  • Removed orphaned modal (functionality replaced by useWarningModal in group.tsx)

Pattern Used

All migrations follow the same pattern:

  • Export [ModalName]Provider as an OverlayComponent
  • Add lazy-loaded export in modals/index.ts as Lazy[ModalName]Provider
  • Update all usages to call launchModal(Lazy[ModalName]Provider, props) instead of the old modal launcher
  • Remove createModalLauncher usage

Testing

Each modal can be tested via:

  • configure-update-strategy-modal: Deployment/DaemonSet actions → "Edit update strategy"
  • configure-ns-pull-secret-modal: Namespace actions → "Edit pull secret"
  • configure-cluster-upstream-modal: ClusterVersion details page → "Channel" pencil icon
  • managed-resource-save-modal: Edit YAML of operator-managed resource → Save
  • rollback-modal: ReplicaSet/ReplicationController actions → "Rollback"

Related

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@rhamilto rhamilto changed the title [WIP] CONSOLE-5212: Migrate modals to overlay pattern [WIP] CONSOLE-5012: Migrate modals to overlay pattern Jan 21, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jan 21, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 21, 2026

@rhamilto: This pull request references CONSOLE-5012 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

This PR continues the migration of legacy modals from the createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook.

Note: This PR builds on #15932, which should merge first.

Changes Included

Modal Migrations

  1. configure-update-strategy-modal (aa2e2d3)
  • Migrated to OverlayComponent pattern
  • Updated usages in Deployment and DaemonSet actions
  1. configure-ns-pull-secret-modal (a9ab259)
  • Migrated to OverlayComponent pattern
  • Updated usage in namespace actions
  1. configure-cluster-upstream-modal (1359e50)
  • Migrated to OverlayComponent pattern
  • Updated usage in ClusterVersion details page
  • Fixed react-modal accessibility warnings
  1. managed-resource-save-modal (b468570)
  • Migrated to OverlayComponent pattern
  • Updated usage in edit-yaml.tsx to use useOverlay hook
  1. rollback-modal (aebae95)
  • Migrated to OverlayComponent pattern
  • Updated useReplicationControllerActions hook
  • Updated useReplicaSetActions hook

Cleanup

  1. remove-user-modal (a3bc91d)
  • Removed orphaned modal (functionality replaced by useWarningModal in group.tsx)

Pattern Used

All migrations follow the same pattern:

  • Export [ModalName]Provider as an OverlayComponent
  • Add lazy-loaded export in modals/index.ts as Lazy[ModalName]Provider
  • Update all usages to call launchModal(Lazy[ModalName]Provider, props) instead of the old modal launcher
  • Remove createModalLauncher usage

Testing

Each modal can be tested via:

  • configure-update-strategy-modal: Deployment/DaemonSet actions → "Edit update strategy"
  • configure-ns-pull-secret-modal: Namespace actions → "Edit pull secret"
  • configure-cluster-upstream-modal: ClusterVersion details page → "Channel" pencil icon
  • managed-resource-save-modal: Edit YAML of operator-managed resource → Save
  • rollback-modal: ReplicaSet/ReplicationController actions → "Rollback"

Related

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 21, 2026

@rhamilto: This pull request references CONSOLE-5012 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

This PR continues the migration of modals from the legacy createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook.

Note: This PR builds on #15932 (PVC modals, delete-modal, configure-update-strategy-modal, configure-ns-pull-secret-modal, configure-cluster-upstream-modal).

This PR includes the following changes:

Modals Migrated (2)

  1. managed-resource-save-modal - Used when editing YAML of managed resources
  • Updated: public/components/modals/managed-resource-save-modal.tsx
  • Updated: public/components/edit-yaml.tsx
  1. remove-user-modal - Removed as orphaned code
  • Deleted: public/components/modals/remove-user-modal.tsx
  • This modal was already replaced by useWarningModal in group.tsx

Additional Fixes

  1. Fixed launchModal dependency issues in existing action hooks
  • The launchModal function from useOverlay() returns a new reference on every render
  • Including it in dependency arrays causes infinite re-render loops
  • Added eslint-disable comments with explanations in:
    • useRetryRolloutAction.ts
    • build-config-provider.ts
    • machine-config-pool-provider.ts
    • edit-yaml.tsx (from managed-resource-save-modal migration)

Changes Made

For each modal:

  • Removed createModalLauncher usage
  • Added OverlayComponent and ModalWrapper imports
  • Exported modal as [Name]Provider wrapping content in ModalWrapper
  • Updated index files to use React.lazy() for code splitting
  • Updated usages to use useOverlay() hook with launchModal()
  • Added appropriate ESLint disable comments for launchModal dependencies to prevent infinite loops

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 21, 2026

@rhamilto: This pull request references CONSOLE-5012 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

This PR continues the migration of modals from the legacy createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook.

Note: This PR builds on #15932. The commits from #15932 are included at the base of this PR.

Commits from PR #15932 (base - 3 commits)

  1. CONSOLE-5012: Migrate PVC modals to overlay pattern
  2. CONSOLE-5012: Migrate delete-modal and actions to overlay pattern
  3. CONSOLE-5012: Fix launchModal dependency in existing action hooks

New Commits in This PR (5 commits)

  1. CONSOLE-5012: Migrate configure-update-strategy-modal to overlay pattern
  • Updated: packages/console-app/src/actions/hooks/useDeploymentActions.ts
  • Updated: public/components/modals/configure-update-strategy-modal.tsx
  1. CONSOLE-5012: Migrate configure-ns-pull-secret-modal to overlay pattern
  • Updated: public/components/modals/configure-ns-pull-secret-modal.tsx
  1. CONSOLE-5012: Migrate configure-cluster-upstream-modal to overlay pattern
  • Updated: public/components/modals/configure-cluster-upstream-modal.tsx
  1. CONSOLE-5012: Migrate managed-resource-save-modal to overlay pattern
  • Updated: public/components/modals/managed-resource-save-modal.tsx
  • Updated: public/components/edit-yaml.tsx
  • Added eslint-disable comment for launchModal dependency
  1. CONSOLE-5012: Remove orphaned remove-user-modal
  • Deleted: public/components/modals/remove-user-modal.tsx
  • This modal was already replaced by useWarningModal in group.tsx

Summary of Changes

For each migrated modal:

  • Removed createModalLauncher usage
  • Added OverlayComponent and ModalWrapper imports
  • Exported modal as [Name]Provider wrapping content in ModalWrapper
  • Updated index files to use React.lazy() for code splitting
  • Updated usages to use useOverlay() hook with launchModal()
  • Added appropriate ESLint disable comments for launchModal dependencies where needed

launchModal Dependency Issue

The launchModal function from useOverlay() returns a new reference on every render (similar to setState from useState). Including it in dependency arrays causes infinite re-render loops. All affected files now have eslint-disable comments documenting this intentional exclusion.

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

1 similar comment
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 21, 2026

@rhamilto: This pull request references CONSOLE-5012 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

This PR continues the migration of modals from the legacy createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook.

Note: This PR builds on #15932. The commits from #15932 are included at the base of this PR.

Commits from PR #15932 (base - 3 commits)

  1. CONSOLE-5012: Migrate PVC modals to overlay pattern
  2. CONSOLE-5012: Migrate delete-modal and actions to overlay pattern
  3. CONSOLE-5012: Fix launchModal dependency in existing action hooks

New Commits in This PR (5 commits)

  1. CONSOLE-5012: Migrate configure-update-strategy-modal to overlay pattern
  • Updated: packages/console-app/src/actions/hooks/useDeploymentActions.ts
  • Updated: public/components/modals/configure-update-strategy-modal.tsx
  1. CONSOLE-5012: Migrate configure-ns-pull-secret-modal to overlay pattern
  • Updated: public/components/modals/configure-ns-pull-secret-modal.tsx
  1. CONSOLE-5012: Migrate configure-cluster-upstream-modal to overlay pattern
  • Updated: public/components/modals/configure-cluster-upstream-modal.tsx
  1. CONSOLE-5012: Migrate managed-resource-save-modal to overlay pattern
  • Updated: public/components/modals/managed-resource-save-modal.tsx
  • Updated: public/components/edit-yaml.tsx
  • Added eslint-disable comment for launchModal dependency
  1. CONSOLE-5012: Remove orphaned remove-user-modal
  • Deleted: public/components/modals/remove-user-modal.tsx
  • This modal was already replaced by useWarningModal in group.tsx

Summary of Changes

For each migrated modal:

  • Removed createModalLauncher usage
  • Added OverlayComponent and ModalWrapper imports
  • Exported modal as [Name]Provider wrapping content in ModalWrapper
  • Updated index files to use React.lazy() for code splitting
  • Updated usages to use useOverlay() hook with launchModal()
  • Added appropriate ESLint disable comments for launchModal dependencies where needed

launchModal Dependency Issue

The launchModal function from useOverlay() returns a new reference on every render (similar to setState from useState). Including it in dependency arrays causes infinite re-render loops. All affected files now have eslint-disable comments documenting this intentional exclusion.

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@rhamilto
Copy link
Member Author

@CodeRabbit review

@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 21, 2026

@rhamilto: This pull request references CONSOLE-5012 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

This PR continues the migration of modals from the legacy createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook.

Note: This PR builds on #15932. The commits from #15932 are included at the base of this PR.

Commits from PR #15932 (base - 3 commits)

  1. CONSOLE-5012: Migrate PVC modals to overlay pattern
  2. CONSOLE-5012: Migrate delete-modal and actions to overlay pattern
  3. CONSOLE-5012: Fix launchModal dependency in existing action hooks

New Commits in This PR (5 commits)

  1. CONSOLE-5012: Migrate configure-update-strategy-modal to overlay pattern
  • Updated: packages/console-app/src/actions/hooks/useDeploymentActions.ts
  • Updated: public/components/modals/configure-update-strategy-modal.tsx
  1. CONSOLE-5012: Migrate configure-ns-pull-secret-modal to overlay pattern
  • Updated: public/components/modals/configure-ns-pull-secret-modal.tsx
  1. CONSOLE-5012: Migrate configure-cluster-upstream-modal to overlay pattern
  • Updated: public/components/modals/configure-cluster-upstream-modal.tsx
  1. CONSOLE-5012: Migrate managed-resource-save-modal to overlay pattern
  • Updated: public/components/modals/managed-resource-save-modal.tsx
  • Updated: public/components/edit-yaml.tsx
  • Added eslint-disable comment for launchModal dependency
  1. CONSOLE-5012: Remove orphaned remove-user-modal
  • Deleted: public/components/modals/remove-user-modal.tsx
  • This modal was already replaced by useWarningModal in group.tsx

Summary of Changes

For each migrated modal:

  • Removed createModalLauncher usage
  • Added OverlayComponent and ModalWrapper imports
  • Exported modal as [Name]Provider wrapping content in ModalWrapper
  • Updated index files to use React.lazy() for code splitting
  • Updated usages to use useOverlay() hook with launchModal()
  • Added appropriate ESLint disable comments for launchModal dependencies where needed

launchModal Dependency Issue

The launchModal function from useOverlay() returns a new reference on every render (similar to setState from useState). Including it in dependency arrays causes infinite re-render loops. All affected files now have eslint-disable comments documenting this intentional exclusion.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

  • Improved modal accessibility configuration for screen readers and assistive technologies.

  • Enabled lazy-loading of modal dialogs for better performance and reduced initial bundle size.

  • Bug Fixes

  • Enhanced modal rendering reliability through Suspense boundaries.

  • Refactor

  • Modernized modal system architecture from direct function calls to provider-based overlay pattern for improved maintainability.

✏️ Tip: You can customize this high-level summary in your review settings.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

📝 Walkthrough

Walkthrough

This pull request converts the modal system from direct launcher patterns to overlay-based provider components with lazy loading support. Multiple action hooks and modal exports are refactored to use LazyDeleteModalProvider, LazyClonePVCModalProvider, and other lazy provider wrappers instead of direct modal invocations. Modal components are wrapped in ModalWrapper inside OverlayComponent provider exports, with closeOverlay wired to close handlers. Suspense boundaries are added to OverlayProvider for lazy component rendering. React Modal is initialized with per-instance appElement handling. Several useMemo dependency arrays are adjusted by removing launchModal with eslint-disable comments. The RemoveUserModal component is deleted entirely. Modal props are simplified by extending ModalComponentProps and removing redundant cancel/close callbacks.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: migration of modals to an overlay pattern, directly reflecting the substantial architectural refactoring across multiple modal components and action hooks throughout the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@frontend/packages/dev-console/src/actions/context-menu.ts`:
- Around line 1-6: Guard against application.resources being undefined by
defaulting to an empty array before iterating: replace direct calls like
application.resources.forEach(...) with (application.resources ??
[]).forEach(...) (or Array.isArray check) in the delete action and any cleanup
loops that touch application.resources (e.g., the delete modal / cleanup logic
using application.resources), and apply the same change to all other occurrences
in this file where application.resources is iterated.

In `@frontend/packages/knative-plugin/src/actions/creators.ts`:
- Around line 120-153: The useMemo in useDeleteKnativeServiceResource is
including the launchModal value from useOverlay in its dependency array which
forces the memo to recreate on every render; remove launchModal from the
dependencies and leave [kind, obj, serviceTypeValue, serviceCreatedFromWebFlag]
instead, and add the same explanatory comment used elsewhere: "missing
launchModal dependency, that causes max depth exceeded error."; apply the same
change/comment pattern to SecretKeySelector's hook where launchModal is
currently included.

In `@frontend/public/components/modals/configure-cluster-upstream-modal.tsx`:
- Around line 169-178: The provider currently spreads {...props} after passing
cancel/close to ConfigureClusterUpstreamModal so caller-supplied cancel/close
can override the provider's closeOverlay; update
ConfigureClusterUpstreamModalProvider to pass {...props} first and then
explicitly set cancel={props.closeOverlay} and close={props.closeOverlay} (or
otherwise ensure the provider's closeOverlay wins) so the ModalWrapper/provider
always controls closing; refer to ConfigureClusterUpstreamModalProvider,
ConfigureClusterUpstreamModal, props, and closeOverlay when making the change.

In `@frontend/public/components/modals/index.ts`:
- Around line 97-102: The lazy import for LazyClonePVCModalProvider should use
the module default export to match the pattern used by
LazyExpandPVCModalProvider and LazyConfigureClusterUpstreamModalProvider; update
the .then handler to return { default: m.default } (or simply use m.default)
instead of { default: m.ClonePVCModalProvider } so it consistently consumes the
component via the module's default export (the component is exported both named
and default as ClonePVCModalProvider).
🧹 Nitpick comments (6)
frontend/packages/console-dynamic-plugin-sdk/src/app/modal-support/OverlayProvider.tsx (1)

55-57: Suspense addition is appropriate for lazy-loaded modal providers.

The fallback={null} is the right choice here—you don't want a loading spinner flashing before the modal materializes. This cleanly supports the lazy provider pattern (React.lazy()) being rolled out across the modal migrations.

One consideration: if a lazy chunk fails to load (network hiccup, 404'd chunk after a deployment), the error will propagate upward with no local catch. You might want to wrap this in an ErrorBoundary to gracefully handle chunk loading failures without potentially unmounting the entire overlay context tree.

💡 Optional: Add ErrorBoundary for chunk loading resilience
+import ErrorBoundary from '@console/shared/src/components/error/ErrorBoundary';
+// Or implement a minimal local ErrorBoundary if preferred
 
 // Inside the render:
       {_.map(componentsMap, (c, id) => (
-        <Suspense key={id} fallback={null}>
-          <c.Component {...c.props} closeOverlay={() => closeOverlay(id)} />
-        </Suspense>
+        <ErrorBoundary key={id} FallbackComponent={() => null}>
+          <Suspense fallback={null}>
+            <c.Component {...c.props} closeOverlay={() => closeOverlay(id)} />
+          </Suspense>
+        </ErrorBoundary>
       ))}

This ensures a failed lazy import doesn't take down the entire overlay system—graceful degradation for production resilience.

frontend/packages/console-app/src/actions/hooks/useRetryRolloutAction.ts (1)

98-100: Avoid stale launchModal by stabilizing it instead of suppressing deps.

Suppressing exhaustive-deps can capture a stale overlay context if the provider remounts; use a ref to keep the latest launchModal and drop the eslint disable.

♻️ Proposed refactor
-import { useMemo } from 'react';
+import { useEffect, useMemo, useRef } from 'react';
@@
   const { t } = useTranslation();
   const launchModal = useOverlay();
+  const launchModalRef = useRef(launchModal);
+  useEffect(() => {
+    launchModalRef.current = launchModal;
+  }, [launchModal]);
@@
-      cta: () =>
-        retryRollout(rcModel, rc).catch((err) => launchModal(ErrorModal, { error: err.message })),
+      cta: () =>
+        retryRollout(rcModel, rc).catch((err) =>
+          launchModalRef.current(ErrorModal, { error: err.message }),
+        ),
@@
-    // missing launchModal dependency, that causes max depth exceeded error
-    // eslint-disable-next-line react-hooks/exhaustive-deps
     [t, dcModel, rcModel, rc, canRetry, resource],
frontend/packages/console-app/src/components/modals/clone/clone-pvc-modal.tsx (1)

279-285: Guard against callers overriding closeOverlay.
Because ...props comes last, any passed cancel/close would override the overlay close handler. Prefer spreading first, then explicitly wiring closeOverlay to enforce correct dismissal.

♻️ Suggested tweak
-export const ClonePVCModalProvider: OverlayComponent<ClonePVCModalProps> = (props) => {
+export const ClonePVCModalProvider: OverlayComponent<ClonePVCModalProps> = ({
+  closeOverlay,
+  ...rest
+}) => {
   return (
-    <ModalWrapper blocking onClose={props.closeOverlay}>
-      <ClonePVCModal cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
+    <ModalWrapper blocking onClose={closeOverlay}>
+      <ClonePVCModal {...rest} cancel={closeOverlay} close={closeOverlay} />
     </ModalWrapper>
   );
 };

Also applies to: 287-288

frontend/public/components/modals/expand-pvc-modal.tsx (1)

99-105: Provider implementation follows the established pattern.

The ModalWrapper correctly receives blocking and onClose. Wiring closeOverlay to both cancel and close ensures the modal dismisses properly on either action.

One minor note: {...props} spreads closeOverlay into ExpandPVCModal, but ExpandPVCModal destructures only resource, kind, close, and cancel. The extra prop is harmless but slightly redundant. Consider destructuring explicitly if you want cleaner prop forwarding:

♻️ Optional cleanup
-export const ExpandPVCModalProvider: OverlayComponent<ExpandPVCModalProps> = (props) => {
+export const ExpandPVCModalProvider: OverlayComponent<ExpandPVCModalProps> = ({
+  closeOverlay,
+  ...rest
+}) => {
   return (
-    <ModalWrapper blocking onClose={props.closeOverlay}>
-      <ExpandPVCModal cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
+    <ModalWrapper blocking onClose={closeOverlay}>
+      <ExpandPVCModal cancel={closeOverlay} close={closeOverlay} {...rest} />
     </ModalWrapper>
   );
 };
frontend/packages/console-app/src/actions/hooks/useDeploymentActions.ts (1)

170-178: Note: resourceLimitsModal still uses legacy pattern.

The EditResourceLimits action still invokes resourceLimitsModal directly rather than through launchModal. Given the PR title indicates WIP, this is presumably planned for a future commit. Just flagging for tracking purposes.

frontend/public/components/modals/configure-update-strategy-modal.tsx (1)

241-253: LGTM - Clean provider implementation following the overlay pattern.

The migration correctly wraps ConfigureUpdateStrategyModal inside ModalWrapper with blocking behavior and wires closeOverlay to both cancel and close handlers. The backward-compatible default export maintains API stability.

Minor observation: The spread {...props} passes closeOverlay to the inner modal which doesn't use it. This is harmless but consider destructuring to keep props clean:

✨ Optional cleanup
-export const ConfigureUpdateStrategyModalProvider: OverlayComponent<ConfigureUpdateStrategyModalProps> = (
-  props,
-) => {
+export const ConfigureUpdateStrategyModalProvider: OverlayComponent<ConfigureUpdateStrategyModalProps> = ({
+  closeOverlay,
+  ...rest
+}) => {
   return (
-    <ModalWrapper blocking onClose={props.closeOverlay}>
+    <ModalWrapper blocking onClose={closeOverlay}>
       <ConfigureUpdateStrategyModal
-        cancel={props.closeOverlay}
-        close={props.closeOverlay}
-        {...props}
+        cancel={closeOverlay}
+        close={closeOverlay}
+        {...rest}
       />
     </ModalWrapper>
   );
 };

Comment on lines 1 to 7
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Action, K8sModel } from '@console/dynamic-plugin-sdk';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { TopologyApplicationObject } from '@console/dynamic-plugin-sdk/src/extensions/topology-types';
import { deleteModal } from '@console/internal/components/modals';
import { LazyDeleteModalProvider } from '@console/internal/components/modals';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard application.resources before forEach.

If application.resources is undefined, the delete action will throw before cleanup. Safer to default to an empty array.

🔧 Proposed fix
-          onSubmit: () => {
-            application.resources.forEach((resource) => {
-              reqs.push(cleanUpWorkload(resource.resource));
-            });
-            return Promise.all(reqs);
-          },
+          onSubmit: () => {
+            (application.resources ?? []).forEach((resource) => {
+              reqs.push(cleanUpWorkload(resource.resource));
+            });
+            return Promise.all(reqs);
+          },

Also applies to: 28-37

🤖 Prompt for AI Agents
In `@frontend/packages/dev-console/src/actions/context-menu.ts` around lines 1 -
6, Guard against application.resources being undefined by defaulting to an empty
array before iterating: replace direct calls like
application.resources.forEach(...) with (application.resources ??
[]).forEach(...) (or Array.isArray check) in the delete action and any cleanup
loops that touch application.resources (e.g., the delete modal / cleanup logic
using application.resources), and apply the same change to all other occurrences
in this file where application.resources is iterated.

Comment on lines 120 to 155
export const useDeleteKnativeServiceResource = (
kind: K8sKind,
obj: K8sResourceKind,
serviceTypeValue: ServiceTypeValue,
serviceCreatedFromWebFlag: boolean,
): Action => ({
id: `delete-resource`,
label:
serviceTypeValue === ServiceTypeValue.Function
? i18next.t('knative-plugin~Delete Function')
: i18next.t('knative-plugin~Delete Service'),
cta: () =>
deleteModal(
serviceCreatedFromWebFlag
? {
kind,
resource: obj,
deleteAllResources: () => cleanUpWorkload(obj),
}
: {
kind,
resource: obj,
},
),
accessReview: asAccessReview(kind, obj, 'delete'),
});
): Action => {
const launchModal = useOverlay();

return useMemo<Action>(
() => ({
id: `delete-resource`,
label:
serviceTypeValue === ServiceTypeValue.Function
? i18next.t('knative-plugin~Delete Function')
: i18next.t('knative-plugin~Delete Service'),
cta: () =>
launchModal(
LazyDeleteModalProvider,
serviceCreatedFromWebFlag
? {
kind,
resource: obj,
deleteAllResources: () => cleanUpWorkload(obj),
}
: {
kind,
resource: obj,
},
),
accessReview: asAccessReview(kind, obj, 'delete'),
}),
[kind, obj, serviceTypeValue, serviceCreatedFromWebFlag, launchModal],
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n frontend/packages/knative-plugin/src/actions/creators.ts | sed -n '120,153p'

Repository: openshift/console

Length of output: 1267


🏁 Script executed:

# Search for launchModal usage with eslint-disable across action hooks
fd -e ts -e tsx frontend/packages/console-app/src/actions | head -20

Repository: openshift/console

Length of output: 530


🏁 Script executed:

# Find all instances of launchModal with eslint-disable comments
rg -n 'launchModal' -B2 -A2 --type ts -g '!*.test.ts' | grep -A2 -B2 'eslint-disable'

Repository: openshift/console

Length of output: 4983


🏁 Script executed:

# Locate and examine the useOverlay hook implementation
find . -name '*useOverlay*' -o -name '*overlay*' -type f | grep -E '\.(ts|tsx)$' | head -10

Repository: openshift/console

Length of output: 143


🏁 Script executed:

# Check for launchModal in providers.ts
rg -n 'launchModal' frontend/packages/knative-plugin/src/providers.ts -B3 -A3

Repository: openshift/console

Length of output: 150


🏁 Script executed:

cat frontend/packages/console-dynamic-plugin-sdk/src/app/modal-support/useOverlay.ts

Repository: openshift/console

Length of output: 2059


🏁 Script executed:

# Find knative providers file
fd 'providers' frontend/packages/knative-plugin/src/ -type f

Repository: openshift/console

Length of output: 231


🏁 Script executed:

# Search for launchModal pattern specifically in knative-plugin
rg -n 'launchModal' frontend/packages/knative-plugin/src/ -B2 -A2

Repository: openshift/console

Length of output: 2841


Exclude launchModal from the dependency array to align with established codebase patterns.

The useOverlay hook returns a context value that is recreated on each render, and including it in the dependency array causes useMemo to unnecessarily recreate the action object on every re-render. This cascades into parent components using useMemo (like those in providers.ts), triggering re-render loops.

The codebase has an established pattern across multiple action hooks in console-app that explicitly excludes launchModal with the comment: "missing launchModal dependency, that causes max depth exceeded error." Apply the same pattern here:

     }),
-    [kind, obj, serviceTypeValue, serviceCreatedFromWebFlag, launchModal],
+    // missing launchModal dependency, that causes max depth exceeded error
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+    [kind, obj, serviceTypeValue, serviceCreatedFromWebFlag],
   );
 };

This also applies to SecretKeySelector.tsx (line 61), which includes launchModal in its dependency array.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const useDeleteKnativeServiceResource = (
kind: K8sKind,
obj: K8sResourceKind,
serviceTypeValue: ServiceTypeValue,
serviceCreatedFromWebFlag: boolean,
): Action => ({
id: `delete-resource`,
label:
serviceTypeValue === ServiceTypeValue.Function
? i18next.t('knative-plugin~Delete Function')
: i18next.t('knative-plugin~Delete Service'),
cta: () =>
deleteModal(
serviceCreatedFromWebFlag
? {
kind,
resource: obj,
deleteAllResources: () => cleanUpWorkload(obj),
}
: {
kind,
resource: obj,
},
),
accessReview: asAccessReview(kind, obj, 'delete'),
});
): Action => {
const launchModal = useOverlay();
return useMemo<Action>(
() => ({
id: `delete-resource`,
label:
serviceTypeValue === ServiceTypeValue.Function
? i18next.t('knative-plugin~Delete Function')
: i18next.t('knative-plugin~Delete Service'),
cta: () =>
launchModal(
LazyDeleteModalProvider,
serviceCreatedFromWebFlag
? {
kind,
resource: obj,
deleteAllResources: () => cleanUpWorkload(obj),
}
: {
kind,
resource: obj,
},
),
accessReview: asAccessReview(kind, obj, 'delete'),
}),
[kind, obj, serviceTypeValue, serviceCreatedFromWebFlag, launchModal],
);
};
export const useDeleteKnativeServiceResource = (
kind: K8sKind,
obj: K8sResourceKind,
serviceTypeValue: ServiceTypeValue,
serviceCreatedFromWebFlag: boolean,
): Action => {
const launchModal = useOverlay();
return useMemo<Action>(
() => ({
id: `delete-resource`,
label:
serviceTypeValue === ServiceTypeValue.Function
? i18next.t('knative-plugin~Delete Function')
: i18next.t('knative-plugin~Delete Service'),
cta: () =>
launchModal(
LazyDeleteModalProvider,
serviceCreatedFromWebFlag
? {
kind,
resource: obj,
deleteAllResources: () => cleanUpWorkload(obj),
}
: {
kind,
resource: obj,
},
),
accessReview: asAccessReview(kind, obj, 'delete'),
}),
// missing launchModal dependency, that causes max depth exceeded error
// eslint-disable-next-line react-hooks/exhaustive-deps
[kind, obj, serviceTypeValue, serviceCreatedFromWebFlag],
);
};
🤖 Prompt for AI Agents
In `@frontend/packages/knative-plugin/src/actions/creators.ts` around lines 120 -
153, The useMemo in useDeleteKnativeServiceResource is including the launchModal
value from useOverlay in its dependency array which forces the memo to recreate
on every render; remove launchModal from the dependencies and leave [kind, obj,
serviceTypeValue, serviceCreatedFromWebFlag] instead, and add the same
explanatory comment used elsewhere: "missing launchModal dependency, that causes
max depth exceeded error."; apply the same change/comment pattern to
SecretKeySelector's hook where launchModal is currently included.

Comment on lines +169 to +178
export const ConfigureClusterUpstreamModalProvider: OverlayComponent<ConfigureClusterUpstreamModalProps> = (
props,
) => {
return (
<ModalWrapper blocking onClose={props.closeOverlay}>
<ConfigureClusterUpstreamModal
cancel={props.closeOverlay}
close={props.closeOverlay}
{...props}
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid overriding closeOverlay via prop spread.

{...props} comes after cancel/close, so any caller-supplied cancel/close would override closeOverlay and potentially prevent the overlay from closing. Flip the order so the provider always controls closing.

🔧 Proposed fix
       <ConfigureClusterUpstreamModal
-        cancel={props.closeOverlay}
-        close={props.closeOverlay}
-        {...props}
+        {...props}
+        cancel={props.closeOverlay}
+        close={props.closeOverlay}
       />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const ConfigureClusterUpstreamModalProvider: OverlayComponent<ConfigureClusterUpstreamModalProps> = (
props,
) => {
return (
<ModalWrapper blocking onClose={props.closeOverlay}>
<ConfigureClusterUpstreamModal
cancel={props.closeOverlay}
close={props.closeOverlay}
{...props}
/>
export const ConfigureClusterUpstreamModalProvider: OverlayComponent<ConfigureClusterUpstreamModalProps> = (
props,
) => {
return (
<ModalWrapper blocking onClose={props.closeOverlay}>
<ConfigureClusterUpstreamModal
{...props}
cancel={props.closeOverlay}
close={props.closeOverlay}
/>
🤖 Prompt for AI Agents
In `@frontend/public/components/modals/configure-cluster-upstream-modal.tsx`
around lines 169 - 178, The provider currently spreads {...props} after passing
cancel/close to ConfigureClusterUpstreamModal so caller-supplied cancel/close
can override the provider's closeOverlay; update
ConfigureClusterUpstreamModalProvider to pass {...props} first and then
explicitly set cancel={props.closeOverlay} and close={props.closeOverlay} (or
otherwise ensure the provider's closeOverlay wins) so the ModalWrapper/provider
always controls closing; refer to ConfigureClusterUpstreamModalProvider,
ConfigureClusterUpstreamModal, props, and closeOverlay when making the change.

Comment on lines 97 to 102
// Lazy-loaded OverlayComponent for Clone PVC Modal
export const LazyClonePVCModalProvider = lazy(() =>
import(
'@console/app/src/components/modals/clone/clone-pvc-modal' /* webpackChunkName: "clone-pvc-modal" */
).then((m) => m.default(props));
).then((m) => ({ default: m.ClonePVCModalProvider })),
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, locate the clone-pvc-modal file
fd -e tsx -e ts "clone-pvc-modal" --type f

Repository: openshift/console

Length of output: 138


🏁 Script executed:

# Inspect the clone-pvc-modal.tsx file to check export pattern
cat -n "frontend/packages/console-app/src/components/modals/clone/clone-pvc-modal.tsx" | head -50

Repository: openshift/console

Length of output: 2515


🏁 Script executed:

# Check file length and view the export statements at the end
wc -l "frontend/packages/console-app/src/components/modals/clone/clone-pvc-modal.tsx"
tail -30 "frontend/packages/console-app/src/components/modals/clone/clone-pvc-modal.tsx"

Repository: openshift/console

Length of output: 942


🏁 Script executed:

# Verify the pattern used by other modals in the index.ts file
grep -A 3 ".then((m)" "frontend/public/components/modals/index.ts" | head -40

Repository: openshift/console

Length of output: 1042


🏁 Script executed:

# View the specific lines around LazyClonePVCModalProvider to understand the pattern
sed -n '90,110p' "frontend/public/components/modals/index.ts"

Repository: openshift/console

Length of output: 867


Use m.default to align with other OverlayComponent lazy-loaded modals.

Line 102 uses m.ClonePVCModalProvider (named export) while LazyExpandPVCModalProvider (line 93) and LazyConfigureClusterUpstreamModalProvider (line 105) both use m.default. Since clone-pvc-modal.tsx exports ClonePVCModalProvider as both a named and default export, change this to m.default for consistency:

Diff
 export const LazyClonePVCModalProvider = lazy(() =>
   import(
     '@console/app/src/components/modals/clone/clone-pvc-modal' /* webpackChunkName: "clone-pvc-modal" */
-  ).then((m) => ({ default: m.ClonePVCModalProvider })),
+  ).then((m) => ({ default: m.default })),
 );
🤖 Prompt for AI Agents
In `@frontend/public/components/modals/index.ts` around lines 97 - 102, The lazy
import for LazyClonePVCModalProvider should use the module default export to
match the pattern used by LazyExpandPVCModalProvider and
LazyConfigureClusterUpstreamModalProvider; update the .then handler to return {
default: m.default } (or simply use m.default) instead of { default:
m.ClonePVCModalProvider } so it consistently consumes the component via the
module's default export (the component is exported both named and default as
ClonePVCModalProvider).

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 21, 2026
Migrates PVC-related modals (expand, clone, delete, restore) from the
legacy createModalLauncher pattern to the modern OverlayComponent pattern
with lazy loading.

Changes include:
- Convert modal exports to OverlayComponent providers
- Implement lazy loading for modal components
- Update action hooks to use useOverlay() and launchModal()
- Set react-modal app element globally in App component
- Maintain backward compatibility with existing modal exports

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@openshift-ci openshift-ci bot added component/shared Related to console-shared component/topology Related to topology labels Jan 21, 2026
@openshift-ci openshift-ci bot added the kind/cypress Related to Cypress e2e integration testing label Jan 21, 2026
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 21, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 21, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: rhamilto

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

rhamilto and others added 7 commits January 21, 2026 14:24
This commit completes the migration from createModalLauncher to the
OverlayComponent pattern for delete modals and related actions.

Changes:
- Refactored delete-modal.tsx to use OverlayComponent pattern
- Added LazyDeleteModalProvider with React.lazy() for code splitting
- Converted action creators to hooks to comply with React rules:
  * DeleteResourceAction → useDeleteResourceAction (context-menu.ts)
  * deleteKnativeServiceResource → useDeleteKnativeServiceResource (creators.ts)
- Updated all consumers to use new hook-based actions:
  * useCommonActions - uses LazyDeleteModalProvider with launchModal
  * deployment-provider - uses useDeleteResourceAction hook
  * deploymentconfig-provider - uses useDeleteResourceAction hook
  * knative-plugin providers - uses useDeleteKnativeServiceResource hook
- Updated public/components/modals/index.ts with lazy export
- Eliminated all deleteModal() function calls

Note: DeleteApplicationAction remains as a non-hook function creator
since it doesn't use modals and doesn't need to comply with hooks rules.

This change maintains backward compatibility through default exports
and preserves lazy loading functionality.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove launchModal from dependency arrays in pre-existing hooks to
prevent infinite loops. These files were not modified as part of the
modal migration work, but had the same issue.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit refactors configure-update-strategy-modal to use the
OverlayComponent pattern, eliminating createModalLauncher.

Changes:
- Refactored configure-update-strategy-modal.tsx to use OverlayComponent
- Added ConfigureUpdateStrategyModalProvider with ModalWrapper
- Added LazyConfigureUpdateStrategyModalProvider with React.lazy()
- Updated useDeploymentActions to use the new lazy provider
- Removed deprecated configureUpdateStrategyModal from index.ts

This change maintains backward compatibility through default exports
and preserves lazy loading functionality.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit migrates the configure namespace pull secret modal from the
legacy createModalLauncher pattern to the new OverlayComponent pattern.

Changes:
- Exported ConfigureNamespacePullSecretModalProvider as OverlayComponent
- Updated index.ts to lazy-load the modal provider
- Modified namespace.jsx to use useOverlay hook instead of direct modal call

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…tern

This commit migrates the configure cluster upstream modal from the legacy
createModalLauncher pattern to the new OverlayComponent pattern and fixes
react-modal accessibility warnings.

Changes:
- Exported ConfigureClusterUpstreamModalProvider as OverlayComponent
- Updated index.ts to lazy-load the modal provider
- Modified details-page.tsx to use useOverlay hook instead of direct modal call
- Removed unnecessary TFunction prop from modal type definition
- Fixed react-modal warnings by using useLayoutEffect for global app element setup
- Added explicit appElement prop to ModalWrapper for robust timing handling

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit migrates the managed resource save modal from the legacy
createModalLauncher pattern to the new OverlayComponent pattern.

Changes:
- Exported ManagedResourceSaveModalProvider as OverlayComponent
- Updated index.ts to lazy-load the modal provider
- Modified edit-yaml.tsx to use useOverlay hook instead of direct modal call
- Removed unnecessary 'kind' prop from modal invocation
- Updated type definition to extend ModalComponentProps

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The remove-user-modal was already replaced by useWarningModal in
group.tsx and is no longer used anywhere in the codebase.

Changes:
- Deleted remove-user-modal.tsx
- Removed LazyRemoveUserModalProvider export from index.ts

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 21, 2026

@rhamilto: This pull request references CONSOLE-5012 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Continues the migration of modals from the legacy createModalLauncher pattern to the new OverlayComponent pattern using the useOverlay hook. This PR migrates 4 additional modals and removes 1 orphaned modal.

Note: This PR builds on #15932.

Changes

Modals Migrated (4 total)

All modals now follow the OverlayComponent pattern with consistent implementation:

  1. ConfigureUpdateStrategyModal (public/components/modals/configure-update-strategy-modal.tsx)
  • Wrapped with ConfigureUpdateStrategyModalProvider: OverlayComponent
  • Exported as LazyConfigureUpdateStrategyModalProvider with lazy loading
  • Updated in useDeploymentActions hook
  1. ConfigureNamespacePullSecretModal (public/components/modals/configure-ns-pull-secret-modal.tsx)
  • Wrapped with ConfigureNamespacePullSecretModalProvider: OverlayComponent
  • Updated in namespace.jsx to use useOverlay() hook
  1. ConfigureClusterUpstreamModal (public/components/modals/configure-cluster-upstream-modal.tsx)
  • Wrapped with ConfigureClusterUpstreamModalProvider: OverlayComponent
  • Updated in details-page.tsx to use useOverlay() hook
  • Fixed react-modal accessibility warnings with proper app element setup
  1. ManagedResourceSaveModal (public/components/modals/managed-resource-save-modal.tsx)
  • Wrapped with ManagedResourceSaveModalProvider: OverlayComponent
  • Updated in edit-yaml.tsx to use useOverlay() hook
  • Removed unnecessary 'kind' prop from modal invocation

Cleanup

  1. RemoveUserModal (public/components/modals/remove-user-modal.tsx)
  • Deleted orphaned modal that was already replaced by useWarningModal in group.tsx
  • Removed LazyRemoveUserModalProvider export from index.ts

Pattern Example

// Modal file
export const ConfigureUpdateStrategyModalProvider: OverlayComponent<ConfigureUpdateStrategyModalProps> = (props) => {
 return (
   <ModalWrapper blocking onClose={props.closeOverlay}>
     <ConfigureUpdateStrategyModal cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
   </ModalWrapper>
 );
};

export default ConfigureUpdateStrategyModalProvider;
// index.ts
export const LazyConfigureUpdateStrategyModalProvider = lazy(() =>
 import('./configure-update-strategy-modal').then((m) => ({ default: m.default })),
);
// Usage in action hook
const launchModal = useOverlay();

return useMemo(
 () => ({
   id: 'edit-update-strategy',
   label: t('public~Edit update strategy'),
   cta: () => launchModal(LazyConfigureUpdateStrategyModalProvider, { deployment }),
 }),
 [t, deployment], // launchModal intentionally omitted
);

Benefits

  • ✅ Consistent pattern across all modals
  • ✅ Better code splitting with lazy loading
  • ✅ Proper React hooks integration
  • ✅ Maintains backward compatibility with default exports
  • ✅ Improved maintainability
  • ✅ Fixed react-modal accessibility warnings

Testing

  • All 4 modals open and close correctly
  • Configure update strategy modal works for Deployments
  • Configure namespace pull secret modal works
  • Configure cluster upstream modal works
  • Managed resource save modal works in YAML editor
  • No console errors or infinite loops
  • Lazy loading works correctly (check Network tab for separate chunks)

Related

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@rhamilto
Copy link
Member Author

/retest

2 similar comments
@rhamilto
Copy link
Member Author

/retest

@rhamilto
Copy link
Member Author

/retest

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 22, 2026

@rhamilto: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. component/core Related to console core functionality component/dev-console Related to dev-console component/knative Related to knative-plugin component/sdk Related to console-plugin-sdk component/shared Related to console-shared component/topology Related to topology do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. kind/cypress Related to Cypress e2e integration testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants