-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathApp.vue
More file actions
144 lines (117 loc) · 3.53 KB
/
Copy pathApp.vue
File metadata and controls
144 lines (117 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<template>
<div id="app" class="drawer lg:drawer-open">
<input id="sidebar-drawer" type="checkbox" class="drawer-toggle" />
<!-- Main content area -->
<div class="drawer-content grid grid-rows-[auto_1fr] h-screen bg-base-200 lg:pl-64">
<!-- Top Header -->
<TopHeader />
<!-- Page content -->
<main class="overflow-y-auto p-6">
<router-view v-slot="{ Component }">
<transition name="page" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</main>
</div>
<!-- Sidebar -->
<SidebarNav />
<!-- Toast Notifications -->
<ToastContainer />
<!-- Connection Status -->
<ConnectionStatus />
<!-- Authentication Error Modal -->
<AuthErrorModal
:show="authModal.show"
:can-close="authModal.canClose"
:last-error="authModal.lastError"
@close="handleAuthModalClose"
@authenticated="handleAuthModalAuthenticated"
@refresh="handleAuthModalRefresh"
/>
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue'
import SidebarNav from '@/components/SidebarNav.vue'
import TopHeader from '@/components/TopHeader.vue'
import ToastContainer from '@/components/ToastContainer.vue'
import ConnectionStatus from '@/components/ConnectionStatus.vue'
import AuthErrorModal from '@/components/AuthErrorModal.vue'
import { useSystemStore } from '@/stores/system'
import { useServersStore } from '@/stores/servers'
import { useAuthStore } from '@/stores/auth'
import api, { type APIAuthEvent } from '@/services/api'
const systemStore = useSystemStore()
const serversStore = useServersStore()
const authStore = useAuthStore()
// Authentication modal state
const authModal = reactive({
show: false,
canClose: true, // Allow closing by default (users can continue without API key for now)
lastError: ''
})
// API event listener cleanup function
let removeAPIListener: (() => void) | null = null
// Authentication modal handlers
function handleAuthModalClose() {
authModal.show = false
authModal.lastError = ''
}
function handleAuthModalAuthenticated() {
authModal.show = false
authModal.lastError = ''
// Refresh data now that we're authenticated
systemStore.connectEventSource()
serversStore.fetchServers()
}
function handleAuthModalRefresh() {
authModal.show = false
authModal.lastError = ''
// Reconnect with potentially new API key
systemStore.connectEventSource()
serversStore.fetchServers()
}
// Handle API authentication errors
function handleAuthError(event: APIAuthEvent) {
console.log('Global auth error received:', event)
authModal.lastError = event.error
authModal.show = true
}
onMounted(async () => {
// Initialize auth state (needed for server edition role-based nav)
await authStore.checkAuth()
// Set up API error listener
removeAPIListener = api.addEventListener(handleAuthError)
// Connect to real-time updates
systemStore.connectEventSource()
// Initial data load
serversStore.fetchServers()
// Fetch version info
systemStore.fetchInfo()
// Fetch routing mode info
systemStore.fetchRouting()
})
onUnmounted(() => {
systemStore.disconnectEventSource()
// Clean up API event listener
if (removeAPIListener) {
removeAPIListener()
}
})
</script>
<style scoped>
/* Page transitions */
.page-enter-active,
.page-leave-active {
transition: all 0.3s ease;
}
.page-enter-from {
opacity: 0;
transform: translateX(10px);
}
.page-leave-to {
opacity: 0;
transform: translateX(-10px);
}
</style>