"use client" import { useState, useRef, useEffect } from "react" import { createPortal } from "react-dom" import Link from "next/link" import { cn } from "@/lib/utils" interface RunActionsMenuProps { runId: string provider: string benchmark: string status: string onAddToLeaderboard: (data: { version?: string; notes?: string }) => Promise onDelete: () => void onTerminate?: () => void onContinue?: () => void } export function RunActionsMenu({ runId, provider, benchmark, status, onAddToLeaderboard, onDelete, onTerminate, onContinue, }: RunActionsMenuProps) { const [open, setOpen] = useState(false) const [showLeaderboardPopover, setShowLeaderboardPopover] = useState(false) const [position, setPosition] = useState({ top: 0, left: 0 }) const [popoverPosition, setPopoverPosition] = useState({ top: 0, left: 0 }) const triggerRef = useRef(null) const dropdownRef = useRef(null) const popoverRef = useRef(null) const isCompleted = status === "completed" const isRunning = status === "running" || status === "pending" const isStopping = status === "stopping" const isFailed = status === "failed" const isPartial = status === "partial" const canContinue = isFailed || isPartial // Calculate dropdown position useEffect(() => { if (open && triggerRef.current) { const rect = triggerRef.current.getBoundingClientRect() const dropdownWidth = 192 setPosition({ top: rect.bottom + 4, left: rect.right - dropdownWidth, }) } }, [open]) // Calculate popover position useEffect(() => { if (showLeaderboardPopover && triggerRef.current) { const rect = triggerRef.current.getBoundingClientRect() const popoverWidth = 320 setPopoverPosition({ top: rect.bottom + 4, left: Math.max(16, rect.right - popoverWidth), }) } }, [showLeaderboardPopover]) // Click outside handler useEffect(() => { function handleClickOutside(event: MouseEvent) { const target = event.target as Node // Handle dropdown if (open && triggerRef.current && dropdownRef.current) { if (!triggerRef.current.contains(target) && !dropdownRef.current.contains(target)) { setOpen(false) } } // Handle popover if (showLeaderboardPopover && popoverRef.current) { if (!popoverRef.current.contains(target)) { setShowLeaderboardPopover(false) } } } document.addEventListener("mousedown", handleClickOutside) return () => document.removeEventListener("mousedown", handleClickOutside) }, [open, showLeaderboardPopover]) const handleOpenLeaderboard = () => { setOpen(false) setShowLeaderboardPopover(true) } return ( <> {/* Dropdown menu */} {open && typeof document !== "undefined" && createPortal(
setOpen(false)} > view details {canContinue && ( <>
)}
{isRunning || isStopping ? ( ) : ( )}
, document.body )} {/* Leaderboard popover */} {showLeaderboardPopover && typeof document !== "undefined" && createPortal( { await onAddToLeaderboard(data) setShowLeaderboardPopover(false) }} onClose={() => setShowLeaderboardPopover(false)} />, document.body )} ) } // Separate popover component for adding to leaderboard import { forwardRef } from "react" interface LeaderboardPopoverProps { position: { top: number; left: number } provider: string benchmark: string onSubmit: (data: { version?: string; notes?: string }) => Promise onClose: () => void } const LeaderboardPopover = forwardRef( ({ position, provider, benchmark, onSubmit, onClose }, ref) => { const [editingVersion, setEditingVersion] = useState(false) const [version, setVersion] = useState("") const [notes, setNotes] = useState("") const [isSubmitting, setIsSubmitting] = useState(false) const versionInputRef = useRef(null) useEffect(() => { if (editingVersion && versionInputRef.current) { versionInputRef.current.focus() } }, [editingVersion]) const handleSubmit = async () => { try { setIsSubmitting(true) await onSubmit({ version: version.trim() || undefined, notes: notes.trim() || undefined, }) } catch (e) { alert(e instanceof Error ? e.message : "failed to add to leaderboard") } finally { setIsSubmitting(false) } } return (
{/* Header */}
add to leaderboard
{/* Provider / Benchmark */}
{provider} / {benchmark}
{/* Version */}
{!editingVersion ? ( ) : ( setVersion(e.target.value)} onBlur={() => setEditingVersion(false)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === "Escape") { setEditingVersion(false) } }} placeholder="baseline" className="w-full px-2 py-1.5 text-sm bg-[#222222] border border-[#444444] rounded text-text-primary placeholder-text-muted focus:outline-none focus:border-accent lowercase" /> )}
{/* Notes */}