mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(logs): added logs structure; connecting to DB now
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { Plus, Settings } from 'lucide-react'
|
import { Plus, ScrollText, Settings } from 'lucide-react'
|
||||||
import { AgentIcon } from '@/components/icons'
|
import { AgentIcon } from '@/components/icons'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||||
@@ -42,7 +42,7 @@ export function Sidebar() {
|
|||||||
<aside className="fixed inset-y-0 left-0 z-10 hidden w-14 flex-col border-r bg-background sm:flex">
|
<aside className="fixed inset-y-0 left-0 z-10 hidden w-14 flex-col border-r bg-background sm:flex">
|
||||||
<nav className="flex flex-col items-center gap-4 px-2 py-5">
|
<nav className="flex flex-col items-center gap-4 px-2 py-5">
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/w/1"
|
||||||
className="group flex h-8 w-8 items-center justify-center rounded-lg bg-[#7F2FFF]"
|
className="group flex h-8 w-8 items-center justify-center rounded-lg bg-[#7F2FFF]"
|
||||||
>
|
>
|
||||||
<AgentIcon className="text-white transition-all group-hover:scale-110 -translate-y-[0.5px] w-5 h-5" />
|
<AgentIcon className="text-white transition-all group-hover:scale-110 -translate-y-[0.5px] w-5 h-5" />
|
||||||
@@ -79,6 +79,22 @@ export function Sidebar() {
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<nav className="flex flex-col items-center gap-4 px-2 py-[18px]">
|
<nav className="flex flex-col items-center gap-4 px-2 py-[18px]">
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
asChild
|
||||||
|
className="flex !h-9 !w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||||
|
>
|
||||||
|
<Link href="/w/logs">
|
||||||
|
<ScrollText className="!h-5 !w-5" />
|
||||||
|
<span className="sr-only">Logs</span>
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="right">Logs</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { RefreshCw, Search } from 'lucide-react'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Input } from '@/components/ui/input'
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control bar for logs page - includes search functionality and refresh/live controls
|
||||||
|
*/
|
||||||
|
export function ControlBar() {
|
||||||
|
const [isLive, setIsLive] = useState(false)
|
||||||
|
const [searchQuery, setSearchQuery] = useState('')
|
||||||
|
|
||||||
|
const handleRefresh = () => {
|
||||||
|
// Implement refresh functionality
|
||||||
|
console.log('Refreshing logs')
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleLive = () => {
|
||||||
|
setIsLive(!isLive)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-16 w-full items-center justify-between bg-background px-6 border-b transition-all duration-300">
|
||||||
|
{/* Left Section - Search */}
|
||||||
|
<div className="relative w-[400px]">
|
||||||
|
<div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
||||||
|
<Search className="h-4 w-4 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
placeholder="Search logs..."
|
||||||
|
className="pl-10 h-9"
|
||||||
|
value={searchQuery}
|
||||||
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Middle Section - Reserved for future use */}
|
||||||
|
<div className="flex-1" />
|
||||||
|
|
||||||
|
{/* Right Section - Actions */}
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={handleRefresh}
|
||||||
|
className="hover:text-foreground"
|
||||||
|
>
|
||||||
|
<RefreshCw className="h-5 w-5" />
|
||||||
|
<span className="sr-only">Refresh</span>
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>Refresh</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant={isLive ? 'default' : 'outline'}
|
||||||
|
className={isLive ? 'bg-[#7F2FFF] hover:bg-[#7F2FFF]/90 text-white' : ''}
|
||||||
|
onClick={toggleLive}
|
||||||
|
>
|
||||||
|
Live
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { ChevronDown } from 'lucide-react'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
|
||||||
|
|
||||||
|
export default function FilterSection({
|
||||||
|
title,
|
||||||
|
defaultOpen = false,
|
||||||
|
content,
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
defaultOpen?: boolean
|
||||||
|
content?: React.ReactNode
|
||||||
|
}) {
|
||||||
|
const [isOpen, setIsOpen] = useState(defaultOpen)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Collapsible open={isOpen} onOpenChange={setIsOpen} className="mb-3">
|
||||||
|
<CollapsibleTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
className="flex w-full justify-between px-2 text-sm font-medium hover:bg-accent rounded-md"
|
||||||
|
>
|
||||||
|
<span>{title}</span>
|
||||||
|
<ChevronDown
|
||||||
|
className={`h-4 w-4 text-muted-foreground transition-transform mr-[5px] ${
|
||||||
|
isOpen ? 'rotate-180' : ''
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent className="pt-2">
|
||||||
|
{content || (
|
||||||
|
<div className="text-sm text-muted-foreground">
|
||||||
|
Filter options for {title} will go here
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { ChevronDown } from 'lucide-react'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu'
|
||||||
|
|
||||||
|
export default function Timeline() {
|
||||||
|
const [selectedTimeRange, setSelectedTimeRange] = useState('Past 30 minutes')
|
||||||
|
const timeRanges = ['Past 30 minutes', 'Past hour', 'Past 24 hours', 'All time']
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="outline" size="sm" className="w-full justify-between text-sm font-normal">
|
||||||
|
{selectedTimeRange}
|
||||||
|
<ChevronDown className="h-4 w-4 ml-2 text-muted-foreground" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="start" className="overflow-y-auto">
|
||||||
|
{timeRanges.map((range) => (
|
||||||
|
<DropdownMenuItem
|
||||||
|
key={range}
|
||||||
|
onClick={() => setSelectedTimeRange(range)}
|
||||||
|
className="flex items-start p-2 cursor-pointer text-sm"
|
||||||
|
>
|
||||||
|
{range}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
))}
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { ChevronDown } from 'lucide-react'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu'
|
||||||
|
import FilterSection from './components/filter-section/filter-section'
|
||||||
|
import Timeline from './components/timeline'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters component for logs page - includes timeline and other filter options
|
||||||
|
*/
|
||||||
|
export function Filters() {
|
||||||
|
return (
|
||||||
|
<div className="p-4 w-64 border-r h-full overflow-auto">
|
||||||
|
<h2 className="text-sm font-medium mb-4 pl-2">Filters</h2>
|
||||||
|
|
||||||
|
{/* Timeline Filter */}
|
||||||
|
<FilterSection title="Timeline" defaultOpen={true} content={<Timeline />} />
|
||||||
|
|
||||||
|
{/* Additional filter sections */}
|
||||||
|
<FilterSection title="Contains Level" />
|
||||||
|
<FilterSection title="Environment" />
|
||||||
|
<FilterSection title="Route" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { ControlBar } from './components/control-bar/control-bar'
|
||||||
|
import { Filters } from './components/filters/filters'
|
||||||
|
|
||||||
|
export default function Logs() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col h-full">
|
||||||
|
<ControlBar />
|
||||||
|
<div className="flex flex-1 overflow-hidden">
|
||||||
|
<Filters />
|
||||||
|
<div className="flex-1 overflow-auto p-4">
|
||||||
|
{/* Logs content will go here */}
|
||||||
|
<div className="text-muted-foreground text-center mt-10">137 total logs found...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import Logs from './logs'
|
||||||
|
|
||||||
|
export default Logs
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'
|
||||||
|
|
||||||
|
const Collapsible = CollapsiblePrimitive.Root
|
||||||
|
|
||||||
|
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
|
||||||
|
|
||||||
|
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
|
||||||
|
|
||||||
|
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|
||||||
Generated
+54
@@ -15,6 +15,7 @@
|
|||||||
"@cerebras/cerebras_cloud_sdk": "^1.23.0",
|
"@cerebras/cerebras_cloud_sdk": "^1.23.0",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.5",
|
"@radix-ui/react-alert-dialog": "^1.1.5",
|
||||||
"@radix-ui/react-checkbox": "^1.1.3",
|
"@radix-ui/react-checkbox": "^1.1.3",
|
||||||
|
"@radix-ui/react-collapsible": "^1.1.3",
|
||||||
"@radix-ui/react-dialog": "^1.1.5",
|
"@radix-ui/react-dialog": "^1.1.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.1.1",
|
||||||
@@ -1866,6 +1867,59 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-collapsible": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-jFSerheto1X03MUC0g6R7LedNW9EEGWdg9W1+MlpkMLwGkgkbUXLPBH/KIuWKXUoeYRVY11llqbTBDzuLg7qrw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.1",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
|
"@radix-ui/react-context": "1.1.1",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-presence": "1.1.2",
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-primitive": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-slot": "1.1.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-collection": {
|
"node_modules/@radix-ui/react-collection": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"@cerebras/cerebras_cloud_sdk": "^1.23.0",
|
"@cerebras/cerebras_cloud_sdk": "^1.23.0",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.5",
|
"@radix-ui/react-alert-dialog": "^1.1.5",
|
||||||
"@radix-ui/react-checkbox": "^1.1.3",
|
"@radix-ui/react-checkbox": "^1.1.3",
|
||||||
|
"@radix-ui/react-collapsible": "^1.1.3",
|
||||||
"@radix-ui/react-dialog": "^1.1.5",
|
"@radix-ui/react-dialog": "^1.1.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.1.1",
|
||||||
|
|||||||
Reference in New Issue
Block a user