fix: cursor-pointer on read-only rows, stable sort, simplify handleCrudPanelChange

This commit is contained in:
Ishaan Jaffer 2026-03-11 19:08:49 -07:00
parent c3540b65d4
commit fd2eeb751c
5 changed files with 29 additions and 20 deletions

View file

@ -315,11 +315,6 @@ model LiteLLM_MCPServerTable {
is_byok Boolean @default(false)
byok_description String[] @default([])
byok_api_key_help_url String?
approval_status String @default("approved")
submitted_by String?
submitted_at DateTime?
reviewed_at DateTime?
review_notes String?
}
// Per-user BYOK credentials for MCP servers

View file

@ -85,11 +85,8 @@ const MCPToolPermissions: React.FC<MCPToolPermissionsProps> = ({
});
}, [servers]);
const handleCrudPanelChange = (serverId: string, allowed: string[] | undefined) => {
// `undefined` from the panel means "allow all" — expand to the full tool list
// rather than collapsing to [] ("allow none").
const resolved = allowed ?? (serverTools[serverId] || []).map((t) => t.name);
onChange({ ...toolPermissions, [serverId]: resolved });
const handleCrudPanelChange = (serverId: string, allowed: string[]) => {
onChange({ ...toolPermissions, [serverId]: allowed });
};
const handleSelectAll = (serverId: string) => {

View file

@ -30,8 +30,8 @@ interface McpCrudPermissionPanelProps {
* An empty array means "allow none".
*/
value: string[] | undefined;
/** Called whenever the allowed set changes. */
onChange: (allowed: string[] | undefined) => void;
/** Called whenever the allowed set changes. Always emits a concrete string[]. */
onChange: (allowed: string[]) => void;
readOnly?: boolean;
}
@ -205,9 +205,9 @@ const McpCrudPermissionPanel: React.FC<McpCrudPermissionPanelProps> = ({
return (
<div
key={tool.name}
className={`flex items-start gap-3 px-4 py-2.5 cursor-pointer transition-colors hover:bg-gray-50 ${
allowed ? "" : "opacity-60"
}`}
className={`flex items-start gap-3 px-4 py-2.5 transition-colors hover:bg-gray-50 ${
!readOnly ? "cursor-pointer" : ""
} ${allowed ? "" : "opacity-60"}`}
onClick={() => toggleTool(tool.name)}
>
<Checkbox

View file

@ -129,6 +129,7 @@ const MCPServers: React.FC<MCPServerProps> = ({ accessToken, userRole, userID })
);
}
const sorted = [...filtered].sort((a, b) => {
if (!a.created_at && !b.created_at) return 0;
if (!a.created_at) return 1;
if (!b.created_at) return -1;
return new Date(b.created_at).getTime() - new Date(a.created_at).getTime();

View file

@ -453,11 +453,27 @@ const MCPToolConfiguration: React.FC<MCPToolConfigurationProps> = ({
{/* CRUD grouped view */}
{viewMode === "crud" && (
<McpCrudPermissionPanel
tools={tools}
value={allowedTools}
onChange={(allowed) => onAllowedToolsChange(allowed ?? tools.map((t) => t.name))}
/>
<>
<Input
placeholder="Search tools by name or description..."
prefix={<SearchOutlined className="text-gray-400" />}
value={toolSearchTerm}
onChange={(e) => setToolSearchTerm(e.target.value)}
allowClear
className="rounded-lg"
size="large"
/>
<McpCrudPermissionPanel
tools={tools.filter(
(t) =>
!toolSearchTerm ||
t.name.toLowerCase().includes(toolSearchTerm.toLowerCase()) ||
(t.description ?? "").toLowerCase().includes(toolSearchTerm.toLowerCase())
)}
value={allowedTools}
onChange={(allowed) => onAllowedToolsChange(allowed)}
/>
</>
)}
{/* Flat list view */}