feat(dashboard): task system with DB persistence, CRUD endpoints, frontend API integration
This commit is contained in:
@@ -103,6 +103,18 @@ interface DashboardQueueItem {
|
||||
status: string
|
||||
}
|
||||
|
||||
interface DashboardTaskResponse {
|
||||
id: string
|
||||
title: string
|
||||
detail: string | null
|
||||
source: string
|
||||
state: string
|
||||
priority: string
|
||||
assignedTo: string | null
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
// ── Agent Catalog (static enrichment) ──
|
||||
|
||||
const AGENT_CATALOG: Record<string, Partial<AgentNodeData>> = {
|
||||
@@ -244,12 +256,8 @@ const busySince = ref(0)
|
||||
// Operations Feed
|
||||
const feedEntries = ref<FeedEntry[]>([])
|
||||
|
||||
// Open Tasks (mock only – no API endpoint)
|
||||
const openTasks = ref<OpenTask[]>([
|
||||
{ id: 't1', title: 'Agent Thinking Panel visualisieren', detail: 'Live-Animation der Denkprozesse im AgentModal', source: 'iris', createdAt: '22:30' },
|
||||
{ id: 't2', title: 'CI/CD Pipeline Monitoring Dashboard', detail: 'Echtzeit-Status der Gitea Actions im Dashboard', source: 'iris', createdAt: '21:15' },
|
||||
{ id: 't3', title: 'Dungeon System Dokumentation', detail: 'API-Doku für Room-Generation-Endpunkte schreiben', source: 'bao', createdAt: '20:00' },
|
||||
])
|
||||
// Open Tasks (fetched from API)
|
||||
const openTasks = ref<OpenTask[]>([])
|
||||
|
||||
// Queue
|
||||
const queue = ref<QueueItem[]>([])
|
||||
@@ -342,6 +350,45 @@ async function fetchQueue(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchTasks(): Promise<void> {
|
||||
try {
|
||||
const res = await apiFetch('/api/dashboard/tasks')
|
||||
if (!res.ok) return
|
||||
const data: DashboardTaskResponse[] = await res.json()
|
||||
openTasks.value = data.map(mapTaskResponse)
|
||||
} catch {
|
||||
// API unreachable – keep current values
|
||||
}
|
||||
}
|
||||
|
||||
function mapTaskResponse(t: DashboardTaskResponse): OpenTask {
|
||||
const source: OpenTask['source'] = t.source === 'iris' ? 'iris' : 'bao'
|
||||
// Format createdAt as relative time string (like "22:30")
|
||||
const created = new Date(t.createdAt)
|
||||
const now = new Date()
|
||||
const diffMs = now.getTime() - created.getTime()
|
||||
const diffMins = Math.floor(diffMs / 60000)
|
||||
|
||||
let createdAt: string
|
||||
if (diffMins < 1) {
|
||||
createdAt = 'just now'
|
||||
} else if (diffMins < 60) {
|
||||
createdAt = `${diffMins}m`
|
||||
} else if (diffMins < 1440) {
|
||||
createdAt = `${Math.floor(diffMins / 60)}h`
|
||||
} else {
|
||||
createdAt = created.toLocaleDateString('de-DE', { month: 'short', day: 'numeric' })
|
||||
}
|
||||
|
||||
return {
|
||||
id: t.id,
|
||||
title: t.title,
|
||||
detail: t.detail ?? '',
|
||||
source,
|
||||
createdAt,
|
||||
}
|
||||
}
|
||||
|
||||
// ── Chat Send ──
|
||||
|
||||
async function sendChatMessage(text: string): Promise<void> {
|
||||
@@ -454,6 +501,7 @@ function startPolling(): void {
|
||||
fetchOperations()
|
||||
fetchChatMessages()
|
||||
fetchQueue()
|
||||
fetchTasks()
|
||||
|
||||
// Polling intervals
|
||||
intervals.push(setInterval(fetchStatus, 5000))
|
||||
@@ -461,6 +509,7 @@ function startPolling(): void {
|
||||
intervals.push(setInterval(fetchOperations, 10000))
|
||||
intervals.push(setInterval(fetchChatMessages, 3000))
|
||||
intervals.push(setInterval(fetchQueue, 10000))
|
||||
intervals.push(setInterval(fetchTasks, 15000))
|
||||
}
|
||||
|
||||
function stopPolling(): void {
|
||||
@@ -512,5 +561,6 @@ export function useDashboardData() {
|
||||
fetchOperations,
|
||||
fetchChatMessages,
|
||||
fetchQueue,
|
||||
fetchTasks,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user