-
Notifications
You must be signed in to change notification settings - Fork 817
Sync RTs with Hub button #6882
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
Sync RTs with Hub button #6882
Conversation
Deploying windmill with
|
| Latest commit: |
7b5cd2f
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://71a5158f.windmill.pages.dev |
| Branch Preview URL: | https://di-sync-rt-button.windmill.pages.dev |
8ae66ab to
7b5cd2f
Compare
|
Claude finished @diegoimbert's task —— View job Code Review Complete ✓OverviewThis PR adds a convenient "Sync resource types with Hub" button to the resource connection UI, replacing manual instructions with a one-click synchronization. The implementation is clean and follows Svelte 5 best practices well. Summary of Changes
Positive Aspects ✅1. Excellent Use of Svelte 5 RunesThe code properly uses 2. Good UX ImprovementReplacing verbose manual instructions with a single button significantly improves the user experience. The loading state and error handling provide good feedback. 3. Proper Permission GatingThe button is correctly gated behind 4. Clean State ManagementThe promise-based approach with Issues & Recommendations🔴 Critical: Security - Hardcoded WorkspaceLocation: AppConnectInner.svelte:522-526 let jobUuid = await JobService.runScriptByPath({
workspace: 'admins', // ⚠️ Hardcoded
path: 'u/admin/hub_sync',
requestBody: {}
})
await pollJobResult(jobUuid, 'admins') // ⚠️ HardcodedIssue: The code hardcodes the 'admins' workspace, which could:
Recommendation:
let hubRtSync = usePromise(
async () => {
try {
let jobUuid = await JobService.runScriptByPath({
workspace: 'admins',
path: 'u/admin/hub_sync',
requestBody: {}
})
await pollJobResult(jobUuid, 'admins')
connectsManual = undefined
await loadResourceTypes()
connects = undefined
await loadConnects()
sendUserToast('Hub resource types sync completed')
} catch (error) {
// More specific error message
throw new Error(`Failed to sync resource types: ${error?.message || 'Unknown error'}`)
}
},
{ loadInit: false }
)🟡 Medium: Type Safety IssueLocation: svelte5Utils.svelte.ts:28-35 export type UsePromiseResult<T> = (
| { status: 'loading'; value?: undefined; error?: undefined }
| { status: 'error'; error: any; value?: undefined } // ⚠️ 'any' type
| { status: 'ok'; value: T; error?: undefined }
| { status: 'idle'; value?: undefined; error?: undefined }
) & {
refresh: () => void
clear: () => void
}Issue: The error type is Recommendation: Use a more specific error type: | { status: 'error'; error: Error | unknown; value?: undefined }🟡 Medium: UI/UX ConsiderationsLocation: AppConnectInner.svelte:651-657 Issues:
Recommendations: {#if $superadmin}
<div class="flex flex-col gap-2">
<Button
loading={hubRtSync.status === 'loading'}
onClick={() => hubRtSync.refresh()}
wrapperClasses="mt-6"
disabled={hubRtSync.status === 'loading'}
>
Sync resource types with Hub
</Button>
{#if hubRtSync.status === 'error'}
<span class="text-red-400 dark:text-red-500 text-xs">
Error syncing resource types: {hubRtSync.error?.message || 'Unknown error'}
</span>
{/if}
{#if hubRtSync.status === 'ok'}
<span class="text-green-600 dark:text-green-400 text-xs">
✓ Resource types synced successfully
</span>
{/if}
</div>
{/if}🟢 Minor: Code OrganizationLocation: AppConnectInner.svelte:519-534 Issue: The Recommendation: Consider extracting this into a separate function: async function syncResourceTypesWithHub() {
let jobUuid = await JobService.runScriptByPath({
workspace: 'admins',
path: 'u/admin/hub_sync',
requestBody: {}
})
await pollJobResult(jobUuid, 'admins')
connectsManual = undefined
await loadResourceTypes()
connects = undefined
await loadConnects()
sendUserToast('Hub resource types sync completed')
}
let hubRtSync = usePromise(syncResourceTypesWithHub, { loadInit: false })🟢 Minor: Svelte 5 Best PracticeLocation: AppConnectInner.svelte:653 Current: onClick={() => hubRtSync.refresh()}Issue: Using Recommendation (Svelte 5 style): onclick={() => hubRtSync.refresh()}However, I notice this is using the 🟢 Minor: Missing Loading State ManagementIssue: While the button shows loading state, the component doesn't disable user interaction with resource type buttons during sync, which could lead to confusing behavior. Recommendation: Consider adding a disabled state to the resource type buttons while sync is in progress, or show a blocking overlay. Performance Considerations ⚡Good:
Could Improve:
await Promise.all([loadResourceTypes(), loadConnects()])Security Review 🔒Concerns:
Good:
Testing Instructions 📋To test this feature, log in as a superadmin user and navigate to the resource connection page (typically accessed when creating a new resource or connecting to an API). At the bottom of the "Others" section showing manual resource types, you should see a new "Sync resource types with Hub" button. Click this button to trigger the synchronization - the button will show a loading spinner while the sync runs. Once complete, the resource type list should refresh automatically with any new types from the Hub. If few resource types (less than 10) are displayed initially, a warning message will appear indicating that resource types haven't been synced yet, prompting you to use the new sync button. SummaryThis is a solid PR that improves the UX significantly. The main concern is the hardcoded workspace reference which should have proper error handling. The other issues are minor improvements that would enhance robustness and user experience. Overall, the code follows Svelte 5 best practices and integrates well with the existing codebase. Recommendation: Address the critical hardcoded workspace issue before merging, and consider the UX improvements for better user feedback. |
| let hubRtSync = usePromise( | ||
| async () => { | ||
| let jobUuid = await JobService.runScriptByPath({ |
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.
The hub sync function uses hard-coded workspace admins and script path. Consider making these configurable constants.
| </Button> | ||
| {#if hubRtSync.status === 'error'} | ||
| <span class="text-red-400 dark:text-red-500 text-xs"> | ||
| Error syncing resource types : {JSON.stringify(hubRtSync.error)} |
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.
Display of sync errors uses JSON.stringify; consider sanitizing or formatting error messages for better UX.
| Error syncing resource types : {JSON.stringify(hubRtSync.error)} | |
| Error syncing resource types : {hubRtSync.error?.message || String(hubRtSync.error)} |
| let hubRtSync = usePromise( | ||
| async () => { | ||
| let jobUuid = await JobService.runScriptByPath({ | ||
| workspace: 'admins', |
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.
🔴 Security/Reliability Concern: Hardcoded workspace name 'admins' could fail if:
- The workspace doesn't exist or has a different name in some deployments
- The hub_sync script doesn't exist at this path
Recommendation: Add error handling with try-catch and provide clear error messages to users if the workspace or script is missing.
| </Button> | ||
| {#if hubRtSync.status === 'error'} | ||
| <span class="text-red-400 dark:text-red-500 text-xs"> | ||
| Error syncing resource types : {JSON.stringify(hubRtSync.error)} |
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.
UX Enhancement: Consider using hubRtSync.error?.message instead of JSON.stringify() to display cleaner error messages. JSON.stringify could produce very long strings that break the UI layout.
|
|
||
| export type UsePromiseResult<T> = ( | ||
| | { status: 'loading'; value?: undefined; error?: undefined } | ||
| | { status: 'error'; error: any; value?: undefined } |
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.
Type Safety: Consider changing error: any to error: Error | unknown for better type safety.
| }) | ||
| await pollJobResult(jobUuid, 'admins') | ||
| connectsManual = undefined | ||
| await loadResourceTypes() |
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.
Performance: Consider parallelizing these reload operations:
await Promise.all([loadResourceTypes(), loadConnects()])This would complete faster than sequential execution.
(Waiting for the redesign PR to get merged into main)
