Migrate to Vue 3 and vite

This commit is contained in:
Adam Goldsmith 2021-11-11 17:29:47 -05:00
parent bdf9b1637f
commit f1995232bb
8 changed files with 109 additions and 114 deletions

View File

@ -1,11 +0,0 @@
{
"plugins": ["@babel/plugin-transform-runtime"],
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
]
}

11
index.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Tool Reservations</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/index.ts"></script>
</body>
</html>

View File

@ -1,30 +1,26 @@
{ {
"browserslist": [
"defaults",
"ios 9.3"
],
"scripts": { "scripts": {
"start": "parcel src/index.html" "start": "npm run dev",
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"serve": "vite preview"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.8.7", "@types/intl": "^1.2.0",
"@babel/plugin-transform-runtime": "^7.8.3", "@vitejs/plugin-legacy": "^1.6.2",
"@babel/preset-env": "^7.8.7", "@vitejs/plugin-vue": "^1.9.4",
"@vue/component-compiler-utils": "^3.0.0",
"sass": "^1.23.1", "sass": "^1.23.1",
"typescript": "^4.2.3", "typescript": "^4.2.3",
"vue-template-compiler": "^2.6.10" "vite": "^2.6.13",
"vue-tsc": "^0.28.10"
}, },
"dependencies": { "dependencies": {
"@fullcalendar/core": "^5.6.0", "@fullcalendar/core": "^5.10.0",
"@fullcalendar/google-calendar": "^5.6.0", "@fullcalendar/google-calendar": "^5.6.0",
"@fullcalendar/timegrid": "^5.6.0", "@fullcalendar/timegrid": "^5.6.0",
"@fullcalendar/vue": "^5.6.0", "@fullcalendar/vue3": "^5.10.0",
"core-js": "^3.6.4",
"equicolor": "^1.1.0", "equicolor": "^1.1.0",
"intl": "^1.2.5", "intl": "^1.2.5",
"vue": "^2.6.10", "vue": "^3.2.20"
"vue-hot-reload-api": "^2.3.4",
"vue-property-decorator": "^9.1.2"
} }
} }

View File

@ -2,18 +2,20 @@
<FullCalendar ref="calendar" :options="calendarOptions"> </FullCalendar> <FullCalendar ref="calendar" :options="calendarOptions"> </FullCalendar>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { Vue, Component } from 'vue-property-decorator'; import { ref, Ref } from 'vue';
import equicolor from 'equicolor/src/Equicolor'; import equicolor from 'equicolor/src/Equicolor';
import FullCalendar from '@fullcalendar/vue'; import '@fullcalendar/core/vdom'; // solve problem with Vite
import FullCalendar, {
EventInput,
Calendar,
CalendarOptions,
} from '@fullcalendar/vue3';
import timeGridPlugin from '@fullcalendar/timegrid'; import timeGridPlugin from '@fullcalendar/timegrid';
import dayGridPlugin from '@fullcalendar/daygrid'; import dayGridPlugin from '@fullcalendar/daygrid';
import googleCalendarPlugin from '@fullcalendar/google-calendar'; import googleCalendarPlugin from '@fullcalendar/google-calendar';
import { EventInput, CalendarOptions } from '@fullcalendar/core';
import { Calendar } from '@fullcalendar/core';
import { googleCalendarApiKey } from './secrets.json'; import { googleCalendarApiKey } from './secrets.json';
const calendars: { [key: string]: string } = { const calendars: { [key: string]: string } = {
@ -31,73 +33,66 @@ const colors: string[] = equicolor.findNextColors(
Object.keys(calendars).length Object.keys(calendars).length
); );
@Component({ components: { FullCalendar } }) const calendarOptions: CalendarOptions = {
export default class App extends Vue { plugins: [timeGridPlugin, dayGridPlugin, googleCalendarPlugin],
calendarOptions: CalendarOptions = { allDaySlot: false,
plugins: [timeGridPlugin, dayGridPlugin, googleCalendarPlugin], nowIndicator: true,
allDaySlot: false, initialView: 'timeGridWeek',
nowIndicator: true, height: 'auto',
initialView: 'timeGridWeek', googleCalendarApiKey,
height: 'auto', slotMinTime: '8:00',
googleCalendarApiKey, slotMaxTime: '22:00',
slotMinTime: '8:00', businessHours: {
slotMaxTime: '22:00', daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
businessHours: { startTime: '10:00',
daysOfWeek: [0, 1, 2, 3, 4, 5, 6], endTime: '21:00',
startTime: '10:00', },
endTime: '21:00', eventSources: Object.values(calendars).map((id, idx) => {
}, return {
eventSources: Object.values(calendars).map((id, idx) => { googleCalendarId: id,
return { color: colors[idx],
googleCalendarId: id, eventDataTransform: eventDataTransform,
color: colors[idx], };
eventDataTransform: this.eventDataTransform, }),
}; slotLabelFormat: {
}), hour: 'numeric',
slotLabelFormat: { minute: '2-digit',
hour: 'numeric', hour12: false,
minute: '2-digit', },
hour12: false, eventTimeFormat: {
}, hour: 'numeric',
eventTimeFormat: { minute: '2-digit',
hour: 'numeric', hour12: false,
minute: '2-digit', },
hour12: false, };
},
};
toolFilter: string | null = null; const urlParams = new URLSearchParams(window.location.search);
const toolFilter: string | null = urlParams.get('tool');
const calendar_ref: Ref<InstanceType<typeof FullCalendar> | null> = ref(null);
created() { // refresh data every five minutes
// refresh data every five minutes window.setInterval(refresh, 5 * 60 * 1000);
window.setInterval(this.refresh, 5 * 60 * 1000);
const urlParams = new URLSearchParams(window.location.search); function refresh() {
this.toolFilter = urlParams.get('tool'); if (calendar_ref.value !== null) {
} const calendar = calendar_ref.value.getApi() as Calendar;
refresh() {
const calendarComponent = this.$refs.calendar as InstanceType<
typeof FullCalendar
>;
const calendar = calendarComponent.getApi() as Calendar;
calendar.refetchEvents(); calendar.refetchEvents();
} }
}
eventDataTransform(eventData: EventInput): EventInput | false { function eventDataTransform(eventData: EventInput): EventInput | false {
// clear the url to prevent clicking on the event // clear the url to prevent clicking on the event
delete eventData.url; delete eventData.url;
const match = eventData?.title?.match(/([^\/]*) \| ([^-]*) - (.*)/); const match = eventData?.title?.match(/([^\/]*) \| ([^-]*) - (.*)/);
if (match) { if (match) {
const [, member, shop, tool] = match; const [, member, shop, tool] = match;
eventData.title = `${tool} - ${member}`; eventData.title = `${tool} - ${member}`;
if (this.toolFilter === null || tool.includes(this.toolFilter)) { if (toolFilter === null || tool.includes(toolFilter)) {
return eventData; return eventData;
}
} }
return false;
} }
return false;
} }
</script> </script>

View File

@ -1,4 +0,0 @@
<body>
<div id="app"></div>
<script src="index.ts"></script>
</body>

View File

@ -1,18 +1,7 @@
import 'core-js/modules/es.object.entries'; import 'core-js/modules/es.object.entries';
// TODO: could probably be a dynamic import import * as Vue from 'vue';
import intl from 'intl';
import 'intl/locale-data/jsonp/en.js';
if (!window.Intl) { import App from './App.vue';
// No `Intl`, so use and load the polyfill.
window.Intl = intl;
}
import Vue from 'vue'; const app = Vue.createApp(App).mount('#app');
import App from './App';
let app = new Vue({
render: (h) => h(App),
}).$mount('#app');

View File

@ -1,9 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "esnext",
"strict": true, "useDefineForClassFields": true,
"module": "es2015", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"resolveJsonModule": true "strict": true,
} "jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
} }

13
vite.config.ts Normal file
View File

@ -0,0 +1,13 @@
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"]
}),
],
});