feat: fetch using a start/end window rather than everything, use eventSources from FC.js

This commit is contained in:
Raito Bezarius 2022-03-06 17:30:42 +01:00
parent dca9888373
commit 4b2426960b
2 changed files with 41 additions and 46 deletions

View file

@ -10,7 +10,7 @@
import frLocale from '@fullcalendar/core/locales/fr'; import frLocale from '@fullcalendar/core/locales/fr';
import EventModal from './EventModal.svelte'; import EventModal from './EventModal.svelte';
import FilterBar from './FilterBar.svelte'; import FilterBar from './FilterBar.svelte';
import { refreshEvents, calendarTree } from './calendar'; import { mkSource, calendarTree } from './calendar';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import 'bootstrap/dist/css/bootstrap.css'; import 'bootstrap/dist/css/bootstrap.css';
@ -57,34 +57,18 @@
month: mobile ? 'numeric' : 'long', month: mobile ? 'numeric' : 'long',
day: 'numeric' day: 'numeric'
}, },
events: [], eventSources: [],
themeSystem: 'bootstrap5' themeSystem: 'bootstrap5'
}); });
let selectedCalendars; let selectedCalendars = [];
let updateTimer;
async function reloadEvents(selectedCalendars) {
const evts = await refreshEvents(selectedCalendars);
return evts.flat();
}
const updateEvents = debounce(calendars => { const updateEvents = debounce(calendars => {
return reloadEvents(calendars).then(events => {
options.update(opts => ({
...opts,
events
}));
});
}, 300);
onMount(async () => {
const events = await reloadEvents(selectedCalendars);
options.update(opts => ({ options.update(opts => ({
...opts, ...opts,
events eventSources: selectedCalendars.map(mkSource).filter(x => !!x)
})); }));
}); }, 300);
$: updateEvents(selectedCalendars); $: updateEvents(selectedCalendars);
</script> </script>

View file

@ -1,5 +1,3 @@
import ICAL from 'ical.js'
const clouds = { const clouds = {
KLUB_RESEAU: 'klub-reseau', KLUB_RESEAU: 'klub-reseau',
ELEVES_ENS: 'eleves-ens' ELEVES_ENS: 'eleves-ens'
@ -29,6 +27,10 @@ const calendars = {
} }
} }
const calendarsByName = Object.fromEntries(
Object.entries(calendars).map(([id, {name}]) => ([name, id]))
);
export const calendarTree = { export const calendarTree = {
'Clubs COF': { 'Clubs COF': {
'Club réseau': {}, 'Club réseau': {},
@ -47,12 +49,17 @@ export const calendarTree = {
const calendarIds = Object.keys(calendars) const calendarIds = Object.keys(calendars)
function mkCalendarUrl(id, { cloud }) { function mkCalendarUrl(id, { cloud }, extra={}) {
return `/cal/${cloud}/${id}/?export&accept=jcal` return `/cal/${cloud}/${id}/?` + new URLSearchParams({
...extra,
export: true,
expand: true,
accept: 'jcal'
});
} }
function fetchCalendar(id, cal) { function fetchCalendar(id, cal, extra={}) {
return fetch(mkCalendarUrl(id, cal), { credentials: 'omit' }) return fetch(mkCalendarUrl(id, cal, extra), { credentials: 'omit' })
.then(resp => resp.json()) .then(resp => resp.json())
.catch(err => console.error(err)) .catch(err => console.error(err))
} }
@ -125,25 +132,29 @@ function mkEventsFromCalendar(id, cal) {
}) })
} }
export function mkEvent(title, start, duration, ...rest) { export function mkSource(name) {
start = new Date(start) const calendarId = calendarsByName[name];
const end = new Date(start) if (!calendarId) return null;
end.setMinutes(start.getMinutes() + duration) const calendar = calendars[calendarId];
return { return {
title, id: name,
start, ...(calendar?.meta || {}),
end, success: calendarData => {
...rest if (calendarData[0] !== 'vcalendar') return;
const cal = new Calendar(calendarId, calendarData);
return cal.events.map(fcEventFromjCalEvent(cal));
},
failure: error => {
console.error(`Fatal error during event source fetching of '${name}': ${error}`);
},
events: (info, successCallback, failureCallback) => {
const { start, end } = info;
fetchCalendar(calendarId, calendar, {
start: start.valueOf() / 1000,
end: end.valueOf() / 1000
})
.then(successCallback, failureCallback);
}
} }
} }
// TODO: move to FullCalendar custom fetcher to control start&end.
export function refreshEvents(selectedCalendars) {
return Promise.all(
calendarIds
.filter(id =>
selectedCalendars ? selectedCalendars.includes(calendars[id].name) : true
)
.map(id => mkEventsFromCalendar(id, calendars[id]))
)
}