Split out iPad-specific wall-display
configuration
This commit is contained in:
parent
7bb3bdcfdd
commit
ed1392ead4
84
src/common.ts
Normal file
84
src/common.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { Calendar, CalendarOptions } from '@fullcalendar/core';
|
||||||
|
import iCalendarPlugin from '@fullcalendar/icalendar';
|
||||||
|
import resourceTimeGridPlugin from '@fullcalendar/resource-timegrid';
|
||||||
|
|
||||||
|
import { unique_colors } from 'unique-colors';
|
||||||
|
|
||||||
|
const calendars: { [key: string]: string } = {
|
||||||
|
computer_lab: '6mmjp85e4732ru6skf1dda54ls@group.calendar.google.com',
|
||||||
|
electronics: '1g8atbdschshrg2inf162rcqt4@group.calendar.google.com',
|
||||||
|
wood_shop: '4unv3ia1n9mc9u31n2n5lv8nd8@group.calendar.google.com',
|
||||||
|
fiber_arts_studio: '7gbndciog37ge0hd8ug33ml70k@group.calendar.google.com',
|
||||||
|
jewelry_studio: 'l0dl2jq3vhbi9f4lfmaf5negc0@group.calendar.google.com',
|
||||||
|
metal_shop: 'a4p97kiiafatqdr52c3a0cpre0@group.calendar.google.com',
|
||||||
|
room_reservations: 'f4ro53uklj2u6pr0se7ucskm6g@group.calendar.google.com',
|
||||||
|
};
|
||||||
|
|
||||||
|
const colors: string[] = unique_colors(Object.keys(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',
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function main(
|
||||||
|
calendarOptions: CalendarOptions,
|
||||||
|
allTools: boolean = false
|
||||||
|
) {
|
||||||
|
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 (allTools) {
|
||||||
|
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);
|
||||||
|
}
|
106
src/index.ts
106
src/index.ts
@ -1,107 +1,5 @@
|
|||||||
import 'core-js/stable/url';
|
import { common_calendarOptions, main } from './common';
|
||||||
import 'core-js/stable/function';
|
|
||||||
|
|
||||||
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 resourceTimeGridPlugin from '@fullcalendar/resource-timegrid';
|
|
||||||
|
|
||||||
import { unique_colors } from 'unique-colors';
|
|
||||||
|
|
||||||
import './index.html';
|
import './index.html';
|
||||||
import './index.css';
|
|
||||||
|
|
||||||
const calendars: { [key: string]: string } = {
|
main(common_calendarOptions);
|
||||||
computer_lab: '6mmjp85e4732ru6skf1dda54ls@group.calendar.google.com',
|
|
||||||
electronics: '1g8atbdschshrg2inf162rcqt4@group.calendar.google.com',
|
|
||||||
wood_shop: '4unv3ia1n9mc9u31n2n5lv8nd8@group.calendar.google.com',
|
|
||||||
fiber_arts_studio: '7gbndciog37ge0hd8ug33ml70k@group.calendar.google.com',
|
|
||||||
jewelry_studio: 'l0dl2jq3vhbi9f4lfmaf5negc0@group.calendar.google.com',
|
|
||||||
metal_shop: 'a4p97kiiafatqdr52c3a0cpre0@group.calendar.google.com',
|
|
||||||
room_reservations: 'f4ro53uklj2u6pr0se7ucskm6g@group.calendar.google.com',
|
|
||||||
};
|
|
||||||
|
|
||||||
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, resourceTimeGridPlugin],
|
|
||||||
allDaySlot: false,
|
|
||||||
nowIndicator: true,
|
|
||||||
headerToolbar: { start: '', center: 'title', end: '' },
|
|
||||||
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();
|
|
||||||
|
13
src/wall-display.html
Normal file
13
src/wall-display.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!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>
|
34
src/wall-display.ts
Normal file
34
src/wall-display.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
main(calendarOptions, !toolFilter);
|
@ -1,8 +1,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
const common = {
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
entry: './src/index.ts',
|
|
||||||
devServer: {
|
devServer: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/calendar': {
|
'/calendar': {
|
||||||
@ -11,7 +10,53 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/i,
|
||||||
|
use: ['style-loader', 'css-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.html$/i,
|
||||||
|
use: {
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
name: '[name].[ext]',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
devtool: 'source-map',
|
devtool: 'source-map',
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.tsx', '.ts', '.js'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
...common,
|
||||||
|
name: 'default',
|
||||||
|
entry: './src/index.ts',
|
||||||
|
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: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
@ -24,26 +69,12 @@ module.exports = {
|
|||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: ['babel-loader', 'ts-loader'],
|
use: ['babel-loader', 'ts-loader'],
|
||||||
},
|
},
|
||||||
{
|
...common.module.rules,
|
||||||
test: /\.css$/i,
|
|
||||||
use: ['style-loader', 'css-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\/index.html$/i,
|
|
||||||
use: {
|
|
||||||
loader: 'file-loader',
|
|
||||||
options: {
|
|
||||||
name: '[name].[ext]',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
resolve: {
|
|
||||||
extensions: ['.tsx', '.ts', '.js'],
|
|
||||||
},
|
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
filename: 'bundle.js',
|
filename: 'bundle-wall-display.js',
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user