feat: phase 1C JWT UI, events/hosts API, Vue frontend

This commit is contained in:
2026-05-26 21:46:34 +10:00
parent d8a8329397
commit bdfc7016e6
27 changed files with 2498 additions and 23 deletions
+46
View File
@@ -0,0 +1,46 @@
<template>
<p><RouterLink to="/events"> События</RouterLink></p>
<p v-if="error" class="error">{{ error }}</p>
<p v-else-if="loading">Загрузка</p>
<template v-else-if="event">
<h1>{{ event.title }}</h1>
<div class="card">
<p><strong>ID:</strong> {{ event.id }} · <strong>event_id:</strong> {{ event.event_id }}</p>
<p><strong>Хост:</strong> {{ event.hostname }} · <strong>Severity:</strong>
<span :class="'sev-' + event.severity">{{ event.severity }}</span>
</p>
<p><strong>Type:</strong> <code>{{ event.type }}</code></p>
<p><strong>Occurred:</strong> {{ event.occurred_at }}</p>
<p>{{ event.summary }}</p>
</div>
<h2>details</h2>
<pre>{{ JSON.stringify(event.details, null, 2) }}</pre>
<h2>payload</h2>
<pre>{{ JSON.stringify(event.payload, null, 2) }}</pre>
</template>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { apiFetch, type EventDetail } from "../api";
const props = defineProps<{ id: string }>();
const event = ref<EventDetail | null>(null);
const loading = ref(false);
const error = ref("");
async function load() {
loading.value = true;
error.value = "";
try {
event.value = await apiFetch<EventDetail>(`/api/v1/events/${props.id}`);
} catch (e) {
error.value = e instanceof Error ? e.message : "Не найдено";
} finally {
loading.value = false;
}
}
onMounted(load);
watch(() => props.id, load);
</script>