237 lines
7.7 KiB
Vue
237 lines
7.7 KiB
Vue
<script setup lang="ts">
|
|
|
|
definePageMeta({
|
|
requiresAuth: true
|
|
})
|
|
|
|
import { ref, onMounted } from "vue"
|
|
|
|
const { apiFetch } = useApi()
|
|
|
|
const servers = ref([])
|
|
const newServer = ref({
|
|
hostname: "",
|
|
description: "",
|
|
owner_id: null
|
|
})
|
|
|
|
const loading = ref(false)
|
|
const error = ref("")
|
|
const showCreateForm = ref(false)
|
|
const editingId = ref<number | null>(null)
|
|
|
|
const editServer = ref({
|
|
hostname: "",
|
|
description: "",
|
|
owner_id: null
|
|
})
|
|
|
|
function startEdit(server: any) {
|
|
editingId.value = Number(server.id)
|
|
editServer.value = {
|
|
hostname: server.hostname,
|
|
description: server.description,
|
|
owner_id: server.owner_id
|
|
}
|
|
}
|
|
function cancelEdit() {
|
|
editingId.value = null
|
|
}
|
|
|
|
async function saveEdit(serverId: number) {
|
|
try {
|
|
const updated = await apiFetch(`/servers/${serverId}`, {
|
|
method: "PUT",
|
|
body: {
|
|
hostname: editServer.value.hostname,
|
|
description: editServer.value.description,
|
|
owner_id: editServer.value.owner_id
|
|
}
|
|
})
|
|
|
|
// Liste aktualisieren
|
|
const idx = servers.value.findIndex(s => s.id === serverId)
|
|
if (idx !== -1) servers.value[idx] = updated
|
|
|
|
editingId.value = null
|
|
} catch (e: any) {
|
|
error.value = e.message
|
|
}
|
|
}
|
|
|
|
|
|
const owners = ref([])
|
|
|
|
async function loadOwners() {
|
|
try {
|
|
owners.value = await apiFetch("/owners")
|
|
} catch (e: any) {
|
|
error.value = e.message
|
|
}
|
|
}
|
|
|
|
async function loadServers() {
|
|
loading.value = true
|
|
try {
|
|
servers.value = await apiFetch("/servers")
|
|
} catch (e: any) {
|
|
error.value = e.message
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function createServer() {
|
|
if (!newServer.value.hostname.trim()) return
|
|
|
|
try {
|
|
const server = await apiFetch("/servers", {
|
|
method: "POST",
|
|
body: {
|
|
hostname: newServer.value.hostname,
|
|
description: newServer.value.description,
|
|
owner_id: newServer.value.owner_id
|
|
}
|
|
})
|
|
|
|
servers.value.push(server)
|
|
newServer.value = { hostname: "", description: "" }
|
|
} catch (e: any) {
|
|
error.value = e.message
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadOwners()
|
|
loadServers()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="space-y-6">
|
|
<h1 class="text-3xl font-bold">Server Verwaltung</h1>
|
|
|
|
<!-- Server-Liste -->
|
|
<div class="p-4 bg-white shadow rounded">
|
|
<h2 class="text-xl font-semibold mb-4">Server Liste</h2>
|
|
|
|
<div v-if="loading">Lade Server…</div>
|
|
<div v-if="error" class="text-red-600">{{ error }}</div>
|
|
|
|
<table class="w-full border-collapse">
|
|
<thead>
|
|
<tr class="border-b">
|
|
<th class="text-left p-2">ID</th>
|
|
<th class="text-left p-2">Name</th>
|
|
<th class="text-left p-2">Beschreibung</th>
|
|
<th class="text-left p-2">Eigentümer</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="server in servers" :key="server.id" class="border-b hover:bg-gray-50">
|
|
<td class="p-2">{{ server.id }}</td>
|
|
<td class="p-2">
|
|
<template v-if="editingId === server.id">
|
|
<input
|
|
v-model="editServer.hostname"
|
|
class="border p-1 rounded w-full"
|
|
/>
|
|
</template>
|
|
<template v-else>
|
|
{{ server.hostname }}
|
|
</template>
|
|
</td>
|
|
|
|
<td class="p-2">
|
|
<template v-if="editingId === server.id">
|
|
<textarea
|
|
v-model="editServer.description"
|
|
class="border p-1 rounded w-full"
|
|
/>
|
|
</template>
|
|
<template v-else>
|
|
{{ server.description }}
|
|
</template>
|
|
</td>
|
|
|
|
<td class="p-2">
|
|
<template v-if="editingId === server.id">
|
|
<select v-model="editServer.owner_id" class="border p-1 rounded">
|
|
<option :value="null">Kein Owner</option>
|
|
<option
|
|
v-for="owner in owners"
|
|
:key="owner.id"
|
|
:value="owner.id"
|
|
>
|
|
{{ owner.name }}
|
|
</option>
|
|
</select>
|
|
</template>
|
|
<template v-else>
|
|
{{ server.owner ? server.owner.name : "—" }}
|
|
</template>
|
|
</td>
|
|
<td class="p-2">
|
|
<template v-if="editingId === server.id">
|
|
<button
|
|
@click="saveEdit(server.id)"
|
|
class="bg-green-600 text-white px-2 py-1 rounded mr-2"
|
|
>
|
|
Speichern
|
|
</button>
|
|
<button
|
|
@click="cancelEdit"
|
|
class="bg-gray-400 text-white px-2 py-1 rounded"
|
|
>
|
|
Abbrechen
|
|
</button>
|
|
</template>
|
|
|
|
<template v-else>
|
|
<button
|
|
@click="startEdit(server)"
|
|
class="bg-blue-600 text-white px-2 py-1 rounded"
|
|
>
|
|
Bearbeiten
|
|
</button>
|
|
</template>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<button
|
|
@click="showCreateForm = !showCreateForm"
|
|
class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
|
|
>
|
|
{{ showCreateForm ? "Formular ausblenden" : "Neuen Server anlegen" }}
|
|
</button>
|
|
|
|
<!-- Neues Server-Formular -->
|
|
<Transition name="fade">
|
|
<div v-if="showCreateForm" class="p-4 bg-white shadow rounded space-y-4">
|
|
<h2 class="text-xl font-semibold">Neuen Server anlegen</h2>
|
|
|
|
<div class="flex flex-col gap-4">
|
|
<input v-model="newServer.hostname" type="text" placeholder="Server Name" class="border p-2 rounded" />
|
|
|
|
<textarea v-model="newServer.description" placeholder="Beschreibung (optional)"
|
|
class="border p-2 rounded" />
|
|
|
|
<select v-model="newServer.owner_id" class="border p-2 rounded">
|
|
<option :value="null">Kein Owner</option>
|
|
<option v-for="owner in owners" :key="owner.id" :value="owner.id">
|
|
{{ owner.name }}
|
|
</option>
|
|
</select>
|
|
|
|
|
|
<button @click="createServer"
|
|
class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 self-start">
|
|
Speichern
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</div>
|
|
</template>
|