Skip to content

HOLD UNTIL REQUESTED: Add "Download all" button that zips a callout's attached documents#1832

Closed
maebeale wants to merge 1 commit into
mainfrom
maebeale/download-all-pdfs-button
Closed

HOLD UNTIL REQUESTED: Add "Download all" button that zips a callout's attached documents#1832
maebeale wants to merge 1 commit into
mainfrom
maebeale/download-all-pdfs-button

Conversation

@maebeale

@maebeale maebeale commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

🤖 PR, suggested 👤 review level: 📖 Read — light-logic: one new public endpoint + a shared-chrome button, no client JS

A single Download all button in the callout page header downloads every attached document on the page as one zip, instead of opening/downloading each one individually.

Where it shows

  • The shared _callout_page chrome renders the button whenever the controller sets @download_all_url — any callout page with more than one downloadable linked resource: handouts and any built-in callout (scholarship, certificate, videoconference) with attached files.
  • Payment is excluded — it manages its own invoice/receipt/W-9 documents in a dedicated Documents section.

How it works (no JavaScript)

  • Button is a plain link_to a per-callout …/documents.zip endpoint (CalloutsController#download_all).
  • The endpoint streams a server-side zip built with rubyzip (now declared explicitly in the Gemfile), entries named by resource title and de-duped. 404s for fewer than two files or the payment callout.

Notes

Tests

spec/requests/events/callouts_spec.rb: button visibility (2+/1/0/payment) and the zip endpoint (streams a named-entry zip, 404s under two files, 404s for payment).

end
cards
end

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 From Claude: The invoice has no stored PDF (it is rendered HTML printed via window.print()), so it can't be bundled as a file download — newTab: true opens its print-to-PDF page instead. Everything else is a real file.

this.itemsValue.forEach((item, index) => {
setTimeout(() => this.trigger(item), index * this.delayValue)
})
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 From Claude: Staggered by delay ms — browsers suppress multiple downloads fired synchronously in one tick, so the burst is spread out.

@maebeale maebeale marked this pull request as ready for review June 22, 2026 05:16
@maebeale maebeale changed the title Add "Download all" button to forms and handouts callout pages WAIT: Add "Download all" button to forms and handouts callout pages Jun 22, 2026
@maebeale maebeale force-pushed the maebeale/download-all-pdfs-button branch from b40d447 to f6ab3cf Compare July 15, 2026 11:52
Copilot AI review requested due to automatic review settings July 15, 2026 11:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@maebeale maebeale changed the title WAIT: Add "Download all" button to forms and handouts callout pages Add "Download all" button to callout pages with attached resources Jul 15, 2026
# shared callout chrome shows whenever a page has downloadable resources
# (handouts and any built-in callout with attachments — Payment passes a nil
# callout here, so its own invoice/receipt/W-9 documents are excluded).
def download_all_urls_for(callout)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 From Claude: Keying the button off a nil callout is what excludes Payment for free — set_builtin_content nils the payment callout before calling this, so its own invoice/receipt/W-9 documents never get bundled here.


start() {
this.urlsValue.forEach((url, index) => {
setTimeout(() => this.download(url), index * this.delayValue)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 From Claude: Staggered by delay ms — browsers suppress multiple downloads fired synchronously in one tick, so the burst is spread out.

Copilot AI review requested due to automatic review settings July 15, 2026 11:55
@maebeale maebeale force-pushed the maebeale/download-all-pdfs-button branch from f6ab3cf to 78b7279 Compare July 15, 2026 11:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@maebeale maebeale force-pushed the maebeale/download-all-pdfs-button branch from 78b7279 to 6f3e844 Compare July 15, 2026 12:05
Copilot AI review requested due to automatic review settings July 15, 2026 12:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

A single header-bar button downloads every attached document on a callout
page as one zip, instead of opening and downloading each one individually.

The shared callout chrome shows it whenever a page has more than one
downloadable resource — handouts and any built-in callout (scholarship,
certificate, videoconference) with linked files. The button links to a
per-callout documents.zip endpoint that streams the bundle server-side
(rubyzip), so no client JavaScript is involved. Payment is excluded: it
manages its own invoice/receipt/W-9 documents in a dedicated section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@maebeale maebeale force-pushed the maebeale/download-all-pdfs-button branch from 6f3e844 to 9d3ae9f Compare July 15, 2026 12:25
Copilot AI review requested due to automatic review settings July 15, 2026 12:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@maebeale maebeale changed the title Add "Download all" button to callout pages with attached resources HOLD UNTIL REQUESTED: Add "Download all" button that zips a callout's attached documents Jul 15, 2026
def download_all
callout = @event.registration_ticket_callouts.find_by(builtin_key: params[:builtin_key])
resources = callout && callout.builtin_key != "payment" ? downloadable_resources(callout) : []
raise ActiveRecord::RecordNotFound if resources.size < 2

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 From Claude: Guards the endpoint independently of the button: payment is excluded and anything with fewer than two files 404s, so a hand-crafted URL can't pull a zip the UI would never offer.

resources.each do |resource|
file = resource.downloadable_asset.file
zip.put_next_entry(unique_entry_name(resource, file, used))
zip.write(file.download)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 From Claude: Builds the whole zip in memory (each file.download loads a blob) — fine for a handful of PDFs per callout; would want streaming if these grew large.

@maebeale maebeale closed this Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants