Refactor Admin and Settings UI to Ethereal Precision aesthetic and improve note import/export functionality
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 1m4s

This commit is contained in:
Antigravity
2026-05-03 12:51:25 +00:00
parent 635e516616
commit b611ec874d
27 changed files with 1151 additions and 1081 deletions

View File

@@ -1,7 +1,6 @@
'use client'
import { useState, useTransition } from 'react'
import { Card } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import {
@@ -117,59 +116,71 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
}
return (
<div className="space-y-6">
<div className="columns-1 lg:columns-2 gap-6 space-y-6">
{/* Section 1: What is MCP */}
<Card className="p-6">
<div className="flex items-start gap-3">
<Info className="h-5 w-5 text-blue-500 mt-0.5 shrink-0" />
<div className="bg-card rounded-lg border border-border shadow-sm overflow-hidden break-inside-avoid">
<div className="flex items-center gap-3 p-6 border-b border-border">
<div className="w-10 h-10 rounded-full bg-blue-500/10 flex items-center justify-center text-blue-500 shrink-0">
<Info className="h-5 w-5" />
</div>
<div>
<h2 className="text-lg font-semibold">{t('mcpSettings.whatIsMcp.title')}</h2>
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
{t('mcpSettings.whatIsMcp.description')}
</p>
<a
href="https://modelcontextprotocol.io"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-sm text-blue-600 dark:text-blue-400 hover:underline mt-2"
>
{t('mcpSettings.whatIsMcp.learnMore')}
<ExternalLink className="h-3 w-3" />
</a>
<h2 className="font-semibold text-foreground">{t('mcpSettings.whatIsMcp.title')}</h2>
</div>
</div>
</Card>
<div className="p-6">
<p className="text-sm text-muted-foreground mt-1">
{t('mcpSettings.whatIsMcp.description')}
</p>
<a
href="https://modelcontextprotocol.io"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-sm text-blue-600 hover:underline mt-4"
>
{t('mcpSettings.whatIsMcp.learnMore')}
<ExternalLink className="h-3 w-3" />
</a>
</div>
</div>
{/* Section 2: Server Status */}
<Card className="p-6">
<div className="flex items-center gap-3 mb-4">
<Server className="h-5 w-5 shrink-0" />
<h2 className="text-lg font-semibold">{t('mcpSettings.serverStatus.title')}</h2>
</div>
<div className="space-y-2 text-sm">
<div className="flex items-center gap-2">
<span className="text-gray-500">{t('mcpSettings.serverStatus.mode')}:</span>
<Badge variant="secondary">{serverStatus.mode.toUpperCase()}</Badge>
<div className="bg-card rounded-lg border border-border shadow-sm overflow-hidden break-inside-avoid">
<div className="flex items-center gap-3 p-6 border-b border-border">
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary shrink-0">
<Server className="h-5 w-5" />
</div>
<div>
<h2 className="font-semibold text-foreground">{t('mcpSettings.serverStatus.title')}</h2>
</div>
{serverStatus.mode === 'sse' && serverStatus.url && (
<div className="flex items-center gap-2">
<span className="text-gray-500">{t('mcpSettings.serverStatus.url')}:</span>
<code className="text-xs bg-gray-100 dark:bg-gray-800 px-2 py-0.5 rounded">
{serverStatus.url}
</code>
</div>
)}
</div>
</Card>
<div className="p-6">
<div className="space-y-4 text-sm">
<div className="flex items-center justify-between">
<span className="text-muted-foreground">{t('mcpSettings.serverStatus.mode')}</span>
<Badge variant="secondary">{serverStatus.mode.toUpperCase()}</Badge>
</div>
{serverStatus.mode === 'sse' && serverStatus.url && (
<div className="space-y-1.5">
<span className="text-muted-foreground block">{t('mcpSettings.serverStatus.url')}</span>
<code className="text-xs bg-muted p-2 rounded block break-all font-mono">
{serverStatus.url}
</code>
</div>
)}
</div>
</div>
</div>
{/* Section 3: API Keys */}
<Card className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="bg-card rounded-lg border border-border shadow-sm overflow-hidden break-inside-avoid">
<div className="flex items-center justify-between p-6 border-b border-border">
<div className="flex items-center gap-3">
<Key className="h-5 w-5 shrink-0" />
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary shrink-0">
<Key className="h-5 w-5" />
</div>
<div>
<h2 className="text-lg font-semibold">{t('mcpSettings.apiKeys.title')}</h2>
<p className="text-sm text-gray-500">
<h2 className="font-semibold text-foreground">{t('mcpSettings.apiKeys.title')}</h2>
<p className="text-sm text-muted-foreground">
{t('mcpSettings.apiKeys.description')}
</p>
</div>
@@ -188,28 +199,32 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
</Dialog>
</div>
{keys.length === 0 ? (
<div className="text-center py-8 text-gray-500">
<Key className="h-8 w-8 mx-auto mb-2 opacity-50" />
<p>{t('mcpSettings.apiKeys.empty')}</p>
</div>
) : (
<div className="space-y-3">
{keys.map(k => (
<KeyCard
key={k.shortId}
keyInfo={k}
onRevoke={handleRevoke}
onDelete={handleDelete}
isPending={isPending}
/>
))}
</div>
)}
</Card>
<div className="p-6">
{keys.length === 0 ? (
<div className="text-center py-8 text-muted-foreground">
<Key className="h-8 w-8 mx-auto mb-2 opacity-50" />
<p>{t('mcpSettings.apiKeys.empty')}</p>
</div>
) : (
<div className="space-y-3">
{keys.map(k => (
<KeyCard
key={k.shortId}
keyInfo={k}
onRevoke={handleRevoke}
onDelete={handleDelete}
isPending={isPending}
/>
))}
</div>
)}
</div>
</div>
{/* Section 4: Configuration Instructions */}
<ConfigInstructions serverStatus={serverStatus} />
<div className="break-inside-avoid">
<ConfigInstructions serverStatus={serverStatus} />
</div>
{/* Raw Key Display Dialog */}
<Dialog open={!!showRawKey} onOpenChange={(open) => { if (!open) setShowRawKey(null) }}>
@@ -222,9 +237,9 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
</DialogHeader>
<div className="space-y-3">
<div>
<Label className="text-xs text-gray-500">{rawKeyName}</Label>
<Label className="text-xs text-muted-foreground">{rawKeyName}</Label>
<div className="flex items-center gap-2 mt-1">
<code className="flex-1 text-xs bg-gray-100 dark:bg-gray-800 p-3 rounded break-all font-mono">
<code className="flex-1 text-xs bg-muted p-3 rounded break-all font-mono">
{showRawKey}
</code>
<Button
@@ -330,7 +345,7 @@ function KeyCard({
}
return (
<div className="flex items-center justify-between p-4 rounded-lg border bg-gray-50 dark:bg-gray-900">
<div className="flex items-center justify-between p-4 rounded-lg border bg-muted/50">
<div className="space-y-1">
<div className="flex items-center gap-2">
<span className="font-medium text-sm">{keyInfo.name}</span>
@@ -340,7 +355,7 @@ function KeyCard({
: t('mcpSettings.apiKeys.revoked')}
</Badge>
</div>
<div className="flex gap-4 text-xs text-gray-500">
<div className="flex gap-4 text-xs text-muted-foreground">
<span>
{t('mcpSettings.apiKeys.createdAt')}: {formatDate(keyInfo.createdAt)}
</span>
@@ -436,23 +451,25 @@ Transport: Streamable HTTP`,
]
return (
<Card className="p-6">
<div className="flex items-center gap-3 mb-4">
<ExternalLink className="h-5 w-5 shrink-0" />
<div className="bg-card rounded-lg border border-border shadow-sm overflow-hidden">
<div className="flex items-center gap-3 p-6 border-b border-border">
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary shrink-0">
<ExternalLink className="h-5 w-5" />
</div>
<div>
<h2 className="text-lg font-semibold">
<h2 className="font-semibold text-foreground">
{t('mcpSettings.configInstructions.title')}
</h2>
<p className="text-sm text-gray-500">
<p className="text-sm text-muted-foreground">
{t('mcpSettings.configInstructions.description')}
</p>
</div>
</div>
<div className="space-y-2">
<div className="p-6 space-y-2">
{configs.map(cfg => (
<div key={cfg.id} className="border rounded-lg overflow-hidden">
<button
className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors"
className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-muted transition-colors"
onClick={() => setExpanded(expanded === cfg.id ? null : cfg.id)}
>
<span className="font-medium text-sm">{cfg.title}</span>
@@ -464,8 +481,8 @@ Transport: Streamable HTTP`,
</button>
{expanded === cfg.id && (
<div className="px-4 pb-4">
<p className="text-sm text-gray-500 mb-2">{cfg.description}</p>
<pre className="text-xs bg-gray-100 dark:bg-gray-800 p-3 rounded overflow-x-auto">
<p className="text-sm text-muted-foreground mb-2">{cfg.description}</p>
<pre className="text-xs bg-muted p-3 rounded overflow-x-auto">
<code>{cfg.snippet}</code>
</pre>
</div>
@@ -473,6 +490,6 @@ Transport: Streamable HTTP`,
</div>
))}
</div>
</Card>
</div>
)
}