fix: all broken integration tests

This commit is contained in:
jamesread
2025-10-11 00:45:41 +01:00
parent 7d5fa999e5
commit b330fbd1a5
44 changed files with 1160 additions and 3196 deletions

View File

@@ -1,73 +1,155 @@
<template>
<div v-if="!dashboard" style = "text-align: center">
<p>Loading... {{ title }}</p>
</div>
<div v-else>
<section v-if="!dashboard && !initError" style = "text-align: center; padding: 2em;">
<HugeiconsIcon :icon="Loading03Icon" width="3em" height="3em" style="animation: spin 1s linear infinite;" />
<p>Loading dashboard...</p>
<p style="color: var(--fg2);">{{ loadingTime }}s</p>
</section>
<section v-if="initError" style="text-align: center; padding: 2em;" class = "bad">
<h2 style="color: var(--error);">Initialization Failed</h2>
<p>{{ initError }}</p>
<p style="color: var(--fg2);">Please check your configuration and try again.</p>
</section>
<div v-else-if="dashboard">
<section v-if="dashboard.contents.length == 0">
<legend>{{ dashboard.title }}</legend>
<p>This dashboard is empty.</p>
<p style = "text-align: center" class = "padding">This dashboard is empty.</p>
</section>
<section class="transparent" v-else>
<div v-for="component in dashboard.contents" :key="component.title">
<div v-if="component.type == 'fieldset'">
<fieldset>
<legend v-if = "dashboard.title != 'Default'">{{ component.title }}</legend>
<fieldset>
<legend v-if = "dashboard.title != 'Default'">{{ component.title }}</legend>
<template v-for="subcomponent in component.contents">
<div v-if="subcomponent.type == 'display'" class="display">
<div v-html="subcomponent.title" />
</div>
<ActionButton v-else-if="subcomponent.type == 'link'" :actionData="subcomponent.action"
:key="subcomponent.title" />
<div v-else-if="subcomponent.type == 'directory'">
<router-link :to="{ name: 'Dashboard', params: { title: subcomponent.title } }"
class="dashboard-link">
<button>
{{ subcomponent.title }}
</button>
</router-link>
</div>
<div v-else>
OTHER: {{ subcomponent.type }}
{{ subcomponent }}
</div>
</template>
</fieldset>
</div>
<ActionButton v-else :actionData="action" v-for="action in component.contents" :key="action.title" />
<template v-for="subcomponent in component.contents">
<DashboardComponent :component="subcomponent" />
</template>
</fieldset>
</div>
</section>
</div>
</template>
<script setup>
import ActionButton from './ActionButton.vue'
import { onMounted, ref } from 'vue'
import DashboardComponent from './components/DashboardComponent.vue'
import { onMounted, onUnmounted, ref } from 'vue'
import { HugeiconsIcon } from '@hugeicons/vue'
import { Loading03Icon } from '@hugeicons/core-free-icons'
const props = defineProps({
title: {
type: String,
required: true
required: false
}
})
const dashboard = ref(null)
const loadingTime = ref(0)
const initError = ref(null)
let loadingTimer = null
let checkInitInterval = null
async function getDashboard() {
const ret = await window.client.getDashboard({
title: props.title,
})
let title = props.title
dashboard.value = ret.dashboard
// If no specific title was provided or it's the placeholder 'default',
// prefer the first configured root dashboard (e.g., "Test").
if ((!title || title === 'default') && window.initResponse.rootDashboards && window.initResponse.rootDashboards.length > 0) {
title = window.initResponse.rootDashboards[0]
}
try {
const ret = await window.client.getDashboard({
title: title,
})
if (!ret || !ret.dashboard) {
throw new Error('No dashboard found')
}
dashboard.value = ret.dashboard
document.title = ret.dashboard.title + ' - OliveTin'
// Clear any previous init error since we successfully loaded
initError.value = null
// Stop the loading timer once dashboard is loaded
if (loadingTimer) {
clearInterval(loadingTimer)
loadingTimer = null
}
// Set attribute to indicate dashboard is loaded successfully
document.body.setAttribute('loaded-dashboard', title || 'default')
} catch (e) {
// On error, provide a safe fallback state
console.error('Failed to load dashboard', e)
dashboard.value = { title: title || 'Default', contents: [] }
document.title = 'Error - OliveTin'
// Stop the loading timer on error
if (loadingTimer) {
clearInterval(loadingTimer)
loadingTimer = null
}
// Set attribute even on error so tests can proceed
document.body.setAttribute('loaded-dashboard', title || 'error')
}
}
function waitForInitAndLoadDashboard() {
// Start the loading timer
loadingTime.value = 0
loadingTimer = setInterval(() => {
loadingTime.value++
}, 1000)
// Check if init has completed successfully
if (window.initCompleted && window.initResponse) {
getDashboard()
} else if (window.initError) {
// Init failed, show error immediately
initError.value = window.initErrorMessage || 'Initialization failed. Please check your configuration and try again.'
// Stop the loading timer since we're showing an error
if (loadingTimer) {
clearInterval(loadingTimer)
loadingTimer = null
}
} else {
// Init hasn't completed yet, poll for completion
checkInitInterval = setInterval(() => {
if (window.initCompleted && window.initResponse) {
clearInterval(checkInitInterval)
checkInitInterval = null
getDashboard()
} else if (window.initError) {
clearInterval(checkInitInterval)
checkInitInterval = null
initError.value = window.initErrorMessage || 'Initialization failed. Please check your configuration and try again.'
// Stop the loading timer since we're showing an error
if (loadingTimer) {
clearInterval(loadingTimer)
loadingTimer = null
}
}
}, 100) // Check every 100ms
}
}
onMounted(() => {
getDashboard()
waitForInitAndLoadDashboard()
})
onUnmounted(() => {
// Clean up the timers when component is unmounted
if (loadingTimer) {
clearInterval(loadingTimer)
loadingTimer = null
}
if (checkInitInterval) {
clearInterval(checkInitInterval)
checkInitInterval = null
}
})
</script>
@@ -80,4 +162,13 @@ fieldset {
justify-content: center;
place-items: stretch;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>