Skip to content

Create vote.hackclub.com galleries from the series page - #121

Merged
leowilkin merged 2 commits into
mainfrom
vote-series-integrations
Sep 9, 2026
Merged

leowilkin merged 2 commits into
mainfrom
vote-series-integrations

Conversation

@leowilkin

Copy link
Copy Markdown
Member

A vote event is per Attend event, but choosing which of a series' events get a voting gallery is a decision about the series — and vote could only be reached from each event's own integrations page, so making that choice meant walking every satellite.

Series owners now get an Integrations page (/admin/series/:slug/integrations) listing every event in the series with either its gallery links or a button to create one, disabled with the reason when an event has no logo and banner yet.

Vote::EventLinker

The create path was inline in Admin::DashboardController, and the order of its checks is the whole substance of it:

  1. already linked
  2. server has a key configured
  3. adopt an existing vote event with this slug rather than duplicating it
  4. insist on a logo and a banner
  5. create
  6. adopt the winner if it loses the create race (409)

That moves into Vote::EventLinker so the series page and the event page share one path instead of a copy each, and it gets the spec coverage it never had. The event's own integrations page keeps its exact behaviour — same flash strings, same redirects.

Notes for review

  • Owner-only, the same bar as issuing a series API key: creating a gallery publishes the event's name and artwork to another service.
  • The page audit-logs its own actions rather than leaning on Admin::BaseController's after_action, which picks whichever record changed most in the request — on the first request after sign-in that's the user's own Devise trackable columns, not the event.
  • Still wants a visual pass (light/dark, mobile) — the page follows the older gray/white styling of its siblings under /admin/series, not the newer token-based styling.

Testing

17 new examples across Vote::EventLinker and the request spec. Full suite green apart from the pre-existing DocuSeal webhook spec that flips when a real master.key is present.

A vote event is per Attend event, but choosing which of a series' events
get a voting gallery is a decision about the series — and vote could only
be reached from each event's own integrations page, so making that choice
meant walking every satellite. Series owners now get an Integrations page
listing every event with its gallery or a button to create one, disabled
with the reason when an event has no logo and banner yet.

The create path was inline in the dashboard controller, and the order of
its checks is the whole substance of it: already linked, server
configured, adopt an existing vote event with this slug, insist on
artwork, create, and adopt the winner if it loses the race. That moves to
Vote::EventLinker so both pages share one path rather than a copy each,
and gets the spec coverage it never had. The event's own page behaves
exactly as before.

Owner-only, the same bar as issuing a series API key: creating a gallery
publishes the event's name and artwork to another service.
@leowilkin
leowilkin enabled auto-merge (squash) September 9, 2026 22:53
Comment thread app/views/admin/series_integrations/show.html.erb Fixed
Comment thread app/views/admin/series_integrations/show.html.erb Fixed
Brakeman's LinkToHref check flagged both links in the events table: vote
decides its own admin and gallery URLs, we store whatever it sends, and by
the time a view renders them they are external input — a stored
`javascript:` URL would become a clickable script.

`external_http_url` returns the URL only when it parses as http(s), and
nil otherwise so the link is simply dropped, which is a real fix rather
than an ignore entry. The event's own integrations page renders the same
two URLs and Brakeman doesn't resolve them there, so it stays as it was.
@leowilkin
leowilkin merged commit dd64227 into main Sep 9, 2026
14 checks passed
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