196 lines
5.4 KiB
JavaScript
196 lines
5.4 KiB
JavaScript
const MAX_COUNTDOWN = 60;
|
|
|
|
var countdown = MAX_COUNTDOWN;
|
|
var now = Date.now();
|
|
var eventsOnNow = [];
|
|
var eventsOnNext = [];
|
|
|
|
grist.ready({
|
|
requiredAccess: 'read table'
|
|
});
|
|
|
|
grist.onRecords(function (records) {
|
|
eventsOnNow = [];
|
|
eventsOnNext = [];
|
|
now = Date.now() + (60 + 50) * 60 * 1000;
|
|
|
|
var i = 0;
|
|
|
|
for (const r of records) {
|
|
let e = new Event(
|
|
i++,
|
|
r["title"],
|
|
r["venue"],
|
|
r["video_privacy"],
|
|
r["Record_override"],
|
|
r["Comments"],
|
|
Date.parse(r["start_date"]),
|
|
Date.parse(r["end_date"])
|
|
);
|
|
|
|
if (e.hasStarted() && !e.hasEnded()) {
|
|
eventsOnNow.push(e);
|
|
} else if (!e.hasStarted() && !e.hasEnded()) {
|
|
eventsOnNext.push(e);
|
|
}
|
|
}
|
|
|
|
eventsOnNow.sort((e1, e2) => {
|
|
return (e1.timeUntilEnd() > e2.timeUntilEnd()) ? 1 : ((e2.timeUntilEnd() > e1.timeUntilEnd()) ? -1 : 0)
|
|
});
|
|
|
|
eventsOnNext.sort((e1, e2) => {
|
|
return (e1.timeUntilStart() > e2.timeUntilStart()) ? 1 : ((e2.timeUntilStart() > e1.timeUntilStart()) ? -1 : 0)
|
|
});
|
|
|
|
populateList("happeningNow", eventsOnNow, false);
|
|
populateList("happeningNext", eventsOnNext, true);
|
|
|
|
window.setInterval(() => handleCountdown(), 1000);
|
|
});
|
|
|
|
|
|
grist.onOptions(function(options, interaction) {
|
|
console.info("Options reloaded");
|
|
});
|
|
|
|
class Event {
|
|
constructor(id, name, venue, privacy, recordOverride, comments, startTime, endTime) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.venue = venue;
|
|
this.privacy = privacy;
|
|
this.recordOverride = recordOverride;
|
|
this.comments = comments;
|
|
this.startTime = startTime;
|
|
this.endTime = endTime;
|
|
}
|
|
|
|
hasStarted() {
|
|
return this.startTime < now;
|
|
}
|
|
|
|
hasEnded() {
|
|
return this.endTime < now;
|
|
}
|
|
|
|
timeUntilStart() {
|
|
return new Date(this.startTime - now);
|
|
}
|
|
|
|
timeUntilEnd() {
|
|
return new Date(this.endTime - now);
|
|
}
|
|
}
|
|
|
|
function makeTextBold(text) {
|
|
return "<b>" + text + "</b>";
|
|
}
|
|
|
|
function convertTimeToString(time) {
|
|
// Using getHours() is bullshit for this usage, it won't include any days in the hours
|
|
let hours = Math.floor(time / (1000 * 60 * 60));
|
|
let minutes = Math.ceil((time - (hours * 60 * 60 * 1000)) / (1000 * 60));
|
|
|
|
return hours + " hours, " + minutes + " minutes";
|
|
}
|
|
|
|
function populateList(elementName, items, getStartsIn) {
|
|
document.getElementById(elementName).innerHTML = "";
|
|
|
|
for (const i of items) {
|
|
var listItem = document.createElement("li");
|
|
|
|
listItem.setAttribute("class", "list-group-item shadow-sm d-flex flex-wrap align-items-center m-2 rounded-3")
|
|
listItem.setAttribute("id", i.id);
|
|
|
|
// Basic info of event name, venue and time
|
|
var title = document.createElement("h4");
|
|
title.setAttribute("class", "me-auto")
|
|
title.innerHTML = i.name;
|
|
|
|
var venue = document.createElement("small");
|
|
venue.setAttribute("class", "text-body-secondary");
|
|
venue.innerHTML = " " + i.venue + " | ";
|
|
|
|
var time = document.createElement("small");
|
|
time.setAttribute("id", i.id + "_time");
|
|
time.setAttribute("class", "text-body-secondary");
|
|
if (getStartsIn) {
|
|
time.innerHTML = convertTimeToString(i.timeUntilStart());
|
|
} else {
|
|
time.innerHTML = "(ends in) " + convertTimeToString(i.timeUntilEnd());
|
|
}
|
|
|
|
// Red border if show starts in 15 minutes
|
|
if (getStartsIn) {
|
|
if (i.timeUntilStart() <= 15 * 60 * 1000){
|
|
listItem.setAttribute("class", listItem.getAttribute("class") + " border-2 border-danger");
|
|
time.setAttribute("class", "text-danger");
|
|
}
|
|
}
|
|
|
|
title.appendChild(venue);
|
|
title.appendChild(time);
|
|
listItem.appendChild(title);
|
|
|
|
// Badges
|
|
var privacyBadge = document.createElement("span");
|
|
|
|
if (i.privacy == "none") {
|
|
privacyBadge.innerHTML = "Do not record"
|
|
privacyBadge.setAttribute("class", "badge text-bg-danger rounded-pill")
|
|
} else if (i.privacy == "review") {
|
|
privacyBadge.innerHTML = "Review"
|
|
privacyBadge.setAttribute("class", "badge text-bg-warning rounded-pill")
|
|
} else {
|
|
privacyBadge.innerHTML = "Record";
|
|
privacyBadge.setAttribute("class", "badge text-bg-success rounded-pill")
|
|
}
|
|
|
|
listItem.appendChild(privacyBadge);
|
|
|
|
if (i.recordOverride) {
|
|
var recordOverrideBadge = document.createElement("span");
|
|
recordOverrideBadge.innerHTML = "Record override";
|
|
recordOverrideBadge.setAttribute("class", "badge text-bg-primary rounded-pill border border-danger")
|
|
listItem.appendChild(recordOverrideBadge);
|
|
}
|
|
|
|
if (i.comments) {
|
|
var commentsBadge = document.createElement("span");
|
|
commentsBadge.innerHTML = i.comments
|
|
commentsBadge.setAttribute("class", "badge text-bg-info rounded-pill")
|
|
listItem.appendChild(commentsBadge);
|
|
}
|
|
|
|
document.getElementById(elementName).appendChild(listItem);
|
|
}
|
|
}
|
|
|
|
function refreshLists() {
|
|
// Clear anything that's finished
|
|
while (eventsOnNow.length >0 && eventsOnNow.at(0).hasEnded()) {
|
|
eventsOnNow.shift();
|
|
}
|
|
|
|
// Get anything that's started and add it to the "Happening now" list
|
|
while (eventsOnNext.length > 0 && eventsOnNext.at(0).hasStarted()) {
|
|
eventsOnNow.push(eventsOnNext.shift());
|
|
}
|
|
}
|
|
|
|
function handleCountdown() {
|
|
countdown--;
|
|
if (countdown == 0) {
|
|
countdown = MAX_COUNTDOWN;
|
|
|
|
refreshLists();
|
|
populateList("happeningNow", eventsOnNow, false);
|
|
populateList("happeningNext", eventsOnNext, true);
|
|
}
|
|
|
|
let counterElement = document.getElementById("counter");
|
|
counterElement.innerHTML = "Next refresh in " + countdown;
|
|
}
|