TaskManager refactor
This commit is contained in:
126
frontend/src/components/TaskHistory.svelte
Normal file
126
frontend/src/components/TaskHistory.svelte
Normal file
@@ -0,0 +1,126 @@
|
||||
<!-- [DEF:TaskHistory:Component] -->
|
||||
<!--
|
||||
@SEMANTICS: task, history, list, status, monitoring
|
||||
@PURPOSE: Displays a list of recent tasks with their status and allows selecting them for viewing logs.
|
||||
@LAYER: UI
|
||||
@RELATION: USES -> frontend/src/lib/stores.js
|
||||
@RELATION: USES -> frontend/src/lib/api.js (inferred)
|
||||
-->
|
||||
<script>
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { selectedTask } from '../lib/stores.js';
|
||||
|
||||
let tasks = [];
|
||||
let loading = true;
|
||||
let error = "";
|
||||
let interval;
|
||||
|
||||
async function fetchTasks() {
|
||||
try {
|
||||
const res = await fetch('/api/tasks?limit=10');
|
||||
if (!res.ok) throw new Error('Failed to fetch tasks');
|
||||
tasks = await res.json();
|
||||
|
||||
// Update selected task if it exists in the list (for status updates)
|
||||
if ($selectedTask) {
|
||||
const updatedTask = tasks.find(t => t.id === $selectedTask.id);
|
||||
if (updatedTask && updatedTask.status !== $selectedTask.status) {
|
||||
selectedTask.set(updatedTask);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function selectTask(task) {
|
||||
selectedTask.set(task);
|
||||
}
|
||||
|
||||
function getStatusColor(status) {
|
||||
switch (status) {
|
||||
case 'SUCCESS': return 'bg-green-100 text-green-800';
|
||||
case 'FAILED': return 'bg-red-100 text-red-800';
|
||||
case 'RUNNING': return 'bg-blue-100 text-blue-800';
|
||||
case 'AWAITING_INPUT': return 'bg-orange-100 text-orange-800';
|
||||
case 'AWAITING_MAPPING': return 'bg-yellow-100 text-yellow-800';
|
||||
default: return 'bg-gray-100 text-gray-800';
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
fetchTasks();
|
||||
interval = setInterval(fetchTasks, 5000); // Poll every 5s
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="bg-white shadow overflow-hidden sm:rounded-lg mb-8">
|
||||
<div class="px-4 py-5 sm:px-6 flex justify-between items-center">
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
Recent Tasks
|
||||
</h3>
|
||||
<button
|
||||
on:click={fetchTasks}
|
||||
class="text-sm text-indigo-600 hover:text-indigo-900 focus:outline-none"
|
||||
>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if loading && tasks.length === 0}
|
||||
<div class="p-4 text-center text-gray-500">Loading tasks...</div>
|
||||
{:else if error}
|
||||
<div class="p-4 text-center text-red-500">{error}</div>
|
||||
{:else if tasks.length === 0}
|
||||
<div class="p-4 text-center text-gray-500">No recent tasks found.</div>
|
||||
{:else}
|
||||
<ul class="divide-y divide-gray-200">
|
||||
{#each tasks as task}
|
||||
<li>
|
||||
<button
|
||||
class="w-full text-left block hover:bg-gray-50 focus:outline-none focus:bg-gray-50 transition duration-150 ease-in-out"
|
||||
class:bg-indigo-50={$selectedTask && $selectedTask.id === task.id}
|
||||
on:click={() => selectTask(task)}
|
||||
>
|
||||
<div class="px-4 py-4 sm:px-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="text-sm font-medium text-indigo-600 truncate">
|
||||
{task.plugin_id}
|
||||
<span class="text-gray-500 text-xs ml-2">({task.id.slice(0, 8)})</span>
|
||||
</p>
|
||||
<div class="ml-2 flex-shrink-0 flex">
|
||||
<p class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {getStatusColor(task.status)}">
|
||||
{task.status}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 sm:flex sm:justify-between">
|
||||
<div class="sm:flex">
|
||||
<p class="flex items-center text-sm text-gray-500">
|
||||
{#if task.params.from_env && task.params.to_env}
|
||||
{task.params.from_env} → {task.params.to_env}
|
||||
{:else}
|
||||
Params: {Object.keys(task.params).length} keys
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-2 flex items-center text-sm text-gray-500 sm:mt-0">
|
||||
<p>
|
||||
Started: {new Date(task.started_at || task.created_at || Date.now()).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- [/DEF:TaskHistory] -->
|
||||
Reference in New Issue
Block a user