feat: rework the UI

This commit is contained in:
Raito Bezarius 2022-02-20 22:29:15 +01:00
parent 139d7b40b1
commit 7674dc956a
4 changed files with 115 additions and 27 deletions

35
package-lock.json generated
View file

@ -43,7 +43,6 @@
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/common/-/common-5.10.1.tgz",
"integrity": "sha512-EumKIJcQTvQdTs75/9dmeREFgjcRVWzqHJS1Xvlz5mNsmB+w9EINCHETRjChtAQg1WD/lTQyVj4sHsKO7vCMSw==",
"dev": true,
"requires": {
"tslib": "^2.1.0"
}
@ -80,6 +79,15 @@
"tslib": "^2.1.0"
}
},
"@fullcalendar/rrule": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/rrule/-/rrule-5.10.1.tgz",
"integrity": "sha512-K5TO8298eVkZiJ70hZrAvAAP81aTMiymgPW1nnaOkflI4bvEDJlkGdFe1MqgE07oTBZca7VU7/33ePiSTs0Pcg==",
"requires": {
"@fullcalendar/common": "~5.10.1",
"tslib": "^2.1.0"
}
},
"@fullcalendar/timegrid": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.10.1.tgz",
@ -1339,6 +1347,12 @@
"yallist": "^4.0.0"
}
},
"luxon": {
"version": "1.28.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz",
"integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==",
"optional": true
},
"magic-string": {
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
@ -2209,6 +2223,22 @@
}
}
},
"rrule": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/rrule/-/rrule-2.6.8.tgz",
"integrity": "sha512-cUaXuUPrz9d1wdyzHsBfT1hptKlGgABeCINFXFvulEPqh9Np9BnF3C3lrv9uO54IIr8VDb58tsSF3LhsW+4VRw==",
"requires": {
"luxon": "^1.21.3",
"tslib": "^1.10.0"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
}
},
"sade": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz",
@ -2582,8 +2612,7 @@
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
"dev": true
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"undici": {
"version": "4.14.1",

View file

@ -27,8 +27,10 @@
"svelte-fullcalendar": "^1.1.1"
},
"dependencies": {
"@fullcalendar/rrule": "^5.10.1",
"@nextcloud/cdav-library": "^1.0.0",
"ical.js": "^1.5.0",
"rrule": "^2.6.8",
"sirv-cli": "^1.0.0"
}
}

View file

@ -2,18 +2,26 @@
import { onMount } from 'svelte';
import FullCalendar from 'svelte-fullcalendar';
import timeGridPlugin from '@fullcalendar/timegrid';
import rrulePlugin from '@fullcalendar/rrule';
import dayGridPlugin from '@fullcalendar/daygrid';
import frLocale from '@fullcalendar/core/locales/fr';
import { refreshEvents } from './calendar';
import { refreshEvents, calendarTree } from './calendar';
let options = {
initialView: 'timeGridWeek',
plugins: [timeGridPlugin],
plugins: [timeGridPlugin, dayGridPlugin, rrulePlugin],
locale: frLocale,
height: "100%",
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
nowIndicator: true,
now: new Date(),
events: []
};
let selectedCalendars;
onMount(async () => {
const evts = await refreshEvents();
const evts = await refreshEvents(selectedCalendars);
options.events = evts.flat();
options = { ...options };
});
@ -21,15 +29,15 @@
$: console.log(options);
</script>
<div style="height:100vh">
<div class="app-container">
<h1 class="title">Calendrier de la vie étudiante à l'ENS</h1>
<div style="height: 100%;">
<!-- <FilterBar {calendarTree} {selectedCalendars}> -->
<FullCalendar {options} />
</div>
</div>
<style>
body {
height: 100vh;
}
main {
text-align: center;
padding: 1em;
@ -37,11 +45,14 @@
margin: 0 auto;
}
h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
.title {
text-align: center;
}
.app-container {
display: flex;
flex-flow: column;
height: 100%;
}
@media (min-width: 640px) {

View file

@ -1,9 +1,24 @@
import ICAL from 'ical.js';
const calendarIds = [
"5WrcagPPARQ3BD87",
"TFEAKjAgNFQZpNjo"
];
const calendars = {
"5WrcagPPARQ3BD87": {
name: "Club réseau",
color: null
},
"TFEAKjAgNFQZpNjo": {
name: "hackENS",
color: null
}
};
export const calendarTree = {
"COF": [
"Club réseau",
"hackENS"
]
};
const calendarIds = Object.keys(calendars);
function mkCalendarUrl(id) {
return `/cal/${id}/?export&accept=jcal`;
@ -14,8 +29,10 @@ function fetchCalendar(id) {
}
class Calendar {
constructor (calendar) {
this.calName = calendar[1][3][3];
constructor (id, calendar) {
const metadata = calendars[id];
this.name = metadata.name;
this.color = metadata.color || calendar[1][4][3];
this.events = calendar[2].filter(item => item[0] === 'vevent').map(item => this._parse_vevent(item[1]));
}
@ -28,11 +45,39 @@ class Calendar {
}
}
function fcEventFromjCalEvent(cal) {
return function (evt) {
const start = new Date(evt.dtstart);
const end = new Date(evt.dtend);
const fcEvent = {
title: `${cal.name}: ${evt.summary}`,
start,
color: cal.color,
duration: end - start // in ms
};
if (evt.description) {
fcEvent.description = evt.description;
}
if (evt.rrule) {
const { freq, byday } = evt.rrule;
fcEvent.rrule = {
freq,
byweekday: byday,
dtstart: evt.dtstart,
};
}
return fcEvent;
}
}
function mkEventsFromCalendar(id) {
return fetchCalendar(id).then(calendar => {
if (calendar[0] !== 'vcalendar') return;
const cal = new Calendar(calendar)
return cal.events.map(evt => ({ title: evt.summary, start: new Date(evt.dtstart), end: new Date(evt.dtend) }))
const cal = new Calendar(id, calendar)
return cal.events.map(fcEventFromjCalEvent(cal))
});
}
@ -48,6 +93,7 @@ export function mkEvent(title, start, duration, ...rest) {
}
}
export function refreshEvents() {
return Promise.all(calendarIds.map(mkEventsFromCalendar))
// TODO: move to FullCalendar custom fetcher to control start&end.
export function refreshEvents(selectedCalendars) {
return Promise.all(calendarIds.filter(id => selectedCalendars ? selectedCalendars.includes(id) : true).map(mkEventsFromCalendar))
}