Initial commit - V1
This commit is contained in:
commit
0e67742c4a
185
calendar.js
Normal file
185
calendar.js
Normal file
@ -0,0 +1,185 @@
|
||||
const raws = {};
|
||||
let hideConfirmed = true;
|
||||
|
||||
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');
|
||||
|
||||
if (status.toLowerCase() === 'confirmed') {
|
||||
// Status toggled to only show upcoming/missing.
|
||||
if (hideConfirmed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
title = `✅ ${title}`;
|
||||
}
|
||||
|
||||
if (status !== 'Confirmed' && status !== 'Tentative') {
|
||||
console.log(status);
|
||||
}
|
||||
|
||||
title = `${title} [${name}]`;
|
||||
|
||||
return {
|
||||
title: title,
|
||||
start: item.getFirstPropertyValue('dtstart').toJSDate(),
|
||||
end: item.getFirstPropertyValue('dtend').toJSDate(),
|
||||
display: 'list-item',
|
||||
};
|
||||
});
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
function keyHandlers(calendar)
|
||||
{
|
||||
window.addEventListener('keydown', function(ev) {
|
||||
const key = ev.key;
|
||||
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case 'ArrowLeft':
|
||||
calendar.prev();
|
||||
break;
|
||||
|
||||
case 'ArrowRight':
|
||||
calendar.next();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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 = true)
|
||||
{
|
||||
const calendarElement = document.querySelector('#sonarr-calendar');
|
||||
let events = [];
|
||||
|
||||
const urls = [
|
||||
// {
|
||||
// url: 'https://tv.cocks.no/sonarr-ics',
|
||||
// name: 'hidden-sea',
|
||||
// },
|
||||
{
|
||||
url: 'https://tv.cocks.no/sonarr-cb-ics',
|
||||
name: 'cold-badlands',
|
||||
},
|
||||
{
|
||||
url: 'https://tv.cocks.no/sonarr-fv-ics',
|
||||
name: 'fancy-valley',
|
||||
},
|
||||
];
|
||||
|
||||
for (const list of urls)
|
||||
{
|
||||
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,
|
||||
},
|
||||
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();
|
||||
});
|
2
ical.min.js
vendored
Normal file
2
ical.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
58
index.html
Normal file
58
index.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="https://cdn.decicus.com/fontawesome/v5.15.4/css/all.min.css"
|
||||
integrity="sha384-rqn26AG5Pj86AF4SO72RK5fyefcQ/x32DNQfChxWvbXIyXFePlEktwD18fEz+kQU" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.decicus.com/water.css/v2.1.1/dark.min.css"
|
||||
integrity="sha384-cJBdsSYaB37lARFjqUmJVoGdRQaQndlSkVAOB0QSVMzFhBAQ6Aymcu3PIkS8CkWl" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.css" integrity="sha256-16PDMvytZTH9heHu9KBPjzrFTaoner60bnABykjNiM0=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fullcalendar/daygrid@5.10.1/main.min.css" integrity="sha256-dPWx9VoFn91TsfLKiK60fNYizBuynczRmMVDO/Yzluo=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fullcalendar/list@5.10.1/main.min.css" integrity="sha256-b1BoveasAh93I+XvngCpnzp5pVCQlXxGPdijHWDjDXc=" crossorigin="anonymous">
|
||||
<style type="text/css">
|
||||
body {
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
:root {
|
||||
--fc-list-event-hover-bg-color: #458680;
|
||||
}
|
||||
|
||||
.fc .fc-list-sticky .fc-list-day > * {
|
||||
background: #202b38;
|
||||
}
|
||||
|
||||
.fc-list-day-text, .fc-list-day-side-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sonarr-calendar {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
<title>Cactflix [Main] — Plex — TV Center</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Cactflix [Main] — Plex — TV Center</h1>
|
||||
|
||||
<h2>Upcoming TV show episodes — English, Norwegian & Anime:</h2>
|
||||
|
||||
<div id="sonarr-calendar">
|
||||
<p id="status-message">Loading... Please wait 🙂</p>
|
||||
</div>
|
||||
</body>
|
||||
<script src="ical.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.js" integrity="sha256-nCXGH8kkPFozCBx4meHWhA5OCqXhhBzoBVpHfM/HmwM=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@fullcalendar/daygrid@5.10.1/main.global.min.js" integrity="sha256-WbQSQ0zYo3bZNQiA5R5YdIL/CGRzzM3wQVcyVtdZtFQ=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@fullcalendar/list@5.10.1/main.global.min.js" integrity="sha256-hv4JZxfujHAembALj9LHpTqw+bX2MDxtqksAOvRy9/c=" crossorigin="anonymous"></script>
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/@fullcalendar/icalendar@5.10.1/main.global.min.js" integrity="sha256-Cw5va3Z2DC0Os2wMB5sXOPHNDiJ7YzP9WpYy5/WV1aA=" crossorigin="anonymous"></script> -->
|
||||
<script src="calendar.js"></script>
|
||||
</html>
|
15
moment.min.js
vendored
Normal file
15
moment.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user