Merge pull request 'Resource timelines for room-based views' (#29) from resource-timelines into master

Reviewed-on: https://git.rz.ens.wtf/Klub-RZ/metis/pulls/29
This commit is contained in:
tomate 2022-07-26 14:36:32 +02:00
commit b7aa57c149
6 changed files with 200 additions and 8 deletions

111
package-lock.json generated
View file

@ -11,6 +11,7 @@
"@fullcalendar/adaptive": "^5.10.1",
"@fullcalendar/bootstrap5": "^5.10.2",
"@fullcalendar/list": "^5.10.1",
"@fullcalendar/resource-timeline": "^5.10.1",
"@fullcalendar/rrule": "^5.10.1",
"@nextcloud/cdav-library": "^1.0.0",
"bootstrap": "^5.1.3",
@ -27,6 +28,7 @@
"@fullcalendar/daygrid": "^5.10.1",
"@fullcalendar/timegrid": "^5.10.1",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"dav": "^1.8.0",
"postcss": "^8.3.11",
@ -166,6 +168,29 @@
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/resource-common": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/resource-common/-/resource-common-5.10.1.tgz",
"integrity": "sha512-20JR8cucAeJEXSbWVSj9USwsPGKb3dVQr8CBiXuHPbD0OLK93j7jhKjBlp/pRldtcJW9mIXC8ENQvw/aNZJ9Cw==",
"dependencies": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-common": "~5.10.1",
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/resource-timeline": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-5.10.1.tgz",
"integrity": "sha512-gsqjr6Z+LQcNbQlHgaTtg/kF8l6yDRtIuMQbhFlTy71RJI//x2mHhLXgV40FJeEE+srp48xJPd89+rIhlyJ5Tw==",
"dependencies": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-common": "~5.10.1",
"@fullcalendar/resource-common": "~5.10.1",
"@fullcalendar/scrollgrid": "~5.10.1",
"@fullcalendar/timeline": "~5.10.1",
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/rrule": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/rrule/-/rrule-5.10.1.tgz",
@ -178,6 +203,16 @@
"rrule": "^2.6.0"
}
},
"node_modules/@fullcalendar/scrollgrid": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-5.10.1.tgz",
"integrity": "sha512-Hj6gzj2/sUUnozIMC0GBK60/ZTeDchp/Gc2S4F+05W6V4BoUXbIwav+EdAerfNFOv7EXWa9vM9Lq3A53iVWFVg==",
"dependencies": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-common": "~5.10.1",
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/timegrid": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.10.1.tgz",
@ -189,6 +224,17 @@
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/timeline": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-5.10.1.tgz",
"integrity": "sha512-pFMhK4nsCvpsA63GPJQtT1RSS2OLlT9a2+fvsf2oQregBLcottJSlCjIsIuKP7hpQLimaSdLr2kNjh5hs8jKlw==",
"dependencies": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-common": "~5.10.1",
"@fullcalendar/scrollgrid": "~5.10.1",
"tslib": "^2.1.0"
}
},
"node_modules/@hapi/hoek": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
@ -283,6 +329,18 @@
"rollup": "^2.30.0"
}
},
"node_modules/@rollup/plugin-json": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz",
"integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^3.0.8"
},
"peerDependencies": {
"rollup": "^1.20.0 || ^2.0.0"
}
},
"node_modules/@rollup/plugin-node-resolve": {
"version": "11.2.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",
@ -4124,6 +4182,29 @@
"tslib": "^2.1.0"
}
},
"@fullcalendar/resource-common": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/resource-common/-/resource-common-5.10.1.tgz",
"integrity": "sha512-20JR8cucAeJEXSbWVSj9USwsPGKb3dVQr8CBiXuHPbD0OLK93j7jhKjBlp/pRldtcJW9mIXC8ENQvw/aNZJ9Cw==",
"requires": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-common": "~5.10.1",
"tslib": "^2.1.0"
}
},
"@fullcalendar/resource-timeline": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-5.10.1.tgz",
"integrity": "sha512-gsqjr6Z+LQcNbQlHgaTtg/kF8l6yDRtIuMQbhFlTy71RJI//x2mHhLXgV40FJeEE+srp48xJPd89+rIhlyJ5Tw==",
"requires": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-common": "~5.10.1",
"@fullcalendar/resource-common": "~5.10.1",
"@fullcalendar/scrollgrid": "~5.10.1",
"@fullcalendar/timeline": "~5.10.1",
"tslib": "^2.1.0"
}
},
"@fullcalendar/rrule": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/rrule/-/rrule-5.10.1.tgz",
@ -4133,6 +4214,16 @@
"tslib": "^2.1.0"
}
},
"@fullcalendar/scrollgrid": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-5.10.1.tgz",
"integrity": "sha512-Hj6gzj2/sUUnozIMC0GBK60/ZTeDchp/Gc2S4F+05W6V4BoUXbIwav+EdAerfNFOv7EXWa9vM9Lq3A53iVWFVg==",
"requires": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-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",
@ -4144,6 +4235,17 @@
"tslib": "^2.1.0"
}
},
"@fullcalendar/timeline": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-5.10.1.tgz",
"integrity": "sha512-pFMhK4nsCvpsA63GPJQtT1RSS2OLlT9a2+fvsf2oQregBLcottJSlCjIsIuKP7hpQLimaSdLr2kNjh5hs8jKlw==",
"requires": {
"@fullcalendar/common": "~5.10.1",
"@fullcalendar/premium-common": "~5.10.1",
"@fullcalendar/scrollgrid": "~5.10.1",
"tslib": "^2.1.0"
}
},
"@hapi/hoek": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
@ -4216,6 +4318,15 @@
"resolve": "^1.17.0"
}
},
"@rollup/plugin-json": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz",
"integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.0.8"
}
},
"@rollup/plugin-node-resolve": {
"version": "11.2.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",

View file

@ -12,6 +12,7 @@
"@fullcalendar/daygrid": "^5.10.1",
"@fullcalendar/timegrid": "^5.10.1",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"dav": "^1.8.0",
"postcss": "^8.3.11",
@ -33,6 +34,7 @@
"@fullcalendar/adaptive": "^5.10.1",
"@fullcalendar/bootstrap5": "^5.10.2",
"@fullcalendar/list": "^5.10.1",
"@fullcalendar/resource-timeline": "^5.10.1",
"@fullcalendar/rrule": "^5.10.1",
"@nextcloud/cdav-library": "^1.0.0",
"bootstrap": "^5.1.3",

View file

@ -7,6 +7,7 @@ import css from 'rollup-plugin-css-only'
import postcss from 'rollup-plugin-postcss'
import dev from 'rollup-plugin-dev'
import copy from 'rollup-plugin-copy'
import json from '@rollup/plugin-json';
const production = !process.env.ROLLUP_WATCH
@ -48,6 +49,8 @@ export default {
}
}),
json(),
// Copy font files
copy({
targets: [

View file

@ -7,6 +7,7 @@
import rrulePlugin from '@fullcalendar/rrule';
import dayGridPlugin from '@fullcalendar/daygrid';
import listPlugin from '@fullcalendar/list';
import resourceTimelinePlugin from '@fullcalendar/resource-timeline';
import frLocale from '@fullcalendar/core/locales/fr';
import EventModal from './EventModal.svelte';
import FilterBar from './FilterBar.svelte';
@ -18,6 +19,8 @@
import 'bootstrap-icons/font/bootstrap-icons.css';
import bootstrap5Plugin from '@fullcalendar/bootstrap5';
import ENSLocations from './static-ens-locations.json';
const event = writable(null);
let openModal = false;
@ -36,12 +39,12 @@
? {
left: 'title',
center: 'prev,today,next',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
right: 'resourceTimelineDay dayGridMonth,timeGridWeek,timeGridDay,listWeek'
}
: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
right: 'resourceTimelineDay dayGridMonth,timeGridWeek,timeGridDay,listWeek'
};
let calendar;
@ -53,12 +56,24 @@
dayGridPlugin,
rrulePlugin,
listPlugin,
resourceTimelinePlugin,
adaptivePlugin,
bootstrap5Plugin
],
locale: frLocale,
allDayContent: '',
headerToolbar: headers,
buttonText: { resourceTimelineDay: 'Salles' },
scrollTime: "08:00:00",
resourceGroupField: 'building',
resourceAreaWidth: '27%',
resources: Object.entries(ENSLocations).flatMap(([building, rooms]) =>
rooms.map(room => ({
id: `${building}-${room}`,
building,
title: room
}))
),
height: '100%',
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
nowIndicator: true,
@ -76,7 +91,8 @@
eventSources: [],
themeSystem: 'bootstrap5',
nextDayThreshold: '05:00:00',
progressiveEventRendering: true
progressiveEventRendering: true,
expandRows: true
});
const flatten = d => {

View file

@ -1,3 +1,5 @@
import STATIC_LOCATIONS from './static-ens-locations.json'
// https://stackoverflow.com/a/35970186
function invertColor(hex) {
if (hex.indexOf('#') === 0) {
@ -92,7 +94,7 @@ const calendars = {
color: null,
initial: false
},
'Ekjb4kDqMMqwJXZF': {
Ekjb4kDqMMqwJXZF: {
cloud: clouds.ELEVES_ENS,
name: 'Rentrée des départements',
short_name: 'Dpt',
@ -104,20 +106,20 @@ const calendars = {
short_name: 'Conf',
color: null
},
'PnRXqeq4SsSC33FM': {
PnRXqeq4SsSC33FM: {
cloud: clouds.ELEVES_ENS,
name: 'Visites de bibliothèques',
short_name: 'Bibli',
initial: false,
color: null
},
'NWPtiEiz62LTtjo2': {
NWPtiEiz62LTtjo2: {
cloud: clouds.ELEVES_ENS,
name: 'Amphis de rentrée',
short_name: 'Prés. de rentrée',
color: null
},
'JiRt58aJXay9kfyk': {
JiRt58aJXay9kfyk: {
cloud: clouds.ELEVES_ENS,
name: 'Réunions de rentrée des Masters',
short_name: 'Masters',
@ -171,7 +173,7 @@ export const calendarTree = {
'Réunions de rentrée des Masters': {},
'Activités pour les étudiants internationaux': {}
},
'Divers': {}
Divers: {}
}
export function getSubCalendars(name, tree = calendarTree) {
@ -231,6 +233,26 @@ class Calendar {
}
}
function findLocationId(location) {
const adhocMap = {
'Amphi Jourdan': 'Amphithéâtre Jourdan',
'R2-21 (Jourdan)': 'R2-21',
'Salle Jean Ibanes (Jourdan, R1-07)': 'Salle Jean Ibanes (R1-07)',
'Salle Madeleine Rebérioux (Jourdan, R2-02)': 'Salle Madeleine Rebérioux (R2-02)',
'Salle Marcel Roncayolo (Jourdan, R2-05)': 'Salle Marcel Roncayolo (R2-05)'
};
const correctedLocation = adhocMap[location] || location;
const result = Object.entries(STATIC_LOCATIONS).find(([building, rooms]) =>
rooms.includes(correctedLocation)
)
if (result === undefined) return undefined
const [building, _] = result
return `${building}-${correctedLocation}`
}
function fcEventFromjCalEvent(cal) {
return function (evt) {
const start = new Date(evt.dtstart)
@ -249,6 +271,10 @@ function fcEventFromjCalEvent(cal) {
fcEvent.description = evt.description
fcEvent.location = evt.location || cal.default_location
if (fcEvent.location) {
fcEvent.resourceId = findLocationId(fcEvent.location)
}
if (evt.status) {
fcEvent.status = evt.status
fcEvent.classNames = [`st-${evt.status.toLowerCase()}`]

View file

@ -0,0 +1,34 @@
{
"45 rue d'Ulm": [
"Amphithéâtre Galois",
"Bibliothèque Lettres",
"Salle Histoire",
"Salle Cavaillès",
"Salle Dussane",
"Salle des Actes",
"Salle des Résistants",
"Salle Cavaillès",
"Salle Cartan",
"Salle Noether",
"Salle Bourbaki",
"Cour aux Ernests",
"Cour du NIR",
"Cour Pasteur",
"Pôt",
"Petit pôt",
"Canopée",
"K-Fêt",
"Cave d'hackENS",
"Gymnase"
],
"24 rue Lhomond": ["Salle CONF IV"],
"29 rue d'Ulm": ["Bibliothèque des sciences expérimentales", "Salle Jaurès"],
"Jourdan": [
"Bibliothèque de Jourdan",
"Salle Marcel Roncayolo (R2-05)",
"Salle Madeleine Rebérioux (R2-02)",
"Amphithéâtre Jourdan",
"R2-21",
"Salle Jean Ibanes"
]
}