Skip to content

Commit 3e5d373

Browse files
aadamgoughAdam Gough
andauthored
changed search for folders and workflows in logs (#1327)
Co-authored-by: Adam Gough <[email protected]>
1 parent 172d51e commit 3e5d373

File tree

2 files changed

+120
-100
lines changed

2 files changed

+120
-100
lines changed

apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/folder.tsx

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
import { useEffect, useState } from 'react'
1+
import { useEffect, useMemo, useState } from 'react'
22
import { Check, ChevronDown } from 'lucide-react'
33
import { useParams } from 'next/navigation'
44
import { Button } from '@/components/ui/button'
5+
import {
6+
Command,
7+
CommandEmpty,
8+
CommandGroup,
9+
CommandInput,
10+
CommandItem,
11+
CommandList,
12+
} from '@/components/ui/command'
513
import {
614
DropdownMenu,
715
DropdownMenuContent,
8-
DropdownMenuItem,
9-
DropdownMenuSeparator,
1016
DropdownMenuTrigger,
1117
} from '@/components/ui/dropdown-menu'
18+
import { createLogger } from '@/lib/logs/console/logger'
1219
import { useFolderStore } from '@/stores/folders/store'
1320
import { useFilterStore } from '@/stores/logs/filters/store'
1421

@@ -26,6 +33,8 @@ export default function FolderFilter() {
2633
const workspaceId = params.workspaceId as string
2734
const [folders, setFolders] = useState<FolderOption[]>([])
2835
const [loading, setLoading] = useState(true)
36+
const [search, setSearch] = useState('')
37+
const logger = useMemo(() => createLogger('LogsFolderFilter'), [])
2938

3039
// Fetch all available folders from the API
3140
useEffect(() => {
@@ -62,7 +71,7 @@ export default function FolderFilter() {
6271
setFolders(folderOptions)
6372
}
6473
} catch (error) {
65-
console.error('Failed to fetch folders:', error)
74+
logger.error('Failed to fetch folders', { error })
6675
} finally {
6776
setLoading(false)
6877
}
@@ -105,49 +114,53 @@ export default function FolderFilter() {
105114
</DropdownMenuTrigger>
106115
<DropdownMenuContent
107116
align='start'
108-
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)]'
117+
className='w-[200px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
109118
>
110-
<DropdownMenuItem
111-
key='all'
112-
onSelect={(e) => {
113-
e.preventDefault()
114-
clearSelections()
115-
}}
116-
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'
117-
>
118-
<span>All folders</span>
119-
{folderIds.length === 0 && <Check className='h-4 w-4 text-muted-foreground' />}
120-
</DropdownMenuItem>
121-
122-
{!loading && folders.length > 0 && <DropdownMenuSeparator />}
123-
124-
{!loading &&
125-
folders.map((folder) => (
126-
<DropdownMenuItem
127-
key={folder.id}
128-
onSelect={(e) => {
129-
e.preventDefault()
130-
toggleFolderId(folder.id)
131-
}}
132-
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'
133-
>
134-
<div className='flex items-center'>
135-
<span className='truncate' title={folder.path}>
136-
{folder.path}
137-
</span>
138-
</div>
139-
{isFolderSelected(folder.id) && <Check className='h-4 w-4 text-muted-foreground' />}
140-
</DropdownMenuItem>
141-
))}
142-
143-
{loading && (
144-
<DropdownMenuItem
145-
disabled
146-
className='rounded-md px-3 py-2 font-[380] text-muted-foreground text-sm'
147-
>
148-
Loading folders...
149-
</DropdownMenuItem>
150-
)}
119+
<Command>
120+
<CommandInput placeholder='Search folders...' onValueChange={(v) => setSearch(v)} />
121+
<CommandList>
122+
<CommandEmpty>{loading ? 'Loading folders...' : 'No folders found.'}</CommandEmpty>
123+
<CommandGroup>
124+
<CommandItem
125+
value='all-folders'
126+
onSelect={() => {
127+
clearSelections()
128+
}}
129+
className='cursor-pointer'
130+
>
131+
<span>All folders</span>
132+
{folderIds.length === 0 && (
133+
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
134+
)}
135+
</CommandItem>
136+
{useMemo(() => {
137+
const q = search.trim().toLowerCase()
138+
const filtered = q
139+
? folders.filter((f) => (f.path || f.name).toLowerCase().includes(q))
140+
: folders
141+
return filtered.map((folder) => (
142+
<CommandItem
143+
key={folder.id}
144+
value={`${folder.path || folder.name}`}
145+
onSelect={() => {
146+
toggleFolderId(folder.id)
147+
}}
148+
className='cursor-pointer'
149+
>
150+
<div className='flex items-center'>
151+
<span className='truncate' title={folder.path}>
152+
{folder.path}
153+
</span>
154+
</div>
155+
{isFolderSelected(folder.id) && (
156+
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
157+
)}
158+
</CommandItem>
159+
))
160+
}, [folders, search, folderIds])}
161+
</CommandGroup>
162+
</CommandList>
163+
</Command>
151164
</DropdownMenuContent>
152165
</DropdownMenu>
153166
)

apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/workflow.tsx

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1-
import { useEffect, useState } from 'react'
1+
import { useEffect, useMemo, useState } from 'react'
22
import { Check, ChevronDown } from 'lucide-react'
33
import { Button } from '@/components/ui/button'
4+
import {
5+
Command,
6+
CommandEmpty,
7+
CommandGroup,
8+
CommandInput,
9+
CommandItem,
10+
CommandList,
11+
} from '@/components/ui/command'
412
import {
513
DropdownMenu,
614
DropdownMenuContent,
7-
DropdownMenuItem,
8-
DropdownMenuSeparator,
915
DropdownMenuTrigger,
1016
} from '@/components/ui/dropdown-menu'
17+
import { createLogger } from '@/lib/logs/console/logger'
1118
import { useFilterStore } from '@/stores/logs/filters/store'
1219

1320
interface WorkflowOption {
@@ -20,6 +27,8 @@ export default function Workflow() {
2027
const { workflowIds, toggleWorkflowId, setWorkflowIds } = useFilterStore()
2128
const [workflows, setWorkflows] = useState<WorkflowOption[]>([])
2229
const [loading, setLoading] = useState(true)
30+
const [search, setSearch] = useState('')
31+
const logger = useMemo(() => createLogger('LogsWorkflowFilter'), [])
2332

2433
// Fetch all available workflows from the API
2534
useEffect(() => {
@@ -37,7 +46,7 @@ export default function Workflow() {
3746
setWorkflows(workflowOptions)
3847
}
3948
} catch (error) {
40-
console.error('Failed to fetch workflows:', error)
49+
logger.error('Failed to fetch workflows', { error })
4150
} finally {
4251
setLoading(false)
4352
}
@@ -80,57 +89,55 @@ export default function Workflow() {
8089
</DropdownMenuTrigger>
8190
<DropdownMenuContent
8291
align='start'
83-
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)]'
84-
style={{
85-
scrollbarWidth: 'none',
86-
msOverflowStyle: 'none',
87-
}}
92+
className='w-[180px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
8893
>
89-
<DropdownMenuItem
90-
key='all'
91-
onSelect={(e) => {
92-
e.preventDefault()
93-
clearSelections()
94-
}}
95-
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'
96-
>
97-
<span>All workflows</span>
98-
{workflowIds.length === 0 && <Check className='h-4 w-4 text-muted-foreground' />}
99-
</DropdownMenuItem>
100-
101-
{!loading && workflows.length > 0 && <DropdownMenuSeparator />}
102-
103-
{!loading &&
104-
workflows.map((workflow) => (
105-
<DropdownMenuItem
106-
key={workflow.id}
107-
onSelect={(e) => {
108-
e.preventDefault()
109-
toggleWorkflowId(workflow.id)
110-
}}
111-
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'
112-
>
113-
<div className='flex items-center'>
114-
<div
115-
className='mr-2 h-2 w-2 rounded-full'
116-
style={{ backgroundColor: workflow.color }}
117-
/>
118-
{workflow.name}
119-
</div>
120-
{isWorkflowSelected(workflow.id) && (
121-
<Check className='h-4 w-4 text-muted-foreground' />
122-
)}
123-
</DropdownMenuItem>
124-
))}
125-
126-
{loading && (
127-
<DropdownMenuItem
128-
disabled
129-
className='rounded-md px-3 py-2 font-[380] text-muted-foreground text-sm'
130-
>
131-
Loading workflows...
132-
</DropdownMenuItem>
133-
)}
94+
<Command>
95+
<CommandInput placeholder='Search workflows...' onValueChange={(v) => setSearch(v)} />
96+
<CommandList>
97+
<CommandEmpty>{loading ? 'Loading workflows...' : 'No workflows found.'}</CommandEmpty>
98+
<CommandGroup>
99+
<CommandItem
100+
value='all-workflows'
101+
onSelect={() => {
102+
clearSelections()
103+
}}
104+
className='cursor-pointer'
105+
>
106+
<span>All workflows</span>
107+
{workflowIds.length === 0 && (
108+
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
109+
)}
110+
</CommandItem>
111+
{useMemo(() => {
112+
const q = search.trim().toLowerCase()
113+
const filtered = q
114+
? workflows.filter((w) => w.name.toLowerCase().includes(q))
115+
: workflows
116+
return filtered.map((workflow) => (
117+
<CommandItem
118+
key={workflow.id}
119+
value={`${workflow.name}`}
120+
onSelect={() => {
121+
toggleWorkflowId(workflow.id)
122+
}}
123+
className='cursor-pointer'
124+
>
125+
<div className='flex items-center'>
126+
<div
127+
className='mr-2 h-2 w-2 rounded-full'
128+
style={{ backgroundColor: workflow.color }}
129+
/>
130+
{workflow.name}
131+
</div>
132+
{isWorkflowSelected(workflow.id) && (
133+
<Check className='ml-auto h-4 w-4 text-muted-foreground' />
134+
)}
135+
</CommandItem>
136+
))
137+
}, [workflows, search, workflowIds])}
138+
</CommandGroup>
139+
</CommandList>
140+
</Command>
134141
</DropdownMenuContent>
135142
</DropdownMenu>
136143
)

0 commit comments

Comments
 (0)