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
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 1m4s
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user