-
Notifications
You must be signed in to change notification settings - Fork 57
CNV-77263: redesign the cd-rom modal #3455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
CNV-77263: redesign the cd-rom modal #3455
Conversation
|
@batyana: This pull request references CNV-77263 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. DetailsIn 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. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: batyana The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
📝 WalkthroughWalkthroughRefactors CD-ROM modal to a radio-based source selector (Mount ISO / Upload / Empty), adds submitCDROM and upload helpers, threads a new onUploadStarted callback through DiskModal → DiskList → StorageTab, introduces upload alert state and translations across locale files. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~35 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@batyana: This pull request references CNV-77263 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. DetailsIn 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/views/virtualmachines/details/tabs/configuration/storage/components/modal/hooks/useMountCDROMForm.ts (1)
74-74:⚠️ Potential issue | 🟠 Major
isFormValiddoesn't account for the empty drive mode — "Add" button will be disabled.When the user selects "Leave empty drive",
selectedISOis''anduploadFileisnull, soisFormValidevaluates tofalse. The submit button will remain disabled for the empty drive option.🐛 Proposed fix
- const isFormValid = Boolean(selectedISO || uploadFile?.filename); + const isFormValid = Boolean(selectedISO || uploadFile?.filename || uploadMode === UPLOAD_MODE_EMPTY);
🤖 Fix all issues with AI agents
In `@src/utils/components/DiskModal/utils/helpers.ts`:
- Around line 330-339: createMutableUploadData currently always fabricates a
dataVolumeTemplate when data.dataVolumeTemplate is undefined; change it to guard
for existence of data.dataVolumeTemplate and only shallow-copy/modify
spec.source when the template exists—i.e., in createMutableUploadData, detect if
data.dataVolumeTemplate is truthy and then return a new object with
dataVolumeTemplate: { ...data.dataVolumeTemplate, spec: {
...data.dataVolumeTemplate.spec, source: {
...data.dataVolumeTemplate.spec?.source } } }, otherwise return the original
data unchanged (or copy other fields without adding dataVolumeTemplate);
reference createMutableUploadData and the dataVolumeTemplate/spec/source
properties to locate the change.
In `@src/utils/components/DiskModal/utils/submit.ts`:
- Around line 239-256: The hot-plug upload path creates the DataVolume with a
generated name inside uploadDataVolume (which uses generateUploadDiskName) but
then reads dvName from data.dataVolumeTemplate?.metadata?.name (which may
instead have been set by createDataVolumeName), causing a mismatch; fix by using
the DataVolume returned by uploadDataVolume to update
data.dataVolumeTemplate.metadata.name and data.volume.dataVolume.name (or
replace data.dataVolumeTemplate and data.volume.dataVolume with the returned
object) inside the uploadPromise.then handler (and keep calling
onUploadedDataVolume/uploadStarted as before) so the VM volume references the
actual uploaded DataVolume name generated by uploadDataVolume.
In
`@src/views/virtualmachines/details/tabs/configuration/storage/components/hooks/useUploadAlert.ts`:
- Around line 8-23: The hook useUploadAlert should declare explicit return types
and its internal handlers should be typed: add a return type for useUploadAlert
(including uploadStatus, uploadError, onUploadStarted, dismissAlert), annotate
onUploadStarted as (uploadPromise: Promise<unknown>) => void and dismissAlert as
() => void, and change the catch handler parameter to err: unknown and narrow it
(e.g., if (err instanceof Error) setUploadError(err.message) else
setUploadError(String(err))) before calling setUploadError; keep using
setUploadStatus('error'/'success'/'uploading') as before.
🧹 Nitpick comments (4)
src/views/virtualmachines/details/tabs/configuration/storage/utils/constants.ts (1)
5-24: RenameuploadAlertConfigto uppercase constant style.This is a utility constant and should follow the repo’s uppercase underscore naming convention. Update call sites accordingly.
Proposed fix
-export const uploadAlertConfig: Record< +export const UPLOAD_ALERT_CONFIG: Record< UploadAlertStatus, { body: string; title: string; variant: AlertVariant } > = {As per coding guidelines, "Define constants in utility files with uppercase and underscore-separated naming (e.g.,
API_URL)."src/utils/components/DiskModal/utils/submit.ts (2)
217-274: Missing explicit return type onsubmitCDROM.Per coding guidelines, functions should always have explicit return types rather than relying on inference.
Proposed fix
export const submitCDROM = async ( data: V1DiskFormState, { isHotPluggable, onSubmit, onUploadedDataVolume, onUploadStarted, selectedISO, uploadData: uploadDataFn, uploadEnabled, vm, }: SubmitCDROMInput, -) => { +): Promise<V1VirtualMachine | void> => {As per coding guidelines, "Always explicitly define return types for functions rather than relying on TypeScript type inference."
230-269: Direct mutation ofdataparameter may cause issues.
submitCDROMmutates itsdataparameter in-place (delete data.dataVolumeTemplate,data.volume = ..., etc.). If the caller or any.then()handler referencesdataafter this call, it will see the mutated state. Consider working on a local copy instead of mutating the input.src/utils/components/DiskModal/AddCDROMModal.tsx (1)
94-104: WraphandleModalSubmitinuseCallbackand add an explicit return type.
handleModalSubmitis recreated every render and passed asonSubmittoTabModal. This can trigger unnecessary child re-renders. Per the project's coding guidelines, memoization tools should be used, and functions should have explicit return types.♻️ Suggested refactor
- const handleModalSubmit = () => - submitCDROM(getValues(), { + const handleModalSubmit = useCallback((): Promise<void> => + submitCDROM(getValues(), { isHotPluggable, onSubmit, onUploadedDataVolume, onUploadStarted, selectedISO, uploadData, uploadEnabled, vm, - }); + }), [getValues, isHotPluggable, onSubmit, onUploadedDataVolume, onUploadStarted, selectedISO, uploadData, uploadEnabled, vm]);You'll also need to add
useCallbackto the React import on line 1:import React, { FC, useCallback, useEffect } from 'react';As per coding guidelines: "Use React's memoization tools (
React.memo,useMemo,useCallback) to avoid unnecessary re-renders." and "Always explicitly define return types for functions rather than relying on TypeScript type inference."
| export const useUploadAlert = () => { | ||
| const [uploadStatus, setUploadStatus] = useState<null | UploadAlertStatus>(null); | ||
| const [uploadError, setUploadError] = useState(''); | ||
|
|
||
| const onUploadStarted = (uploadPromise: Promise<unknown>) => { | ||
| setUploadStatus('uploading'); | ||
| setUploadError(''); | ||
| uploadPromise | ||
| .then(() => setUploadStatus('success')) | ||
| .catch((err) => { | ||
| setUploadStatus('error'); | ||
| setUploadError(err?.message || ''); | ||
| }); | ||
| }; | ||
|
|
||
| const dismissAlert = () => setUploadStatus(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n "src/views/virtualmachines/details/tabs/configuration/storage/components/hooks/useUploadAlert.ts"Repository: kubevirt-ui/kubevirt-plugin
Length of output: 1117
🏁 Script executed:
cat -n "src/views/virtualmachines/details/tabs/configuration/storage/utils/constants.ts" | head -50Repository: kubevirt-ui/kubevirt-plugin
Length of output: 951
Add explicit return types and type the catch handler error as unknown.
Guidelines require explicit function return types for all functions in TypeScript files. Additionally, the caught error must be typed as unknown and narrowed to avoid implicit any.
Suggested fix
+type UploadAlertConfig = (typeof uploadAlertConfig)[UploadAlertStatus];
+
+type UseUploadAlertResult = {
+ alertConfig: UploadAlertConfig | null;
+ dismissAlert: () => void;
+ onUploadStarted: (uploadPromise: Promise<unknown>) => void;
+ uploadError: string;
+};
+
-export const useUploadAlert = () => {
+export const useUploadAlert = (): UseUploadAlertResult => {
const [uploadStatus, setUploadStatus] = useState<null | UploadAlertStatus>(null);
const [uploadError, setUploadError] = useState('');
- const onUploadStarted = (uploadPromise: Promise<unknown>) => {
+ const onUploadStarted = (uploadPromise: Promise<unknown>): void => {
setUploadStatus('uploading');
setUploadError('');
uploadPromise
.then(() => setUploadStatus('success'))
- .catch((err) => {
+ .catch((err: unknown) => {
setUploadStatus('error');
- setUploadError(err?.message || '');
+ setUploadError(err instanceof Error ? err.message : '');
});
};
- const dismissAlert = () => setUploadStatus(null);
+ const dismissAlert = (): void => setUploadStatus(null);🤖 Prompt for AI Agents
In
`@src/views/virtualmachines/details/tabs/configuration/storage/components/hooks/useUploadAlert.ts`
around lines 8 - 23, The hook useUploadAlert should declare explicit return
types and its internal handlers should be typed: add a return type for
useUploadAlert (including uploadStatus, uploadError, onUploadStarted,
dismissAlert), annotate onUploadStarted as (uploadPromise: Promise<unknown>) =>
void and dismissAlert as () => void, and change the catch handler parameter to
err: unknown and narrow it (e.g., if (err instanceof Error)
setUploadError(err.message) else setUploadError(String(err))) before calling
setUploadError; keep using setUploadStatus('error'/'success'/'uploading') as
before.
Signed-off-by: batyana <[email protected]>
ab0acd4 to
ee93633
Compare
|
@batyana: This pull request references CNV-77263 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. DetailsIn 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. |
|
@yfrimanm - do you think we should use |

📝 Description
🎥 Demo
Screen.Recording.2026-02-11.at.14.26.21.mov
Summary by CodeRabbit