+page.svelte
<script lang="ts">
import Nav from '../Nav.svelte';
import Tabs from '../Tabs.svelte';
import { resolve } from '$app/paths';
import { server } from '../../../helpers';
import { onMount } from 'svelte';
const { data, params } = $props();
let jobs = $derived(data.jobs);
let socket: WebSocket | undefined = undefined;
function websocket() {
socket = new WebSocket(`${server}/api/job/${params.user}/${params.repo}/ws`);
socket.onmessage = (event) => {
const j = JSON.parse(event.data);
if (typeof j == 'object') {
if (j?.jobs) {
jobs = j.jobs;
}
}
};
socket.onclose = () => {
socket = undefined;
};
}
onMount(() => {
setInterval(() => {
if (!socket) websocket();
}, 1000);
});
</script>
<svelte:head>
<title>{data.owner} / {data.repo}</title>
</svelte:head>
<div class="p-3">
<Nav user={params.user} repo={params.repo} path={[]} link={true} />
<Tabs
user={params.user}
repo={params.repo}
login={data.login}
channel={data.channel}
active="jobs" />
<div class="p-3">
<h1 class="mt-5">Jobs</h1>
<table class="mt-10 table">
<thead><tr><td>Job</td><td>Started</td><td>Ended</td><td>Status</td><td></td></tr></thead>
<tbody>
{#each jobs as job (job.id)}
<tr>
<td>
<a
class="link link-primary"
href={resolve('/[user]/[repo]/jobs/[job]', {
job: job.id,
...params
})}>{job.id}</a>
</td>
<td>
{job.started}
</td>
<td>
{job.ended}
</td>
<td>
{job.status}
</td>
<td>
<div class="flex flex-wrap gap-3">
<form action="/api/job/{params.user}/{params.repo}/{job.id}/retry" method="post">
<button class="btn btn-primary btn-sm" disabled={!job.ended}>Retry</button>
</form>
<form action="/api/job/{params.user}/{params.repo}/{job.id}/kill" method="post">
<button class="btn btn-error btn-sm" disabled={job.ended}>Kill</button>
</form>
</div>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
</div>