Compare commits
No commits in common. "0eb7df61a8239e25c9c17fdcbcef96eec25f2361" and "2868fc3324e0716a076b8a9cf5b9ee7070e4ef55" have entirely different histories.
0eb7df61a8
...
2868fc3324
@ -28,13 +28,11 @@
|
|||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@fullcalendar/core": "^5.11.3",
|
"@fullcalendar/core": "^5.11.3",
|
||||||
"@fullcalendar/icalendar": "^5.11.3",
|
"@fullcalendar/icalendar": "^5.11.3",
|
||||||
"@fullcalendar/resource-common": "^5.11.3",
|
"@fullcalendar/luxon2": "^5.11.3",
|
||||||
"@fullcalendar/resource-timegrid": "^5.11.3",
|
"@fullcalendar/resource-timegrid": "^5.11.3",
|
||||||
"@fullcalendar/resource-timeline": "^5.11.3",
|
|
||||||
"@fullcalendar/timegrid": "^5.11.3",
|
|
||||||
"core-js": "^3.25.5",
|
"core-js": "^3.25.5",
|
||||||
"intl": "^1.2.5",
|
"intl": "^1.2.5",
|
||||||
"preact": "^10.11.1",
|
"luxon": "^3.0.4",
|
||||||
"unique-colors": "^1.0.1"
|
"unique-colors": "^1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,15 @@ specifiers:
|
|||||||
'@babel/runtime': ^7.19.0
|
'@babel/runtime': ^7.19.0
|
||||||
'@fullcalendar/core': ^5.11.3
|
'@fullcalendar/core': ^5.11.3
|
||||||
'@fullcalendar/icalendar': ^5.11.3
|
'@fullcalendar/icalendar': ^5.11.3
|
||||||
'@fullcalendar/resource-common': ^5.11.3
|
'@fullcalendar/luxon2': ^5.11.3
|
||||||
'@fullcalendar/resource-timegrid': ^5.11.3
|
'@fullcalendar/resource-timegrid': ^5.11.3
|
||||||
'@fullcalendar/resource-timeline': ^5.11.3
|
|
||||||
'@fullcalendar/timegrid': ^5.11.3
|
|
||||||
'@types/intl': ^1.2.0
|
'@types/intl': ^1.2.0
|
||||||
babel-loader: ^8.2.5
|
babel-loader: ^8.2.5
|
||||||
core-js: ^3.25.5
|
core-js: ^3.25.5
|
||||||
css-loader: ^6.7.1
|
css-loader: ^6.7.1
|
||||||
file-loader: ^6.2.0
|
file-loader: ^6.2.0
|
||||||
intl: ^1.2.5
|
intl: ^1.2.5
|
||||||
preact: ^10.11.1
|
luxon: ^3.0.4
|
||||||
style-loader: ^3.3.1
|
style-loader: ^3.3.1
|
||||||
ts-loader: ^9.4.1
|
ts-loader: ^9.4.1
|
||||||
typescript: ^4.8.4
|
typescript: ^4.8.4
|
||||||
@ -30,13 +28,11 @@ dependencies:
|
|||||||
'@babel/runtime': 7.19.0
|
'@babel/runtime': 7.19.0
|
||||||
'@fullcalendar/core': 5.11.3
|
'@fullcalendar/core': 5.11.3
|
||||||
'@fullcalendar/icalendar': 5.11.3
|
'@fullcalendar/icalendar': 5.11.3
|
||||||
'@fullcalendar/resource-common': 5.11.3
|
'@fullcalendar/luxon2': 5.11.3_luxon@3.0.4
|
||||||
'@fullcalendar/resource-timegrid': 5.11.3
|
'@fullcalendar/resource-timegrid': 5.11.3
|
||||||
'@fullcalendar/resource-timeline': 5.11.3
|
|
||||||
'@fullcalendar/timegrid': 5.11.3
|
|
||||||
core-js: 3.25.5
|
core-js: 3.25.5
|
||||||
intl: 1.2.5
|
intl: 1.2.5
|
||||||
preact: 10.11.1
|
luxon: 3.0.4
|
||||||
unique-colors: 1.0.1
|
unique-colors: 1.0.1
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@ -1254,6 +1250,16 @@ packages:
|
|||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@fullcalendar/luxon2/5.11.3_luxon@3.0.4:
|
||||||
|
resolution: {integrity: sha512-facQYF87ovrw1dOaEDG/oQevV4sgrTWSAsV43upIY8FLKkgVQYT3JR6/aG99CL9ceMmOxdBiwF5pQEsVuGmb4A==}
|
||||||
|
peerDependencies:
|
||||||
|
luxon: ^2.0.0
|
||||||
|
dependencies:
|
||||||
|
'@fullcalendar/common': 5.11.3
|
||||||
|
luxon: 3.0.4
|
||||||
|
tslib: 2.4.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@fullcalendar/premium-common/5.11.3:
|
/@fullcalendar/premium-common/5.11.3:
|
||||||
resolution: {integrity: sha512-fvMU8OmIReBXoY1iOkRO+zGwbUHA1YB9xtkYbSL3ZeMQ008P0Lj6ar7Jv/lB5XDRgh50TRfFIgfDjdszESAc4w==}
|
resolution: {integrity: sha512-fvMU8OmIReBXoY1iOkRO+zGwbUHA1YB9xtkYbSL3ZeMQ008P0Lj6ar7Jv/lB5XDRgh50TRfFIgfDjdszESAc4w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1290,25 +1296,6 @@ packages:
|
|||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@fullcalendar/resource-timeline/5.11.3:
|
|
||||||
resolution: {integrity: sha512-iYIXZPfqtiN/qizpGDCYlFVssdDTZv6lU/5N1v0FzvGMZfU2LkHLhCkouQeBQHja8ZCbJisy4sK3kUR9mXh2cg==}
|
|
||||||
dependencies:
|
|
||||||
'@fullcalendar/common': 5.11.3
|
|
||||||
'@fullcalendar/premium-common': 5.11.3
|
|
||||||
'@fullcalendar/resource-common': 5.11.3
|
|
||||||
'@fullcalendar/scrollgrid': 5.11.3
|
|
||||||
'@fullcalendar/timeline': 5.11.3
|
|
||||||
tslib: 2.4.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@fullcalendar/scrollgrid/5.11.3:
|
|
||||||
resolution: {integrity: sha512-JTWDmejPmit65pCoQafUPeplI2+iogXG/3TNbusXMSWYaaMrINHDQiBZ/6EAt46hO2eWyEglmgS0BwVXZNSlGg==}
|
|
||||||
dependencies:
|
|
||||||
'@fullcalendar/common': 5.11.3
|
|
||||||
'@fullcalendar/premium-common': 5.11.3
|
|
||||||
tslib: 2.4.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@fullcalendar/timegrid/5.11.3:
|
/@fullcalendar/timegrid/5.11.3:
|
||||||
resolution: {integrity: sha512-SjIj2ZQ7nTyL1RxZkCPvNbuUQ0xHT+gfYJdUL3FT4bPjPJCxWtQ2CL8hxaeNmVozYYuy0yrGTW5Oup2+9IplbA==}
|
resolution: {integrity: sha512-SjIj2ZQ7nTyL1RxZkCPvNbuUQ0xHT+gfYJdUL3FT4bPjPJCxWtQ2CL8hxaeNmVozYYuy0yrGTW5Oup2+9IplbA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1317,15 +1304,6 @@ packages:
|
|||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@fullcalendar/timeline/5.11.3:
|
|
||||||
resolution: {integrity: sha512-nbMJ2gG9mLGUZgGUB2O726u3D8EFxJkZsKA/O1053j5QiQ7C8Wca1rh8UX+bed/s+wmkWwKV5pB0CiOax4f3gQ==}
|
|
||||||
dependencies:
|
|
||||||
'@fullcalendar/common': 5.11.3
|
|
||||||
'@fullcalendar/premium-common': 5.11.3
|
|
||||||
'@fullcalendar/scrollgrid': 5.11.3
|
|
||||||
tslib: 2.4.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@jridgewell/gen-mapping/0.1.1:
|
/@jridgewell/gen-mapping/0.1.1:
|
||||||
resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==}
|
resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
@ -2789,6 +2767,11 @@ packages:
|
|||||||
yallist: 4.0.0
|
yallist: 4.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/luxon/3.0.4:
|
||||||
|
resolution: {integrity: sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/make-dir/3.1.0:
|
/make-dir/3.1.0:
|
||||||
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
141
src/common.ts
141
src/common.ts
@ -1,141 +0,0 @@
|
|||||||
import { Calendar, CalendarOptions } from '@fullcalendar/core';
|
|
||||||
import iCalendarPlugin from '@fullcalendar/icalendar';
|
|
||||||
import resourceTimeGridPlugin from '@fullcalendar/resource-timegrid';
|
|
||||||
|
|
||||||
import { unique_colors } from 'unique-colors';
|
|
||||||
|
|
||||||
interface Shop {
|
|
||||||
calendar?: string;
|
|
||||||
children?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const shops: { [key: string]: Shop } = {
|
|
||||||
Cafe: {}, // same calendar as mezzanine
|
|
||||||
'Classroom / Computer Lab': {
|
|
||||||
calendar: '6mmjp85e4732ru6skf1dda54ls@group.calendar.google.com',
|
|
||||||
children: ['Printer, Canon iPF8400S 44" 8-Color/Pigment'],
|
|
||||||
},
|
|
||||||
'Digital Fabrication and Electronics Lab': {
|
|
||||||
calendar: '1g8atbdschshrg2inf162rcqt4@group.calendar.google.com',
|
|
||||||
children: [
|
|
||||||
'3d printer, Lulzbot Taz 6',
|
|
||||||
'3d printer, Lulzbot Mini',
|
|
||||||
'Laser Cutter, GLS Hybrid',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'Fiber Arts Studio': {
|
|
||||||
calendar: '7gbndciog37ge0hd8ug33ml70k@group.calendar.google.com',
|
|
||||||
children: ['Mid Arm, Brother DQLT15'],
|
|
||||||
},
|
|
||||||
'Jewelry Studio': {
|
|
||||||
calendar: 'l0dl2jq3vhbi9f4lfmaf5negc0@group.calendar.google.com',
|
|
||||||
},
|
|
||||||
'Metal Shop': {
|
|
||||||
calendar: 'a4p97kiiafatqdr52c3a0cpre0@group.calendar.google.com',
|
|
||||||
children: [
|
|
||||||
'Plasma Cutter, Hypertherm Powermax85',
|
|
||||||
'MIG Welder, Miller 210',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Mezzanine: {
|
|
||||||
calendar: 'f4ro53uklj2u6pr0se7ucskm6g@group.calendar.google.com',
|
|
||||||
},
|
|
||||||
'Wood Shop': {
|
|
||||||
calendar: '4unv3ia1n9mc9u31n2n5lv8nd8@group.calendar.google.com',
|
|
||||||
children: [
|
|
||||||
'ShopBot, PRSstandard 96-48-8, w/2.2hp Spindle',
|
|
||||||
'Table Saw, SawStop 3HP 10"',
|
|
||||||
'Planer, Powermatic 20"',
|
|
||||||
'Jointer, Powermatic 8"',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function extract_calendars(shops: { [key: string]: Shop }): string[] {
|
|
||||||
return Object.values(shops)
|
|
||||||
.map((shop) => shop.calendar)
|
|
||||||
.filter((calendar) => calendar !== undefined) as string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const calendars: string[] = extract_calendars(shops);
|
|
||||||
|
|
||||||
const colors: string[] = unique_colors(calendars.length);
|
|
||||||
|
|
||||||
export const common_calendarOptions: CalendarOptions = {
|
|
||||||
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
|
|
||||||
plugins: [iCalendarPlugin, resourceTimeGridPlugin],
|
|
||||||
allDaySlot: false,
|
|
||||||
nowIndicator: true,
|
|
||||||
headerToolbar: { start: '', center: 'title', end: '' },
|
|
||||||
initialView: 'resourceTimeGrid',
|
|
||||||
height: 'auto',
|
|
||||||
slotMinTime: '8:00',
|
|
||||||
slotMaxTime: '22:00',
|
|
||||||
displayEventTime: true,
|
|
||||||
businessHours: {
|
|
||||||
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
|
|
||||||
startTime: '10:00',
|
|
||||||
endTime: '21:00',
|
|
||||||
},
|
|
||||||
slotLabelFormat: {
|
|
||||||
hour: 'numeric',
|
|
||||||
minute: '2-digit',
|
|
||||||
hour12: false,
|
|
||||||
},
|
|
||||||
eventTimeFormat: {
|
|
||||||
hour: 'numeric',
|
|
||||||
minute: '2-digit',
|
|
||||||
hour12: false,
|
|
||||||
},
|
|
||||||
resources: Object.entries(shops).map(([shop_name, shop]) => {
|
|
||||||
return {
|
|
||||||
id: shop_name,
|
|
||||||
title: shop_name,
|
|
||||||
extendedProps: {
|
|
||||||
calendar: shop.calendar,
|
|
||||||
},
|
|
||||||
children: shop.children?.map((tool) => {
|
|
||||||
return {
|
|
||||||
id: tool,
|
|
||||||
title: tool,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export function main(
|
|
||||||
calendarOptions: CalendarOptions,
|
|
||||||
allTools: boolean = false
|
|
||||||
) {
|
|
||||||
const calendarEl = document.getElementById('calendar');
|
|
||||||
const calendar = new Calendar(calendarEl!, calendarOptions);
|
|
||||||
calendars.forEach((id, idx) =>
|
|
||||||
calendar.addEventSource({
|
|
||||||
url: '/calendar/ical/' + id + '/public/basic.ics',
|
|
||||||
format: 'ics',
|
|
||||||
color: colors[idx],
|
|
||||||
eventDataTransform: (eventData) => {
|
|
||||||
// clear the url to prevent clicking on the event
|
|
||||||
delete eventData.url;
|
|
||||||
|
|
||||||
const match = eventData?.title?.match(/([^\/]*) \| ([^-]*) - (.*)/);
|
|
||||||
if (match) {
|
|
||||||
const [, member, shop, tool] = match;
|
|
||||||
eventData.title = `${member}`;
|
|
||||||
eventData.resourceId = tool;
|
|
||||||
if (allTools) {
|
|
||||||
if (!calendar.getResourceById(tool)) {
|
|
||||||
calendar.addResource({ id: tool, title: tool }, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return eventData;
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
calendar.render();
|
|
||||||
|
|
||||||
return calendar;
|
|
||||||
}
|
|
170
src/index.ts
170
src/index.ts
@ -1,73 +1,109 @@
|
|||||||
import '@fullcalendar/core';
|
import 'core-js/stable/url';
|
||||||
import { CalendarOptions, EventContentArg } from '@fullcalendar/core';
|
import 'core-js/stable/function';
|
||||||
import { ResourceLabelContentArg } from '@fullcalendar/resource-common';
|
|
||||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
|
||||||
import resourceTimelinePlugin from '@fullcalendar/resource-timeline';
|
|
||||||
import { createElement } from 'preact';
|
|
||||||
|
|
||||||
import { common_calendarOptions, main } from './common';
|
import Intl from 'intl';
|
||||||
|
import 'intl/locale-data/jsonp/en.js';
|
||||||
|
window.Intl = Intl;
|
||||||
|
|
||||||
|
import { Calendar, CalendarOptions } from '@fullcalendar/core';
|
||||||
|
import iCalendarPlugin from '@fullcalendar/icalendar';
|
||||||
|
import luxon2Plugin from '@fullcalendar/luxon2';
|
||||||
|
import resourceTimeGridPlugin from '@fullcalendar/resource-timegrid';
|
||||||
|
|
||||||
|
import { unique_colors } from 'unique-colors';
|
||||||
|
|
||||||
import './index.html';
|
import './index.html';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
const calendarOptions: CalendarOptions = {
|
const calendars: { [key: string]: string } = {
|
||||||
...common_calendarOptions,
|
computer_lab: '6mmjp85e4732ru6skf1dda54ls@group.calendar.google.com',
|
||||||
plugins: [
|
electronics: '1g8atbdschshrg2inf162rcqt4@group.calendar.google.com',
|
||||||
...(common_calendarOptions.plugins ?? []),
|
wood_shop: '4unv3ia1n9mc9u31n2n5lv8nd8@group.calendar.google.com',
|
||||||
timeGridPlugin,
|
fiber_arts_studio: '7gbndciog37ge0hd8ug33ml70k@group.calendar.google.com',
|
||||||
resourceTimelinePlugin,
|
jewelry_studio: 'l0dl2jq3vhbi9f4lfmaf5negc0@group.calendar.google.com',
|
||||||
],
|
metal_shop: 'a4p97kiiafatqdr52c3a0cpre0@group.calendar.google.com',
|
||||||
headerToolbar: {
|
room_reservations: 'f4ro53uklj2u6pr0se7ucskm6g@group.calendar.google.com',
|
||||||
start: 'resourceTimeline,timeGridWeek',
|
|
||||||
center: 'title',
|
|
||||||
end: 'prev,next today',
|
|
||||||
},
|
|
||||||
buttonText: {
|
|
||||||
resourceTimeline: 'day',
|
|
||||||
},
|
|
||||||
initialView: 'resourceTimeline',
|
|
||||||
resourceLabelContent: (
|
|
||||||
arg: ResourceLabelContentArg,
|
|
||||||
h: typeof createElement
|
|
||||||
) => {
|
|
||||||
const calendar = arg.resource.extendedProps.calendar;
|
|
||||||
if (calendar) {
|
|
||||||
const embed_link = `https://calendar.google.com/calendar/embed?ctz=America%2FNew_York&src=${calendar}`;
|
|
||||||
const ical_link = `https://calendar.google.com/calendar/ical/${calendar}/public/basic.ics`;
|
|
||||||
return h(
|
|
||||||
'span',
|
|
||||||
null,
|
|
||||||
h('a', { href: embed_link }, arg.resource.title),
|
|
||||||
' ',
|
|
||||||
h('a', { href: ical_link }, ' [iCal 📅]')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
eventContent: (arg: EventContentArg, h: typeof createElement) => {
|
|
||||||
if (arg.view.type != 'resourceTimeline') {
|
|
||||||
let resources = arg.event
|
|
||||||
.getResources()
|
|
||||||
.map((resource) => resource.id.trim())
|
|
||||||
.join('; ');
|
|
||||||
return h(
|
|
||||||
'div',
|
|
||||||
{ class: 'fc-event-main' },
|
|
||||||
h(
|
|
||||||
'div',
|
|
||||||
{ class: 'fc-event-main-frame' },
|
|
||||||
h('div', { class: 'fc-event-time' }, arg.timeText),
|
|
||||||
h(
|
|
||||||
'div',
|
|
||||||
{ class: 'fc-event-title-container' },
|
|
||||||
h(
|
|
||||||
'div',
|
|
||||||
{ class: 'fc-event-title fc-sticky' },
|
|
||||||
`${resources}: ${arg.event.title}`
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
main(calendarOptions, true);
|
const colors: string[] = unique_colors(Object.keys(calendars).length);
|
||||||
|
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const toolFilter: string[] | undefined = urlParams.get('tool')?.split(';');
|
||||||
|
|
||||||
|
const calendarOptions: CalendarOptions = {
|
||||||
|
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
|
||||||
|
plugins: [iCalendarPlugin, luxon2Plugin, resourceTimeGridPlugin],
|
||||||
|
allDaySlot: false,
|
||||||
|
nowIndicator: true,
|
||||||
|
headerToolbar: { start: '', center: 'title', end: '' },
|
||||||
|
titleFormat: "'Reservations for ' cccc LLLL d, yyyy",
|
||||||
|
initialView: 'resourceTimeGrid',
|
||||||
|
height: 'auto',
|
||||||
|
slotMinTime: '8:00',
|
||||||
|
slotMaxTime: '22:00',
|
||||||
|
businessHours: {
|
||||||
|
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
|
||||||
|
startTime: '10:00',
|
||||||
|
endTime: '21:00',
|
||||||
|
},
|
||||||
|
slotLabelFormat: {
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: '2-digit',
|
||||||
|
hour12: false,
|
||||||
|
},
|
||||||
|
eventTimeFormat: {
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: '2-digit',
|
||||||
|
hour12: false,
|
||||||
|
},
|
||||||
|
resources: toolFilter
|
||||||
|
? toolFilter.map((tool) => {
|
||||||
|
return {
|
||||||
|
id: tool,
|
||||||
|
title: tool,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
const calendarEl = document.getElementById('calendar');
|
||||||
|
const calendar = new Calendar(calendarEl!, calendarOptions);
|
||||||
|
Object.values(calendars).forEach((id, idx) =>
|
||||||
|
calendar.addEventSource({
|
||||||
|
url: '/calendar/ical/' + id + '/public/basic.ics',
|
||||||
|
format: 'ics',
|
||||||
|
color: colors[idx],
|
||||||
|
eventDataTransform: (eventData) => {
|
||||||
|
// clear the url to prevent clicking on the event
|
||||||
|
delete eventData.url;
|
||||||
|
|
||||||
|
const match = eventData?.title?.match(/([^\/]*) \| ([^-]*) - (.*)/);
|
||||||
|
if (match) {
|
||||||
|
const [, member, shop, tool] = match;
|
||||||
|
eventData.title = `${member}`;
|
||||||
|
eventData.resourceId = tool;
|
||||||
|
if (!toolFilter) {
|
||||||
|
calendar.addResource({ id: tool, title: tool }, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eventData;
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
calendar.render();
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
calendar.refetchEvents();
|
||||||
|
calendar.today();
|
||||||
|
}
|
||||||
|
|
||||||
|
// refresh data every five minutes
|
||||||
|
window.setInterval(refresh, 5 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.addEventListener('touchmove', (e) => e.preventDefault(), {
|
||||||
|
passive: false,
|
||||||
|
});
|
||||||
|
main();
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
.fc .fc-toolbar.fc-header-toolbar {
|
|
||||||
/* Save some vertical space */
|
|
||||||
margin-bottom: 0;
|
|
||||||
/* iOS 8 Safari doesn't support flexbox */
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fix rendering of now indicators on iOS 8 Safari */
|
|
||||||
.fc .fc-timegrid-now-indicator-container {
|
|
||||||
overflow: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc .fc-timegrid-now-indicator-line {
|
|
||||||
border-color: rgba(255, 0, 0, 0.4);
|
|
||||||
border-top-width: 1px;
|
|
||||||
border-top-color: red;
|
|
||||||
border-bottom-width: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc-direction-ltr .fc-timegrid-now-indicator-arrow {
|
|
||||||
border-width: 10px 0 10px 11px;
|
|
||||||
margin-top: -10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc .fc-timegrid-slots {
|
|
||||||
/* Fix timegrid lines rendering over events on iOS 5.1.1 */
|
|
||||||
z-index: 0 !important;
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<meta name="viewport" content="initial-scale=1, user-scalable=no" />
|
|
||||||
<title>Tool Reservations</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="calendar"></div>
|
|
||||||
<script src="bundle-wall-display.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,42 +0,0 @@
|
|||||||
import 'core-js/stable/url';
|
|
||||||
import 'core-js/stable/function';
|
|
||||||
|
|
||||||
import Intl from 'intl';
|
|
||||||
import 'intl/locale-data/jsonp/en.js';
|
|
||||||
window.Intl = Intl;
|
|
||||||
|
|
||||||
import { CalendarOptions } from '@fullcalendar/core';
|
|
||||||
|
|
||||||
import { common_calendarOptions, main } from './common';
|
|
||||||
|
|
||||||
import './wall-display.html';
|
|
||||||
import './ios-fixes.css';
|
|
||||||
|
|
||||||
document.body.addEventListener('touchmove', (e) => e.preventDefault(), {
|
|
||||||
passive: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
|
||||||
const toolFilter: string[] | undefined = urlParams.get('tool')?.split(';');
|
|
||||||
|
|
||||||
const calendarOptions: CalendarOptions = {
|
|
||||||
...common_calendarOptions,
|
|
||||||
resources: toolFilter
|
|
||||||
? toolFilter.map((tool) => {
|
|
||||||
return {
|
|
||||||
id: tool,
|
|
||||||
title: tool,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const calendar = main(calendarOptions, !toolFilter);
|
|
||||||
|
|
||||||
function refresh() {
|
|
||||||
calendar.refetchEvents();
|
|
||||||
calendar.today();
|
|
||||||
}
|
|
||||||
|
|
||||||
// refresh data every five minutes
|
|
||||||
window.setInterval(refresh, 5 * 60 * 1000);
|
|
@ -1,15 +1,35 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const common = {
|
module.exports = {
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
|
entry: './src/index.ts',
|
||||||
|
devServer: {
|
||||||
|
proxy: {
|
||||||
|
'/calendar': {
|
||||||
|
target: 'https://calendar.google.com',
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
devtool: 'source-map',
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.m?js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: ['babel-loader', 'ts-loader'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/i,
|
test: /\.css$/i,
|
||||||
use: ['style-loader', 'css-loader'],
|
use: ['style-loader', 'css-loader'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.html$/i,
|
test: /\/index.html$/i,
|
||||||
use: {
|
use: {
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
options: {
|
options: {
|
||||||
@ -19,63 +39,11 @@ const common = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
devtool: 'source-map',
|
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.tsx', '.ts', '.js'],
|
extensions: ['.tsx', '.ts', '.js'],
|
||||||
},
|
},
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
filename: 'bundle.js',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
{
|
|
||||||
...common,
|
|
||||||
name: 'default',
|
|
||||||
entry: './src/index.ts',
|
|
||||||
devServer: {
|
|
||||||
allowedHosts: 'all',
|
|
||||||
proxy: {
|
|
||||||
'/calendar': {
|
|
||||||
target: 'https://calendar.google.com',
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.tsx?$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
use: ['ts-loader'],
|
|
||||||
},
|
|
||||||
...common.module.rules,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: path.resolve(__dirname, 'dist'),
|
|
||||||
filename: 'bundle.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...common,
|
|
||||||
name: 'wall-display',
|
|
||||||
entry: './src/wall-display.ts',
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.m?js$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'babel-loader',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.tsx?$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
use: ['babel-loader', 'ts-loader'],
|
|
||||||
},
|
|
||||||
...common.module.rules,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: path.resolve(__dirname, 'dist'),
|
|
||||||
filename: 'bundle-wall-display.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
Loading…
Reference in New Issue
Block a user