QR codes generation
This commit is contained in:
1
Gemfile
1
Gemfile
@@ -46,6 +46,7 @@ gem "bootstrap", "~> 5.3.3"
|
||||
gem "friendly_id", "~> 5.5.0"
|
||||
gem "csv"
|
||||
gem "damerau-levenshtein"
|
||||
gem "rqrcode", "~> 3.0"
|
||||
|
||||
group :development, :test do
|
||||
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
||||
|
||||
@@ -100,6 +100,7 @@ GEM
|
||||
rack-test (>= 0.6.3)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
chunky_png (1.4.0)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.4)
|
||||
crass (1.0.6)
|
||||
@@ -291,6 +292,10 @@ GEM
|
||||
reline (0.6.2)
|
||||
io-console (~> 0.5)
|
||||
rexml (3.4.4)
|
||||
rqrcode (3.1.0)
|
||||
chunky_png (~> 1.0)
|
||||
rqrcode_core (~> 2.0)
|
||||
rqrcode_core (2.0.0)
|
||||
rspec-core (3.13.6)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-expectations (3.13.5)
|
||||
@@ -455,6 +460,7 @@ DEPENDENCIES
|
||||
puma (>= 5.0)
|
||||
pundit (~> 2.5)
|
||||
rails (~> 8.0.2)
|
||||
rqrcode (~> 3.0)
|
||||
rspec-rails
|
||||
rubocop-rails-omakase
|
||||
selenium-webdriver
|
||||
|
||||
@@ -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 ]
|
||||
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_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 ]
|
||||
@@ -42,7 +42,7 @@ class ContestantsController < ApplicationController
|
||||
|
||||
if @contestant.update(contestant_params)
|
||||
update_contestant_categories
|
||||
redirect_to @contest, notice: t("contestants.edit.notice")
|
||||
redirect_to contest_contestants_path(@contest), notice: t("contestants.edit.notice")
|
||||
else
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
@@ -120,6 +120,12 @@ class ContestantsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def generate_qrcodes
|
||||
authorize @contest
|
||||
|
||||
@contestants = @contest.contestants.sort_by { |contestant| contestant.name }
|
||||
end
|
||||
|
||||
def get_public_completion
|
||||
skip_authorization
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
# email :string
|
||||
# name :string
|
||||
# projected_time :string
|
||||
# qrcode :string
|
||||
# time_seconds :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
@@ -27,6 +28,7 @@ class Contestant < ApplicationRecord
|
||||
has_and_belongs_to_many :categories
|
||||
|
||||
before_validation :initialize_time_seconds_if_empty
|
||||
before_commit :generate_qrcode, on: :create
|
||||
|
||||
validates :name, presence: true
|
||||
validates :time_seconds, presence: true
|
||||
@@ -48,4 +50,17 @@ class Contestant < ApplicationRecord
|
||||
self.time_seconds = 0
|
||||
end
|
||||
end
|
||||
|
||||
def generate_qrcode
|
||||
host = Rails.application.config.action_controller.default_url_options[:host]
|
||||
qrcode = RQRCode::QRCode.new("https://#{host}/public/p/#{self.generate_token_for(:token)}")
|
||||
self.qrcode = qrcode.as_svg(
|
||||
color: "000",
|
||||
shape_rendering: "crispEdges",
|
||||
module_size: 3,
|
||||
standalone: true,
|
||||
use_path: true,
|
||||
viewbox: true
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ class Offline < ApplicationRecord
|
||||
belongs_to :contestant, optional: true
|
||||
belongs_to :completion, optional: true
|
||||
|
||||
has_many_attached :images
|
||||
has_many_attached :images, dependent: :destroy
|
||||
|
||||
generates_token_for :token
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class Puzzle < ApplicationRecord
|
||||
belongs_to :contest
|
||||
|
||||
has_many :completions, dependent: :destroy
|
||||
has_one_attached :image
|
||||
has_one_attached :image, dependent: :destroy
|
||||
|
||||
validates :name, presence: true
|
||||
validates :pieces, presence: true
|
||||
|
||||
@@ -35,6 +35,10 @@ class ContestPolicy < ApplicationPolicy
|
||||
owner_or_admin
|
||||
end
|
||||
|
||||
def generate_qrcodes?
|
||||
owner_or_admin
|
||||
end
|
||||
|
||||
def settings_general_edit?
|
||||
edit?
|
||||
end
|
||||
|
||||
11
app/views/contestants/generate_qrcodes.html.slim
Normal file
11
app/views/contestants/generate_qrcodes.html.slim
Normal file
@@ -0,0 +1,11 @@
|
||||
.row.mb-4 style="height: calc(100vh - 280px)"
|
||||
.col.d-flex.flex-column style="height: 100%"
|
||||
.d-flex.flex-column style="overflow-y: auto"
|
||||
- for row in 0..((@contestants.length - 1) / 4)
|
||||
.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"
|
||||
= @contestants[row * 4 + col].name
|
||||
.mt-1 style="width: 200px; height: 200px;"
|
||||
= @contestants[row * 4 + col].qrcode.html_safe
|
||||
@@ -6,6 +6,8 @@
|
||||
| + #{t("helpers.buttons.add")}
|
||||
a.ms-2.btn.btn.btn-primary href=contest_import_path(@contest) style="margin-top: -3px"
|
||||
| #{t("helpers.buttons.import")}
|
||||
a.ms-2.btn.btn.btn-primary href=contest_generate_qrcodes_path(@contest) style="margin-top: -3px"
|
||||
| #{t("helpers.buttons.generate_qrcodes")}
|
||||
a.ms-2.btn.btn.btn-primary href="/contests/#{@contest.id}/export.csv" style="margin-top: -3px"
|
||||
| #{t("helpers.buttons.export")}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ Rails.application.configure do
|
||||
# Set localhost to be used by links generated in mailer templates.
|
||||
config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
|
||||
|
||||
config.action_controller.default_url_options = { host: "localhost" }
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ Rails.application.configure do
|
||||
# Set host to be used by links generated in mailer templates.
|
||||
config.action_mailer.default_url_options = { host: "example.com" }
|
||||
|
||||
config.action_controller.default_url_options = { host: "public-scoreboard.org" }
|
||||
|
||||
# Specify outgoing SMTP server. Remember to add smtp/* credentials via rails credentials:edit.
|
||||
# config.action_mailer.smtp_settings = {
|
||||
# user_name: Rails.application.credentials.dig(:smtp, :user_name),
|
||||
|
||||
@@ -258,6 +258,7 @@ en:
|
||||
edit: "Edit"
|
||||
end: Click here to submit your completion
|
||||
export: Export
|
||||
generate_qrcodes: Generate QR codes
|
||||
import: CSV Import
|
||||
open: Open
|
||||
refresh: Refresh
|
||||
|
||||
@@ -229,6 +229,7 @@ fr:
|
||||
edit: "Modifier"
|
||||
end: Clique ici pour valider ta complétion du puzzle
|
||||
export: Exporter
|
||||
generate_qrcodes: Générer des QR codes
|
||||
import: Importer un CSV
|
||||
open: Détails
|
||||
refresh: Rafraîchir
|
||||
|
||||
@@ -26,6 +26,7 @@ Rails.application.routes.draw do
|
||||
get "import/:id", to: "contestants#convert_csv"
|
||||
post "import/:id", to: "contestants#finalize_import"
|
||||
get "export", to: "contestants#export"
|
||||
get "generate_qrcodes", to: "contestants#generate_qrcodes"
|
||||
end
|
||||
resources :passwords, param: :token
|
||||
resource :session
|
||||
|
||||
5
db/migrate/20251120100813_add_qrcode_to_contestant.rb
Normal file
5
db/migrate/20251120100813_add_qrcode_to_contestant.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddQrcodeToContestant < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
add_column :contestants, :qrcode, :string
|
||||
end
|
||||
end
|
||||
3
db/schema.rb
generated
3
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_11_18_074914) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_11_20_100813) do
|
||||
create_table "active_storage_attachments", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.string "record_type", null: false
|
||||
@@ -83,6 +83,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_18_074914) do
|
||||
t.string "display_time"
|
||||
t.integer "time_seconds"
|
||||
t.string "projected_time"
|
||||
t.string "qrcode"
|
||||
t.index ["contest_id"], name: "index_contestants_on_contest_id"
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user