From 589e46c1fd1f9b933d5710aa6cf06a18ddeb8d77 Mon Sep 17 00:00:00 2001 From: sto Date: Sun, 8 Mar 2026 10:09:55 +0100 Subject: [PATCH] Offer to download QR codes in a ZIP archive --- Gemfile | 1 + Gemfile.lock | 1 + app/controllers/contestants_controller.rb | 22 ++++++++++++++++++- app/policies/contest_policy.rb | 4 ++++ .../contestants/generate_qrcodes.html.slim | 2 ++ config/locales/en.yml | 1 + config/locales/fr.yml | 1 + config/routes.rb | 1 + 8 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 4e0956f..839db83 100644 --- a/Gemfile +++ b/Gemfile @@ -47,6 +47,7 @@ gem "friendly_id", "~> 5.5.0" gem "csv" gem "damerau-levenshtein" gem "rqrcode", "~> 3.0" +gem "rubyzip" group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem diff --git a/Gemfile.lock b/Gemfile.lock index cc7b441..1f62b0c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -473,6 +473,7 @@ DEPENDENCIES rqrcode (~> 3.0) rspec-rails rubocop-rails-omakase + rubyzip selenium-webdriver slim so_many_devices diff --git a/app/controllers/contestants_controller.rb b/app/controllers/contestants_controller.rb index 122281a..b2fd319 100644 --- a/app/controllers/contestants_controller.rb +++ b/app/controllers/contestants_controller.rb @@ -1,8 +1,10 @@ +require "zip" + class ContestantsController < ApplicationController include CompletionsConcern include ContestantsConcern - before_action :set_contest, only: %i[ index edit new create update destroy import upload_csv convert_csv finalize_import export generate_qrcodes generate_qrcodes_pdf ] + before_action :set_contest, only: %i[ index edit new create update destroy import upload_csv convert_csv finalize_import export generate_qrcodes generate_qrcodes_pdf generate_qrcodes_archive ] before_action :set_contestant, only: %i[ destroy edit update] before_action :set_completions, only: %i[edit update ] skip_before_action :require_authentication, only: %i[ get_public_completion post_public_completion public_completion_updated ] @@ -140,6 +142,24 @@ class ContestantsController < ApplicationController end end + def generate_qrcodes_archive + authorize @contest + + generate_contestants_qrcodes(@contest) + + @contestants = @contest.contestants.sort_by { |contestant| contestant.name } + + stringio = Zip::OutputStream.write_buffer do |zio| + @contestants.each do |contestant| + zio.put_next_entry("#{@contest.friendly_id}_#{contestant.name}.svg") + zio.write contestant.qrcode + end + end + binary_data = stringio.string + + send_data binary_data, filename: "#{@contest.friendly_id}_qrcodes.zip", disposition: "attachment" + end + def get_public_completion skip_authorization diff --git a/app/policies/contest_policy.rb b/app/policies/contest_policy.rb index d153826..752182f 100644 --- a/app/policies/contest_policy.rb +++ b/app/policies/contest_policy.rb @@ -119,6 +119,10 @@ class ContestPolicy < ApplicationPolicy owner_or_admin end + def generate_qrcodes_archive? + owner_or_admin + end + def upload_csv? owner_or_admin end diff --git a/app/views/contestants/generate_qrcodes.html.slim b/app/views/contestants/generate_qrcodes.html.slim index a134e61..27f0611 100644 --- a/app/views/contestants/generate_qrcodes.html.slim +++ b/app/views/contestants/generate_qrcodes.html.slim @@ -7,6 +7,8 @@ a.mt-3.mb-3.btn.btn-primary href="#{contest_generate_qrcodes_pdf_path(@contest)}" target="_blank" style="margin-top: -3px" = t("helpers.buttons.open_raw") + a.mt-3.mb-3.ms-3.btn.btn-primary href="#{contest_generate_qrcodes_archive_path(@contest)}" target="_blank" style="margin-top: -3px" + = t("helpers.buttons.download_qrcodes_archive") .col.d-flex.flex-column style="height: calc(100% - 200px)" .d-flex.flex-column style="overflow-y: auto;" diff --git a/config/locales/en.yml b/config/locales/en.yml index 7bb658f..04a3cc4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -282,6 +282,7 @@ en: create: "Create" details: Open delete: "Delete" + download_qrcodes_archive: "Download in a ZIP archive" edit: "Edit" end: Click here to submit your completion export: Export diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 9f93a6d..72fbd63 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -253,6 +253,7 @@ fr: create: "Créer" delete: "Supprimer" details: Détails + download_qrcodes_archive: "Télécharger dans une archive ZIP" edit: "Modifier" end: Clique ici pour valider ta complétion du puzzle export: Exporter diff --git a/config/routes.rb b/config/routes.rb index f3224e8..0572a99 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -37,6 +37,7 @@ Rails.application.routes.draw do get "export", to: "contestants#export" get "generate_qrcodes", to: "contestants#generate_qrcodes" get "generate_qrcodes_pdf", to: "contestants#generate_qrcodes_pdf" + get "generate_qrcodes_archive", to: "contestants#generate_qrcodes_archive" end resources :passwords, param: :token resource :session