Add public scoreboard slug & URL
This commit is contained in:
parent
d47ebf22ab
commit
9a2a3a6f33
@ -69,6 +69,6 @@ class ContestsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def contest_params
|
def contest_params
|
||||||
params.expect(contest: [ :name, :team, :allow_registration ])
|
params.expect(contest: [ :name, :team, :allow_registration, :slug ])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
class SessionsController < ApplicationController
|
class SessionsController < ApplicationController
|
||||||
allow_unauthenticated_access only: %i[ new create ]
|
allow_unauthenticated_access only: %i[ new create ]
|
||||||
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_url, alert: "Try again later." }
|
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_url, alert: "Try again later." }
|
||||||
|
before_action :skip_authorization
|
||||||
|
|
||||||
def new
|
def new
|
||||||
skip_authorization
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
skip_authorization
|
|
||||||
if user = User.authenticate_by(params.permit(:email_address, :password))
|
if user = User.authenticate_by(params.permit(:email_address, :password))
|
||||||
start_new_session_for user
|
start_new_session_for user
|
||||||
redirect_to after_authentication_url
|
redirect_to after_authentication_url
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# allow_registration :boolean default(FALSE)
|
# allow_registration :boolean default(FALSE)
|
||||||
# name :string
|
# name :string
|
||||||
|
# slug :string
|
||||||
# team :boolean default(FALSE)
|
# team :boolean default(FALSE)
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
@ -24,4 +25,7 @@ class Contest < ApplicationRecord
|
|||||||
has_many :completions, dependent: :destroy
|
has_many :completions, dependent: :destroy
|
||||||
has_many :contestants, dependent: :destroy
|
has_many :contestants, dependent: :destroy
|
||||||
has_many :puzzles, dependent: :destroy
|
has_many :puzzles, dependent: :destroy
|
||||||
|
|
||||||
|
validates :name, presence: true
|
||||||
|
validates :slug, presence: true, format: { with: /\A(\w|-)*\z/, message: 'Only alphanumeric characters, "-" and "_" allowed.' }
|
||||||
end
|
end
|
||||||
|
@ -4,6 +4,12 @@
|
|||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :name, autocomplete: "off", class: "form-control"
|
= form.text_field :name, autocomplete: "off", class: "form-control"
|
||||||
= form.label :name, class: "required"
|
= form.label :name, class: "required"
|
||||||
|
.row.mb-3
|
||||||
|
.col
|
||||||
|
.form-floating
|
||||||
|
= form.text_field :slug, autocomplete: "off", class: "form-control"
|
||||||
|
= form.label :slug, class: "required"
|
||||||
|
.form-text This will be used for building the public scoreboard URL: https://puzzle-scoreboard.org/public/<slug>.
|
||||||
.row.mb-3
|
.row.mb-3
|
||||||
.col
|
.col
|
||||||
.form-check.form-switch
|
.form-check.form-switch
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.row.mb-2
|
.row.mb-4
|
||||||
.col
|
.col
|
||||||
css:
|
css:
|
||||||
.badges { margin-top: -18px; position: absolute; }
|
.badges { margin-top: -18px; position: absolute; }
|
||||||
@ -6,10 +6,16 @@
|
|||||||
- @badges.each do |badge|
|
- @badges.each do |badge|
|
||||||
span.badge.text-bg-info.me-2
|
span.badge.text-bg-info.me-2
|
||||||
= badge
|
= badge
|
||||||
|
|
||||||
|
.row.mb-4
|
||||||
|
.col
|
||||||
.float-end
|
.float-end
|
||||||
a.btn.btn-primary href=edit_contest_path(@contest)
|
a.btn.btn-primary href=edit_contest_path(@contest)
|
||||||
| Edit contest
|
| Edit contest
|
||||||
|
p
|
||||||
|
|> Public scoreboard:
|
||||||
|
= link_to root_url + "public/#{@contest.slug}"
|
||||||
|
|
||||||
.row.mb-4
|
.row.mb-4
|
||||||
.col-6
|
.col-6
|
||||||
.row
|
.row
|
||||||
|
@ -2,9 +2,9 @@ ActionView::Base.field_error_proc = proc do |html_tag, instance|
|
|||||||
if html_tag.include? "<label"
|
if html_tag.include? "<label"
|
||||||
appended_html = ""
|
appended_html = ""
|
||||||
if instance.error_message.is_a?(Array)
|
if instance.error_message.is_a?(Array)
|
||||||
appended_html = "<div class='error-message form-text'>#{instance.error_message.map(&:humanize).uniq.join(", ")}</div>"
|
appended_html = "<div class='error-message form-text'>#{instance.error_message.map(&:capitalize).uniq.join(", ")}</div>"
|
||||||
else
|
else
|
||||||
appended_html = "<div class='error-message form-text'>#{instance.error_message.humanize}</div>"
|
appended_html = "<div class='error-message form-text'>#{instance.error_message.capitalize}</div>"
|
||||||
end
|
end
|
||||||
html_tag + appended_html.html_safe
|
html_tag + appended_html.html_safe
|
||||||
else
|
else
|
||||||
|
5
db/migrate/20250322164205_add_slug_to_contest.rb
Normal file
5
db/migrate/20250322164205_add_slug_to_contest.rb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class AddSlugToContest < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_column :contests, :slug, :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.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2025_03_22_071308) do
|
ActiveRecord::Schema[8.0].define(version: 2025_03_22_164205) do
|
||||||
create_table "active_storage_attachments", force: :cascade do |t|
|
create_table "active_storage_attachments", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", null: false
|
t.string "record_type", null: false
|
||||||
@ -67,6 +67,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_22_071308) do
|
|||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.boolean "team", default: false
|
t.boolean "team", default: false
|
||||||
t.boolean "allow_registration", default: false
|
t.boolean "allow_registration", default: false
|
||||||
|
t.string "slug"
|
||||||
t.index ["user_id"], name: "index_contests_on_user_id"
|
t.index ["user_id"], name: "index_contests_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
1
test/fixtures/contests.yml
vendored
1
test/fixtures/contests.yml
vendored
@ -7,6 +7,7 @@
|
|||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# allow_registration :boolean default(FALSE)
|
# allow_registration :boolean default(FALSE)
|
||||||
# name :string
|
# name :string
|
||||||
|
# slug :string
|
||||||
# team :boolean default(FALSE)
|
# team :boolean default(FALSE)
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# allow_registration :boolean default(FALSE)
|
# allow_registration :boolean default(FALSE)
|
||||||
# name :string
|
# name :string
|
||||||
|
# slug :string
|
||||||
# team :boolean default(FALSE)
|
# team :boolean default(FALSE)
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
|
Loading…
x
Reference in New Issue
Block a user