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:
parent
a9b3c5f1f7
commit
d4dbaaf344
10
babel.config.js
Normal file
10
babel.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: ['@babel/plugin-transform-runtime'],
|
||||||
|
presets: [
|
||||||
|
['@babel/preset-env', {
|
||||||
|
useBuiltIns: 'usage',
|
||||||
|
corejs: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
31
package.json
31
package.json
@ -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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
94
src/App.vue
94
src/App.vue
@ -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>
|
|
91
src/index.ts
91
src/index.ts
@ -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);
|
||||||
|
@ -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
48
webpack.config.js
Normal 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',
|
||||||
|
},
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user