Events: kickstart shared scoreboard
This commit is contained in:
7
app/controllers/concerns/contests_concern.rb
Normal file
7
app/controllers/concerns/contests_concern.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module ContestsConcern
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def active_page(path)
|
||||||
|
request.path.starts_with?(path) ? "active" : ""
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
class ContestsController < ApplicationController
|
class ContestsController < ApplicationController
|
||||||
include CompletionsConcern
|
include CompletionsConcern
|
||||||
|
include ContestsConcern
|
||||||
include ContestantsConcern
|
include ContestantsConcern
|
||||||
|
|
||||||
before_action :set_contest, only: %i[ destroy show ]
|
before_action :set_contest, only: %i[ destroy show ]
|
||||||
@@ -168,11 +169,31 @@ class ContestsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def scoreboard
|
def scoreboard
|
||||||
|
if active_page("/public/event")
|
||||||
|
@event = Event.find_by(slug: params[:id])
|
||||||
|
unless @event && @event.shared_scoreboard && !@event.contests.where(public: true).empty?
|
||||||
|
skip_authorization
|
||||||
|
not_found and return
|
||||||
|
end
|
||||||
|
if params.key?(:contest_id)
|
||||||
|
begin
|
||||||
|
@contest = Contest.find(params[:contest_id])
|
||||||
|
if @contest.event != @event
|
||||||
|
@contest = @event.contests.where(public: true).first
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
@contest = @event.contests.where(public: true).first
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@contest = @event.contests.where(public: true).first
|
||||||
|
end
|
||||||
|
else
|
||||||
@contest = Contest.find_by(slug: params[:id])
|
@contest = Contest.find_by(slug: params[:id])
|
||||||
unless @contest && @contest.public
|
unless @contest && @contest.public
|
||||||
skip_authorization
|
skip_authorization
|
||||||
not_found and return
|
not_found and return
|
||||||
end
|
end
|
||||||
|
end
|
||||||
authorize @contest
|
authorize @contest
|
||||||
|
|
||||||
I18n.locale = @contest.lang
|
I18n.locale = @contest.lang
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class EventsController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
authorize @event
|
authorize @event
|
||||||
|
|
||||||
@contests = @event.contests
|
@contests = @event.contests.includes([ :contestants, :puzzles ])
|
||||||
@title = @event.name
|
@title = @event.name
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -65,11 +65,13 @@ class EventsController < ApplicationController
|
|||||||
redirect_to events_path, notice: t("events.destroy.notice")
|
redirect_to events_path, notice: t("events.destroy.notice")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def set_event
|
def set_event
|
||||||
@event = Event.find(params[:id])
|
@event = Event.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def event_params
|
def event_params
|
||||||
params.expect(event: [ :name, :shared_scoreboard ])
|
params.expect(event: [ :lang, :name, :shared_scoreboard ])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
# lang :string default("en")
|
# lang :string default("en")
|
||||||
# name :string
|
# name :string
|
||||||
# shared_scoreboard :boolean
|
# shared_scoreboard :boolean
|
||||||
|
# slug :string
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# user_id :integer not null
|
# user_id :integer not null
|
||||||
@@ -19,8 +20,13 @@
|
|||||||
# user_id (user_id => users.id)
|
# user_id (user_id => users.id)
|
||||||
#
|
#
|
||||||
class Event < ApplicationRecord
|
class Event < ApplicationRecord
|
||||||
|
extend FriendlyId
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_many :contests, dependent: :destroy
|
has_many :contests, dependent: :destroy
|
||||||
|
|
||||||
|
friendly_id :name, use: :slugged
|
||||||
|
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
|
validates :lang, inclusion: { in: Languages::AVAILABLE_LANGUAGES.map { |lang| lang[:id] } }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,13 @@
|
|||||||
.alert.alert-primary role="alert"
|
.alert.alert-primary role="alert"
|
||||||
= t("events.form.shared_scoreboard_message")
|
= t("events.form.shared_scoreboard_message")
|
||||||
|
|
||||||
|
if method == :patch
|
||||||
|
.row.mb-3
|
||||||
|
.col
|
||||||
|
.form-floating
|
||||||
|
= form.select :lang, Languages::AVAILABLE_LANGUAGES.map { |lang| [ lang[:name], lang[:id] ] }, {}, class: "form-select"
|
||||||
|
= form.label :lang
|
||||||
|
|
||||||
.row.mt-4
|
.row.mt-4
|
||||||
.col
|
.col
|
||||||
- if method == :patch
|
- if method == :patch
|
||||||
|
|||||||
@@ -8,7 +8,14 @@
|
|||||||
a.mt-3.btn.btn-primary.mb-4 href=new_contest_path(event: @event.id)
|
a.mt-3.btn.btn-primary.mb-4 href=new_contest_path(event: @event.id)
|
||||||
= t("events.show.new_contest")
|
= t("events.show.new_contest")
|
||||||
|
|
||||||
.row.row-cols-1.row-cols-md-3.g-4
|
- if @event.shared_scoreboard
|
||||||
|
a.btn.btn-success href="/public/event/#{@event.slug}" style="margin-top: -6px;"
|
||||||
|
= t("events.show.open_shared_scoreboard")
|
||||||
|
- else
|
||||||
|
a.btn.btn-success.disabled style="margin-top: -6px;"
|
||||||
|
= t("events.show.shared_scoreboard_disabled")
|
||||||
|
|
||||||
|
.mt-3.row.row-cols-1.row-cols-md-3.g-4
|
||||||
- @contests.each do |contest|
|
- @contests.each do |contest|
|
||||||
.col
|
.col
|
||||||
css:
|
css:
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ en:
|
|||||||
file: File
|
file: File
|
||||||
separator: Separator
|
separator: Separator
|
||||||
event:
|
event:
|
||||||
|
lang: Language for th shared scoreboard
|
||||||
name: Name
|
name: Name
|
||||||
shared_scoreboard: Shared scoreboard
|
shared_scoreboard: Shared scoreboard
|
||||||
shared_scoreboard_description: If activated, there will be a scoreboard link specific to the event, with tabs for each contest
|
shared_scoreboard_description: If activated, there will be a scoreboard link specific to the event, with tabs for each contest
|
||||||
@@ -310,6 +311,8 @@ en:
|
|||||||
manage_contests: Contests in this event
|
manage_contests: Contests in this event
|
||||||
modify: Settings
|
modify: Settings
|
||||||
new_contest: Add a contest to this event
|
new_contest: Add a contest to this event
|
||||||
|
shared_scoreboard_disabled: The shared scoreboard is disabled
|
||||||
|
open_shared_scoreboard: Open shared scoreboard
|
||||||
helpers:
|
helpers:
|
||||||
badges:
|
badges:
|
||||||
registration: "registration"
|
registration: "registration"
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ fr:
|
|||||||
file: Fichier
|
file: Fichier
|
||||||
separator: Délimiteur
|
separator: Délimiteur
|
||||||
event:
|
event:
|
||||||
|
lang: Langue pour le classement partagé
|
||||||
name: Nom
|
name: Nom
|
||||||
shared_scoreboard: Classement partagé
|
shared_scoreboard: Classement partagé
|
||||||
shared_scoreboard_description: Si activé, un lien de classement partagé sera disponible pour l'événement, avec des onglets pour chacune des épreuves.
|
shared_scoreboard_description: Si activé, un lien de classement partagé sera disponible pour l'événement, avec des onglets pour chacune des épreuves.
|
||||||
@@ -281,6 +282,8 @@ fr:
|
|||||||
manage_contests: Épreuves de cet événement
|
manage_contests: Épreuves de cet événement
|
||||||
modify: Paramètres
|
modify: Paramètres
|
||||||
new_contest: Ajouter une épreuve à cet événement
|
new_contest: Ajouter une épreuve à cet événement
|
||||||
|
shared_scoreboard_disabled: Le classement partagé n'est pas activé
|
||||||
|
open_shared_scoreboard: Ouvrir le classement partagé
|
||||||
helpers:
|
helpers:
|
||||||
badges:
|
badges:
|
||||||
registration: "auto-inscription"
|
registration: "auto-inscription"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ Rails.application.routes.draw do
|
|||||||
post "update_contestants", to: "users#update_contestants"
|
post "update_contestants", to: "users#update_contestants"
|
||||||
|
|
||||||
get "public/:id", to: "contests#scoreboard"
|
get "public/:id", to: "contests#scoreboard"
|
||||||
|
get "public/event/:id", to: "contests#scoreboard"
|
||||||
get "public/:id/offline", to: "contests#offline_new"
|
get "public/:id/offline", to: "contests#offline_new"
|
||||||
post "public/:id/offline", to: "contests#offline_create"
|
post "public/:id/offline", to: "contests#offline_create"
|
||||||
get "public/:id/offline/:token", to: "contests#offline_edit"
|
get "public/:id/offline/:token", to: "contests#offline_edit"
|
||||||
|
|||||||
5
db/migrate/20260730055752_add_slug_to_event.rb
Normal file
5
db/migrate/20260730055752_add_slug_to_event.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class AddSlugToEvent < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_column :events, :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: 2026_07_26_114604) do
|
ActiveRecord::Schema[8.0].define(version: 2026_07_30_055752) 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
|
||||||
@@ -126,6 +126,7 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_26_114604) do
|
|||||||
t.integer "user_id", null: false
|
t.integer "user_id", null: false
|
||||||
t.boolean "shared_scoreboard"
|
t.boolean "shared_scoreboard"
|
||||||
t.string "lang", default: "en"
|
t.string "lang", default: "en"
|
||||||
|
t.string "slug"
|
||||||
t.index ["user_id"], name: "index_events_on_user_id"
|
t.index ["user_id"], name: "index_events_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
# lang :string default("en")
|
# lang :string default("en")
|
||||||
# name :string
|
# name :string
|
||||||
# shared_scoreboard :boolean
|
# shared_scoreboard :boolean
|
||||||
|
# slug :string
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# user_id :integer not null
|
# user_id :integer not null
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
# lang :string default("en")
|
# lang :string default("en")
|
||||||
# name :string
|
# name :string
|
||||||
# shared_scoreboard :boolean
|
# shared_scoreboard :boolean
|
||||||
|
# slug :string
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# user_id :integer not null
|
# user_id :integer not null
|
||||||
|
|||||||
Reference in New Issue
Block a user