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/adaptive": "^5.10.1",
"@fullcalendar/bootstrap5": "^5.10.2", "@fullcalendar/bootstrap5": "^5.10.2",
"@fullcalendar/list": "^5.10.1", "@fullcalendar/list": "^5.10.1",
"@fullcalendar/resource-timeline": "^5.10.1",
"@fullcalendar/rrule": "^5.10.1", "@fullcalendar/rrule": "^5.10.1",
"@nextcloud/cdav-library": "^1.0.0", "@nextcloud/cdav-library": "^1.0.0",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",
@ -27,6 +28,7 @@
"@fullcalendar/daygrid": "^5.10.1", "@fullcalendar/daygrid": "^5.10.1",
"@fullcalendar/timegrid": "^5.10.1", "@fullcalendar/timegrid": "^5.10.1",
"@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-node-resolve": "^11.0.0",
"dav": "^1.8.0", "dav": "^1.8.0",
"postcss": "^8.3.11", "postcss": "^8.3.11",
@ -166,6 +168,29 @@
"tslib": "^2.1.0" "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": { "node_modules/@fullcalendar/rrule": {
"version": "5.10.1", "version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/rrule/-/rrule-5.10.1.tgz", "resolved": "https://registry.npmjs.org/@fullcalendar/rrule/-/rrule-5.10.1.tgz",
@ -178,6 +203,16 @@
"rrule": "^2.6.0" "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": { "node_modules/@fullcalendar/timegrid": {
"version": "5.10.1", "version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.10.1.tgz", "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.10.1.tgz",
@ -189,6 +224,17 @@
"tslib": "^2.1.0" "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": { "node_modules/@hapi/hoek": {
"version": "9.2.1", "version": "9.2.1",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
@ -283,6 +329,18 @@
"rollup": "^2.30.0" "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": { "node_modules/@rollup/plugin-node-resolve": {
"version": "11.2.1", "version": "11.2.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",
@ -4124,6 +4182,29 @@
"tslib": "^2.1.0" "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": { "@fullcalendar/rrule": {
"version": "5.10.1", "version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/rrule/-/rrule-5.10.1.tgz", "resolved": "https://registry.npmjs.org/@fullcalendar/rrule/-/rrule-5.10.1.tgz",
@ -4133,6 +4214,16 @@
"tslib": "^2.1.0" "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": { "@fullcalendar/timegrid": {
"version": "5.10.1", "version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.10.1.tgz", "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.10.1.tgz",
@ -4144,6 +4235,17 @@
"tslib": "^2.1.0" "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": { "@hapi/hoek": {
"version": "9.2.1", "version": "9.2.1",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
@ -4216,6 +4318,15 @@
"resolve": "^1.17.0" "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": { "@rollup/plugin-node-resolve": {
"version": "11.2.1", "version": "11.2.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", "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/daygrid": "^5.10.1",
"@fullcalendar/timegrid": "^5.10.1", "@fullcalendar/timegrid": "^5.10.1",
"@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-node-resolve": "^11.0.0",
"dav": "^1.8.0", "dav": "^1.8.0",
"postcss": "^8.3.11", "postcss": "^8.3.11",
@ -33,6 +34,7 @@
"@fullcalendar/adaptive": "^5.10.1", "@fullcalendar/adaptive": "^5.10.1",
"@fullcalendar/bootstrap5": "^5.10.2", "@fullcalendar/bootstrap5": "^5.10.2",
"@fullcalendar/list": "^5.10.1", "@fullcalendar/list": "^5.10.1",
"@fullcalendar/resource-timeline": "^5.10.1",
"@fullcalendar/rrule": "^5.10.1", "@fullcalendar/rrule": "^5.10.1",
"@nextcloud/cdav-library": "^1.0.0", "@nextcloud/cdav-library": "^1.0.0",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",

View file

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

View file

@ -7,6 +7,7 @@
import rrulePlugin from '@fullcalendar/rrule'; import rrulePlugin from '@fullcalendar/rrule';
import dayGridPlugin from '@fullcalendar/daygrid'; import dayGridPlugin from '@fullcalendar/daygrid';
import listPlugin from '@fullcalendar/list'; import listPlugin from '@fullcalendar/list';
import resourceTimelinePlugin from '@fullcalendar/resource-timeline';
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';
@ -18,6 +19,8 @@
import 'bootstrap-icons/font/bootstrap-icons.css'; import 'bootstrap-icons/font/bootstrap-icons.css';
import bootstrap5Plugin from '@fullcalendar/bootstrap5'; import bootstrap5Plugin from '@fullcalendar/bootstrap5';
import ENSLocations from './static-ens-locations.json';
const event = writable(null); const event = writable(null);
let openModal = false; let openModal = false;
@ -36,12 +39,12 @@
? { ? {
left: 'title', left: 'title',
center: 'prev,today,next', center: 'prev,today,next',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' right: 'resourceTimelineDay dayGridMonth,timeGridWeek,timeGridDay,listWeek'
} }
: { : {
left: 'prev,next today', left: 'prev,next today',
center: 'title', center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' right: 'resourceTimelineDay dayGridMonth,timeGridWeek,timeGridDay,listWeek'
}; };
let calendar; let calendar;
@ -53,12 +56,24 @@
dayGridPlugin, dayGridPlugin,
rrulePlugin, rrulePlugin,
listPlugin, listPlugin,
resourceTimelinePlugin,
adaptivePlugin, adaptivePlugin,
bootstrap5Plugin bootstrap5Plugin
], ],
locale: frLocale, locale: frLocale,
allDayContent: '', allDayContent: '',
headerToolbar: headers, 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%', height: '100%',
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives', schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
nowIndicator: true, nowIndicator: true,
@ -76,7 +91,8 @@
eventSources: [], eventSources: [],
themeSystem: 'bootstrap5', themeSystem: 'bootstrap5',
nextDayThreshold: '05:00:00', nextDayThreshold: '05:00:00',
progressiveEventRendering: true progressiveEventRendering: true,
expandRows: true
}); });
const flatten = d => { const flatten = d => {

View file

@ -1,3 +1,5 @@
import STATIC_LOCATIONS from './static-ens-locations.json'
// https://stackoverflow.com/a/35970186 // https://stackoverflow.com/a/35970186
function invertColor(hex) { function invertColor(hex) {
if (hex.indexOf('#') === 0) { if (hex.indexOf('#') === 0) {
@ -92,7 +94,7 @@ const calendars = {
color: null, color: null,
initial: false initial: false
}, },
'Ekjb4kDqMMqwJXZF': { Ekjb4kDqMMqwJXZF: {
cloud: clouds.ELEVES_ENS, cloud: clouds.ELEVES_ENS,
name: 'Rentrée des départements', name: 'Rentrée des départements',
short_name: 'Dpt', short_name: 'Dpt',
@ -104,20 +106,20 @@ const calendars = {
short_name: 'Conf', short_name: 'Conf',
color: null color: null
}, },
'PnRXqeq4SsSC33FM': { PnRXqeq4SsSC33FM: {
cloud: clouds.ELEVES_ENS, cloud: clouds.ELEVES_ENS,
name: 'Visites de bibliothèques', name: 'Visites de bibliothèques',
short_name: 'Bibli', short_name: 'Bibli',
initial: false, initial: false,
color: null color: null
}, },
'NWPtiEiz62LTtjo2': { NWPtiEiz62LTtjo2: {
cloud: clouds.ELEVES_ENS, cloud: clouds.ELEVES_ENS,
name: 'Amphis de rentrée', name: 'Amphis de rentrée',
short_name: 'Prés. de rentrée', short_name: 'Prés. de rentrée',
color: null color: null
}, },
'JiRt58aJXay9kfyk': { JiRt58aJXay9kfyk: {
cloud: clouds.ELEVES_ENS, cloud: clouds.ELEVES_ENS,
name: 'Réunions de rentrée des Masters', name: 'Réunions de rentrée des Masters',
short_name: 'Masters', short_name: 'Masters',
@ -171,7 +173,7 @@ export const calendarTree = {
'Réunions de rentrée des Masters': {}, 'Réunions de rentrée des Masters': {},
'Activités pour les étudiants internationaux': {} 'Activités pour les étudiants internationaux': {}
}, },
'Divers': {} Divers: {}
} }
export function getSubCalendars(name, tree = calendarTree) { 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) { function fcEventFromjCalEvent(cal) {
return function (evt) { return function (evt) {
const start = new Date(evt.dtstart) const start = new Date(evt.dtstart)
@ -249,6 +271,10 @@ function fcEventFromjCalEvent(cal) {
fcEvent.description = evt.description fcEvent.description = evt.description
fcEvent.location = evt.location || cal.default_location fcEvent.location = evt.location || cal.default_location
if (fcEvent.location) {
fcEvent.resourceId = findLocationId(fcEvent.location)
}
if (evt.status) { if (evt.status) {
fcEvent.status = evt.status fcEvent.status = evt.status
fcEvent.classNames = [`st-${evt.status.toLowerCase()}`] 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"
]
}