You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

128 lines
3.8 KiB

<script setup lang="ts">
const { data, refresh } = await useHttpFetch("/api/scheduler/tasks")
const stats = await useHttpFetch("/api/scheduler/stats")
const showCreateModal = ref(false)
const editingTask = ref<any>(null)
const columns = [
{ key: "name", label: "Name" },
{ key: "cronExpression", label: "Cron" },
{ key: "type", label: "Type" },
{ key: "enabled", label: "Status" },
{ key: "actions", label: "" },
]
function statusBadge(enabled: number) {
return enabled ? { label: "Active", color: "green" } : { label: "Paused", color: "gray" }
}
async function handleDelete(id: string) {
await $fetch(`/api/scheduler/tasks/${id}`, { method: "DELETE" })
refresh()
}
async function handleToggle(id: string, enabled: boolean) {
await $fetch(`/api/scheduler/tasks/${id}/toggle`, {
method: "POST",
body: { enabled },
})
refresh()
}
async function handleTrigger(id: string) {
await $fetch(`/api/scheduler/tasks/${id}/trigger`, { method: "POST" })
}
function openEdit(task: any) {
editingTask.value = task
showCreateModal.value = true
}
function openCreate() {
editingTask.value = null
showCreateModal.value = true
}
function onModalClose() {
showCreateModal.value = false
editingTask.value = null
refresh()
}
</script>
<template>
<div class="p-6 max-w-6xl mx-auto">
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold">Scheduled Tasks</h1>
<UButton @click="openCreate">Create Task</UButton>
</div>
<!-- Stats bar -->
<div class="grid grid-cols-4 gap-4 mb-6">
<div class="rounded-lg border p-4">
<div class="text-sm text-gray-500">Total</div>
<div class="text-2xl font-bold">{{ stats?.data?.totalTasks ?? 0 }}</div>
</div>
<div class="rounded-lg border p-4">
<div class="text-sm text-gray-500">Active</div>
<div class="text-2xl font-bold">{{ stats?.data?.enabledTasks ?? 0 }}</div>
</div>
<div class="rounded-lg border p-4">
<div class="text-sm text-gray-500">Jobs Running</div>
<div class="text-2xl font-bold">{{ stats?.data?.activeJobs ?? 0 }}</div>
</div>
<div class="rounded-lg border p-4">
<div class="text-sm text-gray-500">24h Executions</div>
<div class="text-2xl font-bold">{{ stats?.data?.last24hExecutions ?? 0 }}</div>
</div>
</div>
<!-- Task table -->
<div class="rounded-lg border">
<UTable :rows="data?.list ?? []" :columns="columns">
<template #enabled-data="{ row }">
<UBadge :color="statusBadge(row.enabled).color" variant="subtle">
{{ statusBadge(row.enabled).label }}
</UBadge>
</template>
<template #actions-data="{ row }">
<div class="flex gap-1 justify-end">
<UButton
size="xs"
variant="ghost"
@click="handleTrigger(row.id)"
>Trigger</UButton>
<UButton
size="xs"
variant="ghost"
@click="handleToggle(row.id, !row.enabled)"
>
{{ row.enabled ? "Pause" : "Resume" }}
</UButton>
<UButton
size="xs"
variant="ghost"
:to="`/admin/scheduler/${row.id}`"
>Detail</UButton>
<UButton size="xs" variant="ghost" @click="openEdit(row)">Edit</UButton>
<UButton
size="xs"
variant="ghost"
color="red"
@click="handleDelete(row.id)"
>Delete</UButton>
</div>
</template>
</UTable>
</div>
<!-- Create/Edit Modal -->
<SchedulerTaskModal
v-if="showCreateModal"
:task="editingTask"
:registered-functions="data?.registeredFunctions ?? []"
@close="onModalClose"
/>
</div>
</template>