UI: lås session-opdatering ved in-flight request (#93)
This commit is contained in:
@@ -30,7 +30,8 @@
|
||||
<div id="answerOptions"></div>
|
||||
<p id="guessStatus">Vælg et svar.</p>
|
||||
<button id="guessSubmitBtn" onclick="submitGuess()" disabled>3) Submit gæt</button>
|
||||
<button onclick="sessionDetail()">Opdater session-status</button>
|
||||
<button id="sessionDetailBtn" onclick="sessionDetail()">Opdater session-status</button>
|
||||
<p id="sessionRefreshHint">Session-opdatering klar.</p>
|
||||
<button id="playerAutoRefreshToggleBtn" onclick="togglePlayerAutoRefresh()">Auto-refresh: OFF</button>
|
||||
<p id="playerAutoRefreshHint">Auto-refresh er slået fra.</p>
|
||||
<p id="playerLastRefreshStatus">Session-data ikke opdateret endnu.</p>
|
||||
@@ -48,6 +49,7 @@ var joinInFlight=false;
|
||||
var currentSessionStatus="";
|
||||
var playerAutoRefreshEnabled=false;
|
||||
var playerAutoRefreshTimer=null;
|
||||
var sessionDetailInFlight=false;
|
||||
var playerLastRefreshAtLabel="";
|
||||
var playerLastRefreshFailed=false;
|
||||
function code(){return document.getElementById("code").value.trim().toUpperCase();}
|
||||
@@ -69,9 +71,10 @@ function markPlayerSessionRefresh(status){if(status>=200&&status<300){playerLast
|
||||
function updatePlayerLastRefreshStatus(){var el=document.getElementById("playerLastRefreshStatus");if(!el){return;}if(!playerLastRefreshAtLabel){el.textContent=playerLastRefreshFailed?"Session-data kan være forældet (ingen succesfuld opdatering endnu).":"Session-data ikke opdateret endnu.";return;}if(playerLastRefreshFailed){el.textContent="Session-data kan være forældet (seneste succes: "+playerLastRefreshAtLabel+").";return;}el.textContent="Sidst opdateret: "+playerLastRefreshAtLabel+".";}
|
||||
function updatePlayerAutoRefreshUi(){var btn=document.getElementById("playerAutoRefreshToggleBtn");var hint=document.getElementById("playerAutoRefreshHint");if(btn){btn.textContent="Auto-refresh: "+(playerAutoRefreshEnabled?"ON":"OFF");}if(!hint){return;}if(!playerAutoRefreshEnabled){hint.textContent="Auto-refresh er slået fra.";return;}if(!code()){hint.textContent="Auto-refresh venter: angiv sessionkode.";return;}if(currentSessionStatus==="finished"){hint.textContent="Auto-refresh stoppet: spillet er afsluttet.";return;}hint.textContent="Auto-refresh aktiv (10s) for spillerstatus.";}
|
||||
function stopPlayerAutoRefresh(reason){playerAutoRefreshEnabled=false;if(playerAutoRefreshTimer){clearInterval(playerAutoRefreshTimer);playerAutoRefreshTimer=null;}if(reason){var hint=document.getElementById("playerAutoRefreshHint");if(hint){hint.textContent=reason;}}updatePlayerAutoRefreshUi();savePlayerContext();}
|
||||
function startPlayerAutoRefresh(){if(!code()){updatePlayerAutoRefreshUi();return;}playerAutoRefreshEnabled=true;if(playerAutoRefreshTimer){clearInterval(playerAutoRefreshTimer);}playerAutoRefreshTimer=setInterval(function(){if(!code()){return;}if(currentSessionStatus==="finished"){stopPlayerAutoRefresh("Auto-refresh stoppet: spillet er afsluttet.");return;}sessionDetail();},10000);updatePlayerAutoRefreshUi();savePlayerContext();}
|
||||
function startPlayerAutoRefresh(){if(!code()){updatePlayerAutoRefreshUi();return;}playerAutoRefreshEnabled=true;if(playerAutoRefreshTimer){clearInterval(playerAutoRefreshTimer);}playerAutoRefreshTimer=setInterval(function(){if(!code()||sessionDetailInFlight){return;}if(currentSessionStatus==="finished"){stopPlayerAutoRefresh("Auto-refresh stoppet: spillet er afsluttet.");return;}sessionDetail();},10000);updatePlayerAutoRefreshUi();savePlayerContext();}
|
||||
function togglePlayerAutoRefresh(){if(playerAutoRefreshEnabled){stopPlayerAutoRefresh();return;}startPlayerAutoRefresh();}
|
||||
function updatePlayerErrorHint(status,data){var el=document.getElementById("playerErrorHint");if(!el){return;}if(status>=200&&status<300){el.textContent="Ingen fejl.";return;}var errKey=normalizeApiError(data);el.textContent="Fejl: "+mapUiErrorMessage(errKey)+" ("+(errKey||("http_"+status))+")";}
|
||||
function updateSessionDetailState(){var btn=document.getElementById("sessionDetailBtn");var hint=document.getElementById("sessionRefreshHint");if(btn){btn.disabled=sessionDetailInFlight||!code();}if(!hint){return;}if(sessionDetailInFlight){hint.textContent="Opdaterer session-status…";return;}if(!code()){hint.textContent="Angiv sessionkode for at opdatere session-status.";return;}hint.textContent="Session-opdatering klar.";}
|
||||
function updateJoinState(){var btn=document.getElementById("joinBtn");var status=document.getElementById("joinStatus");var joined=!!(pid()&&document.getElementById("sessionToken").value.trim());var canJoin=canAttemptJoin();if(btn){btn.disabled=joinInFlight||joined||!canJoin;}if(!status){updateContextLockState();return;}if(joinInFlight){status.textContent="Joiner…";updateContextLockState();return;}if(joined){status.textContent="Join gennemført.";updateContextLockState();return;}if(!canJoin){status.textContent="Udfyld kode og nickname for at join.";updateContextLockState();return;}status.textContent="Klar til join.";updateContextLockState();}
|
||||
|
||||
function guessStorageKey(){var c=code();var p=pid();var q=rq();if(!c||!p||!q){return "";}return ["wppGuess",c,p,q].join(":");}
|
||||
@@ -89,11 +92,11 @@ updateJoinState();}
|
||||
function renderAnswerOptions(roundQuestion){var wrap=document.getElementById("answerOptions");wrap.innerHTML="";availableAnswers=[];guessSubmitted=false;setGuess("",false);lieSubmitted=false;setLieState("",false);if(!roundQuestion||!Array.isArray(roundQuestion.answers)){updateGuessSubmitState();updateLieSubmitState();return;}roundQuestion.answers.forEach(function(item){if(!item||!item.text){return;}availableAnswers.push(item.text);var btn=document.createElement("button");btn.type="button";btn.dataset.answer=item.text;btn.textContent=item.text;btn.onclick=function(){if(guessSubmitted){return;}setGuess(item.text,false);persistGuessState(item.text,false);};wrap.appendChild(btn);});var saved=loadGuessState();if(saved&&availableAnswers.indexOf(saved.selected_text)!==-1){setGuess(saved.selected_text,!!saved.submitted);}updateGuessSubmitState();}
|
||||
async function api(path,method,payload){var o={method:method||"GET",headers:{"Accept":"application/json"}};if(payload!==null){o.headers["Content-Type"]="application/json";o.body=JSON.stringify(payload);}var r=await fetch(path,o);var d=await r.json().catch(function(){return {};});var isSessionDetailRead=(method||"GET")==="GET"&&/^\/lobby\/sessions\/[A-Z0-9]+$/.test(path);if(isSessionDetailRead){markPlayerSessionRefresh(r.status);}document.getElementById("out").textContent=JSON.stringify({status:r.status,data:d},null,2);if(d.player&&d.player.id){document.getElementById("playerId").value=d.player.id;}if(d.player&&d.player.session_token){document.getElementById("sessionToken").value=d.player.session_token;}if(d.round_question&&d.round_question.id){document.getElementById("roundQuestionId").value=d.round_question.id;}if(d.session&&d.session.status){currentSessionStatus=d.session.status;}if(d.round_question){renderAnswerOptions(d.round_question);var savedLie=loadLieState();if(savedLie){setLieState(savedLie.text||"",!!savedLie.submitted);}}if(d.guess&&d.guess.round_question_id){document.getElementById("roundQuestionId").value=d.guess.round_question_id;setGuess(d.guess.selected_text||"",true);persistGuessState(d.guess.selected_text||"",true);}updatePlayerErrorHint(r.status,d);updatePhaseStatus();updateLieSubmitState();updateGuessSubmitState();if(currentSessionStatus==="finished"&&playerAutoRefreshEnabled){stopPlayerAutoRefresh("Auto-refresh stoppet: spillet er afsluttet.");}else{updatePlayerAutoRefreshUi();}savePlayerContext();return d;}
|
||||
function joinSession(){if(joinInFlight){return Promise.resolve({error:"join_in_flight"});}if(!canAttemptJoin()){updateJoinState();return Promise.resolve({error:"missing_join_input"});}if(pid()&&document.getElementById("sessionToken").value.trim()){updateJoinState();return Promise.resolve({error:"already_joined_client"});}joinInFlight=true;updateJoinState();return api("/lobby/sessions/join","POST",{code:code(),nickname:document.getElementById("nickname").value.trim()}).then(function(d){joinInFlight=false;if(d&&d.player&&d.player.id){updateJoinState();return d;}updateJoinState();document.getElementById("joinStatus").textContent="Join fejlede – prøv igen.";return d;}).catch(function(err){joinInFlight=false;updateJoinState();document.getElementById("joinStatus").textContent="Join fejlede – prøv igen.";throw err;});}
|
||||
function sessionDetail(){return api("/lobby/sessions/"+code(),"GET",null);}
|
||||
function sessionDetail(){if(!code()){updateSessionDetailState();return Promise.resolve({error:"missing_session_code"});}if(sessionDetailInFlight){return Promise.resolve({error:"session_detail_in_flight"});}sessionDetailInFlight=true;updateSessionDetailState();return api("/lobby/sessions/"+code(),"GET",null).finally(function(){sessionDetailInFlight=false;updateSessionDetailState();});}
|
||||
function submitLie(){if(lieSubmitted){return Promise.resolve({error:"lie_already_submitted_client"});}if(lieSubmitInFlight){return Promise.resolve({error:"lie_submit_in_flight"});}if(!hasSubmitContext()){updateLieSubmitState();return Promise.resolve({error:"missing_submit_context"});}var text=(document.getElementById("lieText").value||"").trim();if(!text){updateLieSubmitState();return Promise.resolve({error:"empty_lie_text"});}lieSubmitInFlight=true;updateLieSubmitState();return api("/lobby/sessions/"+code()+"/questions/"+rq()+"/lies/submit","POST",{player_id:parseInt(pid(),10),session_token:document.getElementById("sessionToken").value,text:text}).then(function(d){if(d&&d.lie&&d.lie.id){lieSubmitted=true;persistLieState(text,true);}return d;}).finally(function(){lieSubmitInFlight=false;updateLieSubmitState();});}
|
||||
document.getElementById("lieText").addEventListener("input",function(){if(!lieSubmitted){updateLieSubmitState();persistLieState(document.getElementById("lieText").value,false);}});updateLieSubmitState();
|
||||
function submitGuess(){if(guessSubmitInFlight){return Promise.resolve({error:"guess_submit_in_flight"});}if(!hasSubmitContext()){updateGuessSubmitState();document.getElementById("out").textContent=JSON.stringify({status:400,data:{error:"Join først for at aktivere gæt"}},null,2);return Promise.resolve({error:"missing_submit_context"});}var selected=document.getElementById("guessText").value;if(availableAnswers.indexOf(selected)===-1){document.getElementById("out").textContent=JSON.stringify({status:400,data:{error:"Vælg et af de viste svarmuligheder"}},null,2);return Promise.resolve({error:"invalid_client_guess"});}guessSubmitInFlight=true;updateGuessSubmitState();return api("/lobby/sessions/"+code()+"/questions/"+rq()+"/guesses/submit","POST",{player_id:parseInt(pid(),10),session_token:document.getElementById("sessionToken").value,selected_text:selected}).finally(function(){guessSubmitInFlight=false;updateGuessSubmitState();});}
|
||||
["code","nickname","playerId","sessionToken","roundQuestionId"].forEach(function(fieldId){var field=document.getElementById(fieldId);if(!field){return;}field.addEventListener("input",function(){updateLieSubmitState();updateGuessSubmitState();updateJoinState();savePlayerContext();});field.addEventListener("change",function(){updateLieSubmitState();updateGuessSubmitState();updateJoinState();savePlayerContext();});});
|
||||
["code","nickname","playerId","sessionToken","roundQuestionId"].forEach(function(fieldId){var field=document.getElementById(fieldId);if(!field){return;}field.addEventListener("input",function(){updateLieSubmitState();updateGuessSubmitState();updateJoinState();updateSessionDetailState();savePlayerContext();});field.addEventListener("change",function(){updateLieSubmitState();updateGuessSubmitState();updateJoinState();updateSessionDetailState();savePlayerContext();});});
|
||||
updatePhaseStatus();
|
||||
updateGuessSubmitState();
|
||||
updateJoinState();
|
||||
|
||||
@@ -844,9 +844,14 @@ class UiScreenTests(TestCase):
|
||||
self.assertContains(response, "id=\"playerAutoRefreshToggleBtn\"")
|
||||
self.assertContains(response, "id=\"playerAutoRefreshHint\"")
|
||||
self.assertContains(response, "id=\"playerLastRefreshStatus\"")
|
||||
self.assertContains(response, "id=\"sessionDetailBtn\"")
|
||||
self.assertContains(response, "id=\"sessionRefreshHint\"")
|
||||
self.assertContains(response, "togglePlayerAutoRefresh")
|
||||
self.assertContains(response, "markPlayerSessionRefresh")
|
||||
self.assertContains(response, "updatePlayerLastRefreshStatus")
|
||||
self.assertContains(response, "updateSessionDetailState")
|
||||
self.assertContains(response, "session_detail_in_flight")
|
||||
self.assertContains(response, "Opdaterer session-status…")
|
||||
self.assertContains(response, "Session-data ikke opdateret endnu.")
|
||||
self.assertContains(response, "Sidst opdateret:")
|
||||
self.assertContains(response, "Session-data kan være forældet")
|
||||
|
||||
Reference in New Issue
Block a user