Skip to content

Commit

Permalink
feat: show messages/queries in sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
rmrt1n committed Feb 29, 2024
1 parent fdd2273 commit 2a61730
Showing 1 changed file with 105 additions and 38 deletions.
143 changes: 105 additions & 38 deletions src/routes/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { BookDashed, MessageSquareCode, SearchCode } from 'lucide-react'

import { useCardinal } from '@/lib/cardinal-provider'
import logo from '@/assets/world.svg'
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { cn } from '@/lib/utils'
import { ThemeToggle } from '@/components/theme-toggle'
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
import { BookDashed, MessageSquareCode, SearchCode } from 'lucide-react'

// TODO: autofill from cardinal, will probably need custom components for queries & messages
const sidebarItems = [
{
title: 'Queries',
icon: <MessageSquareCode size={20} strokeWidth={2.1} />,
items: []
},
{
title: 'Messages',
icon: <SearchCode size={20} strokeWidth={2.1} />,
items: []
},
]
import { cn } from '@/lib/utils'
import { useCardinal } from '@/lib/cardinal-provider'

export const Route = createRootRoute({
component: Root
})

function Root() {
const { cardinalUrl, setCardinalUrl, isCardinalConnected } = useCardinal()
const { data } = useQuery({
queryKey: ['world'],
queryFn: async () => {
const res = await fetch(`${cardinalUrl}/debug/world`)
return await res.json()
},
refetchInterval: 1000 * 60 * 5, // refetch every 5 minutes
enabled: isCardinalConnected,
})
const sidebarItems = [
{
title: 'Messages',
icon: <MessageSquareCode size={20} strokeWidth={2.1} />,
items: data?.messages ?? []
},
{
title: 'Queries',
icon: <SearchCode size={20} strokeWidth={2.1} />,
items: data?.queries ?? []
},
]

return (
<>
Expand All @@ -40,7 +49,7 @@ function Root() {
<label htmlFor="host" className="flex-shrink-0 text-xs text-muted-foreground">Cardinal URL</label>
<Input
id="host"
placeholder="localhost:3333"
placeholder="localhost:4040"
value={cardinalUrl}
onChange={(e) => setCardinalUrl(e.target.value)}
className="h-8"
Expand All @@ -53,25 +62,7 @@ function Root() {
<aside className="flex flex-col justify-between px-3 pt-4 pb-2 min-w-64 border-r text-sm">
<div>
{sidebarItems.map((item, i) => (
<Accordion key={i} collapsible type="single" defaultValue="default">
<AccordionItem value="default" className="border-0">
<AccordionTrigger className="px-2">
<p className="flex items-center gap-2 font-bold">{item.icon} {item.title}</p>
</AccordionTrigger>
<AccordionContent>
{item.items.length > 0 ? (
<>unimplemented...</>
) : (
<div className="flex flex-col gap-4 items-center bg-muted text-muted-foreground py-4 rounded-lg">
<BookDashed size={24} strokeWidth={2.5} />
<div className="space-y-2 text-center">
<p className="text-xs font-semibold">No {item.title} Found</p>
</div>
</div>
)}
</AccordionContent>
</AccordionItem>
</Accordion>
<SideBarItem key={i} item={item} />
))}
</div>
<ThemeToggle className="self-end" />
Expand All @@ -83,3 +74,79 @@ function Root() {
</>
)
}

interface SideBarItemProps {
item: {
title: string,
icon: React.ReactNode,
items: {
name: string,
fields: {
[param: string]: string
}
}[]
}
}

function SideBarItem({ item }: SideBarItemProps) {
const items = item.items
const formatName = (name: string) => {
let s = name.replace(/-/g, ' ')
return s.charAt(0).toUpperCase() + s.slice(1)
}

return (
<>
<Accordion collapsible type="single" defaultValue="default">
<AccordionItem value="default" className="border-0">
<AccordionTrigger className="px-2">
<p className="flex items-center gap-2 font-bold">{item.icon} {item.title}</p>
</AccordionTrigger>
<AccordionContent className="space-y-2">
{items.length > 0 ? (
items.map((item, i) => (
<Accordion
collapsible
key={i}
type="single"
className="bg-muted border border-border rounded-lg"
>
<AccordionItem value="default" className="border-0 [&_.params]:data-[state=open]:hidden">
<AccordionTrigger
title={formatName(item.name)}
className="p-2 max-w-full rounded-lg border-b border-border data-[state=closed]:bg-background"
>
<p className="text-sm text-left max-w-[85%] truncate">{formatName(item.name)}</p>
</AccordionTrigger>
<div className="params px-2 py-0.5 font-medium text-xs text-muted-foreground">
{Object.keys(item.fields).join(', ')}
</div>
<AccordionContent className="p-2 space-y-2">
{Object.keys(item.fields).map((param) => (
<div className="space-y-1">
<p className="font-medium space-x-2">
<span>{param}</span>
<span className="text-muted-foreground font-normal">{item.fields[param]}</span>
</p>
<Input className="h-8" />
</div>
))}
<Button className="w-full h-8">Send</Button>
</AccordionContent>
</AccordionItem>
</Accordion>
))
) : (
<div className="flex flex-col gap-4 items-center bg-muted text-muted-foreground py-4 rounded-lg">
<BookDashed size={24} strokeWidth={2.5} />
<div className="space-y-2 text-center">
<p className="text-xs font-semibold">No {item.title} Found</p>
</div>
</div>
)}
</AccordionContent>
</AccordionItem>
</Accordion>
</>
)
}

0 comments on commit 2a61730

Please sign in to comment.