Improve public scoreboard UI + make it responsive
This commit is contained in:
parent
d28f888ee2
commit
1b34d10dee
@ -78,6 +78,8 @@ class ContestsController < ApplicationController
|
|||||||
@title = I18n.t("contests.scoreboard.title", name: @contest.name)
|
@title = I18n.t("contests.scoreboard.title", name: @contest.name)
|
||||||
@contestants = @contest.contestants.sort_by { |contestant| [ -contestant.completions.size, contestant.time_seconds ] }
|
@contestants = @contest.contestants.sort_by { |contestant| [ -contestant.completions.size, contestant.time_seconds ] }
|
||||||
@puzzles = @contest.puzzles.order(:id)
|
@puzzles = @contest.puzzles.order(:id)
|
||||||
|
@action_name = t("helpers.buttons.refresh")
|
||||||
|
@action_path = "/public/#{@contest.friendly_id}"
|
||||||
render :scoreboard
|
render :scoreboard
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,2 +1,20 @@
|
|||||||
module ContestsHelper
|
module ContestsHelper
|
||||||
|
def pad(n)
|
||||||
|
if n > 9
|
||||||
|
return n.to_s
|
||||||
|
end
|
||||||
|
"0" + n.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def display_time(time)
|
||||||
|
h = time / 3600
|
||||||
|
m = (time % 3600) / 60
|
||||||
|
s = (time % 3600) % 60
|
||||||
|
if h > 0
|
||||||
|
return h.to_s + ":" + pad(m) + ":" + pad(s)
|
||||||
|
elsif m > 0
|
||||||
|
return m.to_s + ":" + pad(s)
|
||||||
|
end
|
||||||
|
s.to_s
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,56 +1,122 @@
|
|||||||
.d-flex.flex-column style="height: calc(100vh - 180px)"
|
javascript:
|
||||||
.d-flex.flex-row.justify-content-center.mb-5
|
function refresh() {
|
||||||
|
const el = document.querySelector('input[type="checkbox"]');
|
||||||
|
if (el.checked) location.replace("/public/#{@contest.friendly_id}?refresh=1")
|
||||||
|
setTimeout(refresh, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/ const params = new URL(document.location.toString()).searchParams;
|
||||||
|
/ if (params.get("refresh") == "1") {
|
||||||
|
/ const el = document.querySelector('input[type="checkbox"]');
|
||||||
|
/ el.checked = true;
|
||||||
|
/ }
|
||||||
|
|
||||||
|
/ setTimeout(refresh, 5000);
|
||||||
|
|
||||||
|
css:
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
a.btn { display: none; }
|
||||||
|
.col-5 { display: none; }
|
||||||
|
.col-6 { width: 100% !important; display: block !important; }
|
||||||
|
.small-screen-image { display: block !important; }
|
||||||
|
.container { margin-top: 2rem !important; }
|
||||||
|
}
|
||||||
|
|
||||||
|
- if @contest.puzzles.size <= 1
|
||||||
|
.row.small-screen-image style="display: none"
|
||||||
- @contest.puzzles.each do |puzzle|
|
- @contest.puzzles.each do |puzzle|
|
||||||
= image_tag(puzzle.image, class: "img-fluid ms-3 me-3", style: "max-height: 220px") if puzzle.image.attached?
|
.d-flex.flex-column.justify-content-center.mb-5
|
||||||
|
= image_tag(puzzle.image, style: "max-height: 200px; object-fit: contain") if puzzle.image.attached?
|
||||||
javascript:
|
.mt-2.fs-6 style="text-align: center"
|
||||||
function refresh() {
|
=> "#{puzzle.name} -"
|
||||||
const el = document.querySelector('input[type="checkbox"]');
|
= puzzle.brand
|
||||||
if (el.checked) location.replace("/public/#{@contest.friendly_id}?refresh=1")
|
.row
|
||||||
setTimeout(refresh, 5000);
|
.col-6.d-flex.flex-column style="height: calc(100vh - 180px)"
|
||||||
}
|
/ = form_with model: Contest do |form|
|
||||||
|
/ .row.mb-3
|
||||||
|
/ .col
|
||||||
|
/ .form-check.form-switch
|
||||||
|
/ = form.check_box :refresh, class: "form-check-input"
|
||||||
|
/ = form.label t("contests.scoreboard.refresh")
|
||||||
|
|
||||||
/ const params = new URL(document.location.toString()).searchParams;
|
.d-flex.flex-column style="overflow-y: auto"
|
||||||
/ if (params.get("refresh") == "1") {
|
table.table.table-striped.table-hover
|
||||||
/ const el = document.querySelector('input[type="checkbox"]');
|
thead
|
||||||
/ el.checked = true;
|
tr
|
||||||
/ }
|
th
|
||||||
|
= t("helpers.rank")
|
||||||
|
th
|
||||||
|
= t("activerecord.attributes.contestant.name")
|
||||||
|
- if @contest.puzzles.size > 1
|
||||||
|
th
|
||||||
|
= t("activerecord.attributes.contestant.completions")
|
||||||
|
th style="width: 170px"
|
||||||
|
= t("activerecord.attributes.contestant.display_time")
|
||||||
|
tbody
|
||||||
|
- @contestants.each_with_index do |contestant, index|
|
||||||
|
tr scope="row"
|
||||||
|
td
|
||||||
|
= index + 1
|
||||||
|
td
|
||||||
|
= contestant.name
|
||||||
|
- if @contest.puzzles.size > 1
|
||||||
|
td
|
||||||
|
= contestant.completions.length
|
||||||
|
td style="position: relative"
|
||||||
|
- if index > 0 && contestant.time_seconds > 0
|
||||||
|
.relative-time style="position:absolute; margin: 1px 0 0 64px; font-size: 14px; color: grey"
|
||||||
|
|> +
|
||||||
|
= display_time(contestant.time_seconds - @contestants[index - 1].time_seconds)
|
||||||
|
= contestant.display_time
|
||||||
|
.col-1
|
||||||
|
.col-5
|
||||||
|
- @contest.puzzles.each do |puzzle|
|
||||||
|
= image_tag(puzzle.image, class: "img-fluid ms-3 me-3") if puzzle.image.attached?
|
||||||
|
.mt-3.fs-4 style="margin-left: 15px"
|
||||||
|
= puzzle.name
|
||||||
|
.fs-6 style="margin-left: 15px"
|
||||||
|
b
|
||||||
|
= puzzle.brand
|
||||||
|
|
||||||
/ setTimeout(refresh, 5000);
|
- else
|
||||||
|
.d-flex.flex-column style="height: calc(100vh - 180px)"
|
||||||
|
.d-flex.flex-row.justify-content-center.mb-5
|
||||||
|
- @contest.puzzles.each do |puzzle|
|
||||||
|
= image_tag(puzzle.image, class: "img-fluid ms-3 me-3", style: "max-height: 220px") if puzzle.image.attached?
|
||||||
|
|
||||||
.mb-3 style="display: inline-flex"
|
.mb-3 style="display: inline-flex"
|
||||||
a.btn.btn-primary href="/public/#{@contest.friendly_id}"
|
a.btn.btn-primary href="/public/#{@contest.friendly_id}"
|
||||||
= t("helpers.buttons.refresh")
|
= t("helpers.buttons.refresh")
|
||||||
|
|
||||||
/ = form_with model: Contest do |form|
|
/ = form_with model: Contest do |form|
|
||||||
/ .row.mb-3
|
/ .row.mb-3
|
||||||
/ .col
|
/ .col
|
||||||
/ .form-check.form-switch
|
/ .form-check.form-switch
|
||||||
/ = form.check_box :refresh, class: "form-check-input"
|
/ = form.check_box :refresh, class: "form-check-input"
|
||||||
/ = form.label t("contests.scoreboard.refresh")
|
/ = form.label t("contests.scoreboard.refresh")
|
||||||
|
|
||||||
.d-flex.flex-column style="overflow-y: auto"
|
.d-flex.flex-column style="overflow-y: auto"
|
||||||
table.table.table-striped.table-hover
|
table.table.table-striped.table-hover
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th scope="col"
|
|
||||||
= t("helpers.rank")
|
|
||||||
th scope="col"
|
|
||||||
= t("activerecord.attributes.contestant.name")
|
|
||||||
- if @contest.puzzles.size > 1
|
|
||||||
th scope="col"
|
th scope="col"
|
||||||
= t("activerecord.attributes.contestant.completions")
|
= t("helpers.rank")
|
||||||
th scope="col"
|
th scope="col"
|
||||||
= t("activerecord.attributes.contestant.display_time")
|
= t("activerecord.attributes.contestant.name")
|
||||||
tbody
|
|
||||||
- @contestants.each_with_index do |contestant, index|
|
|
||||||
tr scope="row"
|
|
||||||
td
|
|
||||||
= index + 1
|
|
||||||
td
|
|
||||||
= contestant.name
|
|
||||||
- if @contest.puzzles.size > 1
|
- if @contest.puzzles.size > 1
|
||||||
|
th scope="col"
|
||||||
|
= t("activerecord.attributes.contestant.completions")
|
||||||
|
th scope="col"
|
||||||
|
= t("activerecord.attributes.contestant.display_time")
|
||||||
|
tbody
|
||||||
|
- @contestants.each_with_index do |contestant, index|
|
||||||
|
tr scope="row"
|
||||||
td
|
td
|
||||||
= contestant.completions.length
|
= index + 1
|
||||||
td
|
td
|
||||||
= contestant.display_time
|
= contestant.name
|
||||||
|
- if @contest.puzzles.size > 1
|
||||||
|
td
|
||||||
|
= contestant.completions.length
|
||||||
|
td
|
||||||
|
= contestant.display_time
|
Loading…
x
Reference in New Issue
Block a user