Require contest durations, prefill end times for unfinished puzzles & allow to modify them
This commit is contained in:
@@ -57,6 +57,7 @@ class ContestsController < ApplicationController
|
|||||||
|
|
||||||
@contest = Contest.new
|
@contest = Contest.new
|
||||||
@title = I18n.t("contests.new.title")
|
@title = I18n.t("contests.new.title")
|
||||||
|
@nonav = true
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@@ -69,6 +70,8 @@ class ContestsController < ApplicationController
|
|||||||
if @contest.save
|
if @contest.save
|
||||||
redirect_to "/contests/#{@contest.id}/settings/general", notice: t("contests.new.notice")
|
redirect_to "/contests/#{@contest.id}/settings/general", notice: t("contests.new.notice")
|
||||||
else
|
else
|
||||||
|
@title = I18n.t("contests.new.title")
|
||||||
|
@nonav = true
|
||||||
render :new, status: :unprocessable_entity
|
render :new, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -203,7 +206,7 @@ class ContestsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def new_contest_params
|
def new_contest_params
|
||||||
params.expect(contest: [ :name ])
|
params.expect(contest: [ :name, :duration ])
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings_general_params
|
def settings_general_params
|
||||||
|
|||||||
@@ -68,11 +68,7 @@ class Completion < ApplicationRecord
|
|||||||
self.time_seconds = arr[0].to_i
|
self.time_seconds = arr[0].to_i
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if self.contest.duration_seconds.present?
|
|
||||||
self.time_seconds = self.contest.duration_seconds
|
self.time_seconds = self.contest.duration_seconds
|
||||||
else
|
|
||||||
self.time_seconds = 2 * 3600
|
|
||||||
end
|
|
||||||
self.display_time_from_start = display_time(self.time_seconds)
|
self.display_time_from_start = display_time(self.time_seconds)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -82,9 +78,6 @@ class Completion < ApplicationRecord
|
|||||||
self.remaining_pieces = nil
|
self.remaining_pieces = nil
|
||||||
else
|
else
|
||||||
self.missing_pieces = nil
|
self.missing_pieces = nil
|
||||||
if !self.offline.present?
|
|
||||||
self.display_time_from_start = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class Contest < ApplicationRecord
|
|||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
validates :lang, inclusion: { in: Languages::AVAILABLE_LANGUAGES.map { |lang| lang[:id] } }
|
validates :lang, inclusion: { in: Languages::AVAILABLE_LANGUAGES.map { |lang| lang[:id] } }
|
||||||
validates :ranking_mode, inclusion: { in: Ranking::AVAILABLE_RANKING_MODES.map { |lang| lang[:id] } }
|
validates :ranking_mode, inclusion: { in: Ranking::AVAILABLE_RANKING_MODES.map { |lang| lang[:id] } }
|
||||||
validates :duration, format: { with: /\A(\d\d:\d\d|\d:\d\d)\z/ }, if: -> { duration.present? }
|
validates :duration, presence: true, format: { with: /\A(\d\d:\d\d|\d:\d\d)\z/ }
|
||||||
|
|
||||||
generates_token_for :token
|
generates_token_for :token
|
||||||
|
|
||||||
|
|||||||
@@ -43,19 +43,19 @@
|
|||||||
const missingPiecesEl = document.getElementById('missing_pieces');
|
const missingPiecesEl = document.getElementById('missing_pieces');
|
||||||
const remainingPiecesEl = document.getElementById('remaining_pieces');
|
const remainingPiecesEl = document.getElementById('remaining_pieces');
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
timeEl.style.display = 'block';
|
timeEl.value = '#{@completion.display_time_from_start}';
|
||||||
missingPiecesEl.style.display = 'block';
|
missingPiecesEl.style.display = 'block';
|
||||||
remainingPiecesEl.style.display = 'none';
|
remainingPiecesEl.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
timeEl.style.display = 'none';
|
timeEl.value = '#{display_time(@contest.duration_seconds)}';
|
||||||
missingPiecesEl.style.display = 'none';
|
missingPiecesEl.style.display = 'none';
|
||||||
remainingPiecesEl.style.display = 'block';
|
remainingPiecesEl.style.display = 'block';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.row.mb-3 id="time"
|
.row.mb-3
|
||||||
.col
|
.col
|
||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :display_time_from_start, autocomplete: "off", class: "form-control"
|
= form.text_field :display_time_from_start, autocomplete: "off", class: "form-control", id: "time"
|
||||||
= form.label :display_time_from_start, class: "required"
|
= form.label :display_time_from_start, class: "required"
|
||||||
.row.mb-3 id="missing_pieces"
|
.row.mb-3 id="missing_pieces"
|
||||||
.col
|
.col
|
||||||
@@ -69,15 +69,12 @@
|
|||||||
= form.label :remaining_pieces
|
= form.label :remaining_pieces
|
||||||
javascript:
|
javascript:
|
||||||
completedEl = document.getElementById('completion_completed');
|
completedEl = document.getElementById('completion_completed');
|
||||||
timeEl = document.getElementById('time');
|
|
||||||
missingPiecesEl = document.getElementById('missing_pieces');
|
missingPiecesEl = document.getElementById('missing_pieces');
|
||||||
remainingPiecesEl = document.getElementById('remaining_pieces');
|
remainingPiecesEl = document.getElementById('remaining_pieces');
|
||||||
if (completedEl.checked) {
|
if (completedEl.checked) {
|
||||||
timeEl.style.display = 'block';
|
|
||||||
missingPiecesEl.style.display = 'block';
|
missingPiecesEl.style.display = 'block';
|
||||||
remainingPiecesEl.style.display = 'none';
|
remainingPiecesEl.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
timeEl.style.display = 'none';
|
|
||||||
missingPiecesEl.style.display = 'none';
|
missingPiecesEl.style.display = 'none';
|
||||||
remainingPiecesEl.style.display = 'block';
|
remainingPiecesEl.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 :duration, autocomplete: "off", class: "form-control"
|
||||||
|
= form.label :duration, class: "required"
|
||||||
|
.form-text = t("activerecord.attributes.contest.duration_description")
|
||||||
.row.mt-4
|
.row.mt-4
|
||||||
.col
|
.col
|
||||||
= form.submit t("helpers.buttons.create"), class: "btn btn-primary"
|
= form.submit t("helpers.buttons.create"), class: "btn btn-primary"
|
||||||
@@ -52,7 +52,7 @@ html
|
|||||||
- else
|
- else
|
||||||
= @title
|
= @title
|
||||||
|
|
||||||
- if @contest && active_page("/public") != "active" && active_page("/contests/new") != "active" && active_page("/contests/create") != "active" && active_page("/contests") == "active"
|
- if @contest && active_page("/contests") == "active" && !@nonav
|
||||||
= render "contest_nav"
|
= render "contest_nav"
|
||||||
|
|
||||||
= yield
|
= yield
|
||||||
@@ -117,6 +117,7 @@ en:
|
|||||||
contest:
|
contest:
|
||||||
attributes:
|
attributes:
|
||||||
duration:
|
duration:
|
||||||
|
blank: Must be filled
|
||||||
invalid: Invalid duration
|
invalid: Invalid duration
|
||||||
name:
|
name:
|
||||||
blank: The contest name cannot be empty
|
blank: The contest name cannot be empty
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ fr:
|
|||||||
contest:
|
contest:
|
||||||
attributes:
|
attributes:
|
||||||
duration:
|
duration:
|
||||||
|
blank: Obligatoire
|
||||||
invalid: Durée invalide
|
invalid: Durée invalide
|
||||||
name:
|
name:
|
||||||
blank: Le nom du concours ne peut pas être vide
|
blank: Le nom du concours ne peut pas être vide
|
||||||
|
|||||||
Reference in New Issue
Block a user