TV-Center/calendar.js
2022-08-25 15:45:09 +02:00

218 lines
4.9 KiB
JavaScript

const raws = {};
let hideConfirmed = true;
const icsUrls = [
{
url: '/sonarr-hs-ics',
name: 'hidden-sea',
},
{
url: '/sonarr-cb-ics',
name: 'cold-badlands',
},
{
url: '/sonarr-fv-ics',
name: 'fancy-valley',
},
];
async function fetchIcs(url, name)
{
let icalRaw = raws[name] || '';
if (!raws[name]) {
const response = await fetch(url);
icalRaw = await response.text();
raws[name] = icalRaw;
}
const parse = ICAL.parse(icalRaw.trim());
const component = new ICAL.Component(parse);
// console.log(component);
const eventComps = component.getAllSubcomponents('vevent');
const events = eventComps.map((item) => {
if (item.getFirstPropertyValue('class') === 'PRIVATE') {
return null;
}
let title = item.getFirstPropertyValue('summary');
const status = item.getFirstPropertyValue('status');
const start = item.getFirstPropertyValue('dtstart').toJSDate();
const end = item.getFirstPropertyValue('dtend').toJSDate();
let isAdded = false;
if (status.toLowerCase() === 'confirmed') {
// Status toggled to only show upcoming/missing.
if (hideConfirmed) {
return null;
}
isAdded = true;
title = `${title}`;
}
const now = Date.now();
if (!isAdded)
{
/**
* Start date in the past
*/
if (now > start.getTime()) {
title = `🟠 ${title}`;
}
else {
title = `${title}`;
}
}
// if (status.toLowerCase() !== 'confirmed' && status !== 'tentative') {
// console.log(status);
// }
title = `${title} [${name}]`;
return {
title: title,
start,
end,
display: 'list-item',
};
});
return events;
}
let keyHandlersAdded = false;
function keyHandlers(calendar)
{
if (keyHandlersAdded) {
return;
}
window.addEventListener('keydown', function(ev) {
const key = ev.key;
if (!key) {
return;
}
switch (key) {
case 'ArrowLeft':
calendar.prev();
break;
case 'ArrowRight':
calendar.next();
break;
}
});
keyHandlersAdded = true;
}
function scrollToCalendarDay()
{
const date = new Date();
const today = date.toISOString().split('T')[0];
const dateRow = document.querySelector(`[data-date="${today}"]`);
if (!dateRow) {
console.log('Could not find date row', today);
return;
}
dateRow.scrollIntoView({
behavior: 'smooth',
block: 'start',
});
}
const showAllText = 'Show all tracked episodes';
const showTrackedText = 'Show only missing/upcoming episodes';
const toggleButton = {
text: (hideConfirmed ? showAllText : showTrackedText),
click: async function(event) {
const btn = event.target;
console.log(btn);
if (!hideConfirmed) {
toggleButton.text = showAllText;
}
else {
toggleButton.text = showTrackedText;
}
hideConfirmed = !hideConfirmed;
await loadSonarrCalendar(false);
},
};
async function loadSonarrCalendar(shouldScroll = false)
{
const calendarElement = document.querySelector('#sonarr-calendar');
let events = [];
for (const list of icsUrls)
{
try {
const { url, name } = list;
let fetched = await fetchIcs(url, name);
fetched = fetched.filter(x => x !== null);
events = [...events, ...fetched];
}
catch (err) {
console.error(err);
}
}
const calendar = new FullCalendar.Calendar(calendarElement, {
// initialView: 'dayGridMonth',
customButtons: {
toggleButton,
},
themeSystem: 'bootstrap5',
initialView: 'listWeek',
initialDate: new Date(),
headerToolbar: {
left: 'prev,next today toggleButton',
center: 'title',
right: 'dayGridMonth,dayGridWeek,dayGridDay,listWeek',
},
events: events,
});
const message = document.querySelector('#status-message');
try {
calendar.render();
if (message) {
message.remove();
}
keyHandlers(calendar);
if (shouldScroll) {
scrollToCalendarDay();
}
}
catch (err) {
console.error(err);
message.textContent = 'An error occurred loading schedule...';
}
}
window.addEventListener('DOMContentLoaded', function() {
loadSonarrCalendar();
this.setInterval(
function() {
loadSonarrCalendar(false);
},
60 * 1000
);
});