Drop dependency on Vue and use Webpack instead of Vite

Couldn't get Vue/Vite to transpile for ios 8 correctly, and I don't
really need it anyway...
This commit is contained in:
Adam Goldsmith 2021-11-15 16:43:54 -05:00
parent a9b3c5f1f7
commit d4dbaaf344
7 changed files with 166 additions and 133 deletions

10
babel.config.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
plugins: ['@babel/plugin-transform-runtime'],
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3,
},
],
],
};

View File

@ -1,27 +1,34 @@
{ {
"browserslist": [
"defaults",
"ios 8.4"
],
"scripts": { "scripts": {
"start": "npm run dev", "start": "npm run serve",
"dev": "vite", "build": "webpack build",
"build": "vue-tsc --noEmit && vite build", "serve": "webpack serve"
"serve": "vite preview"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.16.0",
"@babel/preset-env": "^7.16.0",
"@types/intl": "^1.2.0", "@types/intl": "^1.2.0",
"@vitejs/plugin-legacy": "^1.6.2", "babel-loader": "^8.2.3",
"@vitejs/plugin-vue": "^1.9.4", "css-loader": "^6.5.1",
"sass": "^1.23.1", "style-loader": "^3.3.1",
"ts-loader": "^9.2.6",
"typescript": "^4.2.3", "typescript": "^4.2.3",
"vite": "^2.6.13", "webpack": "^5.64.0",
"vue-tsc": "^0.29.4" "webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0"
}, },
"dependencies": { "dependencies": {
"@fullcalendar/core": "^5.10.0", "@fullcalendar/core": "^5.10.0",
"@fullcalendar/icalendar": "^5.10.1", "@fullcalendar/icalendar": "^5.10.1",
"@fullcalendar/timegrid": "^5.6.0", "@fullcalendar/timegrid": "^5.6.0",
"@fullcalendar/vue3": "^5.10.0", "core-js": "^3.19.1",
"ical.js": "github:ekreative/ical.js#var-ical", "ical.js": "github:ekreative/ical.js#var-ical",
"intl": "^1.2.5", "intl": "^1.2.5",
"unique-colors": "^1.0.1", "unique-colors": "^1.0.1"
"vue": "^3.2.20"
} }
} }

View File

@ -5,7 +5,7 @@
<title>Tool Reservations</title> <title>Tool Reservations</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="calendar"></div>
<script type="module" src="/src/index.ts"></script> <script src="bundle.js"></script>
</body> </body>
</html> </html>

View File

@ -1,94 +0,0 @@
<template>
<FullCalendar ref="calendar" :options="calendarOptions"> </FullCalendar>
</template>
<script setup lang="ts">
import { ref, Ref } from 'vue';
import {unique_colors} from 'unique-colors';
import '@fullcalendar/core/vdom'; // solve problem with Vite
import FullCalendar, {
EventInput,
Calendar,
CalendarOptions,
} from '@fullcalendar/vue3';
import timeGridPlugin from '@fullcalendar/timegrid';
import dayGridPlugin from '@fullcalendar/daygrid';
import iCalendarPlugin from '@fullcalendar/icalendar';
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);
const calendarOptions: CalendarOptions = {
plugins: [timeGridPlugin, dayGridPlugin, iCalendarPlugin],
allDaySlot: false,
nowIndicator: true,
initialView: 'timeGridWeek',
height: 'auto',
slotMinTime: '8:00',
slotMaxTime: '22:00',
businessHours: {
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
startTime: '10:00',
endTime: '21:00',
},
eventSources: Object.values(calendars).map((id, idx) => {
return {
url: "/calendar/ical/" + id + "/public/basic.ics",
format: "ics",
color: colors[idx],
eventDataTransform: eventDataTransform,
};
}),
slotLabelFormat: {
hour: 'numeric',
minute: '2-digit',
hour12: false,
},
eventTimeFormat: {
hour: 'numeric',
minute: '2-digit',
hour12: false,
},
};
const urlParams = new URLSearchParams(window.location.search);
const toolFilter: string | null = urlParams.get('tool');
const calendar_ref: Ref<InstanceType<typeof FullCalendar> | null> = ref(null);
// refresh data every five minutes
window.setInterval(refresh, 5 * 60 * 1000);
function refresh() {
if (calendar_ref.value !== null) {
const calendar = calendar_ref.value.getApi() as Calendar;
calendar.refetchEvents();
}
}
function eventDataTransform(eventData: EventInput): EventInput | false {
// 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 = `${tool} - ${member}`;
if (toolFilter === null || tool.includes(toolFilter)) {
return eventData;
}
}
return false;
}
</script>
<style lang="scss"></style>

View File

@ -1,7 +1,90 @@
import 'core-js/modules/es.object.entries'; // TODO: could probably be a dynamic import
import intl from 'intl';
import 'intl/locale-data/jsonp/en.js';
import * as Vue from 'vue'; if (!window.Intl) {
// No `Intl`, so use and load the polyfill.
window.Intl = intl;
}
import App from './App.vue'; import { EventInput, Calendar, CalendarOptions } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import iCalendarPlugin from '@fullcalendar/icalendar';
const app = Vue.createApp(App).mount('#app'); 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);
const urlParams = new URLSearchParams(window.location.search);
const toolFilter: string | null = urlParams.get('tool');
function eventDataTransform(eventData: EventInput): EventInput | false {
// 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 = `${tool} - ${member}`;
if (toolFilter === null || tool.includes(toolFilter)) {
return eventData;
}
}
return false;
}
const calendarOptions: CalendarOptions = {
plugins: [timeGridPlugin, dayGridPlugin, iCalendarPlugin],
allDaySlot: false,
nowIndicator: true,
initialView: 'timeGridWeek',
height: 'auto',
slotMinTime: '8:00',
slotMaxTime: '22:00',
businessHours: {
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
startTime: '10:00',
endTime: '21:00',
},
eventSources: Object.values(calendars).map((id, idx) => {
return {
url: '/calendar/ical/' + id + '/public/basic.ics',
format: 'ics',
color: colors[idx],
eventDataTransform: eventDataTransform,
};
}),
slotLabelFormat: {
hour: 'numeric',
minute: '2-digit',
hour12: false,
},
eventTimeFormat: {
hour: 'numeric',
minute: '2-digit',
hour12: false,
},
};
const calendarEl = document.getElementById('calendar');
const calendar = new Calendar(calendarEl!, calendarOptions);
calendar.render();
function refresh() {
calendar.refetchEvents();
}
// refresh data every five minutes
window.setInterval(refresh, 5 * 60 * 1000);

View File

@ -1,21 +0,0 @@
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import legacy from '@vitejs/plugin-legacy'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
legacy({
targets: ['defaults', 'not IE 11', "ios 8.4"]
}),
],
server: {
proxy: {
'/calendar': {
target: 'https://calendar.google.com',
changeOrigin: true,
},
},
},
});

48
webpack.config.js Normal file
View File

@ -0,0 +1,48 @@
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.ts',
devServer: {
proxy: {
'/calendar': {
target: 'https://calendar.google.com',
changeOrigin: true,
},
},
},
devtool: "eval-cheap-source-map",
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
'babel-loader',
{
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/],
},
}
],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
}
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
};