Skip to content

Commit 720bb06

Browse files
committed
chore: fix evault uris
1 parent 759b771 commit 720bb06

File tree

6 files changed

+417
-384
lines changed

6 files changed

+417
-384
lines changed

infrastructure/control-panel/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"flowbite": "^3.1.2",
5151
"flowbite-svelte": "^1.10.7",
5252
"flowbite-svelte-icons": "^2.2.1",
53-
"lowdb": "^9.1.0",
53+
"lowdb": "^7.0.1",
5454
"lucide-svelte": "^0.539.0",
5555
"tailwind-merge": "^3.0.2"
5656
}

infrastructure/control-panel/src/lib/components/EVaultList.svelte

Lines changed: 166 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,140 +4,219 @@
44
import type { EVault } from '../../routes/api/evaults/+server';
55
66
let evaults: EVault[] = [];
7-
let loading = false;
8-
let cacheStatus: any = null;
9-
let lastRefresh = '';
7+
let loading = true;
8+
let error: string | null = null;
9+
let cacheStatus: { lastUpdated: number; isStale: boolean; itemCount: number };
1010
11-
// Load eVaults on component mount
1211
onMount(async () => {
13-
await loadEVaults();
14-
// Get cache status for debugging
15-
cacheStatus = EVaultService.getCacheStatus();
12+
try {
13+
await loadEVaults();
14+
cacheStatus = EVaultService.getCacheStatus();
15+
} catch (err) {
16+
error = 'Failed to load eVaults';
17+
console.error(err);
18+
} finally {
19+
loading = false;
20+
}
1621
});
1722
1823
async function loadEVaults() {
19-
loading = true;
2024
try {
21-
// This will return cached data immediately and refresh in background
2225
evaults = await EVaultService.getEVaults();
23-
lastRefresh = new Date().toLocaleTimeString();
24-
} catch (error) {
25-
console.error('Failed to load eVaults:', error);
26-
} finally {
27-
loading = false;
26+
cacheStatus = EVaultService.getCacheStatus();
27+
} catch (err) {
28+
console.error('Error loading eVaults:', err);
29+
throw err;
2830
}
2931
}
3032
3133
async function forceRefresh() {
32-
loading = true;
3334
try {
34-
// Force refresh and get fresh data
35+
loading = true;
3536
evaults = await EVaultService.forceRefresh();
36-
lastRefresh = new Date().toLocaleTimeString();
37-
// Update cache status
3837
cacheStatus = EVaultService.getCacheStatus();
39-
} catch (error) {
40-
console.error('Failed to force refresh:', error);
38+
} catch (err) {
39+
error = 'Failed to refresh eVaults';
40+
console.error(err);
4141
} finally {
4242
loading = false;
4343
}
4444
}
4545
4646
async function clearCache() {
47-
await EVaultService.clearCache();
48-
cacheStatus = EVaultService.getCacheStatus();
49-
// Reload data
50-
await loadEVaults();
47+
try {
48+
await EVaultService.clearCache();
49+
evaults = [];
50+
cacheStatus = EVaultService.getCacheStatus();
51+
} catch (err) {
52+
console.error('Error clearing cache:', err);
53+
}
54+
}
55+
56+
function formatTimestamp(timestamp: number): string {
57+
if (timestamp === 0) return 'Never';
58+
return new Date(timestamp).toLocaleString();
5159
}
5260
</script>
5361

5462
<div class="p-6">
55-
<div class="mb-6 flex items-center justify-between">
56-
<h1 class="text-2xl font-bold">eVault Control Panel</h1>
57-
<div class="flex gap-2">
63+
<div class="mb-6">
64+
<h1 class="mb-4 text-2xl font-bold text-gray-900">eVault Management</h1>
65+
66+
<!-- Cache Status -->
67+
<div class="mb-4 rounded-lg bg-gray-50 p-4">
68+
<h3 class="mb-2 text-sm font-medium text-gray-700">Cache Status</h3>
69+
<div class="grid grid-cols-3 gap-4 text-sm">
70+
<div>
71+
<span class="text-gray-500">Last Updated:</span>
72+
<span class="ml-2 font-mono"
73+
>{formatTimestamp(cacheStatus?.lastUpdated || 0)}</span
74+
>
75+
</div>
76+
<div>
77+
<span class="text-gray-500">Status:</span>
78+
<span
79+
class="ml-2 {cacheStatus?.isStale
80+
? 'text-orange-600'
81+
: 'text-green-600'} font-medium"
82+
>
83+
{cacheStatus?.isStale ? 'Stale' : 'Fresh'}
84+
</span>
85+
</div>
86+
<div>
87+
<span class="text-gray-500">Items:</span>
88+
<span class="ml-2 font-mono">{cacheStatus?.itemCount || 0}</span>
89+
</div>
90+
</div>
91+
</div>
92+
93+
<!-- Action Buttons -->
94+
<div class="mb-6 flex gap-3">
5895
<button
5996
on:click={loadEVaults}
6097
disabled={loading}
61-
class="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600 disabled:opacity-50"
98+
class="rounded-lg bg-blue-600 px-4 py-2 text-white hover:bg-blue-700 disabled:opacity-50"
6299
>
63100
{loading ? 'Loading...' : 'Refresh'}
64101
</button>
102+
65103
<button
66104
on:click={forceRefresh}
67105
disabled={loading}
68-
class="rounded bg-green-500 px-4 py-2 text-white hover:bg-green-600 disabled:opacity-50"
106+
class="rounded-lg bg-green-600 px-4 py-2 text-white hover:bg-green-700 disabled:opacity-50"
69107
>
70108
Force Refresh
71109
</button>
110+
72111
<button
73112
on:click={clearCache}
74-
class="rounded bg-red-500 px-4 py-2 text-white hover:bg-red-600"
113+
class="rounded-lg bg-red-600 px-4 py-2 text-white hover:bg-red-700"
75114
>
76115
Clear Cache
77116
</button>
78117
</div>
79118
</div>
80119

81-
<!-- Cache Status -->
82-
{#if cacheStatus}
83-
<div class="mb-6 rounded-lg bg-gray-100 p-4">
84-
<h3 class="mb-2 font-semibold">Cache Status</h3>
85-
<div class="grid grid-cols-3 gap-4 text-sm">
86-
<div>
87-
<strong>Last Updated:</strong><br />
88-
{new Date(cacheStatus.lastUpdated).toLocaleString()}
89-
</div>
90-
<div>
91-
<strong>Status:</strong><br />
92-
<span
93-
class="rounded px-2 py-1 text-xs {cacheStatus.isStale
94-
? 'bg-yellow-200 text-yellow-800'
95-
: 'bg-green-200 text-green-800'}"
96-
>
97-
{cacheStatus.isStale ? 'Stale' : 'Fresh'}
98-
</span>
99-
</div>
100-
<div>
101-
<strong>Cached Items:</strong><br />
102-
{cacheStatus.count} eVaults
103-
</div>
104-
</div>
120+
<!-- Error Display -->
121+
{#if error}
122+
<div class="mb-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-red-700">
123+
{error}
105124
</div>
106125
{/if}
107126

108-
<!-- Last Refresh Info -->
109-
{#if lastRefresh}
110-
<div class="mb-4 text-sm text-gray-600">
111-
Last refresh: {lastRefresh}
127+
<!-- Loading State -->
128+
{#if loading}
129+
<div class="py-8 text-center">
130+
<div
131+
class="inline-block h-8 w-8 animate-spin rounded-full border-b-2 border-blue-600"
132+
></div>
133+
<p class="mt-2 text-gray-600">Loading eVaults...</p>
112134
</div>
113-
{/if}
114-
115-
<!-- eVault List -->
116-
<div class="grid gap-4">
117-
{#if evaults.length === 0}
118-
<div class="py-8 text-center text-gray-500">
119-
{loading ? 'Loading eVaults...' : 'No eVaults found'}
120-
</div>
121-
{:else}
122-
{#each evaults as evault}
123-
<div class="rounded-lg border p-4 transition-shadow hover:shadow-md">
124-
<h3 class="text-lg font-semibold">{evault.name || 'Unnamed eVault'}</h3>
125-
<div class="mt-2 text-sm text-gray-600">
126-
<strong>Namespace:</strong>
127-
{evault.namespace}<br />
128-
<strong>Pod:</strong>
129-
{evault.podName}<br />
130-
<strong>Status:</strong>
131-
<span
132-
class="rounded px-2 py-1 text-xs {evault.status === 'Running'
133-
? 'bg-green-200 text-green-800'
134-
: 'bg-red-200 text-red-800'}"
135+
{:else if evaults.length === 0}
136+
<!-- Empty State -->
137+
<div class="py-8 text-center">
138+
<p class="text-gray-500">No eVaults found</p>
139+
<p class="mt-1 text-sm text-gray-400">
140+
Try refreshing or check your Kubernetes connection
141+
</p>
142+
</div>
143+
{:else}
144+
<!-- eVault List -->
145+
<div class="overflow-hidden rounded-lg bg-white shadow">
146+
<table class="min-w-full divide-y divide-gray-200">
147+
<thead class="bg-gray-50">
148+
<tr>
149+
<th
150+
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
135151
>
136-
{evault.status}
137-
</span>
138-
</div>
139-
</div>
140-
{/each}
141-
{/if}
142-
</div>
152+
Name
153+
</th>
154+
<th
155+
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
156+
>
157+
Namespace
158+
</th>
159+
<th
160+
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
161+
>
162+
Status
163+
</th>
164+
<th
165+
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
166+
>
167+
Age
168+
</th>
169+
<th
170+
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
171+
>
172+
Service URL
173+
</th>
174+
</tr>
175+
</thead>
176+
<tbody class="divide-y divide-gray-200 bg-white">
177+
{#each evaults as evault}
178+
<tr class="hover:bg-gray-50">
179+
<td
180+
class="whitespace-nowrap px-6 py-4 text-sm font-medium text-gray-900"
181+
>
182+
{evault.name}
183+
</td>
184+
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500">
185+
{evault.namespace}
186+
</td>
187+
<td class="whitespace-nowrap px-6 py-4">
188+
<span
189+
class="inline-flex rounded-full px-2 py-1 text-xs font-semibold {evault.status ===
190+
'Running'
191+
? 'bg-green-100 text-green-800'
192+
: evault.status === 'Pending'
193+
? 'bg-yellow-100 text-yellow-800'
194+
: 'bg-red-100 text-red-800'}"
195+
>
196+
{evault.status}
197+
</span>
198+
</td>
199+
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500">
200+
{evault.age || 'Unknown'}
201+
</td>
202+
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500">
203+
{#if evault.serviceUrl}
204+
<a
205+
href={evault.serviceUrl}
206+
target="_blank"
207+
rel="noopener noreferrer"
208+
class="text-blue-600 underline hover:text-blue-800"
209+
>
210+
{evault.serviceUrl}
211+
</a>
212+
{:else}
213+
<span class="text-gray-400">No external access</span>
214+
{/if}
215+
</td>
216+
</tr>
217+
{/each}
218+
</tbody>
219+
</table>
220+
</div>
221+
{/if}
143222
</div>

0 commit comments

Comments
 (0)