Files
keystone/resources/js/pages/service-replicas/Show.vue
Harry Bayliss 5b977c1f41
Some checks failed
CI / Lint (push) Failing after 22s
CI / Tests (push) Failing after 33s
wowowowowo
2026-05-28 15:15:41 +01:00

159 lines
5.9 KiB
Vue

<script setup lang="ts">
import OperationTimeline from "@/components/operations/OperationTimeline.vue";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import AppLayout from "@/layouts/AppLayout.vue";
import { Head, Link, router } from "@inertiajs/vue3";
import { PlayIcon, RefreshCwIcon, SquareIcon } from "lucide-vue-next";
const props = defineProps<{
server: Record<string, any>;
service: Record<string, any>;
replica: Record<string, any>;
}>();
const restartReplica = (): void => {
router.post(
route("service-replicas.restart", {
organisation: props.server.organisation_id,
server: props.server.id,
service: props.service.id,
replica: props.replica.id,
}),
);
};
const startReplica = (): void => {
router.post(
route("service-replicas.start", {
organisation: props.server.organisation_id,
server: props.server.id,
service: props.service.id,
replica: props.replica.id,
}),
);
};
const stopReplica = (): void => {
router.post(
route("service-replicas.stop", {
organisation: props.server.organisation_id,
server: props.server.id,
service: props.service.id,
replica: props.replica.id,
}),
);
};
</script>
<template>
<Head :title="replica.container_name" />
<AppLayout
:breadcrumbs="[
{
title: 'Servers',
href: route('servers.index', { organisation: $page.props.organisation.id }),
},
{
title: server.name,
href: route('servers.show', {
organisation: $page.props.organisation.id,
server: server.id,
}),
},
{
title: service.name,
href: route('services.show', {
organisation: $page.props.organisation.id,
server: server.id,
service: service.id,
}),
},
{ title: replica.container_name },
]"
>
<div class="flex h-full flex-1 flex-col gap-4 p-4">
<div class="flex flex-wrap items-center justify-between gap-3">
<div>
<div class="flex flex-wrap items-center gap-2">
<h2 class="text-3xl font-bold tracking-tight">
{{ replica.container_name }}
</h2>
<Badge variant="outline">{{ replica.status }}</Badge>
<Badge :variant="replica.health_status === 'healthy' ? 'success' : 'secondary'">
{{ replica.health_status }}
</Badge>
</div>
<p class="mt-1 text-sm text-muted-foreground">
{{ replica.internal_host }}:{{ replica.internal_port }}
<span v-if="replica.public_port"> · public {{ replica.public_port }}</span>
</p>
</div>
<div class="flex flex-wrap gap-2">
<Button variant="secondary" @click="startReplica">
<PlayIcon class="size-4" />
Start
</Button>
<Button variant="secondary" @click="stopReplica">
<SquareIcon class="size-4" />
Stop
</Button>
<Button @click="restartReplica">
<RefreshCwIcon class="size-4" />
Restart
</Button>
</div>
</div>
<div class="grid gap-4 lg:grid-cols-2">
<Card>
<CardHeader>
<CardTitle>Runtime</CardTitle>
<CardDescription>Container and image details.</CardDescription>
</CardHeader>
<CardContent class="grid gap-2 text-sm">
<div>Container ID: {{ replica.container_id ?? "not captured" }}</div>
<div>Image digest: {{ replica.image_digest ?? "not captured" }}</div>
<div>CPU limit: {{ replica.cpu_limit ?? "default" }}</div>
<div>Memory MB: {{ replica.memory_limit_mb ?? "default" }}</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Service</CardTitle>
</CardHeader>
<CardContent class="grid gap-2 text-sm">
<Link
:href="
route('services.show', {
organisation: $page.props.organisation.id,
server: server.id,
service: service.id,
})
"
class="font-medium hover:underline"
>
{{ service.name }}
</Link>
<div class="text-muted-foreground">
{{ service.type }} · {{ service.category }}
</div>
</CardContent>
</Card>
</div>
<Card>
<CardHeader>
<CardTitle>Operations</CardTitle>
</CardHeader>
<CardContent>
<OperationTimeline :operations="replica.operations" />
</CardContent>
</Card>
</div>
</AppLayout>
</template>