feat(jobs)!: SnapOtter 2.0 phase 2 job spine: async queues, worker pools, object storage, admin dashboard (#217)

This commit is contained in:
SnapOtter
2026-06-13 10:17:13 +08:00
parent 1c724d5d21
commit c451b939c7
130 changed files with 10438 additions and 3592 deletions
@@ -1,4 +1,7 @@
import { Loader2, Upload } from "lucide-react";
import { Loader2, Upload, X } from "lucide-react";
import { useState } from "react";
import { useTranslation } from "@/contexts/i18n-context";
import { useFileStore } from "@/stores/file-store";
interface ProgressCardProps {
active: boolean;
@@ -10,6 +13,11 @@ interface ProgressCardProps {
}
export function ProgressCard({ active, phase, label, stage, percent, elapsed }: ProgressCardProps) {
const { t } = useTranslation();
const activeJobId = useFileStore((s) => s.activeJobId);
const cancelCurrentJob = useFileStore((s) => s.cancelCurrentJob);
const [canceling, setCanceling] = useState(false);
if (!active) return null;
const icon =
@@ -45,6 +53,24 @@ export function ProgressCard({ active, phase, label, stage, percent, elapsed }:
style={{ width: `${Math.min(100, percent)}%` }}
/>
</div>
{activeJobId && cancelCurrentJob && (
<button
type="button"
disabled={canceling}
onClick={async () => {
setCanceling(true);
try {
await cancelCurrentJob();
} finally {
setCanceling(false);
}
}}
className="w-full py-1.5 rounded-lg border border-border text-xs text-muted-foreground hover:text-foreground hover:bg-muted flex items-center justify-center gap-1.5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
<X className="h-3 w-3" />
{t.common.cancel}
</button>
)}
</div>
);
}