mirror of
https://github.com/Wolvan/poll.horse.git
synced 2024-11-22 04:58:00 +01:00
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:
parent
dca2cc3eeb
commit
e9aaedb494
5 changed files with 42 additions and 3 deletions
|
@ -9,6 +9,8 @@
|
||||||
"MAX_POLL_OPTIONS": "readonly",
|
"MAX_POLL_OPTIONS": "readonly",
|
||||||
"MAX_CHARACTER_LENGTH": "readonly",
|
"MAX_CHARACTER_LENGTH": "readonly",
|
||||||
"POLL_VOTE_DATA_STRING": "readonly",
|
"POLL_VOTE_DATA_STRING": "readonly",
|
||||||
|
"POLL_BACKEND_URL": "readonly",
|
||||||
|
"POLL_ID": "readonly",
|
||||||
|
|
||||||
"textFit": "readonly",
|
"textFit": "readonly",
|
||||||
"google": "readonly"
|
"google": "readonly"
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js" defer="true"></script>
|
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js" defer="true"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
const POLL_VOTE_DATA_STRING = `{{ POLL_OPTION_VOTES }}`;
|
const POLL_VOTE_DATA_STRING = `{{ POLL_OPTION_VOTES }}`;
|
||||||
|
const POLL_BACKEND_URL = "{{ BACKEND_BASE_PATH }}";
|
||||||
|
const POLL_ID = "{{ POLL_ID }}";
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="/static/js/result.js" defer="true"></script>
|
<script type="text/javascript" src="/static/js/result.js" defer="true"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -41,7 +41,7 @@ main .notepad .poll-option .progress .poll-bar {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: calc(100% - 60px);
|
width: calc(100% - 50px);
|
||||||
}
|
}
|
||||||
main .notepad .poll-option .progress .poll-bar .poll-bar-fill {
|
main .notepad .poll-option .progress .poll-bar .poll-bar-fill {
|
||||||
height: calc(100% - 5px);
|
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 {
|
main .notepad .poll-option .progress .poll-bar-text {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
|
}
|
||||||
|
main .notepad .poll-option .progress .poll-bar-text::after {
|
||||||
|
content: "%";
|
||||||
|
margin-left: 5px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +64,7 @@ aside#chart {
|
||||||
right: -200px;
|
right: -200px;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 750px) {
|
@media screen and (max-width: 750px) {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const POLL_REFRESH_INTERVAL = 5000;
|
||||||
|
|
||||||
const textFitOptions = {
|
const textFitOptions = {
|
||||||
multiLine: true
|
multiLine: true
|
||||||
};
|
};
|
||||||
|
@ -42,6 +44,33 @@ function domLoaded() {
|
||||||
textFit(document.querySelector(".poll-title"), textFitOptions);
|
textFit(document.querySelector(".poll-title"), textFitOptions);
|
||||||
document.querySelectorAll(".poll-option .poll-option-text").forEach(element => textFit(element, 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();
|
if (document.readyState === "complete" || document.readyState === "loaded") domLoaded();
|
||||||
|
|
|
@ -106,14 +106,14 @@ export default function init(router: Router): void {
|
||||||
if (!poll || poll.error) return res.redirect("/");
|
if (!poll || poll.error) return res.redirect("/");
|
||||||
const totalVotes = Object.values(poll.votes).reduce((acc, cur) => acc + cur, 0);
|
const totalVotes = Object.values(poll.votes).reduce((acc, cur) => acc + cur, 0);
|
||||||
const pollOptionsDivs = Object.entries(poll.votes).map(([option, votes]) => `
|
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-info">
|
||||||
<div class="poll-option-text">${ option }</div><div class="poll-option-votes">${ votes }</div>
|
<div class="poll-option-text">${ option }</div><div class="poll-option-votes">${ votes }</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
<div class="poll-bar">
|
<div class="poll-bar">
|
||||||
<div class="poll-bar-fill" style="width: ${ (votes / totalVotes) * 100 }%"></div>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
`).join("");
|
`).join("");
|
||||||
|
@ -123,6 +123,7 @@ export default function init(router: Router): void {
|
||||||
"POLL_TITLE": poll.title,
|
"POLL_TITLE": poll.title,
|
||||||
"POLL_OPTION_DIVS": pollOptionsDivs,
|
"POLL_OPTION_DIVS": pollOptionsDivs,
|
||||||
"POLL_VOTES_TOTAL": totalVotes,
|
"POLL_VOTES_TOTAL": totalVotes,
|
||||||
|
"BACKEND_BASE_PATH": (program.opts().backendBaseUrl || ""),
|
||||||
"POLL_OPTION_VOTES": JSON.stringify(Object.entries(poll.votes))
|
"POLL_OPTION_VOTES": JSON.stringify(Object.entries(poll.votes))
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
Loading…
Reference in a new issue