@@ -62,6 +62,15 @@ interface WorkerStats {
62
62
cpu_usage: number
63
63
}
64
64
65
+ interface Job {
66
+ id: string
67
+ name: string
68
+ queue: string
69
+ status: ' queued' | ' processing' | ' failed' | ' completed'
70
+ runtime? : number
71
+ started_at? : string
72
+ }
73
+
65
74
// Mock data for demonstration
66
75
const queues = ref <Record <string , QueueStats >>({
67
76
default: {
@@ -296,6 +305,11 @@ onMounted(async () => {
296
305
await new Promise (resolve => setTimeout (resolve , 500 ))
297
306
isLoading .value = false
298
307
})
308
+
309
+ const handleRetry = async (job : Job ) => {
310
+ // Implement retry logic
311
+ console .log (' Retrying job:' , job .id )
312
+ }
299
313
</script >
300
314
301
315
<template >
@@ -427,102 +441,112 @@ onMounted(async () => {
427
441
428
442
<!-- Queue Stats -->
429
443
<div class =" mt-8 px-4 lg:px-8 sm:px-6" >
430
- <div class =" bg-white dark:bg-blue-gray-700 rounded-lg shadow" >
431
- <div class =" p-6" >
432
- <div class =" sm:flex sm:items-center" >
433
- <div class =" sm:flex-auto" >
434
- <h3 class =" text-base font-medium text-gray-900 dark:text-gray-100" >Queue Statistics</h3 >
435
- <p class =" mt-1 text-sm text-gray-500 dark:text-gray-400" >Detailed breakdown of jobs by queue and status</p >
436
- </div >
444
+ <div class =" sm:flex sm:items-center" >
445
+ <div class =" sm:flex-auto" >
446
+ <h3 class =" text-base font-medium text-gray-900 dark:text-gray-100" >Queue Statistics</h3 >
447
+ <p class =" mt-1 text-sm text-gray-500 dark:text-gray-400" >Detailed breakdown of jobs by queue and status</p >
448
+ </div >
449
+ <div class =" mt-4 sm:ml-16 sm:mt-0 sm:flex-none" >
450
+ <router-link
451
+ to =" /dashboard/jobs/history"
452
+ class =" inline-flex items-center space-x-1 text-sm text-blue-600 hover:text-blue-500 dark:text-blue-400 dark:hover:text-blue-300"
453
+ >
454
+ <span >View Full History</span >
455
+ <div class =" i-heroicons-arrow-right h-4 w-4" />
456
+ </router-link >
457
+ </div >
458
+ </div >
459
+
460
+ <div class =" mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3 sm:grid-cols-2" >
461
+ <div v-for =" (stats, name) in queues" :key =" name" class =" bg-white dark:bg-blue-gray-700 rounded-lg shadow p-6" >
462
+ <div class =" flex items-center justify-between mb-4" >
463
+ <h4 class =" inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800 dark:bg-blue-gray-600 dark:text-gray-200" >
464
+ {{ name }}
465
+ </h4 >
437
466
</div >
438
467
439
- <div class =" mt-6 space-y-8" >
440
- <div v-for =" (stats, name) in queues" :key =" name" class =" space-y-4" >
441
- <div class =" flex items-center justify-between" >
442
- <div class =" flex items-center space-x-2" >
443
- <h4 class =" inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800 dark:bg-blue-gray-600 dark:text-gray-200" >
444
- {{ name }}
445
- </h4 >
446
- </div >
447
- <div class =" flex items-center space-x-3" >
448
- <div v-for =" (value, status) in stats" :key =" status"
449
- class =" group relative" >
450
- <div class =" flex items-center space-x-2 cursor-help" >
451
- <div :class =" [getQueueStatusColor(status), 'h-2.5 w-2.5 rounded-full']" ></div >
452
- <span class =" text-xs font-mono text-gray-700 dark:text-gray-300" >{{ value }}</span >
453
- </div >
454
- <div class =" absolute bottom-full left-1/2 -translate-x-1/2 mb-2 hidden group-hover:block z-10" >
455
- <div class =" relative" >
456
- <div class =" px-2 py-1 text-xs font-medium text-white bg-gray-900 dark:bg-gray-700 rounded shadow-lg whitespace-nowrap" >
457
- {{ status.charAt(0).toUpperCase() + status.slice(1) }} Jobs
458
- </div >
459
- <div class =" absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-gray-900 dark:border-t-gray-700" ></div >
460
- </div >
461
- </div >
462
- </div >
463
- </div >
468
+ <div class =" space-y-4" >
469
+ <!-- Queue Stats -->
470
+ <div class =" grid grid-cols-3 gap-4" >
471
+ <div v-for =" (value, status) in stats" :key =" status" class =" text-center" >
472
+ <div class =" text-2xl font-semibold" :class =" {
473
+ 'text-blue-600 dark:text-blue-400': status === 'queued',
474
+ 'text-yellow-600 dark:text-yellow-400': status === 'processing',
475
+ 'text-green-600 dark:text-green-400': status === 'processed',
476
+ 'text-purple-600 dark:text-purple-400': status === 'released',
477
+ 'text-red-600 dark:text-red-400': status === 'failed'
478
+ }" >{{ value }}</div >
479
+ <div class =" text-xs text-gray-500 dark:text-gray-400 capitalize" >{{ status }}</div >
480
+ </div >
481
+ </div >
482
+
483
+ <!-- Queue Progress -->
484
+ <div class =" h-2 bg-gray-100 dark:bg-blue-gray-600 rounded-full overflow-hidden" >
485
+ <div class =" flex h-full" >
486
+ <div class =" bg-green-500 h-full" :style =" { width: `${(stats.processed / (stats.processed + stats.failed)) * 100}%` }" />
487
+ <div class =" bg-red-500 h-full" :style =" { width: `${(stats.failed / (stats.processed + stats.failed)) * 100}%` }" />
464
488
</div >
465
489
</div >
490
+ <div class =" flex justify-between text-xs text-gray-500 dark:text-gray-400" >
491
+ <span >Success Rate: {{ ((stats.processed / (stats.processed + stats.failed)) * 100).toFixed(1) }}%</span >
492
+ <span >Failure Rate: {{ ((stats.failed / (stats.processed + stats.failed)) * 100).toFixed(1) }}%</span >
493
+ </div >
466
494
</div >
467
495
</div >
468
496
</div >
469
497
</div >
470
498
471
499
<!-- Recent Jobs -->
472
- <div class =" mt-8 px-4 lg:px-8 sm:px-6" >
473
- <div class =" bg-white dark:bg-blue-gray-700 rounded-lg shadow" >
474
- <div class =" p-6" >
475
- <div class =" sm:flex sm:items-center" >
476
- <div class =" sm:flex-auto" >
477
- <h3 class =" text-base font-medium text-gray-900 dark:text-gray-100" >Recent Jobs</h3 >
478
- <p class =" mt-1 text-sm text-gray-500 dark:text-gray-400" >Latest jobs processed by the system</p >
479
- </div >
480
- </div >
481
-
482
- <div class =" mt-6" >
483
- <div class =" overflow-x-auto" >
484
- <table class =" min-w-full divide-y divide-gray-200 dark:divide-gray-600" >
500
+ <div class =" mt-8 bg-white dark:bg-blue-gray-700 rounded-lg shadow" >
501
+ <div class =" px-4 py-5 sm:p-6" >
502
+ <h3 class =" text-base font-semibold leading-6 text-gray-900 dark:text-gray-100" >Recent Jobs</h3 >
503
+ <div class =" mt-4 flow-root" >
504
+ <div class =" -mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8" >
505
+ <div class =" inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8" >
506
+ <table class =" min-w-full divide-y divide-gray-300 dark:divide-blue-gray-600" >
485
507
<thead >
486
508
<tr >
487
- <th scope =" col" class =" px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100" >Job</th >
509
+ <th scope =" col" class =" py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100 sm:pl-0 " >Job</th >
488
510
<th scope =" col" class =" px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100" >Queue</th >
489
511
<th scope =" col" class =" px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100" >Status</th >
490
512
<th scope =" col" class =" px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100" >Runtime</th >
491
513
<th scope =" col" class =" px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100" >Started</th >
492
- <th scope =" col" class =" relative py-3.5 pl-3 pr-4 sm:pr-6 " >
514
+ <th scope =" col" class =" relative py-3.5 pl-3 pr-4 sm:pr-0 " >
493
515
<span class =" sr-only" >Actions</span >
494
516
</th >
495
517
</tr >
496
518
</thead >
497
- <tbody class =" divide-y divide-gray-200 dark:divide-gray-600" >
498
- <tr v-for =" job in recentJobs" :key =" job.id" class =" hover:bg-gray-50 dark:hover:bg-blue-gray-600/50" >
519
+ <tbody class =" divide-y divide-gray-200 dark:divide-blue-gray-600" >
520
+ <tr v-for =" job in recentJobs" :key =" job.id" >
521
+ <td class =" whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 dark:text-gray-100 sm:pl-0" >{{ job.name }}</td >
522
+ <td class =" whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400" >{{ job.queue }}</td >
499
523
<td class =" whitespace-nowrap px-3 py-4 text-sm" >
500
- <div class =" font-medium text-gray-900 dark:text-gray-100" >{{ job.name }}</div >
501
- <div class =" text-gray-500 dark:text-gray-400 font-mono text-xs" >{{ job.id }}</div >
502
- </td >
503
- <td class =" whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400" >
504
- {{ job.queue }}
505
- </td >
506
- <td class =" whitespace-nowrap px-3 py-4 text-sm" >
507
- <span class =" inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset"
508
- :class =" getJobStatusColor(job.status)" >
524
+ <span
525
+ class =" inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset"
526
+ :class =" getJobStatusColor(job.status)"
527
+ >
509
528
{{ job.status }}
510
529
</span >
511
530
</td >
512
- <td class =" whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400 font-mono" >
513
- {{ job.runtime ? `${job.runtime}s` : '-' }}
514
- </td >
515
- <td class =" whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400" >
516
- {{ job.started_at }}
517
- </td >
518
- <td class =" relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6" >
519
- <button
520
- v-if =" job.status === 'failed'"
521
- type =" button"
522
- class =" text-blue-600 hover:text-blue-900 dark:hover:text-blue-400"
523
- >
524
- Retry
525
- </button >
531
+ <td class =" whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400 font-mono" >{{ job.runtime ? `${job.runtime.toFixed(1)}s` : '-' }}</td >
532
+ <td class =" whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400" >{{ job.started_at }}</td >
533
+ <td class =" relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-0" >
534
+ <div class =" flex justify-end space-x-2" >
535
+ <router-link
536
+ :to =" `/dashboard/jobs/${job.id}`"
537
+ class =" text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300"
538
+ >
539
+ View
540
+ </router-link >
541
+ <button
542
+ v-if =" job.status === 'failed'"
543
+ type =" button"
544
+ class =" text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300"
545
+ @click =" handleRetry(job)"
546
+ >
547
+ Retry
548
+ </button >
549
+ </div >
526
550
</td >
527
551
</tr >
528
552
</tbody >
0 commit comments