Skip to content

🐛 Fix screenshot upload failure and overlapping info tooltips#4134

Merged
clubanderson merged 1 commit intomainfrom
fix/ui-issues
Apr 1, 2026
Merged

🐛 Fix screenshot upload failure and overlapping info tooltips#4134
clubanderson merged 1 commit intomainfrom
fix/ui-issues

Conversation

@clubanderson
Copy link
Copy Markdown
Collaborator

Summary

  • Fix The screenshot upload functionality is not working #4118: Screenshot uploads caused form submission to fail silently. Root causes: Fiber default body limit (4 MB) too small for base64-encoded images, GitHub API upload timeout (10s) too short, frontend timeout (15s) insufficient, and base64 padding validation failing when browsers omit trailing =.
  • Fix Overlapping Hover Tooltips on Info Icon #4120: Info icon on cards showed both a native browser tooltip ("Card information") and the custom portal tooltip at the same time, causing overlapping text. Removed the native title attribute since the custom tooltip already provides the card description.

Changes

  • Backend: Increased Fiber body limit to 20 MB for screenshot uploads, added 60s upload timeout for GitHub Contents API, fixed base64 padding normalization
  • Frontend: Added 90s timeout constant (FEEDBACK_UPLOAD_TIMEOUT_MS) used when screenshots are attached, removed duplicate title attribute from InfoTooltip button
  • 7 files changed across backend (Go) and frontend (TypeScript)

Test plan

  • Submit a bug report with 1-3 screenshots attached — should succeed
  • Submit a bug report without screenshots — should still work as before
  • Hover over the info icon on any card — should show only the custom tooltip, no overlapping browser tooltip
  • Verify TypeScript compiles: cd web && npx tsc --noEmit
  • Verify Go builds: go build ./...

Closes #4118
Closes #4120

Fix #4118: Screenshot uploads caused form submission to fail silently due to:
- Fiber default body limit (4 MB) too small for base64-encoded images
- GitHub API upload timeout (10s) too short for large screenshots
- Frontend API timeout (15s) insufficient for server-side GitHub uploads
- Base64 padding validation failure when browsers omit trailing '='

Fix #4120: Info icon showed both a native browser tooltip ("Card
information") and a custom portal tooltip simultaneously, causing
overlapping text. Removed the native title attribute since the custom
tooltip already provides the card description.

Closes #4118
Closes #4120

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
Copilot AI review requested due to automatic review settings April 1, 2026 13:05
@kubestellar-prow kubestellar-prow bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Apr 1, 2026
@kubestellar-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clubanderson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@netlify
Copy link
Copy Markdown

netlify bot commented Apr 1, 2026

Deploy Preview for kubestellarconsole ready!

Name Link
🔨 Latest commit 643b25b
🔍 Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/69cd180abd95a40008e45379
😎 Deploy Preview https://deploy-preview-4134.console-deploy-preview.kubestellar.io
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@clubanderson clubanderson merged commit e4ef89e into main Apr 1, 2026
21 of 22 checks passed
@kubestellar-prow kubestellar-prow bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Apr 1, 2026
@kubestellar-prow kubestellar-prow bot deleted the fix/ui-issues branch April 1, 2026 13:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes feedback submission failures when screenshots are attached by increasing request/body limits and timeouts, and resolves overlapping “info” tooltips by relying solely on the custom tooltip.

Changes:

  • Add a dedicated frontend timeout for feedback submissions that include screenshot uploads
  • Increase backend request body limit and GitHub upload timeout, and normalize base64 padding for screenshots
  • Remove the native title tooltip from the info icon to prevent duplicated tooltip UI

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
web/src/lib/constants/network.ts Adds FEEDBACK_UPLOAD_TIMEOUT_MS for longer-running screenshot submissions
web/src/hooks/useFeatureRequests.ts Extends createRequest to accept request options (e.g., timeout)
web/src/components/feedback/FeedbackModal.tsx Uses extended timeout only when screenshots are present
web/src/components/feedback/FeatureRequestModal.tsx Uses extended timeout only when screenshots are present
web/src/components/cards/CardWrapper.tsx Removes native tooltip to avoid overlap with custom tooltip
pkg/api/server.go Increases Fiber BodyLimit to allow larger screenshot payloads
pkg/api/handlers/feedback.go Normalizes base64 padding and extends GitHub upload timeout for screenshots

Comment on lines +303 to +306
const createRequest = useCallback(async (input: CreateFeatureRequestInput, options?: { timeout?: number }) => {
try {
setIsSubmitting(true)
const { data } = await api.post<FeatureRequest>('/api/feedback/requests', input)
const { data } = await api.post<FeatureRequest>('/api/feedback/requests', input, options)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The new options parameter is typed as { timeout?: number } but is passed directly to api.post(...) as the request config. If api is an Axios-like client (or a custom wrapper that supports more config fields), this type is overly restrictive and can lead to unsafe/incorrect usage (callers can’t pass other supported config, and the shape may not match what api.post expects). Prefer typing options to the actual config type used by api.post (e.g., AxiosRequestConfig or your project’s ApiRequestOptions) and/or narrowing it at the call site instead of widening the hook API.

Copilot uses AI. Check for mistakes.
Comment on lines 302 to 306
onMouseEnter={() => setIsVisible(true)}
onMouseLeave={() => setIsVisible(false)}
className="p-0.5 rounded text-muted-foreground/50 hover:text-muted-foreground transition-colors"
aria-label={t('cardWrapper.cardInfo')}
title={t('cardWrapper.cardInfo')}
>
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

With the native title removed, the tooltip content is now only discoverable via mouse hover handlers (onMouseEnter/Leave). Keyboard users won’t trigger the custom tooltip, and screen readers will only get the button name (aria-label) without the descriptive tooltip text. Consider also toggling visibility on onFocus/onBlur and associating the tooltip content via aria-describedby (or ensuring the tooltip implementation itself handles focus/ARIA) so the information is accessible without relying on the removed native tooltip.

Copilot uses AI. Check for mistakes.
Comment on lines +197 to +203
// feedbackBodyLimit allows base64-encoded screenshot uploads (up to ~20 MB)
const feedbackBodyLimit = 20 * 1024 * 1024
app := fiber.New(fiber.Config{
ErrorHandler: customErrorHandler,
ReadBufferSize: 16384,
WriteBufferSize: 16384,
BodyLimit: feedbackBodyLimit,
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

Setting BodyLimit on the global Fiber app raises the max body size for all endpoints, which can increase memory pressure and amplify DoS risk from large request bodies unrelated to feedback. If only feedback endpoints need the larger limit, prefer applying a body-limit middleware scoped to the feedback routes (e.g., Fiber bodylimit middleware on a route group) while keeping a smaller global default, and/or pair this with rate limiting on the feedback submission endpoint.

Copilot uses AI. Check for mistakes.
Comment on lines +1701 to +1703
// Use a longer timeout for screenshot uploads (large base64 payloads)
uploadClient := &http.Client{Timeout: screenshotUploadTimeout}
resp, err := uploadClient.Do(req)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

Creating a new http.Client here bypasses any custom configuration on h.httpClient (custom Transport, proxies, tracing, keep-alive tuning) and makes timeout behavior inconsistent across GitHub calls. Prefer keeping a single configured client and using a per-request timeout via context.WithTimeout (and req = req.WithContext(ctx) / http.NewRequestWithContext), or if a separate client is required, initialize it once (e.g., on the handler struct) reusing the same Transport as h.httpClient and only changing the timeout.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Thank you for your contribution! Your PR has been merged.

Check out what's new:

Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

👋 Hey @clubanderson — thanks for opening this PR!

🤖 This project is developed exclusively using AI coding assistants.

Please do not attempt to code anything for this project manually.
All contributions should be authored using an AI coding tool such as:

This ensures consistency in code style, architecture patterns, test coverage,
and commit quality across the entire codebase.


This is an automated message.

clubanderson added a commit that referenced this pull request Apr 1, 2026
- Include ClusterRole name in error messages for easier debugging (client.go)
- Add machine-readable errorCode to sync endpoint 501 response (console_persistence.go)
- Fix test hygiene: check json.Marshal/io.ReadAll errors, close response
  bodies, explicitly discard hash.Write returns (feedback_test.go)
- Add onFocus/onBlur and aria-describedby to InfoTooltip for keyboard
  and screen-reader accessibility (CardWrapper.tsx)
- Reuse h.httpClient with context.WithTimeout instead of creating a new
  http.Client per screenshot upload (feedback.go)
- Scope elevated 20 MB body limit to feedback creation route only via
  per-route middleware guard (server.go)

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
clubanderson added a commit that referenced this pull request Apr 1, 2026
- Include ClusterRole name in error messages for easier debugging (client.go)
- Add machine-readable errorCode to sync endpoint 501 response (console_persistence.go)
- Fix test hygiene: check json.Marshal/io.ReadAll errors, close response
  bodies, explicitly discard hash.Write returns (feedback_test.go)
- Add onFocus/onBlur and aria-describedby to InfoTooltip for keyboard
  and screen-reader accessibility (CardWrapper.tsx)
- Reuse h.httpClient with context.WithTimeout instead of creating a new
  http.Client per screenshot upload (feedback.go)
- Scope elevated 20 MB body limit to feedback creation route only via
  per-route middleware guard (server.go)

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
@clubanderson
Copy link
Copy Markdown
Collaborator Author

🔄 Auto-Applying Copilot Code Review

Copilot code review found 0 code suggestion(s) and 4 general comment(s).

Also address these general comments:

  • web/src/hooks/useFeatureRequests.ts (line 306): The new options parameter is typed as { timeout?: number } but is passed directly to api.post(...) as the request
  • web/src/components/cards/CardWrapper.tsx (line 306): With the native title removed, the tooltip content is now only discoverable via mouse hover handlers (`onMouseEnter/Le
  • pkg/api/server.go (line 203): Setting BodyLimit on the global Fiber app raises the max body size for all endpoints, which can increase memory pres
  • pkg/api/handlers/feedback.go (line 1703): Creating a new http.Client here bypasses any custom configuration on h.httpClient (custom Transport, proxies, tracin

Push all fixes in a single commit. Run cd web && npm run build && npm run lint before committing.


Auto-generated by copilot-review-apply workflow.

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

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overlapping Hover Tooltips on Info Icon The screenshot upload functionality is not working

3 participants