Spaces:
Sleeping
Sleeping
Commit
·
d83197f
1
Parent(s):
0c91a71
feat: enhance StatusIndicator with Tooltip support
Browse files- Updated StatusIndicator component to utilize Tooltip for displaying additional hover information.
- Introduced hoverInfo prop to provide context for server statuses, including sandbox URLs and error messages.
- Refactored status rendering logic for improved clarity and maintainability.
components/mcp-server-manager.tsx
CHANGED
|
@@ -37,6 +37,12 @@ import {
|
|
| 37 |
AccordionTrigger
|
| 38 |
} from "./ui/accordion";
|
| 39 |
import { KeyValuePair, MCPServer, ServerStatus, useMCP } from "@/lib/context/mcp-context";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
// Default template for a new MCP server
|
| 42 |
const INITIAL_NEW_SERVER: Omit<MCPServer, 'id'> = {
|
|
@@ -79,42 +85,67 @@ const maskValue = (value: string): string => {
|
|
| 79 |
return value.substring(0, 3) + '•'.repeat(Math.min(10, value.length - 4)) + value.substring(value.length - 1);
|
| 80 |
};
|
| 81 |
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
const isClickable = !!onClick;
|
|
|
|
| 84 |
|
| 85 |
-
const className = `flex-shrink-0 flex items-center gap-1 ${isClickable ? 'cursor-pointer
|
| 86 |
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
<div className=
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
<
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
<
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
<div className=
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
}
|
|
|
|
|
|
|
|
|
|
| 118 |
};
|
| 119 |
|
| 120 |
export const MCPServerManager = ({
|
|
@@ -466,18 +497,27 @@ export const MCPServerManager = ({
|
|
| 466 |
|
| 467 |
// UI element to display the correct server URL
|
| 468 |
const getServerDisplayUrl = (server: MCPServer): string => {
|
| 469 |
-
//
|
| 470 |
-
if (server.type === 'stdio' && server.sandboxUrl &&
|
| 471 |
-
(server.status === 'connected' || server.status === 'connecting')) {
|
| 472 |
-
return server.sandboxUrl;
|
| 473 |
-
}
|
| 474 |
-
|
| 475 |
-
// Otherwise show the configured URL or command
|
| 476 |
return server.type === 'sse'
|
| 477 |
? server.url
|
| 478 |
: `${server.command} ${server.args?.join(' ')}`;
|
| 479 |
};
|
| 480 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
return (
|
| 482 |
<Dialog open={open} onOpenChange={onOpenChange}>
|
| 483 |
<DialogContent className="sm:max-w-[480px] max-h-[85vh] overflow-hidden flex flex-col">
|
|
@@ -554,6 +594,7 @@ export const MCPServerManager = ({
|
|
| 554 |
<StatusIndicator
|
| 555 |
status={server.status}
|
| 556 |
onClick={() => server.errorMessage && toast.error(server.errorMessage)}
|
|
|
|
| 557 |
/>
|
| 558 |
|
| 559 |
{/* Server actions */}
|
|
|
|
| 37 |
AccordionTrigger
|
| 38 |
} from "./ui/accordion";
|
| 39 |
import { KeyValuePair, MCPServer, ServerStatus, useMCP } from "@/lib/context/mcp-context";
|
| 40 |
+
import {
|
| 41 |
+
Tooltip,
|
| 42 |
+
TooltipContent,
|
| 43 |
+
TooltipProvider,
|
| 44 |
+
TooltipTrigger,
|
| 45 |
+
} from "./ui/tooltip";
|
| 46 |
|
| 47 |
// Default template for a new MCP server
|
| 48 |
const INITIAL_NEW_SERVER: Omit<MCPServer, 'id'> = {
|
|
|
|
| 85 |
return value.substring(0, 3) + '•'.repeat(Math.min(10, value.length - 4)) + value.substring(value.length - 1);
|
| 86 |
};
|
| 87 |
|
| 88 |
+
// Update the StatusIndicator to use Tooltip component
|
| 89 |
+
const StatusIndicator = ({ status, onClick, hoverInfo }: {
|
| 90 |
+
status?: ServerStatus,
|
| 91 |
+
onClick?: () => void,
|
| 92 |
+
hoverInfo?: string
|
| 93 |
+
}) => {
|
| 94 |
const isClickable = !!onClick;
|
| 95 |
+
const hasHoverInfo = !!hoverInfo;
|
| 96 |
|
| 97 |
+
const className = `flex-shrink-0 flex items-center gap-1 ${isClickable ? 'cursor-pointer' : ''}`;
|
| 98 |
|
| 99 |
+
const statusIndicator = (status: ServerStatus | undefined) => {
|
| 100 |
+
switch (status) {
|
| 101 |
+
case 'connected':
|
| 102 |
+
return (
|
| 103 |
+
<div className={className} onClick={onClick}>
|
| 104 |
+
<div className="w-2 h-2 rounded-full bg-green-500 animate-pulse" />
|
| 105 |
+
<span className="text-xs text-green-500 hover:underline">Connected</span>
|
| 106 |
+
</div>
|
| 107 |
+
);
|
| 108 |
+
case 'connecting':
|
| 109 |
+
return (
|
| 110 |
+
<div className={className} onClick={onClick}>
|
| 111 |
+
<RefreshCw className="w-3 h-3 text-amber-500 animate-spin" />
|
| 112 |
+
<span className="text-xs text-amber-500">Connecting</span>
|
| 113 |
+
</div>
|
| 114 |
+
);
|
| 115 |
+
case 'error':
|
| 116 |
+
return (
|
| 117 |
+
<div className={className} onClick={onClick}>
|
| 118 |
+
<AlertTriangle className="w-3 h-3 text-red-500" />
|
| 119 |
+
<span className="text-xs text-red-500 hover:underline">Error</span>
|
| 120 |
+
</div>
|
| 121 |
+
);
|
| 122 |
+
case 'disconnected':
|
| 123 |
+
default:
|
| 124 |
+
return (
|
| 125 |
+
<div className={className} onClick={onClick}>
|
| 126 |
+
<div className="w-2 h-2 rounded-full bg-gray-400" />
|
| 127 |
+
<span className="text-xs text-muted-foreground">Disconnected</span>
|
| 128 |
+
</div>
|
| 129 |
+
);
|
| 130 |
+
}
|
| 131 |
+
};
|
| 132 |
+
|
| 133 |
+
// Use Tooltip if we have hover info
|
| 134 |
+
if (hasHoverInfo) {
|
| 135 |
+
return (
|
| 136 |
+
<Tooltip>
|
| 137 |
+
<TooltipTrigger asChild>
|
| 138 |
+
{statusIndicator(status)}
|
| 139 |
+
</TooltipTrigger>
|
| 140 |
+
<TooltipContent side="top" align="center" className="max-w-[300px] break-all text-wrap">
|
| 141 |
+
{hoverInfo}
|
| 142 |
+
</TooltipContent>
|
| 143 |
+
</Tooltip>
|
| 144 |
+
);
|
| 145 |
}
|
| 146 |
+
|
| 147 |
+
// Otherwise just return the status indicator
|
| 148 |
+
return statusIndicator(status);
|
| 149 |
};
|
| 150 |
|
| 151 |
export const MCPServerManager = ({
|
|
|
|
| 497 |
|
| 498 |
// UI element to display the correct server URL
|
| 499 |
const getServerDisplayUrl = (server: MCPServer): string => {
|
| 500 |
+
// Always show the configured URL or command, not the sandbox URL
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 501 |
return server.type === 'sse'
|
| 502 |
? server.url
|
| 503 |
: `${server.command} ${server.args?.join(' ')}`;
|
| 504 |
};
|
| 505 |
|
| 506 |
+
// Update the hover info function to return richer content
|
| 507 |
+
const getServerStatusHoverInfo = (server: MCPServer): string | undefined => {
|
| 508 |
+
// For connected stdio servers, show the sandbox URL as hover info
|
| 509 |
+
if (server.type === 'stdio' && server.status === 'connected' && server.sandboxUrl) {
|
| 510 |
+
return `Running at: ${server.sandboxUrl}`;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
// For error status, show the error message
|
| 514 |
+
if (server.status === 'error' && server.errorMessage) {
|
| 515 |
+
return `Error: ${server.errorMessage}`;
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
return undefined;
|
| 519 |
+
};
|
| 520 |
+
|
| 521 |
return (
|
| 522 |
<Dialog open={open} onOpenChange={onOpenChange}>
|
| 523 |
<DialogContent className="sm:max-w-[480px] max-h-[85vh] overflow-hidden flex flex-col">
|
|
|
|
| 594 |
<StatusIndicator
|
| 595 |
status={server.status}
|
| 596 |
onClick={() => server.errorMessage && toast.error(server.errorMessage)}
|
| 597 |
+
hoverInfo={getServerStatusHoverInfo(server)}
|
| 598 |
/>
|
| 599 |
|
| 600 |
{/* Server actions */}
|