diff --git a/Gemfile b/Gemfile index e909d95..01a26ac 100644 --- a/Gemfile +++ b/Gemfile @@ -77,3 +77,5 @@ group :test do end gem "pundit", "~> 2.5" + +gem "ferrum_pdf", "~> 3.0" diff --git a/Gemfile.lock b/Gemfile.lock index 286feb6..641e82b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -128,6 +128,15 @@ GEM railties (>= 6.1.0) faker (3.5.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) activerecord (>= 4.0.0) fugit (1.12.1) @@ -420,6 +429,7 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) + webrick (1.9.1) websocket (1.2.11) websocket-driver (0.8.0) base64 @@ -452,6 +462,7 @@ DEPENDENCIES debug factory_bot_rails faker + ferrum_pdf (~> 3.0) friendly_id (~> 5.5.0) importmap-rails jbuilder diff --git a/app/controllers/contestants_controller.rb b/app/controllers/contestants_controller.rb index 51b14f1..ada0019 100644 --- a/app/controllers/contestants_controller.rb +++ b/app/controllers/contestants_controller.rb @@ -2,7 +2,7 @@ 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 ] + 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_completions, only: %i[edit update ] 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 Contestant.create(name: row[@form.name_column], contest: @contest) else - logger.info("Email") Contestant.create(name: row[@form.name_column], email: row[@form.email_column], contest: @contest) end end @@ -115,7 +114,7 @@ class ContestantsController < ApplicationController respond_to do |format| format.csv do 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 @@ -126,6 +125,18 @@ class ContestantsController < ApplicationController @contestants = @contest.contestants.sort_by { |contestant| contestant.name } 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 skip_authorization diff --git a/app/policies/contest_policy.rb b/app/policies/contest_policy.rb index dd20025..dfe842c 100644 --- a/app/policies/contest_policy.rb +++ b/app/policies/contest_policy.rb @@ -79,6 +79,10 @@ class ContestPolicy < ApplicationPolicy owner_or_admin end + def generate_qrcodes_pdf? + 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 da786a9..651eb85 100644 --- a/app/views/contestants/generate_qrcodes.html.slim +++ b/app/views/contestants/generate_qrcodes.html.slim @@ -1,20 +1,25 @@ - if @contest.code.present? - .row.mb-4 style="height: calc(100vh - 280px)" + .mb-4 style="height: calc(100vh - 280px)" .row .col .alert.alert-info = 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) .mt-4.d-flex.flex-row - - for col in 0..4 - - if row * 5 + col < @contestants.length + - for col in 0..3 + - if row * 4 + col < @contestants.length .d-flex.flex-column.ms-5 style="align-items: center" - = @contestants[row * 5 + col].name - - if @contestants[row * 5 + col].qrcode.present? - .mt-1 style="width: 180px; height: 180px;" - = @contestants[row * 5 + col].qrcode.html_safe + - 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 - else .row .col diff --git a/app/views/contestants/generate_qrcodes_pdf.html.slim b/app/views/contestants/generate_qrcodes_pdf.html.slim new file mode 100644 index 0000000..b598849 --- /dev/null +++ b/app/views/contestants/generate_qrcodes_pdf.html.slim @@ -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 \ No newline at end of file diff --git a/app/views/layouts/blank.html.slim b/app/views/layouts/blank.html.slim new file mode 100644 index 0000000..44479a0 --- /dev/null +++ b/app/views/layouts/blank.html.slim @@ -0,0 +1,6 @@ +doctype html +html + = render "layouts/header" + + body + = yield \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index df34e7b..2c68ad1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,6 +27,7 @@ Rails.application.routes.draw do post "import/:id", to: "contestants#finalize_import" get "export", to: "contestants#export" get "generate_qrcodes", to: "contestants#generate_qrcodes" + get "generate_qrcodes_pdf", to: "contestants#generate_qrcodes_pdf" end resources :passwords, param: :token resource :session