Auto refresh feature on public scoreboards
All checks were successful
CI / scan_ruby (push) Successful in 19s
CI / scan_js (push) Successful in 13s
CI / lint (push) Successful in 13s
CI / test (push) Successful in 38s

#12
#13
This commit is contained in:
sto
2025-12-08 17:11:47 +01:00
parent 1fc05bea63
commit ee250b96ad
8 changed files with 89 additions and 56 deletions

View File

@@ -1,5 +1,3 @@
= render "selectors"
.row
.mt-3.col-6.d-flex.flex-column style="height: calc(100vh - 250px)"
.d-flex.flex-column style="overflow-y: auto"

View File

@@ -9,8 +9,6 @@ css:
=> "#{@puzzles[0].name} -"
= "#{@puzzles[0].brand} #{@puzzles[0].pieces}p"
= render "selectors"
.row
.mt-3.d-flex.flex-column style="height: calc(100vh - 250px)"
.d-flex.flex-column style="overflow-y: auto"

View File

@@ -1,15 +1,3 @@
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
@@ -17,29 +5,29 @@ javascript:
option value=-1
= t("contests.scoreboard.all_categories")
- @contest.categories.each do |category|
option value=category.id
= category.name
- if @category == category.id.to_s
option value=category.id selected=true
= category.name
- else
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();
document.getElementById('categories').addEventListener('change', (e) => {
addParam('category', e.target.value);
})
- if @contest.offline_form && @contest.puzzles.length < 2
.row
.col
input type="checkbox" id="offline" style="padding: 5px;"
- if @hide_offline
input type="checkbox" id="offline" style="padding: 5px;" checked=true
- else
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();
document.getElementById('offline').addEventListener('change', (e) => {
console.log('changed');
if (e.target.checked) addParam('hide_offline', e.target.checked);
else removeParam('hide_offline');
})

View File

@@ -2,15 +2,20 @@ css:
@media (max-width: 800px) {
.mobile-single { display: block !important; }
.desktop-single { display: none; }
#scoreboard-switches { display: none; }
}
- if @contest.puzzles.size < 2
= render "selectors"
- if @contest.puzzles.size < 2
.mobile-single style="display: none;"
= render "scoreboard_mobile_single"
.desktop-single
= render "scoreboard_desktop_single"
turbo-frame id="scoreboard"
a.btn.btn-primary href="" id="refresh-button" style="display: none;"
.mobile-single style="display: none;"
= render "scoreboard_mobile_single"
.desktop-single
= render "scoreboard_desktop_single"
- else
= render "scoreboard_desktop_marathon"
turbo-frame id="scoreboard"
a.btn.btn-primary href="" id="refresh-button" style="display: none;"
= render "scoreboard_desktop_marathon"

View File

@@ -43,19 +43,62 @@ html
.toast-body
= msg
h1.mb-5
h1.mb-4
- if @contest && @contest.id.present?
= @contest.name
- if active_page("/public") == "active" && @action_path
a.ms-4.btn.btn-primary href=@action_path style="margin-top: -6px"
= t("helpers.buttons.refresh")
- if active_page("/contests") == "active"
= @contest.name
.float-end style="margin-top: -5px;" id="scoreboard-switches"
.d-inline-flex.align-items-center
.ms-4.form-check.form-switch style="font-size: 16px; font-weight: 300;"
input.form-check-input type="checkbox" id="refresh-checkbox"
label.ms-1 style="font-size: 16px; font-weight: 300;"
= t("contests.scoreboard.auto_refresh")
.js data-turbo="false"
javascript:
function refresh() {
if (document.getElementById('refresh-checkbox').checked) {
addParam('autorefresh', 1);
setTimeout(refresh, 30000);
}
}
function addParam(key, value) {
const urlParams = new URLSearchParams(window.location.search);
urlParams.delete(key);
urlParams.append(key, value);
const refreshBtn = document.getElementById('refresh-button')
refreshBtn.href = `/public/#{@contest.friendly_id}?${urlParams.toString()}`;
refreshBtn.click();
}
function removeParam(key) {
const urlParams = new URLSearchParams(window.location.search);
urlParams.delete(key);
const refreshBtn = document.getElementById('refresh-button')
refreshBtn.href = `/public/#{@contest.friendly_id}?${urlParams.toString()}`;
refreshBtn.click();
}
function autoRefresh() {
if (document.getElementById('refresh-checkbox').checked) setTimeout(refresh, 30000);
document.getElementById('refresh-checkbox').addEventListener('change', (e) => {
if (e.target.checked) refresh();
else removeParam('autorefresh');
});
}
async function startAutoRefresh(count) {
if (count == 0) return;
if (document.getElementById('refresh-button') && document.getElementById('refresh-checkbox')) autoRefresh();
else setTimeout(() => startAutoRefresh(count - 1), 10);
}
startAutoRefresh(200);
- elsif active_page("/contests") == "active"
= @contest.name
- if @contest.public
a.ms-4.btn.btn-success href="/public/#{@contest.slug}" style="margin-top: -6px;"
= t("contests.show.open_public_scoreboard")
- else
a.ms-4.btn.btn-success.disabled style="margin-top: -6px;"
= t("contests.show.public_scoreboard_disabled")
- else
= @contest.name
- else
= @title