Skip to content

Commit ccdbc9e

Browse files
committed
improve incidents ui. Add Mcp usage card to Credentials page.
1 parent e257fd1 commit ccdbc9e

5 files changed

Lines changed: 100 additions & 21 deletions

File tree

packages/dashboard/src/app/(layout)/credentials/components/ApiKeyDisplay.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import { useState, useEffect } from "react"
44
import { Button } from "@/components/ui/button"
55
import { Copy, CopyCheck, RefreshCw } from "lucide-react"
66
import { toast } from "sonner"
7+
import {useRouter} from "next/navigation";
78

89
export const ApiKeyDisplay = () => {
910
const [key, setKey] = useState<string | null>(null)
1011
const [isCopied, setIsCopied] = useState(false)
1112
const [isReissuing, setIsReissuing] = useState(false)
13+
const router = useRouter()
1214

1315
useEffect(() => {
1416
fetchApiKey()
@@ -48,6 +50,7 @@ export const ApiKeyDisplay = () => {
4850
const data = await response.json()
4951
setKey(data.apiKey)
5052
toast.success("API key reissued successfully")
53+
router.refresh()
5154
} catch (err) {
5255
console.error("Failed to reissue API key:", err)
5356
toast.error("Failed to reissue API key")
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"use client"
2+
3+
import {FC, useState} from "react"
4+
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/components/ui/card"
5+
import {Button} from "@/components/ui/button"
6+
import {Copy, CopyCheck} from "lucide-react"
7+
import Link from "next/link";
8+
9+
interface MCPConfigProps {
10+
apiKey: string
11+
}
12+
13+
14+
export const MCPConfig: FC<MCPConfigProps> = ({apiKey}) => {
15+
const [isCopied, setIsCopied] = useState(false)
16+
17+
const config = `{
18+
"mcpServers": {
19+
"api200": {
20+
"command": "npx",
21+
"args": [
22+
"api200-mcp@latest"
23+
],
24+
"env": {
25+
"USER_KEY": "${apiKey}"
26+
}
27+
}
28+
}
29+
}`
30+
31+
const handleCopy = async () => {
32+
try {
33+
await navigator.clipboard.writeText(config)
34+
setIsCopied(true)
35+
setTimeout(() => setIsCopied(false), 2000)
36+
} catch (err) {
37+
console.error('Failed to copy MCP config:', err)
38+
}
39+
}
40+
41+
return (
42+
<Card>
43+
<CardHeader>
44+
<CardTitle>MCP Usage</CardTitle>
45+
<CardDescription>How to use MCP for API 200 </CardDescription>
46+
</CardHeader>
47+
<CardContent>
48+
<p className="text-sm">
49+
To use API 200 MCP server with your LLM client, add following config (<Link target="_blank" className={"hover:underline text-blue-600"} href="https://modelcontextprotocol.io/quickstart/user">help</Link>):
50+
</p>
51+
<pre className="mt-2 flex-grow p-2 bg-gray-100 rounded-md font-mono text-sm relative">
52+
<div className="absolute right-2 top-2">
53+
<Button variant="outline" size="sm" onClick={handleCopy} className="h-8 w-8 p-0">
54+
{isCopied ? (
55+
<CopyCheck className="h-4 w-4 text-green-500"/>
56+
) : (
57+
<Copy className="h-4 w-4"/>
58+
)}
59+
</Button>
60+
</div>
61+
<code>
62+
{config}
63+
</code>
64+
</pre>
65+
</CardContent>
66+
</Card>
67+
)
68+
}
69+
70+
export default MCPConfig

packages/dashboard/src/app/(layout)/credentials/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Separator } from "@/components/ui/separator";
44
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
55
import { ApiKeyDisplay } from "./components/ApiKeyDisplay";
66
import { env } from "next-runtime-env";
7+
import MCPConfig from "@/app/(layout)/credentials/components/MCPConfig";
78

89
export default async function PrivatePage() {
910
const supabase = await createClient()
@@ -61,6 +62,7 @@ export default async function PrivatePage() {
6162
</pre>
6263
</CardContent>
6364
</Card>
65+
<MCPConfig apiKey={apiKey?.key}/>
6466
</div>
6567
</div>
6668
<div>
Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import { Button } from "@/components/ui/button"
2-
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
3-
import { ArrowRight, Check, X } from "lucide-react"
4-
import { redirect } from 'next/navigation'
5-
import { type EnhancedIncident } from '../types'
1+
import {Button} from "@/components/ui/button"
2+
import {Card, CardContent, CardHeader, CardTitle} from "@/components/ui/card"
3+
import {ArrowRight, Check, CheckCheck, X} from "lucide-react"
4+
import {redirect} from 'next/navigation'
5+
import {type EnhancedIncident} from '../types'
6+
import {format} from "date-fns";
67

78
type Props = {
89
incident: EnhancedIncident
910
onClose: () => void
1011
onResolve: () => void
1112
}
1213

13-
export function IncidentCard({ incident, onClose, onResolve }: Props) {
14+
export function IncidentCard({incident, onClose, onResolve}: Props) {
1415
const goToEndpoint = () => {
1516
const endpoint = incident.endpoint as EnhancedIncident['endpoint'];
1617
const service = endpoint.service;
@@ -20,43 +21,46 @@ export function IncidentCard({ incident, onClose, onResolve }: Props) {
2021
return (
2122
<Card>
2223
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
23-
<CardTitle className="text-lg font-medium">
24+
<CardTitle>
2425
{incident.title}
2526
</CardTitle>
26-
<Button onClick={goToEndpoint}>Go To Endpoint <ArrowRight /></Button>
2727
<Button variant="ghost" size="icon" onClick={onClose}>
28-
<X className="h-4 w-4" />
28+
<X className="h-4 w-4"/>
2929
</Button>
3030
</CardHeader>
3131
<CardContent className="space-y-4">
3232
<div>
3333
<h3 className="text-sm font-medium text-muted-foreground">Type</h3>
34-
<div>{incident.type || "Unknown"}</div>
34+
<div className="text-sm">{incident.type || "Unknown"}</div>
3535
</div>
3636

3737
<div>
3838
<h3 className="text-sm font-medium text-muted-foreground">Status</h3>
39-
<div>{incident.resolved ? <div className="flex gap-1">Resolved <Check /></div> : "Active"}</div>
39+
<div className="text-sm">{incident.resolved ?
40+
<div className="flex gap-1 items-center">Resolved <Check className={"h-4 w-4"}/></div> : "Active"}</div>
4041
</div>
4142

4243
<div>
4344
<h3 className="text-sm font-medium text-muted-foreground">Details</h3>
44-
<pre className="mt-2 rounded-md bg-muted div-4 overflow-auto">
45+
<pre className="mt-2 p-4 rounded-md bg-muted div-4 overflow-auto text-xs">
4546
{JSON.stringify(incident.details, null, 2)}
4647
</pre>
4748
</div>
4849

4950
<div>
50-
<h3 className="text-sm font-medium text-muted-foreground">Created</h3>
51-
<div>{new Date(incident.created_at!).toLocaleString()}</div>
51+
<h3 className="text-sm font-medium text-muted-foreground">Occured at</h3>
52+
<div className="text-sm">{format(new Date(incident.created_at!), "MMM dd HH:mm:ss")}</div>
53+
</div>
54+
<div className="flex gap-2">
55+
<Button className="w-full" variant={"outline"} onClick={goToEndpoint}>Go To Endpoint <ArrowRight/></Button>
56+
{!incident.resolved && (
57+
<Button className="w-full" onClick={onResolve}>
58+
Mark as Resolved <CheckCheck/>
59+
</Button>
60+
)}
5261
</div>
5362

54-
{!incident.resolved && (
55-
<Button className="w-full" onClick={onResolve}>
56-
Mark as Resolved
57-
</Button>
58-
)}
5963
</CardContent>
6064
</Card>
6165
)
62-
}
66+
}

packages/mcp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "api200-mcp",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"description": "API200 MCP server for Claude and other model context protocol clients",
55
"type": "module",
66
"main": "./dist/index.js",

0 commit comments

Comments
 (0)