-
Notifications
You must be signed in to change notification settings - Fork 24
✨ Manage Profiles page UX improvements #1223
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?
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
b98d364 to
88be395
Compare
📝 WalkthroughWalkthroughRefactors the Profile Manager UI across multiple files. ProfileEditorForm: consolidates status UI into a HelperText region, removes Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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 |
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: 2
🤖 Fix all issues with AI agents
In `@webview-ui/src/components/ProfileManager/ProfileList.tsx`:
- Around line 128-138: The Delete DropdownItem currently only disables based on
profile.readOnly; update its isDisabled prop to also respect the component’s
isDisabled analysis flag (same as Make Active and Duplicate) so deletion is
blocked during analysis — locate the DropdownItem that calls
setProfileToDelete(profile) and setIsOpen(false) and change its isDisabled check
to combine profile.readOnly with the existing isDisabled flag (e.g., isDisabled
|| profile.readOnly) so it mirrors the other actions.
In `@webview-ui/src/components/ProfileManager/ProfileManagerPage.tsx`:
- Around line 246-248: The JSX block rendering ProfileEditorForm has extra
two-space indentation causing lint errors; locate the conditional rendering
around selectedProfile in ProfileManagerPage (the ternary/conditional that
returns <ProfileEditorForm ... />) and remove the extra leading spaces so the
opening tag for ProfileEditorForm and its props (e.g., allProfiles={profiles})
align with the surrounding JSX indentation style used in ProfileManagerPage.tsx;
ensure the closing tag and any nested props follow the same indentation to
satisfy the linter.
🧹 Nitpick comments (3)
webview-ui/src/index.css (1)
238-244: Consider using a CSS variable for theme consistency.The hardcoded
rgba(0, 0, 0, 0.25)may not work well across all VS Code themes (particularly light themes where a darker border might be more appropriate). Given that the rest of this file uses CSS variable mappings for theming, consider defining a variable or using an existing border color variable.That said, if this value was tested across both light and dark VS Code themes and works acceptably, this is fine to keep as-is for now.
webview-ui/src/components/ProfileManager/ProfileManagerPage.tsx (1)
222-222: Magic number for masthead height.The
calc(100vh - 56px)assumes the masthead is exactly 56px tall. If PatternFly's masthead height changes in future versions, this could cause layout issues.Consider either:
- Adding a comment explaining the 56px assumption
- Using a CSS variable if PatternFly provides one for masthead height
This is low-risk for now but worth noting.
webview-ui/src/components/ProfileManager/ProfileEditorForm.tsx (1)
38-55: UnusedisPendingstate inuseDebouncedCallback.The hook still tracks
isPending(lines 40, 44, 50, 53), but since line 81 only destructurescallback, this state is computed but never read. This is dead code that could be cleaned up.♻️ Simplified hook without isPending
function useDebouncedCallback(callback: (...args: any[]) => void, delay: number) { const timeoutRef = useRef<NodeJS.Timeout | null>(null); - const [isPending, setIsPending] = useState(false); - return { - callback: (...args: any[]) => { - setIsPending(true); - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } - timeoutRef.current = setTimeout(() => { - callback(...args); - setIsPending(false); - }, delay); - }, - isPending, - }; + return (...args: any[]) => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + timeoutRef.current = setTimeout(() => { + callback(...args); + }, delay); + }; }Then update usage:
- const { callback: debouncedChange } = useDebouncedCallback(onChange, 300); + const debouncedChange = useDebouncedCallback(onChange, 300);
| <DropdownItem | ||
| key="delete" | ||
| onClick={() => { | ||
| setProfileToDelete(profile); | ||
| setIsOpen(false); | ||
| }} | ||
| isDisabled={profile.readOnly} | ||
| isDanger | ||
| > | ||
| Delete | ||
| </DropdownItem> |
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 webview-ui/src/components/ProfileManager/ProfileList.tsx | sed -n '100,160p'Repository: konveyor/editor-extensions
Length of output: 2635
🏁 Script executed:
cat -n webview-ui/src/components/ProfileManager/ProfileList.tsx | head -50Repository: konveyor/editor-extensions
Length of output: 2000
🏁 Script executed:
rg -n "ProfileList" webview-ui/src/components --type=ts -A 10 | head -80Repository: konveyor/editor-extensions
Length of output: 3532
🏁 Script executed:
rg -n "handleDeleteProfile" webview-ui/src/components/ProfileManager --type=ts -B 2 -A 15Repository: konveyor/editor-extensions
Length of output: 5159
Delete action should also respect isDisabled prop during analysis.
The Delete button only checks profile.readOnly (line 134) while Make Active (line 113) and Duplicate (line 124) respect the isDisabled prop (which reflects analysis state). This creates an inconsistency—users cannot modify profiles during analysis via Make Active or Duplicate, but can still initiate deletion.
For consistency and to prevent unintended profile deletion during active analysis, add the isDisabled check:
Suggested fix
<DropdownItem
key="delete"
onClick={() => {
setProfileToDelete(profile);
setIsOpen(false);
}}
- isDisabled={profile.readOnly}
+ isDisabled={profile.readOnly || isDisabled}
isDanger
>
Delete
</DropdownItem>📝 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.
| <DropdownItem | |
| key="delete" | |
| onClick={() => { | |
| setProfileToDelete(profile); | |
| setIsOpen(false); | |
| }} | |
| isDisabled={profile.readOnly} | |
| isDanger | |
| > | |
| Delete | |
| </DropdownItem> | |
| <DropdownItem | |
| key="delete" | |
| onClick={() => { | |
| setProfileToDelete(profile); | |
| setIsOpen(false); | |
| }} | |
| isDisabled={profile.readOnly || isDisabled} | |
| isDanger | |
| > | |
| Delete | |
| </DropdownItem> |
🤖 Prompt for AI Agents
In `@webview-ui/src/components/ProfileManager/ProfileList.tsx` around lines 128 -
138, The Delete DropdownItem currently only disables based on profile.readOnly;
update its isDisabled prop to also respect the component’s isDisabled analysis
flag (same as Make Active and Duplicate) so deletion is blocked during analysis
— locate the DropdownItem that calls setProfileToDelete(profile) and
setIsOpen(false) and change its isDisabled check to combine profile.readOnly
with the existing isDisabled flag (e.g., isDisabled || profile.readOnly) so it
mirrors the other actions.
a664358 to
ddfb8c0
Compare
- Add masthead with split button for New Profile/Import actions - Fixed split-panel layout with independent scrolling - Replace empty state with proper PatternFly EmptyState component - Switch profile list from DataList to SimpleList - Replace active label with compact star icon - Fix profile name truncation and kebab menu wrapping - Move profile info and auto-save status to masthead - Fix split button border color in theme - Change custom rules labels to outline variant Signed-off-by: Ian Bolton <[email protected]>
Signed-off-by: Ian Bolton <[email protected]>
Signed-off-by: Ian Bolton <[email protected]>
7b8a2d3 to
13383c0
Compare
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: 1
🤖 Fix all issues with AI agents
In `@webview-ui/src/components/ProfileManager/ProfileList.tsx`:
- Around line 147-159: The ConfirmDialog usage in ProfileList passes
confirmButtonText="Delete" but ConfirmDialog component does not destructure or
forward confirmButtonText to WarningModal; update the ConfirmDialog component to
destructure confirmButtonText (alongside confirmButtonVariant) and pass it into
the underlying WarningModal (the same place confirmButtonVariant is forwarded),
so the "Delete" label from ProfileList is actually used; check ConfirmDialog's
parameter list and its call to WarningModal to add this prop.
🧹 Nitpick comments (3)
webview-ui/src/components/ProfileManager/ProfileManagerPage.tsx (2)
201-213: Auto-saved indicator is static.The "Auto-saved" status always displays regardless of actual save state. The
useDebouncedCallbackhook inProfileEditorForm.tsxexposesisPendingwhich could indicate when a save is in progress. Consider lifting this state up or using a context to show "Saving..." during debounce and "Auto-saved" after completion for better user feedback.
222-222: Consider using CSS variable or calc for masthead height.The hardcoded
56pxfor masthead height is fragile. If the masthead styling changes, this will need manual adjustment. Consider using a CSS variable or measuring the actual masthead height dynamically.webview-ui/src/components/ProfileManager/ProfileEditorForm.tsx (1)
38-55:isPendingis defined but never used.The
useDebouncedCallbackhook (lines 40, 53) exposesisPendingstate, but line 81 only destructurescallback. This creates unused state updates. Either useisPendingto show a saving indicator (which would address the static "Auto-saved" feedback in the masthead), or remove it from the hook to avoid unnecessary re-renders.Option A: Remove unused state from hook
function useDebouncedCallback(callback: (...args: any[]) => void, delay: number) { const timeoutRef = useRef<NodeJS.Timeout | null>(null); - const [isPending, setIsPending] = useState(false); - return { - callback: (...args: any[]) => { - setIsPending(true); + return (...args: any[]) => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } timeoutRef.current = setTimeout(() => { callback(...args); - setIsPending(false); }, delay); - }, - isPending, }; }Then update line 81:
- const { callback: debouncedChange } = useDebouncedCallback(onChange, 300); + const debouncedChange = useDebouncedCallback(onChange, 300);Also applies to: 81-81
| <ConfirmDialog | ||
| isOpen={profileToDelete !== null} | ||
| title="Delete profile?" | ||
| message={`Are you sure you want to delete the profile "${profileToDelete?.name}"? This action cannot be undone.`} | ||
| confirmButtonText="Delete" | ||
| onConfirm={() => { | ||
| if (profileToDelete) { | ||
| onDelete(profileToDelete.id); | ||
| } | ||
| setProfileToDelete(null); | ||
| }} | ||
| onCancel={() => setProfileToDelete(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:
# First, locate the ConfirmDialog component
fd -type f -name "*ConfirmDialog*" webview-ui/src/components
# Then search for confirmButtonText usage
rg -n "confirmButtonText" webview-ui/src/components --type tsx --type tsRepository: konveyor/editor-extensions
Length of output: 268
🏁 Script executed:
# Locate the ConfirmDialog component
fd "ConfirmDialog" webview-ui/src/components
# Search for confirmButtonText usage
rg "confirmButtonText" webview-ui/src/components -nRepository: konveyor/editor-extensions
Length of output: 457
🏁 Script executed:
cat -n webview-ui/src/components/ConfirmDialog/ConfirmDialog.tsxRepository: konveyor/editor-extensions
Length of output: 1071
confirmButtonText prop is not used by ConfirmDialog.
The confirmButtonText="Delete" prop passed here has no effect. Although defined in the ConfirmDialog interface, it is not destructured in the component parameters and is never passed to the underlying WarningModal component. Compare with confirmButtonVariant, which is properly destructured (line 19) and passed to WarningModal (line 27).
🤖 Prompt for AI Agents
In `@webview-ui/src/components/ProfileManager/ProfileList.tsx` around lines 147 -
159, The ConfirmDialog usage in ProfileList passes confirmButtonText="Delete"
but ConfirmDialog component does not destructure or forward confirmButtonText to
WarningModal; update the ConfirmDialog component to destructure
confirmButtonText (alongside confirmButtonVariant) and pass it into the
underlying WarningModal (the same place confirmButtonVariant is forwarded), so
the "Delete" label from ProfileList is actually used; check ConfirmDialog's
parameter list and its call to WarningModal to add this prop.
Screen.Recording.2026-01-28.at.5.23.04.PM.mov
Improve Profile Manager UI/UX
Summary
Redesigns the Profile Manager screen with improved layout, visual hierarchy, and user experience. The changes address multiple UX issues including the sparse empty state, cramped form layout, and various styling inconsistencies.
Changes
Layout & Structure
EmptyStatecomponent featuring icon, descriptive text, and action buttonsProfile List (Left Panel)
DataListtoSimpleListfor cleaner, less bordered appearanceappendTo: "inline"to dropdown for proper positioningProfile Editor Form (Right Panel)
HelperTextitems for validation errors and disabled warningsStyling Fixes
.pf-v6-c-menu-toggle.pf-m-split-button.pf-m-primaryborder colorFiles Changed
webview-ui/src/components/ProfileManager/ProfileManagerPage.tsxwebview-ui/src/components/ProfileManager/ProfileList.tsxwebview-ui/src/components/ProfileManager/ProfileEditorForm.tsxwebview-ui/src/index.cssSummary by CodeRabbit
UI Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.