Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@ import {
HoverCardContent,
HoverCardTrigger,
} from "@superset/ui/hover-card";
import { Separator } from "@superset/ui/separator";
import { toast } from "@superset/ui/sonner";
import { cn } from "@superset/ui/utils";
import { LuLoaderCircle, LuX } from "react-icons/lu";
import { STROKE_WIDTH } from "renderer/screens/main/components/WorkspaceSidebar/constants";
import { STATUS_PRIORITY } from "shared/tabs-types";
import { useDashboardSidebarAgentKill } from "../../hooks/useDashboardSidebarAgentKill";
import { useDashboardSidebarChipHoverSuppression } from "../../hooks/useDashboardSidebarChipHoverSuppression";
import type { DashboardSidebarRunningAgent } from "../../hooks/useDashboardSidebarWorkspaceRunningAgents";
import { DashboardSidebarAgentAvatar } from "./components/DashboardSidebarAgentAvatar";
Expand All @@ -24,14 +19,13 @@ interface DashboardSidebarAgentsChipProps {
/**
* Running-agents chip on the workspace row: one avatar (the agent whose
* status most needs attention, newest session on ties) plus the total count.
* Hovering or clicking the chip opens a card listing each agent with its own
* open/stop actions; clicking the chip again closes the card.
* Hovering or clicking the chip opens a card listing each agent with an
* open action; clicking the chip again closes the card.
*/
export function DashboardSidebarAgentsChip({
workspaceId,
agents,
}: DashboardSidebarAgentsChipProps) {
const { isPending, killAgents } = useDashboardSidebarAgentKill(workspaceId);
const { isOpen, onOpenChange, onPointerEnter, onPointerLeave, toggleOpen } =
useDashboardSidebarChipHoverSuppression();

Expand All @@ -44,20 +38,6 @@ export function DashboardSidebarAgentsChip({
return agent.startedAt > best.startedAt ? agent : best;
});

const handleStopAll = async () => {
if (isPending) return;
const stoppedCount = await killAgents(
agents.map((agent) => agent.terminalId),
);
if (stoppedCount > 0) {
toast.success(
stoppedCount === 1
? "Stopped 1 agent"
: `Stopped ${stoppedCount} agents`,
);
}
};

return (
<HoverCard
open={isOpen}
Expand All @@ -83,24 +63,15 @@ export function DashboardSidebarAgentsChip({
event.stopPropagation();
}
}}
disabled={isPending}
aria-busy={isPending}
aria-expanded={isOpen}
aria-label={`${agents.length} running agents — ${isOpen ? "hide" : "show"} details`}
className={cn(
"group/chip h-[18px] overflow-visible bg-muted/60 px-1.5 py-0 text-[9px] font-medium tabular-nums text-muted-foreground",
"[&>svg]:size-2.5 hover:bg-muted hover:text-foreground disabled:opacity-70",
"[&>svg]:size-2.5 hover:bg-muted hover:text-foreground",
)}
>
<DashboardSidebarAgentAvatar agent={primaryAgent} />
{isPending ? (
<LuLoaderCircle
className="size-2.5 shrink-0 animate-spin"
strokeWidth={STROKE_WIDTH}
/>
) : (
<span className="shrink-0">{agents.length}</span>
)}
<span className="shrink-0">{agents.length}</span>
</button>
</Badge>
</HoverCardTrigger>
Expand All @@ -123,16 +94,6 @@ export function DashboardSidebarAgentsChip({
/>
))}
</div>
<Separator className="my-1" />
<button
type="button"
onClick={() => void handleStopAll()}
disabled={isPending}
className="flex w-full items-center gap-1.5 rounded-sm px-2 py-1 text-xs hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:opacity-70"
>
<LuX className="size-3" strokeWidth={STROKE_WIDTH} />
Stop all agents
</button>
</HoverCardContent>
</HoverCard>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { cn } from "@superset/ui/utils";
import { useNavigate } from "@tanstack/react-router";
import { LuX } from "react-icons/lu";
import { navigateToV2Workspace } from "renderer/routes/_authenticated/_dashboard/utils/workspace-navigation";
import { getStatusTooltip } from "renderer/screens/main/components/StatusIndicator";
import { STROKE_WIDTH } from "renderer/screens/main/components/WorkspaceSidebar/constants";
import { useDashboardSidebarAgentKill } from "../../../../hooks/useDashboardSidebarAgentKill";
import type {
DashboardSidebarRunningAgent,
RunningAgentStatus,
Expand All @@ -29,7 +26,6 @@ export function DashboardSidebarAgentHoverRow({
agent,
}: DashboardSidebarAgentHoverRowProps) {
const navigate = useNavigate();
const { isPending, killAgent } = useDashboardSidebarAgentKill(workspaceId);

const handleOpen = () => {
void navigateToV2Workspace(workspaceId, navigate, {
Expand All @@ -44,7 +40,7 @@ export function DashboardSidebarAgentHoverRow({
agent.status === "idle" ? "Idle" : getStatusTooltip(agent.status);

return (
<div className="group/row flex items-center gap-1.5 rounded-sm px-2 py-1 hover:bg-muted">
<div className="flex items-center gap-1.5 rounded-sm px-2 py-1 hover:bg-muted">
<button
type="button"
onClick={handleOpen}
Expand All @@ -53,29 +49,10 @@ export function DashboardSidebarAgentHoverRow({
<DashboardSidebarAgentAvatar agent={agent} />
<span className="min-w-0 truncate text-xs">{agent.label}</span>
</button>
{/* Status text and the × occupy one grid cell, swapped via visibility
so the row never changes size on hover. */}
<span className="grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1">
<span
className={cn(
"text-[10px] group-focus-within/row:invisible group-hover/row:invisible",
STATUS_TEXT_CLASS[agent.status],
)}
>
{statusLabel}
</span>
<button
type="button"
onClick={() => {
if (isPending) return;
void killAgent(agent.terminalId);
}}
disabled={isPending}
aria-label={`Stop ${agent.label}`}
className="invisible flex size-5 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-focus-within/row:visible group-hover/row:visible"
>
<LuX className="size-3" strokeWidth={STROKE_WIDTH} />
</button>
<span
className={cn("shrink-0 text-[10px]", STATUS_TEXT_CLASS[agent.status])}
>
{statusLabel}
</span>
</div>
);
Expand Down

This file was deleted.

This file was deleted.

Loading