Spaces:
Sleeping
Sleeping
File size: 5,449 Bytes
05c5ed5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | "use client";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "ui/card";
import { Avatar, AvatarFallback, AvatarImage } from "ui/avatar";
import { useTranslations } from "next-intl";
import { format } from "date-fns";
import { cn } from "lib/utils";
import { ShareableActions, type Visibility } from "./shareable-actions";
import { WorkflowSummary } from "app-types/workflow";
import { AgentSummary } from "app-types/agent";
import { MCPServerInfo } from "app-types/mcp";
import { MCPIcon } from "ui/mcp-icon";
import Link from "next/link";
export interface ShareableIcon {
value?: string;
style?: {
backgroundColor?: string;
};
}
interface ShareableCardProps {
type: "agent" | "workflow" | "mcp";
item: AgentSummary | WorkflowSummary | MCPServerInfo;
isOwner?: boolean;
href: string;
onBookmarkToggle?: (itemId: string, isBookmarked: boolean) => void;
onVisibilityChange?: (itemId: string, visibility: Visibility) => void;
onDelete?: (itemId: string) => void;
isVisibilityChangeLoading?: boolean;
isBookmarkToggleLoading?: boolean;
isDeleteLoading?: boolean;
actionsDisabled?: boolean;
}
export function ShareableCard({
type,
item,
isOwner = true,
href,
onBookmarkToggle,
onVisibilityChange,
onDelete,
isBookmarkToggleLoading,
isVisibilityChangeLoading,
isDeleteLoading,
actionsDisabled,
}: ShareableCardProps) {
const t = useTranslations();
const isPublished = (item as WorkflowSummary).isPublished;
const isBookmarked =
type === "mcp" ? undefined : (item as AgentSummary).isBookmarked;
return (
<Link href={href} title={item.name}>
<Card
className={cn(
"w-full min-h-[196px] @container transition-colors group flex flex-col gap-3 cursor-pointer hover:bg-input",
)}
data-testid={`${type}-card`}
data-item-name={item.name}
data-item-id={item.id}
>
<CardHeader className="shrink gap-y-0">
<CardTitle className="flex gap-3 items-stretch min-w-0">
<div
style={{ backgroundColor: item.icon?.style?.backgroundColor }}
className="p-2 rounded-lg flex items-center justify-center ring ring-background border shrink-0"
>
{type === "mcp" ? (
<MCPIcon className="fill-white size-6" />
) : (
<Avatar className="size-6">
<AvatarImage src={item.icon?.value} />
<AvatarFallback />
</Avatar>
)}
</div>
<div className="flex flex-col justify-around min-w-0 flex-1 overflow-hidden">
<span
className="truncate font-medium"
data-testid={`${type}-card-name`}
>
{item.name}
</span>
<div className="text-xs text-muted-foreground flex items-center gap-1 min-w-0">
<time className="shrink-0">
{format(item.updatedAt || new Date(), "MMM d, yyyy")}
</time>
{type === "workflow" && !isPublished && (
<span className="px-2 rounded-sm bg-secondary text-foreground shrink-0">
{t("Workflow.draft")}
</span>
)}
</div>
</div>
</CardTitle>
</CardHeader>
<CardContent className="min-h-0 grow">
<CardDescription className="text-xs line-clamp-3 break-words overflow-hidden">
{item.description}
</CardDescription>
</CardContent>
<CardFooter className="shrink min-h-0 overflow-visible">
<div className="flex items-center justify-between w-full min-w-0">
<div onClick={(e) => e.stopPropagation()}>
<ShareableActions
type={type}
visibility={item.visibility}
isOwner={isOwner}
isBookmarked={isBookmarked}
editHref={href}
onVisibilityChange={
onVisibilityChange
? (visibility) => onVisibilityChange(item.id, visibility)
: undefined
}
onBookmarkToggle={
onBookmarkToggle
? (isBookmarked) => onBookmarkToggle(item.id, isBookmarked)
: undefined
}
onDelete={onDelete ? () => onDelete(item.id) : undefined}
isBookmarkToggleLoading={isBookmarkToggleLoading}
isVisibilityChangeLoading={isVisibilityChangeLoading}
isDeleteLoading={isDeleteLoading}
disabled={actionsDisabled}
/>
</div>
{!isOwner && item.userName && (
<div className="flex items-center gap-1.5 min-w-0">
<Avatar className="size-4 ring shrink-0 rounded-full">
<AvatarImage src={item.userAvatar || undefined} />
<AvatarFallback>
{item.userName[0]?.toUpperCase()}
</AvatarFallback>
</Avatar>
<span className="text-xs text-muted-foreground font-medium truncate min-w-0">
{item.userName}
</span>
</div>
)}
</div>
</CardFooter>
</Card>
</Link>
);
}
|