- Added a new job status 'extracting_pages' to represent the first sub-phase of thumbnail generation. - Updated the database schema to include a timestamp for when thumbnail generation starts. - Enhanced job progress components to handle the new status, including UI updates for displaying progress and status labels. - Refactored job-related logic to accommodate the two-phase process: extracting pages and generating thumbnails. - Adjusted SQL queries and job detail responses to include the new fields and statuses. This change improves the clarity of job processing states and enhances user feedback during the thumbnail generation process.
135 lines
3.7 KiB
TypeScript
135 lines
3.7 KiB
TypeScript
import { ReactNode } from "react";
|
|
|
|
type BadgeVariant =
|
|
| "default"
|
|
| "primary"
|
|
| "secondary"
|
|
| "destructive"
|
|
| "outline"
|
|
| "success"
|
|
| "warning"
|
|
| "error"
|
|
| "muted"
|
|
| "unread"
|
|
| "in-progress"
|
|
| "completed";
|
|
|
|
interface BadgeProps {
|
|
children: ReactNode;
|
|
variant?: BadgeVariant;
|
|
className?: string;
|
|
}
|
|
|
|
const variantStyles: Record<BadgeVariant, string> = {
|
|
// shadcn/ui compatible
|
|
default: "bg-primary/90 text-primary-foreground border-transparent hover:bg-primary/80 backdrop-blur-md",
|
|
secondary: "bg-secondary/80 text-secondary-foreground border-transparent hover:bg-secondary/60 backdrop-blur-md",
|
|
destructive: "bg-destructive/90 text-destructive-foreground border-transparent hover:bg-destructive/80 backdrop-blur-md",
|
|
outline: "text-foreground border-border bg-background/50",
|
|
|
|
// Legacy + Additional variants
|
|
primary: "bg-primary/90 text-primary-foreground backdrop-blur-md",
|
|
success: "bg-success/90 text-success-foreground backdrop-blur-md",
|
|
warning: "bg-warning/90 text-white backdrop-blur-md",
|
|
error: "bg-destructive/90 text-destructive-foreground backdrop-blur-md",
|
|
muted: "bg-muted/60 text-muted-foreground backdrop-blur-md",
|
|
|
|
// Status badges from StripStream
|
|
unread: "badge-unread backdrop-blur-md",
|
|
"in-progress": "badge-in-progress backdrop-blur-md",
|
|
completed: "badge-completed backdrop-blur-md",
|
|
};
|
|
|
|
export function Badge({ children, variant = "default", className = "" }: BadgeProps) {
|
|
return (
|
|
<span className={`
|
|
inline-flex items-center
|
|
px-2.5 py-0.5
|
|
rounded-full
|
|
text-xs font-semibold
|
|
border
|
|
transition-colors duration-200
|
|
${variantStyles[variant]}
|
|
${className}
|
|
`}>
|
|
{children}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
// Status badge for jobs/tasks
|
|
const statusVariants: Record<string, BadgeVariant> = {
|
|
running: "in-progress",
|
|
extracting_pages: "in-progress",
|
|
generating_thumbnails: "in-progress",
|
|
success: "completed",
|
|
completed: "completed",
|
|
failed: "error",
|
|
cancelled: "muted",
|
|
pending: "warning",
|
|
unread: "unread",
|
|
};
|
|
|
|
const statusLabels: Record<string, string> = {
|
|
extracting_pages: "Extracting pages",
|
|
generating_thumbnails: "Thumbnails",
|
|
};
|
|
|
|
interface StatusBadgeProps {
|
|
status: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function StatusBadge({ status, className = "" }: StatusBadgeProps) {
|
|
const key = status.toLowerCase();
|
|
const variant = statusVariants[key] || "default";
|
|
const label = statusLabels[key] ?? status;
|
|
return <Badge variant={variant} className={className}>{label}</Badge>;
|
|
}
|
|
|
|
// Job type badge
|
|
const jobTypeVariants: Record<string, BadgeVariant> = {
|
|
rebuild: "primary",
|
|
full_rebuild: "warning",
|
|
thumbnail_rebuild: "secondary",
|
|
thumbnail_regenerate: "warning",
|
|
};
|
|
|
|
const jobTypeLabels: Record<string, string> = {
|
|
rebuild: "Index",
|
|
full_rebuild: "Full Index",
|
|
thumbnail_rebuild: "Thumbnails",
|
|
thumbnail_regenerate: "Regen. Thumbnails",
|
|
cbr_to_cbz: "CBR → CBZ",
|
|
};
|
|
|
|
interface JobTypeBadgeProps {
|
|
type: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function JobTypeBadge({ type, className = "" }: JobTypeBadgeProps) {
|
|
const key = type.toLowerCase();
|
|
const variant = jobTypeVariants[key] || "default";
|
|
const label = jobTypeLabels[key] ?? type;
|
|
return <Badge variant={variant} className={className}>{label}</Badge>;
|
|
}
|
|
|
|
// Progress badge (shows percentage)
|
|
interface ProgressBadgeProps {
|
|
progress: number;
|
|
className?: string;
|
|
}
|
|
|
|
export function ProgressBadge({ progress, className = "" }: ProgressBadgeProps) {
|
|
let variant: BadgeVariant = "unread";
|
|
if (progress === 100) variant = "completed";
|
|
else if (progress > 0) variant = "in-progress";
|
|
|
|
return (
|
|
<Badge variant={variant} className={className}>
|
|
{progress}%
|
|
</Badge>
|
|
);
|
|
}
|