From cd032e3456c691d71606718bcfba5262b853b481 Mon Sep 17 00:00:00 2001 From: sto Date: Thu, 6 Nov 2025 10:40:47 +0100 Subject: [PATCH] Show offline participants on public scoreboard + filter --- app/controllers/contests_controller.rb | 4 ++ .../contests/_category_selector.html.slim | 19 -------- app/views/contests/_selectors.html.slim | 45 +++++++++++++++++++ app/views/contests/scoreboard.html.slim | 7 ++- config/locales/en.yml | 2 + config/locales/fr.yml | 2 + 6 files changed, 58 insertions(+), 21 deletions(-) delete mode 100644 app/views/contests/_category_selector.html.slim create mode 100644 app/views/contests/_selectors.html.slim diff --git a/app/controllers/contests_controller.rb b/app/controllers/contests_controller.rb index a98aa83..f09fbf0 100644 --- a/app/controllers/contests_controller.rb +++ b/app/controllers/contests_controller.rb @@ -92,6 +92,9 @@ class ContestsController < ApplicationController contestant.time_seconds ] } 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) @@ -99,6 +102,7 @@ class ContestsController < ApplicationController else @action_path = "/public/#{@contest.friendly_id}" end + @space = " " render :scoreboard end diff --git a/app/views/contests/_category_selector.html.slim b/app/views/contests/_category_selector.html.slim deleted file mode 100644 index 2ac3d2e..0000000 --- a/app/views/contests/_category_selector.html.slim +++ /dev/null @@ -1,19 +0,0 @@ -- if @contest.categories.size > 0 - .row - .col - select.mb-2 id="categories" style="padding: 5px" - option value=-1 - | Tous.tes les participant.e.s - - @contest.categories.each do |category| - option value=category.id - = category.name - javascript: - categorySelectEl = document.getElementById('categories'); - urlParams = new URLSearchParams(window.location.search); - selectedCategory = urlParams.get('category'); - Array.from(categorySelectEl.children).forEach((option) => { - if (option.value == selectedCategory) option.selected = true; - }); - categorySelectEl.addEventListener('change', (e) => { - window.location.replace(`/public/#{@contest.slug}?category=${e.target.value}`); - }) \ No newline at end of file diff --git a/app/views/contests/_selectors.html.slim b/app/views/contests/_selectors.html.slim new file mode 100644 index 0000000..a2e94ff --- /dev/null +++ b/app/views/contests/_selectors.html.slim @@ -0,0 +1,45 @@ +javascript: + function updateParams() { + categorySelectEl = document.getElementById('categories'); + offlineInputEl = document.getElementById('offline'); + if (categorySelectEl && !offlineInputEl) { + window.location.replace(`/public/#{@contest.slug}?category=${categorySelectEl.value}`); + } else if (!categorySelectEl) { + window.location.replace(`/public/#{@contest.slug}?hide_offline=${offlineInputEl.checked}`); + } else { + window.location.replace(`/public/#{@contest.slug}?category=${categorySelectEl.value}&hide_offline=${offlineInputEl.checked}`); + } + } +- if @contest.categories.size > 0 + .row + .col + select.mb-2 id="categories" style="padding: 5px" + option value=-1 + = t("contests.scoreboard.all_categories") + - @contest.categories.each do |category| + option value=category.id + = category.name + javascript: + categorySelectEl = document.getElementById('categories'); + urlParams = new URLSearchParams(window.location.search); + selectedCategory = urlParams.get('category'); + Array.from(categorySelectEl.children).forEach((option) => { + if (option.value == selectedCategory) option.selected = true; + }); + categorySelectEl.addEventListener('change', (e) => { + updateParams(); + }) +- if @contest.offline_form + .row + .col + input type="checkbox" id="offline" style="padding: 5px;" + label for="offline" + .ms-2 + = t("contests.scoreboard.hide_offline") + javascript: + offlineInputEl = document.getElementById('offline'); + urlParams = new URLSearchParams(window.location.search); + offlineInputEl.checked = urlParams.get('hide_offline') == "true"; + offlineInputEl.addEventListener('change', (e) => { + updateParams(); + }) \ No newline at end of file diff --git a/app/views/contests/scoreboard.html.slim b/app/views/contests/scoreboard.html.slim index a48dd7a..1f32aa2 100644 --- a/app/views/contests/scoreboard.html.slim +++ b/app/views/contests/scoreboard.html.slim @@ -16,10 +16,10 @@ css: => "#{puzzle.name} -" = "#{puzzle.brand} #{puzzle.pieces}p" - = render "category_selector" + = render "selectors" .row - .col-6.d-flex.flex-column style="height: calc(100vh - 180px)" + .mt-3.col-6.d-flex.flex-column style="height: calc(100vh - 250px)" .d-flex.flex-column style="overflow-y: auto" table.table.table-striped.table-hover thead @@ -38,6 +38,9 @@ css: tr scope="row" td = index + 1 + - if contestant.offline.present? + = @space + | (hors-ligne) td = contestant.name - if @contest.puzzles.size > 1 diff --git a/config/locales/en.yml b/config/locales/en.yml index fb6b1d2..bcd254a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -168,6 +168,8 @@ en: notice: Contest added title: New jigsaw puzzle contest scoreboard: + all_categories: All categories + hide_offline: Hide offline participants refresh: Activate auto-refresh (every 5s) title: "%{name}" show: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 4a7c41e..56f4bfb 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -139,6 +139,8 @@ fr: notice: Concours ajouté title: Nouveau concours scoreboard: + all_categories: Toutes les catégories + hide_offline: Cacher les participant.e.s hors-ligne refresh: Activer le rafraichissement automatique de la page (toutes les 5s) title: "%{name}" show: