Show active jobs in the sidebar of the ui

This commit is contained in:
Jaret Burkett 2026-05-25 08:21:42 -06:00
parent a798e06dd2
commit 3d836ac371
2 changed files with 95 additions and 22 deletions

View File

@ -0,0 +1,73 @@
'use client';
import Link from 'next/link';
import { CgSpinner } from 'react-icons/cg';
import useJobsList from '@/hooks/useJobsList';
import { JobConfig } from '@/types';
export default function ActiveJobWidget() {
const { jobs } = useJobsList({ onlyActive: true, reloadInterval: 5000 });
if (!jobs || jobs.length === 0) return null;
return (
<div className="px-3 pb-2">
<div className="w-[196px]">
<ul className="max-h-48 overflow-y-auto space-y-2">
{jobs.map(job => {
let totalSteps: number | undefined;
try {
const cfg: JobConfig = JSON.parse(job.job_config);
totalSteps = cfg.config.process[0].train?.steps;
} catch {
totalSteps = undefined;
}
const isTrain = job.job_type === 'train';
const pct = isTrain && totalSteps ? Math.min(100, (job.step / totalSteps) * 100) : 0;
const isRunning = job.status === 'running' || job.status === 'stopping';
let label = job.name;
if (job.job_type === 'caption') {
const splits = (job.job_ref ?? '').split(/[/\\]/);
label = splits[splits.length - 1] || job.name;
}
let statusColor = 'text-gray-400';
if (job.status === 'running') statusColor = 'text-blue-400';
if (job.status === 'queued') statusColor = 'text-yellow-400';
if (job.status === 'stopping') statusColor = 'text-orange-400';
return (
<li key={job.id} className="min-w-0">
<Link
href={`/jobs/${job.id}`}
className="block px-3 py-2 bg-gray-800 hover:bg-gray-950 rounded-lg transition-colors min-w-0"
>
<div className="flex items-center gap-1.5 min-w-0">
{isRunning && <CgSpinner className="animate-spin text-blue-400 flex-shrink-0" />}
<span className="text-xs text-gray-100 truncate min-w-0 flex-1">{label}</span>
</div>
{isTrain && totalSteps ? (
<div className="mt-1.5">
<div className="bg-gray-700 rounded-full h-1">
<div className="bg-blue-500 h-1 rounded-full transition-all" style={{ width: `${pct}%` }} />
</div>
<div className="flex justify-between mt-0.5">
<span className={`text-[10px] ${statusColor}`}>{job.status}</span>
<span className="text-[10px] text-gray-400">
{job.step} / {totalSteps}
</span>
</div>
</div>
) : (
<div className={`text-[10px] mt-0.5 ${statusColor}`}>{job.status}</div>
)}
</Link>
</li>
);
})}
</ul>
</div>
</div>
);
}

View File

@ -8,6 +8,7 @@ import { FaXTwitter, FaDiscord, FaYoutube } from 'react-icons/fa6';
import { createGlobalState } from 'react-global-hooks';
import ThemeToggle from './ThemeToggle';
import ThemeLogo from './ThemeLogo';
import ActiveJobWidget from './ActiveJobWidget';
export const mobileSidebarState = createGlobalState<boolean>(false);
@ -75,29 +76,28 @@ const Sidebar = () => {
))}
</ul>
</nav>
<div className="px-3 py-3">
<a
href="https://ostris.com/support"
target="_blank"
rel="noreferrer"
className="flex items-center justify-center space-x-2 px-4 py-2.5 rounded-full bg-gray-800 hover:bg-gray-700 shadow-md hover:shadow-lg ring-1 ring-gray-700 hover:ring-gray-600 transition-all duration-200 hover:-translate-y-0.5 active:translate-y-0 active:shadow-sm"
<ActiveJobWidget />
<a
href="https://ostris.com/support"
target="_blank"
rel="noreferrer"
className="group flex items-center space-x-2 px-4 py-3 text-gray-400 hover:text-gray-200 transition-colors"
>
<svg
height="20"
width="20"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style={{ overflow: 'visible' }}
>
<svg
height="20"
width="20"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style={{ overflow: 'visible' }}
>
<path
className="animate-heartbeat"
d="m7 3c-1.5355 0-3.0784 0.5-4.25 1.7-2.3431 2.4-2.2788 6.1 0 8.5l9.25 9.8 9.25-9.8c2.279-2.4 2.343-6.1 0-8.5-2.343-2.3-6.157-2.3-8.5 0l-0.75 0.8-0.75-0.8c-1.172-1.2-2.7145-1.7-4.25-1.7z"
fill="#c0392b"
/>
</svg>
<span className="uppercase text-gray-200 text-sm font-semibold tracking-wide">Support AI-Toolkit</span>
</a>
</div>
<path
className="animate-heartbeat"
d="m7 3c-1.5355 0-3.0784 0.5-4.25 1.7-2.3431 2.4-2.2788 6.1 0 8.5l9.25 9.8 9.25-9.8c2.279-2.4 2.343-6.1 0-8.5-2.343-2.3-6.157-2.3-8.5 0l-0.75 0.8-0.75-0.8c-1.172-1.2-2.7145-1.7-4.25-1.7z"
fill="#c0392b"
/>
</svg>
<span className="uppercase text-sm font-medium tracking-wide">Support AI-Toolkit</span>
</a>
{/* Social links grid */}
<div className="px-1 py-1 border-t border-gray-800">