mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
changed search for folders and workflows in logs (#1327)
Co-authored-by: Adam Gough <adamgough@Mac.attlocal.net>
This commit is contained in:
@@ -1,14 +1,21 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Check, ChevronDown } from 'lucide-react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from '@/components/ui/command'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { useFolderStore } from '@/stores/folders/store'
|
||||
import { useFilterStore } from '@/stores/logs/filters/store'
|
||||
|
||||
@@ -26,6 +33,8 @@ export default function FolderFilter() {
|
||||
const workspaceId = params.workspaceId as string
|
||||
const [folders, setFolders] = useState<FolderOption[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [search, setSearch] = useState('')
|
||||
const logger = useMemo(() => createLogger('LogsFolderFilter'), [])
|
||||
|
||||
// Fetch all available folders from the API
|
||||
useEffect(() => {
|
||||
@@ -62,7 +71,7 @@ export default function FolderFilter() {
|
||||
setFolders(folderOptions)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch folders:', error)
|
||||
logger.error('Failed to fetch folders', { error })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -105,49 +114,53 @@ export default function FolderFilter() {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align='start'
|
||||
className='max-h-[300px] w-[200px] overflow-y-auto rounded-lg border-[#E5E5E5] bg-[#FFFFFF] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
className='w-[200px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
>
|
||||
<DropdownMenuItem
|
||||
key='all'
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
clearSelections()
|
||||
}}
|
||||
className='flex cursor-pointer items-center justify-between rounded-md px-3 py-2 font-[380] text-card-foreground text-sm hover:bg-secondary/50 focus:bg-secondary/50'
|
||||
>
|
||||
<span>All folders</span>
|
||||
{folderIds.length === 0 && <Check className='h-4 w-4 text-muted-foreground' />}
|
||||
</DropdownMenuItem>
|
||||
|
||||
{!loading && folders.length > 0 && <DropdownMenuSeparator />}
|
||||
|
||||
{!loading &&
|
||||
folders.map((folder) => (
|
||||
<DropdownMenuItem
|
||||
key={folder.id}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
toggleFolderId(folder.id)
|
||||
}}
|
||||
className='flex cursor-pointer items-center justify-between rounded-md px-3 py-2 font-[380] text-card-foreground text-sm hover:bg-secondary/50 focus:bg-secondary/50'
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<span className='truncate' title={folder.path}>
|
||||
{folder.path}
|
||||
</span>
|
||||
</div>
|
||||
{isFolderSelected(folder.id) && <Check className='h-4 w-4 text-muted-foreground' />}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
|
||||
{loading && (
|
||||
<DropdownMenuItem
|
||||
disabled
|
||||
className='rounded-md px-3 py-2 font-[380] text-muted-foreground text-sm'
|
||||
>
|
||||
Loading folders...
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<Command>
|
||||
<CommandInput placeholder='Search folders...' onValueChange={(v) => setSearch(v)} />
|
||||
<CommandList>
|
||||
<CommandEmpty>{loading ? 'Loading folders...' : 'No folders found.'}</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
value='all-folders'
|
||||
onSelect={() => {
|
||||
clearSelections()
|
||||
}}
|
||||
className='cursor-pointer'
|
||||
>
|
||||
<span>All folders</span>
|
||||
{folderIds.length === 0 && (
|
||||
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
|
||||
)}
|
||||
</CommandItem>
|
||||
{useMemo(() => {
|
||||
const q = search.trim().toLowerCase()
|
||||
const filtered = q
|
||||
? folders.filter((f) => (f.path || f.name).toLowerCase().includes(q))
|
||||
: folders
|
||||
return filtered.map((folder) => (
|
||||
<CommandItem
|
||||
key={folder.id}
|
||||
value={`${folder.path || folder.name}`}
|
||||
onSelect={() => {
|
||||
toggleFolderId(folder.id)
|
||||
}}
|
||||
className='cursor-pointer'
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<span className='truncate' title={folder.path}>
|
||||
{folder.path}
|
||||
</span>
|
||||
</div>
|
||||
{isFolderSelected(folder.id) && (
|
||||
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
|
||||
)}
|
||||
</CommandItem>
|
||||
))
|
||||
}, [folders, search, folderIds])}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Check, ChevronDown } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from '@/components/ui/command'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { useFilterStore } from '@/stores/logs/filters/store'
|
||||
|
||||
interface WorkflowOption {
|
||||
@@ -20,6 +27,8 @@ export default function Workflow() {
|
||||
const { workflowIds, toggleWorkflowId, setWorkflowIds } = useFilterStore()
|
||||
const [workflows, setWorkflows] = useState<WorkflowOption[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [search, setSearch] = useState('')
|
||||
const logger = useMemo(() => createLogger('LogsWorkflowFilter'), [])
|
||||
|
||||
// Fetch all available workflows from the API
|
||||
useEffect(() => {
|
||||
@@ -37,7 +46,7 @@ export default function Workflow() {
|
||||
setWorkflows(workflowOptions)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch workflows:', error)
|
||||
logger.error('Failed to fetch workflows', { error })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -80,57 +89,55 @@ export default function Workflow() {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align='start'
|
||||
className='max-h-[300px] w-[180px] overflow-y-auto rounded-lg border-[#E5E5E5] bg-[#FFFFFF] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
style={{
|
||||
scrollbarWidth: 'none',
|
||||
msOverflowStyle: 'none',
|
||||
}}
|
||||
className='w-[180px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
>
|
||||
<DropdownMenuItem
|
||||
key='all'
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
clearSelections()
|
||||
}}
|
||||
className='flex cursor-pointer items-center justify-between rounded-md px-3 py-2 font-[380] text-card-foreground text-sm hover:bg-secondary/50 focus:bg-secondary/50'
|
||||
>
|
||||
<span>All workflows</span>
|
||||
{workflowIds.length === 0 && <Check className='h-4 w-4 text-muted-foreground' />}
|
||||
</DropdownMenuItem>
|
||||
|
||||
{!loading && workflows.length > 0 && <DropdownMenuSeparator />}
|
||||
|
||||
{!loading &&
|
||||
workflows.map((workflow) => (
|
||||
<DropdownMenuItem
|
||||
key={workflow.id}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
toggleWorkflowId(workflow.id)
|
||||
}}
|
||||
className='flex cursor-pointer items-center justify-between rounded-md px-3 py-2 font-[380] text-card-foreground text-sm hover:bg-secondary/50 focus:bg-secondary/50'
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<div
|
||||
className='mr-2 h-2 w-2 rounded-full'
|
||||
style={{ backgroundColor: workflow.color }}
|
||||
/>
|
||||
{workflow.name}
|
||||
</div>
|
||||
{isWorkflowSelected(workflow.id) && (
|
||||
<Check className='h-4 w-4 text-muted-foreground' />
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
|
||||
{loading && (
|
||||
<DropdownMenuItem
|
||||
disabled
|
||||
className='rounded-md px-3 py-2 font-[380] text-muted-foreground text-sm'
|
||||
>
|
||||
Loading workflows...
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<Command>
|
||||
<CommandInput placeholder='Search workflows...' onValueChange={(v) => setSearch(v)} />
|
||||
<CommandList>
|
||||
<CommandEmpty>{loading ? 'Loading workflows...' : 'No workflows found.'}</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
value='all-workflows'
|
||||
onSelect={() => {
|
||||
clearSelections()
|
||||
}}
|
||||
className='cursor-pointer'
|
||||
>
|
||||
<span>All workflows</span>
|
||||
{workflowIds.length === 0 && (
|
||||
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
|
||||
)}
|
||||
</CommandItem>
|
||||
{useMemo(() => {
|
||||
const q = search.trim().toLowerCase()
|
||||
const filtered = q
|
||||
? workflows.filter((w) => w.name.toLowerCase().includes(q))
|
||||
: workflows
|
||||
return filtered.map((workflow) => (
|
||||
<CommandItem
|
||||
key={workflow.id}
|
||||
value={`${workflow.name}`}
|
||||
onSelect={() => {
|
||||
toggleWorkflowId(workflow.id)
|
||||
}}
|
||||
className='cursor-pointer'
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<div
|
||||
className='mr-2 h-2 w-2 rounded-full'
|
||||
style={{ backgroundColor: workflow.color }}
|
||||
/>
|
||||
{workflow.name}
|
||||
</div>
|
||||
{isWorkflowSelected(workflow.id) && (
|
||||
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
|
||||
)}
|
||||
</CommandItem>
|
||||
))
|
||||
}, [workflows, search, workflowIds])}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user