LeLab / src /components /jobs /HubModelCard.tsx
GitHub CI
Sync from leLab @ 7317f7103e3a9d7f45fe4c0d6e4660a8f9d295e3
fc9bd9f
import React from "react";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { HubModel } from "@/lib/jobsApi";
import { ExternalLink, Lock, Upload } from "lucide-react";
interface Props {
model: HubModel;
}
function relativeTime(iso: string | null): string {
if (!iso) return "—";
const t = Date.parse(iso);
if (Number.isNaN(t)) return "—";
const diff = Math.max(0, (Date.now() - t) / 1000);
if (diff < 60) return `${Math.floor(diff)}s ago`;
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
return `${Math.floor(diff / 86400)}d ago`;
}
const HubModelCard: React.FC<Props> = ({ model }) => {
const url = `https://huggingface.co/${model.repo_id}`;
const shortName = model.repo_id.includes("/")
? model.repo_id.split("/").slice(1).join("/")
: model.repo_id;
return (
<Card
onClick={() => window.open(url, "_blank", "noopener,noreferrer")}
className="bg-slate-800/50 border-slate-700 rounded-xl cursor-pointer hover:border-slate-500 transition-colors"
>
<CardContent className="p-4 space-y-3">
<div className="flex items-start justify-between gap-2">
<div className="flex items-center gap-1.5 text-xs font-semibold text-sky-400">
<Upload className="w-3.5 h-3.5" />
Uploaded
</div>
<Button
variant="ghost"
size="icon"
asChild
className="h-7 w-7 text-slate-400 hover:text-white"
aria-label="View on Hub"
>
<a
href={url}
target="_blank"
rel="noopener noreferrer"
onClick={(e) => e.stopPropagation()}
>
<ExternalLink className="w-3.5 h-3.5" />
</a>
</Button>
</div>
<div>
<div
className="text-white font-semibold truncate flex items-center gap-1.5"
title={model.repo_id}
>
{model.private ? (
<Lock className="w-3.5 h-3.5 text-slate-400 shrink-0" />
) : null}
<span className="truncate">{shortName}</span>
</div>
<div className="text-xs text-slate-400 truncate" title={model.repo_id}>
{model.repo_id} · updated {relativeTime(model.last_modified)}
</div>
</div>
</CardContent>
</Card>
);
};
export default HubModelCard;