fix: enhance components with error handling and improve rate limit logic#234
Open
IamKirbki wants to merge 1 commit into
Open
fix: enhance components with error handling and improve rate limit logic#234IamKirbki wants to merge 1 commit into
IamKirbki wants to merge 1 commit into
Conversation
jeroenrinzema
previously approved these changes
May 12, 2026
There was a problem hiding this comment.
Pull request overview
This PR improves the Console form UX (schema-driven error display, required-field validation, and removal of DOM/ref warnings) and refactors provider rate-limit handling to use a nested { limit, interval } shape consistently across UI and backend.
Changes:
- Add field-level error rendering to
SchemaFields/FormSchemaFields, plus required-field pre-submit validation in integration setup. - Refactor integration rate limit form fields to a nested
rate_limit.{limit,interval}shape and adjust actions search query behavior. - Small UI fixes: forwardRef textarea, remove nested button warning in project switcher, cursor pointer on tabs.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/http/controllers/v1/management/providers.go | Changes rate limit assignment behavior in create/update provider handlers. |
| console/src/views/users/ListCreateForm.tsx | Adds pointer cursor styling to tab triggers. |
| console/src/views/settings/IntegrationSetup.tsx | Refactors rate limit form shape and adds required-field validation before submit. |
| console/src/views/settings/Integrations.tsx | Omits search query param when the search term is empty. |
| console/src/components/ui/textarea.tsx | Wraps Textarea in forwardRef for react-hook-form compatibility. |
| console/src/components/schema-fields.tsx | Adds error rendering and boolean defaults; introduces RHF adapter + error extraction. |
| console/src/components/project-switcher.tsx | Uses asChild to avoid nested button DOM warnings. |
Comments suppressed due to low confidence (1)
console/src/views/settings/IntegrationSetup.tsx:624
valueAsNumber: truewill produceNaNwhen the number input is cleared. With the newbody.rate_limit = values.rate_limitbehavior, that can end up serializinglimitasnull(viaJSON.stringify(NaN)) or otherwise producing an invalid payload. Consider normalizing the value (e.g., convertNaNto0/undefined) before submit, or usesetValueAs/validation to preventNaNfrom reaching the request body.
<Input
type="number"
min={0}
max={maxRateLimit ?? undefined}
placeholder={String(
manifestRateLimit.limit,
)}
className="w-28"
{...form.register("rate_limit.limit", {
valueAsNumber: true,
min: 0,
max: maxRateLimit ?? undefined,
})}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+397
to
+399
| if body.RateLimit.Limit > 0 { | ||
| update.RateLimit = &body.RateLimit.Limit | ||
| } |
Comment on lines
+397
to
+402
| if body.RateLimit.Limit > 0 { | ||
| update.RateLimit = &body.RateLimit.Limit | ||
| } | ||
| if body.RateLimit.Interval != "" { | ||
| update.RateInterval = &body.RateLimit.Interval | ||
| } |
| rate_limit: null, | ||
| rate_interval: "1s", | ||
| rate_limit: { | ||
| limit: manifestRateLimit?.limit ?? 0, |
Comment on lines
+412
to
+425
| // Extract field-level errors from react-hook-form for the parent path | ||
| const errors = useMemo(() => { | ||
| const parentErrors = formErrors[parent] | ||
| if (!parentErrors || typeof parentErrors !== "object") return undefined | ||
| const result: Record<string, string | undefined> = {} | ||
| for (const [key, err] of Object.entries( | ||
| parentErrors as Record<string, { message?: string }>, | ||
| )) { | ||
| if (err?.message) { | ||
| result[key] = err.message | ||
| } | ||
| } | ||
| return Object.keys(result).length > 0 ? result : undefined | ||
| }, [formErrors, parent]) |
Comment on lines
350
to
356
| <SchemaFields | ||
| schema={item} | ||
| value={(value[key] as Record<string, unknown>) ?? {}} | ||
| onChange={(nested) => set(key, nested)} | ||
| variables={variables} | ||
| errors={errors} | ||
| /> |
26ca237 to
232938f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Form validation, required fields, and rate limit shape cleanup
What
project-switcher.tsx: addasChildtoDropdownMenuTriggerso it stops rendering its own<button>inside theSidebarMenuButton. Kills the nested button DOM warning.textarea.tsx: wrap inReact.forwardRefsoreact-hook-form'sControllercan actually pass a ref through. Kills the "Function components cannot be given refs" warning and lets RHF auto-focus on validation errors.schema-fields.tsx:errorsprop keyed by property name, rendered as destructive-styled text under each field (file, template, code, select, primitive, boolean, nested object).falseso they round-trip cleanly through the form.Boolean(value[key])for consistency.errorsrecursively into nestedSchemaFields.FormSchemaFieldsnow extracts field-level errors fromform.formState.errors[parent], forwards them down, and callsform.clearErrors(fieldName)when a field changes so stale errors don't linger.UseFormReturn<any>typing with a narrowFormAdapterinterface so the component doesn't depend on the full RHF surface.IntegrationSetup.tsx:rate_limitandrate_intervalinto a single nestedrate_limit: { limit, interval }shape on the form values, defaults, register call, and submit body. Controller name updated torate_limit.interval, register updated torate_limit.limit.dataSchema.required: missing or whitespace-only values getform.setErrorwith a translated "This field is required" message and submission is aborted.Integrations.tsx: only includesearchin the actions list query whendebouncedQueryis non-empty, so the param isn't sent as an empty string.ListCreateForm.tsx: addcursor-pointerto the dynamic/staticTabsTriggers.providers.go(CreateProvider,UpdateProvider): only assignRateLimit/RateIntervalwhen the incoming values are non-zero / non-empty, so partial payloads don't wipe existing values.Why
Schema-driven fields had no way to surface validation errors and required fields slipped through on submit. The split
rate_limit/rate_intervalshape was awkward on both sides of the wire and easy to desync, the nested object matches the manifest shape and lets the backend treat empty values as "leave alone." The two console warnings were noise that masked real issues.