Contest language & top buttons
This commit is contained in:
@@ -70,6 +70,8 @@ class ContestsController < ApplicationController
|
||||
end
|
||||
authorize @contest
|
||||
|
||||
I18n.locale = @contest.lang
|
||||
|
||||
@title = I18n.t("contests.scoreboard.title", name: @contest.name)
|
||||
@contestants = @contest.contestants.sort_by { |contestant| [ -contestant.completions.size, contestant.time_seconds ] }
|
||||
@puzzles = @contest.puzzles.order(:id)
|
||||
@@ -89,6 +91,6 @@ class ContestsController < ApplicationController
|
||||
end
|
||||
|
||||
def contest_params
|
||||
params.expect(contest: [ :name, :team, :allow_registration ])
|
||||
params.expect(contest: [ :lang, :name, :team, :allow_registration ])
|
||||
end
|
||||
end
|
||||
|
@@ -1,3 +1,3 @@
|
||||
module Languages
|
||||
AVAILABLE_LANGUAGES = [ { id: "en", name: "English" }, { id: "fr", name: "French" } ]
|
||||
AVAILABLE_LANGUAGES = [ { id: "en", name: "English" }, { id: "fr", name: "Français" } ]
|
||||
end
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# allow_registration :boolean default(FALSE)
|
||||
# lang :string default("en")
|
||||
# name :string
|
||||
# slug :string
|
||||
# team :boolean default(FALSE)
|
||||
@@ -32,6 +33,7 @@ class Contest < ApplicationRecord
|
||||
friendly_id :name, use: :slugged
|
||||
|
||||
validates :name, presence: true
|
||||
validates :lang, inclusion: { in: Languages::AVAILABLE_LANGUAGES.map { |lang| lang[:id] } }
|
||||
|
||||
generates_token_for :token
|
||||
end
|
||||
|
@@ -4,6 +4,11 @@
|
||||
.form-floating
|
||||
= form.text_field :name, autocomplete: "off", class: "form-control"
|
||||
= form.label :name, class: "required"
|
||||
.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.mb-3
|
||||
.col
|
||||
.form-check.form-switch
|
||||
|
@@ -2,13 +2,14 @@ table.table.table-striped.table-hover
|
||||
thead
|
||||
tr
|
||||
th scope="col"
|
||||
| Rank
|
||||
= t("helpers.rank")
|
||||
th scope="col"
|
||||
| Name
|
||||
= t("activerecord.attributes.contestant.name")
|
||||
- if @contest.puzzles.size > 1
|
||||
th scope="col"
|
||||
= t("activerecord.attributes.contestant.completions")
|
||||
th scope="col"
|
||||
| Completed puzzles
|
||||
th scope="col"
|
||||
| Total time
|
||||
= t("activerecord.attributes.contestant.display_time")
|
||||
tbody
|
||||
- @contestants.each_with_index do |contestant, index|
|
||||
tr scope="row"
|
||||
@@ -16,7 +17,8 @@ table.table.table-striped.table-hover
|
||||
= index + 1
|
||||
td
|
||||
= contestant.name
|
||||
td
|
||||
= contestant.completions.length
|
||||
- if @contest.puzzles.size > 1
|
||||
td
|
||||
= contestant.completions.length
|
||||
td
|
||||
= contestant.display_time
|
@@ -1,21 +1,31 @@
|
||||
.row.mb-4
|
||||
- if @badges.size > 0
|
||||
.row.mb-4
|
||||
.col
|
||||
.badges style="margin-top: -18px; position: absolute"
|
||||
- @badges.each do |badge|
|
||||
span.badge.text-bg-info.me-2
|
||||
= badge
|
||||
|
||||
javascript:
|
||||
async function copyExtensionUrlToClipboard() {
|
||||
await navigator.clipboard.writeText("#{message_url}?token=#{@contest.generate_token_for(:token)}");
|
||||
}
|
||||
|
||||
.row.mb-5
|
||||
.col
|
||||
css:
|
||||
.badges { margin-top: -18px; position: absolute; }
|
||||
.badges
|
||||
- @badges.each do |badge|
|
||||
span.badge.text-bg-info.me-2
|
||||
= badge
|
||||
|
||||
.row
|
||||
.col.alert.alert-success
|
||||
= t("contests.show.public_scoreboard")
|
||||
= link_to root_url + "public/#{@contest.slug}", root_url + "public/#{@contest.slug}"
|
||||
|
||||
.row.mb-4
|
||||
.col.alert.alert-success
|
||||
|> URL for the public scoreboard extension:
|
||||
= link_to "#{message_url}?token=#{@contest.generate_token_for(:token)}"
|
||||
a.btn.btn-success href="/public/#{@contest.slug}"
|
||||
= t("contests.show.open_public_scoreboard")
|
||||
button.btn.btn-success.ms-3 onclick="copyExtensionUrlToClipboard()"
|
||||
css:
|
||||
button > svg {
|
||||
margin-right: 2px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16">
|
||||
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1z"/>
|
||||
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0z"/>
|
||||
</svg>
|
||||
=< t("contests.show.copy_extension_url")
|
||||
|
||||
.row.mb-4
|
||||
.col-7
|
||||
|
Reference in New Issue
Block a user