Compare commits
2 Commits
97ea17b7c2
...
f91145637f
| Author | SHA1 | Date | |
|---|---|---|---|
| f91145637f | |||
| cdf87e48f2 |
@@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base
|
||||
include Authentication
|
||||
include Pundit::Authorization
|
||||
|
||||
before_action :set_title, :set_current_user, :set_lang
|
||||
before_action :set_current_user, :set_lang
|
||||
after_action :verify_authorized
|
||||
|
||||
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
||||
@@ -12,13 +12,6 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
private
|
||||
|
||||
def set_title
|
||||
t_action_name = action_name
|
||||
t_action_name = "new" if action_name == "create"
|
||||
t_action_name = "edit" if action_name == "update"
|
||||
@title = I18n.t("#{controller_name}.#{t_action_name}.title")
|
||||
end
|
||||
|
||||
def set_current_user
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
@@ -8,21 +8,11 @@ class CompletionsController < ApplicationController
|
||||
|
||||
def edit
|
||||
authorize @contest
|
||||
|
||||
if @contestant
|
||||
@action_name = t("helpers.buttons.back_to_contestant")
|
||||
@action_path = edit_contest_contestant_path(@contest, @contestant)
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
authorize @contest
|
||||
|
||||
if @contestant
|
||||
@action_name = t("helpers.buttons.back_to_contestant")
|
||||
@action_path = edit_contest_contestant_path(@contest, @contestant)
|
||||
end
|
||||
|
||||
@completion = Completion.new
|
||||
@completion.completed = true
|
||||
if params[:contestant_id]
|
||||
@@ -47,11 +37,6 @@ class CompletionsController < ApplicationController
|
||||
else
|
||||
if params[:completion].key?(:message_id)
|
||||
@message = Message.find(params[:completion][:message_id])
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
elsif @contestant
|
||||
@action_name = t("helpers.buttons.back_to_contestant")
|
||||
@action_path = edit_contest_contestant_path(@contest, @contestant)
|
||||
end
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
@@ -69,10 +54,6 @@ class CompletionsController < ApplicationController
|
||||
redirect_to @contest, notice: t("completions.edit.notice")
|
||||
end
|
||||
else
|
||||
if @contestant
|
||||
@action_name = t("helpers.buttons.back_to_contestant")
|
||||
@action_path = edit_contest_contestant_path(@contest, @contestant)
|
||||
end
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
12
app/controllers/concerns/contestants_concern.rb
Normal file
12
app/controllers/concerns/contestants_concern.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
module ContestantsConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def ranked_contestants(contest)
|
||||
contest.contestants.sort_by { |contestant| [
|
||||
-contestant.completions.where(remaining_pieces: nil).size,
|
||||
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
|
||||
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
|
||||
contestant.time_seconds
|
||||
] }
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,6 @@
|
||||
class ContestantsController < ApplicationController
|
||||
include ContestantsConcern
|
||||
|
||||
before_action :set_contest
|
||||
before_action :set_contestant, only: %i[ destroy edit update]
|
||||
before_action :set_completions, only: %i[edit update ]
|
||||
@@ -6,29 +8,17 @@ class ContestantsController < ApplicationController
|
||||
def index
|
||||
authorize @contest
|
||||
|
||||
@title = @contest.name
|
||||
@contestants = @contest.contestants.sort_by { |contestant| [
|
||||
-contestant.completions.where(remaining_pieces: nil).size,
|
||||
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
|
||||
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
|
||||
contestant.time_seconds
|
||||
] }
|
||||
@contestants = @contest.contestants.sort_by { |contestant| contestant.name }
|
||||
filter_contestants_per_category
|
||||
end
|
||||
|
||||
def edit
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@title = @contestant.name
|
||||
end
|
||||
|
||||
def new
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@contestant = Contestant.new
|
||||
end
|
||||
|
||||
@@ -41,8 +31,6 @@ class ContestantsController < ApplicationController
|
||||
update_contestant_categories
|
||||
redirect_to contest_path(@contest), notice: t("contestants.new.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -54,8 +42,6 @@ class ContestantsController < ApplicationController
|
||||
update_contestant_categories
|
||||
redirect_to @contest, notice: t("contestants.edit.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -83,8 +69,6 @@ class ContestantsController < ApplicationController
|
||||
if @csv_import.save
|
||||
redirect_to "/contests/#{@contest.id}/import/#{@csv_import.id}"
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
render :import, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -92,8 +76,6 @@ class ContestantsController < ApplicationController
|
||||
def convert_csv
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@csv_import = CsvImport.find(params[:id])
|
||||
@content = JSON.parse(@csv_import.content)
|
||||
@form = Forms::CsvConversionForm.new
|
||||
@@ -119,8 +101,6 @@ class ContestantsController < ApplicationController
|
||||
end
|
||||
redirect_to contest_path(@contest), notice: t("contestants.import.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
render :convert_csv, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -128,12 +108,7 @@ class ContestantsController < ApplicationController
|
||||
def export
|
||||
authorize @contest
|
||||
|
||||
@contestants = @contest.contestants.sort_by { |contestant| [
|
||||
-contestant.completions.where(remaining_pieces: nil).size,
|
||||
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
|
||||
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
|
||||
contestant.time_seconds
|
||||
] }
|
||||
@contestants = ranked_contestants(@contest)
|
||||
|
||||
respond_to do |format|
|
||||
format.csv do
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
class ContestsController < ApplicationController
|
||||
include CompletionsConcern
|
||||
include ContestantsConcern
|
||||
|
||||
before_action :set_contest, only: %i[ destroy edit show update ]
|
||||
before_action :set_contest, only: %i[ destroy show ]
|
||||
before_action :set_settings_contest, only: %i[ settings_general_edit settings_general_update settings_offline_edit settings_offline_update settings_categories_edit ]
|
||||
before_action :offline_setup, only: %i[ offline_new offline_create offline_edit offline_update offline_completed ]
|
||||
skip_before_action :require_authentication, only: %i[ scoreboard offline_new offline_create offline_edit offline_update offline_completed ]
|
||||
@@ -19,35 +20,16 @@ class ContestsController < ApplicationController
|
||||
redirect_to contest_contestants_path(@contest)
|
||||
end
|
||||
|
||||
def edit
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
end
|
||||
|
||||
def settings_general_edit
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@title = t("contests.edit.title")
|
||||
end
|
||||
|
||||
def settings_offline_edit
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@title = t("contests.edit.title")
|
||||
end
|
||||
|
||||
def settings_categories_edit
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@title = t("contests.edit.title")
|
||||
end
|
||||
|
||||
def settings_general_update
|
||||
@@ -56,9 +38,6 @@ class ContestsController < ApplicationController
|
||||
if @contest.update(settings_general_params)
|
||||
redirect_to "/contests/#{@contest.id}/settings/general", notice: t("contests.edit.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@title = t("contests.edit.title")
|
||||
render :settings_general_edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -69,9 +48,6 @@ class ContestsController < ApplicationController
|
||||
if @contest.update(settings_offline_params)
|
||||
redirect_to "/contests/#{@contest.id}/settings/offline", notice: t("contests.edit.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@title = t("contests.edit.title")
|
||||
render :settings_offline_edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -85,7 +61,7 @@ class ContestsController < ApplicationController
|
||||
def create
|
||||
authorize :contest
|
||||
|
||||
@contest = Contest.new(contest_params)
|
||||
@contest = Contest.new(new_contest_params)
|
||||
@contest.user_id = current_user.id
|
||||
if @contest.save
|
||||
redirect_to "/contests/#{@contest.id}/settings/general", notice: t("contests.new.notice")
|
||||
@@ -94,18 +70,6 @@ class ContestsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @contest
|
||||
|
||||
if @contest.update(contest_params)
|
||||
redirect_to @contest, notice: t("contests.edit.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @contest
|
||||
|
||||
@@ -124,20 +88,18 @@ class ContestsController < ApplicationController
|
||||
I18n.locale = @contest.lang
|
||||
|
||||
@title = I18n.t("contests.scoreboard.title", name: @contest.name)
|
||||
@contestants = @contest.contestants.sort_by { |contestant| [
|
||||
-contestant.completions.where(remaining_pieces: nil).size,
|
||||
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
|
||||
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
|
||||
contestant.time_seconds
|
||||
] }
|
||||
@contestants = ranked_contestants(@contest)
|
||||
filter_contestants_per_category
|
||||
if params.key?(:hide_offline) && params[:hide_offline] == "true"
|
||||
@contestants = @contestants.select { |contestant| !contestant.offline.present? }
|
||||
end
|
||||
@puzzles = @contest.puzzles.order(:id)
|
||||
@action_name = t("helpers.buttons.refresh")
|
||||
if params.key?(:category)
|
||||
if params.key?(:hide_offline) && params.key?(:category)
|
||||
@action_path = "/public/#{@contest.friendly_id}?hide_offline=#{params[:hide_offline]}&category=#{params[:category]}"
|
||||
elsif params.key?(:category)
|
||||
@action_path = "/public/#{@contest.friendly_id}?category=#{params[:category]}"
|
||||
elsif params.key?(:hide_offline)
|
||||
@action_path = "/public/#{@contest.friendly_id}?hide_offline=#{params[:hide_offline]}"
|
||||
else
|
||||
@action_path = "/public/#{@contest.friendly_id}"
|
||||
end
|
||||
@@ -236,12 +198,12 @@ class ContestsController < ApplicationController
|
||||
@contest = Contest.find(params[:contest_id])
|
||||
end
|
||||
|
||||
def contest_params
|
||||
params.expect(contest: [ :lang, :name, :offline_form, :public, :team, :allow_registration ])
|
||||
def new_contest_params
|
||||
params.expect(contest: [ :name ])
|
||||
end
|
||||
|
||||
def settings_general_params
|
||||
params.expect(contest: [ :lang, :name, :public, :team, :allow_registration ])
|
||||
params.expect(contest: [ :lang, :name, :public, :ranking_mode, :team, :allow_registration ])
|
||||
end
|
||||
|
||||
def settings_offline_params
|
||||
|
||||
@@ -79,9 +79,6 @@ class MessagesController < ApplicationController
|
||||
def convert
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
|
||||
@completion = Completion.new()
|
||||
@completion.display_time_from_start = @message.display_time
|
||||
@completion.completed = true
|
||||
|
||||
@@ -11,16 +11,11 @@ class PuzzlesController < ApplicationController
|
||||
|
||||
def edit
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
end
|
||||
|
||||
def new
|
||||
authorize @contest
|
||||
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
@puzzle = Puzzle.new
|
||||
end
|
||||
|
||||
@@ -32,8 +27,6 @@ class PuzzlesController < ApplicationController
|
||||
if @puzzle.save
|
||||
redirect_to contest_path(@contest), notice: t("puzzles.new.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -44,8 +37,6 @@ class PuzzlesController < ApplicationController
|
||||
if @puzzle.update(puzzle_params)
|
||||
redirect_to @contest, notice: t("puzzles.edit.notice")
|
||||
else
|
||||
@action_name = t("helpers.buttons.back")
|
||||
@action_path = contest_path(@contest)
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,11 +4,14 @@ class UsersController < ApplicationController
|
||||
def index
|
||||
authorize :user
|
||||
|
||||
@title = t("users.index.title")
|
||||
@users = User.all
|
||||
end
|
||||
|
||||
def edit
|
||||
authorize @user
|
||||
|
||||
@title = t("users.edit.title")
|
||||
end
|
||||
|
||||
def update
|
||||
|
||||
3
app/lib/ranking.rb
Normal file
3
app/lib/ranking.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
module Ranking
|
||||
AVAILABLE_RANKING_MODES = [ { id: "actual", name: I18n.t("lib.ranking.actual") }, { id: "theorical", name: I18n.t("lib.ranking.theorical") } ]
|
||||
end
|
||||
@@ -8,6 +8,7 @@
|
||||
# name :string
|
||||
# offline_form :boolean default(FALSE)
|
||||
# public :boolean default(FALSE)
|
||||
# ranking_mode :string
|
||||
# slug :string
|
||||
# team :boolean default(FALSE)
|
||||
# created_at :datetime not null
|
||||
@@ -38,6 +39,7 @@ class Contest < ApplicationRecord
|
||||
|
||||
validates :name, presence: true
|
||||
validates :lang, inclusion: { in: Languages::AVAILABLE_LANGUAGES.map { |lang| lang[:id] } }
|
||||
validates :ranking_mode, inclusion: { in: Ranking::AVAILABLE_RANKING_MODES.map { |lang| lang[:id] } }
|
||||
|
||||
generates_token_for :token
|
||||
end
|
||||
|
||||
@@ -42,3 +42,12 @@ javascript:
|
||||
li.nav-item
|
||||
a.nav-link class=active_page(contest_messages_path(@contest)) href=contest_messages_path(@contest)
|
||||
= t("messages.plural").capitalize
|
||||
li.nav-item
|
||||
a.nav-link class=active_page("/contests/#{@contest.id}/settings/general") href="/contests/#{@contest.id}/settings/general"
|
||||
= t("contests.form.general")
|
||||
li.nav-item
|
||||
a.nav-link class=active_page("/contests/#{@contest.id}/settings/offline") href="/contests/#{@contest.id}/settings/offline"
|
||||
= t("contests.form.offline")
|
||||
li.nav-item
|
||||
a.nav-link class=active_page("/contests/#{@contest.id}/settings/categories") href="/contests/#{@contest.id}/settings/categories"
|
||||
= t("contests.form.categories")
|
||||
@@ -1,7 +1,3 @@
|
||||
.row
|
||||
.col
|
||||
h3 Informations
|
||||
|
||||
= form_with model: contestant, url: url, method: method do |form|
|
||||
.row.mb-3
|
||||
.col
|
||||
@@ -15,7 +11,7 @@
|
||||
= form.label :email
|
||||
.form-text
|
||||
= t("activerecord.attributes.contestant.email_description")
|
||||
- if @contest.categories
|
||||
- if @contest.categories && method == :patch
|
||||
.row.mt-4
|
||||
.col
|
||||
- @contest.categories.each do |category|
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
= render "contest_nav"
|
||||
|
||||
.row.mb-4 style="height: calc(100vh - 280px)"
|
||||
.col.d-flex.flex-column style="height: 100%"
|
||||
.row.mb-4
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
h5.mb-3 = t("contestants.new.title")
|
||||
= render "form", contest: @contest, contestant: @contestant, submit_text: t("helpers.buttons.add"), method: :post, url: "/contests/#{@contest.id}/contestants"
|
||||
@@ -1,12 +0,0 @@
|
||||
.row
|
||||
.col
|
||||
ul.nav.nav-tabs.mb-4
|
||||
li.nav-item
|
||||
a.nav-link class=active_page("/contests/#{@contest.id}/settings/general") href="/contests/#{@contest.id}/settings/general"
|
||||
= t("contests.form.general")
|
||||
li.nav-item
|
||||
a.nav-link class=active_page("/contests/#{@contest.id}/settings/offline") href="/contests/#{@contest.id}/settings/offline"
|
||||
= t("contests.form.offline")
|
||||
li.nav-item
|
||||
a.nav-link class=active_page("/contests/#{@contest.id}/settings/categories") href="/contests/#{@contest.id}/settings/categories"
|
||||
= t("contests.form.categories")
|
||||
@@ -1,5 +1,3 @@
|
||||
= render "settings_nav"
|
||||
|
||||
= form_with model: Category, url: "/contests/#{@contest.id}/categories" do |form|
|
||||
- if @contest.categories.size > 0
|
||||
.row
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
= render "settings_nav"
|
||||
|
||||
= form_with model: @contest, url: "/contests/#{@contest.id}/settings/general" do |form|
|
||||
.row.mt-2.mb-3
|
||||
.col
|
||||
@@ -16,6 +14,11 @@
|
||||
.form-check.form-switch
|
||||
= form.check_box :public, class: "form-check-input"
|
||||
= form.label :public
|
||||
.row.mb-3
|
||||
.col
|
||||
.form-floating
|
||||
= form.select :ranking_mode, Ranking::AVAILABLE_RANKING_MODES.map { |mode| [ mode[:name], mode[:id] ] }, {}, class: "form-select"
|
||||
= form.label :ranking_mode
|
||||
.row.mb-3
|
||||
.col
|
||||
.form-check.form-switch
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
= render "settings_nav"
|
||||
|
||||
- if @contest.puzzles.length > 1
|
||||
.row
|
||||
.col
|
||||
|
||||
@@ -44,9 +44,15 @@ html
|
||||
= msg
|
||||
|
||||
h1.mb-4
|
||||
= @title
|
||||
- if @action_path
|
||||
- if @contest
|
||||
= @contest.name
|
||||
- if active_page("/public") == "active" && @action_path
|
||||
a.ms-4.btn.btn-primary href=@action_path style="margin-top: -6px"
|
||||
= @action_name
|
||||
= t("helpers.buttons.refresh")
|
||||
- else
|
||||
= @title
|
||||
|
||||
- if @contest && active_page("/public") != "active"
|
||||
= render "contest_nav"
|
||||
|
||||
= yield
|
||||
@@ -1,5 +1,3 @@
|
||||
= render "contest_nav"
|
||||
|
||||
.row.mb-4 style="height: calc(100vh - 280px)"
|
||||
.col.d-flex.flex-column style="height: 100%"
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
= render "contest_nav"
|
||||
|
||||
.row.mb-4 style="height: calc(100vh - 280px)"
|
||||
.col.d-flex.flex-column style="height: 100%"
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ en:
|
||||
offline_form_description: Offline participants will have to fill the form by providing an image taken of the puzzle before starting solving it, and validate their finish time with an upload of an image of the completed puzzle
|
||||
offline_form_warning: Only for single-puzzle contests
|
||||
public: Enable the public scoreboard
|
||||
ranking_mode: Ranking mode (public scoreboard & CSV exports)
|
||||
team: Team contest
|
||||
team_description: For UI display purposes mainly
|
||||
allow_registration: Allow registration
|
||||
@@ -259,6 +260,10 @@ en:
|
||||
field: Field
|
||||
none: No field selected
|
||||
rank: Rank
|
||||
lib:
|
||||
ranking:
|
||||
actual: First by time if completed, then by number of pieces assembled
|
||||
theorical: By time only (projected time calculated with the ppm count)
|
||||
messages:
|
||||
index:
|
||||
no_messages: No messages received yet
|
||||
|
||||
@@ -29,6 +29,7 @@ fr:
|
||||
offline_form_description: Les participant.e.s hors-ligne pourront participer en prenant une photo du puzzle avant de le commencer, puis valider leur temps avec une photo du puzzle une fois complété
|
||||
offline_form_warning: Activable uniquement pour les concours avec un seul puzzle
|
||||
public: Activer le classement public
|
||||
ranking_mode: Mode de classement (classement public & exports CSV)
|
||||
team: Concours par équipes
|
||||
team_description: Principalement pour des raisons d'affichage
|
||||
allow_registration: Autoriser l'inscription via l'interface
|
||||
@@ -230,6 +231,10 @@ fr:
|
||||
field: Champ
|
||||
none: Aucun champ sélectionné
|
||||
rank: Rang
|
||||
lib:
|
||||
ranking:
|
||||
actual: Par temps d'abord, puis par nombre de pièces assemblées
|
||||
theorical: Par temps uniquement (temps projeté calculé à partir de la vitesse d'assemblage)
|
||||
messages:
|
||||
index:
|
||||
no_messages: Pas de messages reçus pour le moment
|
||||
|
||||
5
db/migrate/20251114085123_add_ranking_mode_to_contest.rb
Normal file
5
db/migrate/20251114085123_add_ranking_mode_to_contest.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddRankingModeToContest < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
add_column :contests, :ranking_mode, :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_10_110151) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_11_14_085123) do
|
||||
create_table "active_storage_attachments", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.string "record_type", null: false
|
||||
@@ -95,6 +95,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_10_110151) do
|
||||
t.string "lang", default: "en"
|
||||
t.boolean "public", default: false
|
||||
t.boolean "offline_form", default: false
|
||||
t.string "ranking_mode"
|
||||
t.index ["slug"], name: "index_contests_on_slug", unique: true
|
||||
t.index ["user_id"], name: "index_contests_on_user_id"
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# name :string
|
||||
# offline_form :boolean default(FALSE)
|
||||
# public :boolean default(FALSE)
|
||||
# ranking_mode :string
|
||||
# slug :string
|
||||
# team :boolean default(FALSE)
|
||||
# created_at :datetime not null
|
||||
|
||||
Reference in New Issue
Block a user