|
| 1 | +import { useNavigate } from "@tanstack/react-router"; |
| 2 | +import { Clock, GitBranch, Play } from "lucide-react"; |
| 3 | + |
| 4 | +import { InlineStack } from "@/components/ui/layout"; |
| 5 | +import { |
| 6 | + Tooltip, |
| 7 | + TooltipContent, |
| 8 | + TooltipTrigger, |
| 9 | +} from "@/components/ui/tooltip"; |
| 10 | +import { Paragraph, Text } from "@/components/ui/typography"; |
| 11 | +import { |
| 12 | + type RecentlyViewedItem, |
| 13 | + useRecentlyViewed, |
| 14 | +} from "@/hooks/useRecentlyViewed"; |
| 15 | +import { EDITOR_PATH, RUNS_BASE_PATH } from "@/routes/router"; |
| 16 | + |
| 17 | +function getRecentlyViewedUrl(item: RecentlyViewedItem): string { |
| 18 | + if (item.type === "pipeline") return `${EDITOR_PATH}/${item.id}`; |
| 19 | + if (item.type === "run") return `${RUNS_BASE_PATH}/${item.id}`; |
| 20 | + // component support to be added later |
| 21 | + return "/"; |
| 22 | +} |
| 23 | + |
| 24 | +const RecentlyViewedChip = ({ item }: { item: RecentlyViewedItem }) => { |
| 25 | + const navigate = useNavigate(); |
| 26 | + |
| 27 | + const tooltipContent = |
| 28 | + item.type === "run" ? `${item.name} #${item.id}` : item.name; |
| 29 | + |
| 30 | + return ( |
| 31 | + <Tooltip> |
| 32 | + <TooltipTrigger asChild> |
| 33 | + <div |
| 34 | + onClick={() => navigate({ to: getRecentlyViewedUrl(item) })} |
| 35 | + className={`flex items-center gap-1.5 pl-2 pr-2 py-1 border rounded-md cursor-pointer w-48 ${ |
| 36 | + item.type === "pipeline" |
| 37 | + ? "bg-violet-50/50 hover:bg-violet-50 border-violet-100" |
| 38 | + : "bg-emerald-50/50 hover:bg-emerald-50 border-emerald-100" |
| 39 | + }`} |
| 40 | + > |
| 41 | + {item.type === "pipeline" ? ( |
| 42 | + <GitBranch className="h-3.5 w-3.5 shrink-0 text-muted-foreground" /> |
| 43 | + ) : ( |
| 44 | + <Play className="h-3.5 w-3.5 shrink-0 text-muted-foreground" /> |
| 45 | + )} |
| 46 | + <span className="text-sm truncate">{item.name}</span> |
| 47 | + </div> |
| 48 | + </TooltipTrigger> |
| 49 | + <TooltipContent>{tooltipContent}</TooltipContent> |
| 50 | + </Tooltip> |
| 51 | + ); |
| 52 | +}; |
| 53 | + |
| 54 | +export const RecentlyViewedSection = () => { |
| 55 | + const { recentlyViewed } = useRecentlyViewed(); |
| 56 | + |
| 57 | + return ( |
| 58 | + <div className="flex flex-col gap-2"> |
| 59 | + <InlineStack blockAlign="center" gap="1"> |
| 60 | + <Clock className="h-4 w-4 text-muted-foreground" /> |
| 61 | + <Text as="h2" size="sm" weight="semibold"> |
| 62 | + Recently Viewed |
| 63 | + </Text> |
| 64 | + </InlineStack> |
| 65 | + |
| 66 | + {recentlyViewed.length === 0 ? ( |
| 67 | + <Paragraph tone="subdued" size="sm"> |
| 68 | + Nothing viewed yet. Open a pipeline or run to see it here. |
| 69 | + </Paragraph> |
| 70 | + ) : ( |
| 71 | + <div className="flex gap-2"> |
| 72 | + {recentlyViewed.map((item) => ( |
| 73 | + <RecentlyViewedChip key={`${item.type}-${item.id}`} item={item} /> |
| 74 | + ))} |
| 75 | + </div> |
| 76 | + )} |
| 77 | + </div> |
| 78 | + ); |
| 79 | +}; |
0 commit comments