Implement auto update

Every 5 seconds the system attempts to fetch the most recent vote state
of the poll and display it to the user.
This commit is contained in:
Wolvan 2022-01-06 20:44:29 +01:00
parent dca2cc3eeb
commit e9aaedb494
5 changed files with 42 additions and 3 deletions

View file

@ -9,6 +9,8 @@
"MAX_POLL_OPTIONS": "readonly",
"MAX_CHARACTER_LENGTH": "readonly",
"POLL_VOTE_DATA_STRING": "readonly",
"POLL_BACKEND_URL": "readonly",
"POLL_ID": "readonly",
"textFit": "readonly",
"google": "readonly"

View file

@ -13,6 +13,8 @@
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js" defer="true"></script>
<script type="text/javascript">
const POLL_VOTE_DATA_STRING = `{{ POLL_OPTION_VOTES }}`;
const POLL_BACKEND_URL = "{{ BACKEND_BASE_PATH }}";
const POLL_ID = "{{ POLL_ID }}";
</script>
<script type="text/javascript" src="/static/js/result.js" defer="true"></script>
</head>

View file

@ -41,7 +41,7 @@ main .notepad .poll-option .progress .poll-bar {
vertical-align: top;
display: inline-block;
height: 100%;
width: calc(100% - 60px);
width: calc(100% - 50px);
}
main .notepad .poll-option .progress .poll-bar .poll-bar-fill {
height: calc(100% - 5px);
@ -51,6 +51,10 @@ main .notepad .poll-option .progress .poll-bar .poll-bar-fill {
}
main .notepad .poll-option .progress .poll-bar-text {
width: 50px;
}
main .notepad .poll-option .progress .poll-bar-text::after {
content: "%";
margin-left: 5px;
padding-right: 10px;
}
@ -60,6 +64,7 @@ aside#chart {
right: -200px;
width: 200px;
height: 200px;
visibility: hidden;
}
@media screen and (max-width: 750px) {

View file

@ -1,5 +1,7 @@
"use strict";
const POLL_REFRESH_INTERVAL = 5000;
const textFitOptions = {
multiLine: true
};
@ -42,6 +44,33 @@ function domLoaded() {
textFit(document.querySelector(".poll-title"), textFitOptions);
document.querySelectorAll(".poll-option .poll-option-text").forEach(element => textFit(element, textFitOptions));
});
let prevResult = null;
async function fetchNewestResults() {
try {
const response = await fetch(POLL_BACKEND_URL + "/_backend/poll-result/" + POLL_ID);
const json = await response.json();
if (json.error) throw new Error(json.error);
const votes = json.votes;
const totalVotes = Object.values(votes).reduce((a, b) => a + b, 0);
if (!prevResult || Object.entries(votes).some(([key, value]) => value !== prevResult[key])) {
drawChart(Object.entries(votes));
Object.entries(votes).forEach(([key, value]) => {
const el = document.querySelector("main .notepad .poll-option[option='" + key + "']");
if (!el) return;
el.querySelector(".poll-option-votes").innerText = value;
el.querySelector(".poll-bar-fill").style.width = (value / totalVotes * 100) + "%";
el.querySelector(".poll-bar-text").innerText = Math.round(value / totalVotes * 100);
});
prevResult = votes;
}
} catch (error) {
console.warn(error);
}
setTimeout(fetchNewestResults, POLL_REFRESH_INTERVAL);
}
setTimeout(fetchNewestResults, POLL_REFRESH_INTERVAL);
}
if (document.readyState === "complete" || document.readyState === "loaded") domLoaded();

View file

@ -106,14 +106,14 @@ export default function init(router: Router): void {
if (!poll || poll.error) return res.redirect("/");
const totalVotes = Object.values(poll.votes).reduce((acc, cur) => acc + cur, 0);
const pollOptionsDivs = Object.entries(poll.votes).map(([option, votes]) => `
<div class="poll-option">
<div class="poll-option" option="${ option }">
<div class="poll-option-info">
<div class="poll-option-text">${ option }</div><div class="poll-option-votes">${ votes }</div>
</div>
<div class="progress">
<div class="poll-bar">
<div class="poll-bar-fill" style="width: ${ (votes / totalVotes) * 100 }%"></div>
</div><div class="poll-bar-text">${ Math.round((votes / totalVotes) * 100) }%</div>
</div><div class="poll-bar-text">${ Math.round((votes / totalVotes) * 100) }</div>
</div>
</div>
`).join("");
@ -123,6 +123,7 @@ export default function init(router: Router): void {
"POLL_TITLE": poll.title,
"POLL_OPTION_DIVS": pollOptionsDivs,
"POLL_VOTES_TOTAL": totalVotes,
"BACKEND_BASE_PATH": (program.opts().backendBaseUrl || ""),
"POLL_OPTION_VOTES": JSON.stringify(Object.entries(poll.votes))
});
} catch (error) {