Skip to content

Fix/download output#1445

Merged
rogefm merged 5 commits into
mainfrom
fix/download-output
May 14, 2026
Merged

Fix/download output#1445
rogefm merged 5 commits into
mainfrom
fix/download-output

Conversation

@rogefm
Copy link
Copy Markdown
Contributor

@rogefm rogefm commented May 14, 2026

📝 Description

The ellipsis menu for downloading session results had disappeared from the frontend. This PR restores it and unifies all download entry points into a single, reusable component used by Audit session details, the Webclient log area, and the Runbooks runner.

The menu offers TXT for any output and additionally CSV / JSON when the connection produces tabular output. Downloads under 2MB are generated client-side from the already-loaded payload; larger payloads (or sessions flagged with has-large-payload?) fall back to the existing backend token flow, keeping the 4MB threshold behavior intact.

The standalone "Download" button that previously lived in the session header for >4MB payloads has been removed, so users now see a single predictable entry point on every results surface.

It also honors the existing DISABLE_SESSIONS_DOWNLOAD server policy: the menu (and the input-script download button in the large-input warning) are hidden when the policy is on, preventing the client-side path from bypassing the rule that the backend enforces at session.go:493.

🔗 Related Issue

Fixes #

🚀 Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🎨 Style/UI update
  • ♻️ Code refactor
  • ⚡ Performance improvement
  • ✅ Test update
  • 🔧 Build configuration change
  • 🧹 Chore

📋 Changes Made

  • Added a new reusable webapp.components.results-download-menu component built on Radix DropdownMenu, offering TXT (always) and CSV/JSON (for tabular outputs). Uses a 2MB threshold to decide between client-side blob generation (via papaparse's unparse for CSV) and the existing backend token flow (:audit->session-file-generate).
  • Wired the menu into webapp.audit.views.results-container so it appears next to the Plain text / Table tabs on session details.
  • Wired the same menu into webapp.webclient.log-area.main, which automatically covers both the Webclient editor output and the Runbooks runner.
  • Removed the duplicate "Download" button from webapp.sessions.components.session-header and dropped the now-unused :has-large-payload? / :download-extension props at the call site, unifying every download entry point into the ellipsis menu.
  • Added a new re-frame subscription :gateway->sessions-download-disabled? in webapp.events.gateway-info that reads disable_sessions_download from /serverinfo, and used it to hide the menu and the large-input-warning download button when DISABLE_SESSIONS_DOWNLOAD=true.
  • Aligned the menu trigger vertically with the tabs (space-between / items-center) and removed custom hover:bg-gray-2 classes on DropdownMenu.Item so each entry inherits the default Radix hover styling, matching webapp.webclient.log-area.logs.

🧪 Testing

Test Configuration:

  • Browser(s): Chrome (latest)
  • OS: macOS / Linux

Tests performed:

  • Unit tests pass
  • Integration tests pass
  • Manual testing completed

Manual scenarios to validate:

  • SQL session with small result (<2MB): TXT, CSV, JSON entries appear; each downloads client-side with filename {connection}-{sid}-{timestamp}.{ext}.
  • SQL session with has-large-payload? (>4MB): menu falls back to the backend token endpoint and opens the temporary download URL.
  • Exec / command-line session: only TXT is offered.
  • Runbook executed from the Webclient: menu appears next to the Logs/Tabular tabs and downloads the rendered output.
  • With DISABLE_SESSIONS_DOWNLOAD=true on the gateway: the ellipsis menu no longer renders, and the input-script "Download" button in the large-input warning is hidden.
  • With DISABLE_CLIPBOARD_COPY_CUT=true: download menu is unaffected (separate policy, by design).

📸 Screenshots (if applicable)

Screenshot 2026-05-13 at 20 50 35 Screenshot 2026-05-13 at 20 51 56

✅ Checklist

  • I have run make generate-openapi-docs to update the OpenAPI docs (not applicable — frontend-only change, no API surface modified)
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes
  • I have checked my code and corrected any misspellings

📄 Additional Notes

  • Build verification gap: the sandbox running this branch blocks access to repo.clojars.org, so npx shadow-cljs compile hoop-ui could not download thheller:shadow-cljs:2.28.14 and the build was not executed end-to-end. Manual review confirmed every JS/Radix/lucide symbol used (DropdownMenu, IconButton, Flex, Text, MoreHorizontal, FileText, Sheet, Braces, papa/unparse) is exported by the locked versions in package.json. Please run npm run dev:hoop-ui locally to confirm.
  • Reviewer focus: behavior parity between the client-side CSV path (papa.unparse of the matrix already shown in the Table tab) and the backend CSV path (parseBlobStream with withCsvFmt: true) — they use different parsers, so a >2MB SQL session may produce a slightly different CSV than a small one. If exact parity is required we should consider routing all CSV through the backend.
  • The two policies (DISABLE_CLIPBOARD_COPY_CUT and DISABLE_SESSIONS_DOWNLOAD) are kept independent on purpose, matching the existing codebase convention.

rogefm added 5 commits May 13, 2026 21:08
Reintroduce the ellipsis menu next to the output tabs on session results
in Audit, Webclient and Runbooks. The menu offers TXT for any output and
adds CSV/JSON for tabular SQL connections. Downloads under 2MB are built
client-side from the already-loaded payload; larger payloads (or sessions
flagged as has-large-payload) fall back to the existing backend token flow
via /sessions/:id?extension=, keeping the 4MB threshold behaviour intact.

Unifies the separate "Download" button that lived in the session header
for >4MB payloads into the same menu so users see a single, predictable
entry point in every results surface.
Drop the custom hover/class overrides on DropdownMenu.Item so each entry
inherits Radix's built-in hover state, matching the existing webclient
output menu in log_area/logs.cljs. Each item now wraps its icon and
label in a Flex with a Text component, mirroring the project pattern.

Center-align the tabs row in audit results and webclient log area so the
ellipsis trigger sits on the same baseline as the tab text instead of
floating at the bottom.
Add a :gateway->sessions-download-disabled? subscription that reads
disable_sessions_download from /serverinfo, and gate the results
download menu on it. Without this gate the client-side blob path
(< 2MB) bypassed the policy entirely; the backend already rejects the
large-payload path with 403 at session.go:493 but the user would still
see a snackbar error instead of a hidden action.

Also hide the input-script download button in large-input-warning when
the policy is on, since that flow shares the same backend endpoint.
…primitives

Inside the audit session-details modal the dropdown items had no hover
and no cursor change because Radix Dialog's focus trap fights with
DropdownMenu's default modal focus management. Set :modal false on
DropdownMenu.Root and restore the cursor-pointer / hover:bg-gray-2
classes used by the existing Approve dropdown in session_details.cljs,
which is the proven pattern for in-modal dropdowns in this codebase.

Also replace the raw :div elements I introduced in results-container
with Radix Box and Flex to follow the project's component conventions.
@rogefm rogefm requested a review from luanlorenzo May 14, 2026 00:08
@rogefm rogefm self-assigned this May 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Migration Safety Analysis

No database migrations were changed in this PR. Safe to deploy to sandbox.

@sandromello
Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=1445.0.0-aed70d5

@rogefm rogefm added the patch Bumps the patch version on release (bug fixes) label May 14, 2026
@rogefm rogefm merged commit 4f0d592 into main May 14, 2026
23 of 24 checks passed
@rogefm rogefm deleted the fix/download-output branch May 14, 2026 15:06
@github-actions github-actions Bot locked and limited conversation to collaborators May 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

patch Bumps the patch version on release (bug fixes)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants