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(); var i = 0; console.info(records); for (const r of records) { let privacy = r["video_privacy"]; let videoNeeded = r["Video_team_attending"]; if (privacy == "none" || videoNeeded == true) { let e = new Event( i++, r["title"], r["venue"], videoNeeded, privacy, 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) }); console.log(eventsOnNext); populateList("happeningNow", eventsOnNow); populateList("happeningNext", eventsOnNext); window.setInterval(() => handleCountdown(), 1000); }); grist.onOptions(function(options, interaction) { console.info("Options reloaded"); }); class Event { constructor(id, name, venue, videoNeeded, privacy, comments, startTime, endTime) { this.id = id; this.name = name; this.venue = venue; this.videoNeeded = videoNeeded; this.privacy = privacy; 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 "" + text + ""; } 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)); if (hours < 10) { hours = "0" + hours } let minutes = time.getMinutes(); if (minutes < 10) { minutes = "0" + minutes } return hours + ":" + minutes; } function populateList(elementName, items) { for (const i of items) { const col = document.createElement("div"); col.setAttribute("class", "col-sm-12 col-bg-12") const card = document.createElement("div"); card.setAttribute("class", "card m-3") const cardHeader = document.createElement("div"); cardHeader.setAttribute("class", "card-header") cardHeader.innerHTML = i.name; const list = document.createElement("ul"); list.setAttribute("class", "list-group list-group-flush") list.setAttribute("id", i.id); var venue = document.createElement("ul"); var videoNeeded = document.createElement("ul"); var privacy = document.createElement("ul"); var comments = document.createElement("ul"); var startsIn = document.createElement("ul"); venue.setAttribute("class", "list-group-item"); videoNeeded.setAttribute("class", "list-group-item"); privacy.setAttribute("class", "list-group-item"); comments.setAttribute("class", "list-group-item"); startsIn.setAttribute("class", "list-group-item"); startsIn.setAttribute("id", i.id + "_time"); venue.innerHTML = "Venue: " + i.venue; videoNeeded.innerHTML = "Video Team Present: " + i.videoNeeded; privacy.innerHTML = "Privacy: " + i.privacy; comments.innerHTML = "Comment: " + i.comments; startsIn.innerHTML = "Starts In: " + convertTimeToString(i.timeUntilStart()) + "(" + i.startTime.toLocaleString("en-GB", { timeZone: "UTC" }) + ")"; list.appendChild(venue); list.appendChild(videoNeeded); list.appendChild(privacy); if (i.comments) { list.appendChild(comments); } list.appendChild(startsIn); // Colour in any rows if (i.privacy != "public") { if (i.privacy == "none") { privacy.setAttribute("class", "list-group-item bg-danger") privacy.innerHTML = makeTextBold("Privacy: Do not record!"); } else if (i.privacy == "review") { privacy.setAttribute("class", "list-group-item bg-warning") privacy.innerHTML = makeTextBold(privacy.innerHTML); } } if (i.comments) { comments.setAttribute("class", "list-group-item bg-info"); console.log(i.comments); comments.innerHTML = makeTextBold(comments.innerHTML); } if (i.videoNeeded == true) { videoNeeded.setAttribute("class", "list-group-item bg-warning"); videoNeeded.innerHTML = makeTextBold(videoNeeded.innerHTML); } card.appendChild(cardHeader); card.appendChild(list); col.append(card); document.getElementById(elementName).appendChild(col); } } function refreshTables() { var toDelete = []; now = Date.now(); for (const nowItem of eventsOnNow) { let timeUntilEnd = nowItem.timeUntilEnd(); let timeField = document.getElementById(nowItem.id + "_time"); timeField.innerHTML = convertTimeToString(nowItem.timeUntilEnd()); } for (const nextItem of eventsOnNext) { let timeField = document.getElementById(nextItem.id + "_time"); timeField.innerHTML = convertTimeToString(nextItem.timeUntilEnd()); } } function handleCountdown() { countdown--; if (countdown == 0) { countdown = MAX_COUNTDOWN; window.reload(); } let counterElement = document.getElementById("counter"); counterElement.innerHTML = "Next refresh in " + countdown; }