Add PDF generation for QR codes
Some checks failed
CI / scan_ruby (push) Failing after 24s
CI / scan_js (push) Successful in 14s
CI / lint (push) Successful in 13s
CI / test (push) Failing after 39s

This commit is contained in:
sto
2025-11-24 10:58:26 +01:00
parent 024b254808
commit 7a64fa181a
8 changed files with 64 additions and 12 deletions

View File

@@ -77,3 +77,5 @@ group :test do
end end
gem "pundit", "~> 2.5" gem "pundit", "~> 2.5"
gem "ferrum_pdf", "~> 3.0"

View File

@@ -128,6 +128,15 @@ GEM
railties (>= 6.1.0) railties (>= 6.1.0)
faker (3.5.2) faker (3.5.2)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
ferrum (0.17.1)
addressable (~> 2.5)
base64 (~> 0.2)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (~> 0.7)
ferrum_pdf (3.0.1)
actionpack (>= 6.0.0)
ferrum (~> 0.15)
friendly_id (5.5.1) friendly_id (5.5.1)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
fugit (1.12.1) fugit (1.12.1)
@@ -420,6 +429,7 @@ GEM
activemodel (>= 6.0.0) activemodel (>= 6.0.0)
bindex (>= 0.4.0) bindex (>= 0.4.0)
railties (>= 6.0.0) railties (>= 6.0.0)
webrick (1.9.1)
websocket (1.2.11) websocket (1.2.11)
websocket-driver (0.8.0) websocket-driver (0.8.0)
base64 base64
@@ -452,6 +462,7 @@ DEPENDENCIES
debug debug
factory_bot_rails factory_bot_rails
faker faker
ferrum_pdf (~> 3.0)
friendly_id (~> 5.5.0) friendly_id (~> 5.5.0)
importmap-rails importmap-rails
jbuilder jbuilder

View File

@@ -2,7 +2,7 @@ class ContestantsController < ApplicationController
include CompletionsConcern include CompletionsConcern
include ContestantsConcern include ContestantsConcern
before_action :set_contest, only: %i[ index edit new create update destroy import upload_csv convert_csv finalize_import export generate_qrcodes ] 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_contestant, only: %i[ destroy edit update] before_action :set_contestant, only: %i[ destroy edit update]
before_action :set_completions, only: %i[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 ] skip_before_action :require_authentication, only: %i[ get_public_completion post_public_completion public_completion_updated ]
@@ -96,7 +96,6 @@ class ContestantsController < ApplicationController
if @form.email_column == -1 if @form.email_column == -1
Contestant.create(name: row[@form.name_column], contest: @contest) Contestant.create(name: row[@form.name_column], contest: @contest)
else else
logger.info("Email")
Contestant.create(name: row[@form.name_column], email: row[@form.email_column], contest: @contest) Contestant.create(name: row[@form.name_column], email: row[@form.email_column], contest: @contest)
end end
end end
@@ -115,7 +114,7 @@ class ContestantsController < ApplicationController
respond_to do |format| respond_to do |format|
format.csv do format.csv do
response.headers["Content-Type"] = "text/csv" response.headers["Content-Type"] = "text/csv"
response.headers["Content-Disposition"] = "attachment; filename=export.csv" response.headers["Content-Disposition"] = "attachment; filename=#{contest.friendly_id}_results.csv"
end end
end end
end end
@@ -126,6 +125,18 @@ class ContestantsController < ApplicationController
@contestants = @contest.contestants.sort_by { |contestant| contestant.name } @contestants = @contest.contestants.sort_by { |contestant| contestant.name }
end end
def generate_qrcodes_pdf
authorize @contest
@contestants = @contest.contestants.sort_by { |contestant| contestant.name }
@nonav = true
respond_to do |format|
format.html
format.pdf { render ferrum_pdf: {}, disposition: :inline, filename: "#{@contest.friendly_id}_qrcodes.pdf", layout: "blank" }
end
end
def get_public_completion def get_public_completion
skip_authorization skip_authorization

View File

@@ -79,6 +79,10 @@ class ContestPolicy < ApplicationPolicy
owner_or_admin owner_or_admin
end end
def generate_qrcodes_pdf?
owner_or_admin
end
def upload_csv? def upload_csv?
owner_or_admin owner_or_admin
end end

View File

@@ -1,20 +1,25 @@
- if @contest.code.present? - if @contest.code.present?
.row.mb-4 style="height: calc(100vh - 280px)" .mb-4 style="height: calc(100vh - 280px)"
.row .row
.col .col
.alert.alert-info .alert.alert-info
= t("contestants.generate_qrcodes.note") = t("contestants.generate_qrcodes.note")
.col.d-flex.flex-column style="height: 100%"
.d-flex.flex-column style="overflow-y: auto" a.mt-3.mb-3.btn.btn-primary href="#{contest_generate_qrcodes_pdf_path(@contest)}.pdf" target="_blank" style="margin-top: -3px"
= t("helpers.buttons.download_pdf")
.col.d-flex.flex-column style="height: calc(100% - 200px)"
.d-flex.flex-column style="overflow-y: auto;"
- for row in 0..((@contestants.length - 1) / 5) - for row in 0..((@contestants.length - 1) / 5)
.mt-4.d-flex.flex-row .mt-4.d-flex.flex-row
- for col in 0..4 - for col in 0..3
- if row * 5 + col < @contestants.length - if row * 4 + col < @contestants.length
.d-flex.flex-column.ms-5 style="align-items: center" .d-flex.flex-column.ms-5 style="align-items: center"
= @contestants[row * 5 + col].name - if @contestants[row * 4 + col].qrcode.present?
- if @contestants[row * 5 + col].qrcode.present? .mt-1 style="width: 128px; height: 120px;"
.mt-1 style="width: 180px; height: 180px;" = @contestants[row * 4 + col].qrcode.html_safe
= @contestants[row * 5 + col].qrcode.html_safe .name.text-center.mt-3 style="font-size: 0.7rem; max-width: 128px; height: 30px;"
= @contestants[row * 4 + col].name
- else - else
.row .row
.col .col

View File

@@ -0,0 +1,12 @@
h1.text-center.mb-5 = @contest.name
- for row in 0..((@contestants.length - 1) / 5)
.mt-4.d-flex.flex-row
- for col in 0..3
- if row * 4 + col < @contestants.length
.d-flex.flex-column.ms-5 style="align-items: center"
- if @contestants[row * 4 + col].qrcode.present?
.mt-1 style="width: 128px; height: 120px;"
= @contestants[row * 4 + col].qrcode.html_safe
.name.text-center.mt-3 style="font-size: 0.7rem; max-width: 128px; height: 30px;"
= @contestants[row * 4 + col].name

View File

@@ -0,0 +1,6 @@
doctype html
html
= render "layouts/header"
body
= yield

View File

@@ -27,6 +27,7 @@ Rails.application.routes.draw do
post "import/:id", to: "contestants#finalize_import" post "import/:id", to: "contestants#finalize_import"
get "export", to: "contestants#export" get "export", to: "contestants#export"
get "generate_qrcodes", to: "contestants#generate_qrcodes" get "generate_qrcodes", to: "contestants#generate_qrcodes"
get "generate_qrcodes_pdf", to: "contestants#generate_qrcodes_pdf"
end end
resources :passwords, param: :token resources :passwords, param: :token
resource :session resource :session