"Introduce version check mechanism with notifications for updates; enhance Vite build process for automated server update handling."

This commit is contained in:
Jeppe Bundgaard
2025-12-01 14:59:56 +01:00
parent ac7ddc37fb
commit 933eba04aa
3 changed files with 116 additions and 1 deletions
+2
View File
@@ -5,6 +5,7 @@ import { SessionUser } from "@/components/session/token/SessionUser.vue";
// Set the favicon to the /favicon.ico file
import { useHead } from "@vueuse/head";
import favicon from '@/assets/favicon.ico';
import VersionCheck from "@/components/global/VersionCheck.vue";
useHead({
link: [
@@ -23,6 +24,7 @@ onMounted(() => {
</header>
<main>
<DefaultPageWrapper>
<VersionCheck/>
<router-view />
</DefaultPageWrapper>
</main>
+100
View File
@@ -0,0 +1,100 @@
<script setup lang="ts">
import { onMounted, ref, computed } from "vue";
import Swal from "sweetalert2";
import { SessionUser } from "@/components/session/token/SessionUser.vue";
const VITE_COMMIT_HASH = import.meta.env.VITE_COMMIT_HASH || 'No commit hash';
const VITE_IS_DEV = import.meta.env.DEV || false;
/**
* Variables
*/
const localVersion = VITE_COMMIT_HASH;
const localStorageLastCheckKey = "lastVersionCheck";
const versionCheckUrl = "/worker/version";
const versionCheckDelay = 1000 * 60 * 5; // 5 minutes
const latestVersion = ref<string | null>(null);
const lastVersionCheck = ref(localStorage.getItem(localStorageLastCheckKey) ? parseInt(localStorage.getItem(localStorageLastCheckKey) || "0") : 0);
/**
* Computed
*/
const currentVersion = computed(() => localVersion || "unknown");
const isUpdateAvailable = computed(() => {
return latestVersion.value !== null && latestVersion.value !== currentVersion.value;
});
const shouldCheckForUpdate = computed(() => {
// In dev mode, do not check for updates
if (VITE_IS_DEV) {
return false;
}
// If never checked before, should check
if (lastVersionCheck.value === 0) {
return true;
}
// If enough time has passed since last check, should check
const now = Date.now();
return (now - lastVersionCheck.value) > versionCheckDelay;
});
/**
* Methods
*/
const showUpdateAvailableNotification = () => {
Swal.fire({
title: 'Opdatering tilgængelig',
text: `En ny version (${latestVersion.value}) er tilgængelig! Du bruger i øjeblikket version ${currentVersion.value}. Opdater venligst siden for at få den nyeste version.`,
icon: 'info',
confirmButtonText: 'Opdater nu',
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const checkForUpdate = async () => {
const response = await SessionUser.request(
versionCheckUrl,
'GET',
);
// Verify response
if (!response || !response.data || !response.data.data || !response.data.data.version) {
console.error("Invalid version check response:", response);
return;
}
// Update last check time
lastVersionCheck.value = Date.now();
localStorage.setItem(localStorageLastCheckKey, lastVersionCheck.value.toString());
// Update latest version
latestVersion.value = response.data.data.version;
console.warn("Version check response:", latestVersion.value);
// Notify user if update is available
if (isUpdateAvailable.value) {
showUpdateAvailableNotification();
}
return response;
}
/**
* Lifecycle Hooks
*/
onMounted(() => {
if (shouldCheckForUpdate.value) {
checkForUpdate();
}
window.addEventListener('focus', () => {
if (shouldCheckForUpdate.value) {
checkForUpdate();
}
});
window.setInterval(() => {
if (shouldCheckForUpdate.value) {
checkForUpdate();
}
}, versionCheckDelay);
});
</script>
<template>
</template>
<style scoped>
</style>
+14 -1
View File
@@ -25,7 +25,20 @@ export default defineConfig(({ mode }) => {
process.env.COMMIT_HASH = commit
process.env.APP_VERSION = version
process.env.IS_DEV = !isProd ? 'true' : 'false'
// If the build is a production build, update the server with the new version
if (isProd) {
console.log('Updating server with new version...')
const token = process.env.SERVER_UPDATE_TOKEN
if (!token) {
console.warn('SERVER_UPDATE_TOKEN is not set. Skipping server update.')
} else {
// Run GET request to update version endpoint
const url = `https://api.truckwash.dk:4433/worker/update-version?version=${commit}`
const bearer = `Bearer ${token}`
console.log(`Calling URL: ${url}`)
execSync(`curl -X GET "${url}" -H "Authorization: ${bearer}"`)
}
}
// Keep a relative base for static hosting; align manifest with base
const base = '/'
const pwaScope = base === './' ? '.' : base