mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-22 13:28:04 -05:00
fix: add the ability to select multiple workflows in logs
This commit is contained in:
@@ -3,14 +3,16 @@ import { Check, ChevronDown } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { useFilterStore } from '@/app/w/logs/stores/store'
|
||||
|
||||
export default function Workflow() {
|
||||
const { logs, workflowId, setWorkflowId } = useFilterStore()
|
||||
const { logs, workflowIds, toggleWorkflowId, setWorkflowIds } = useFilterStore()
|
||||
|
||||
// Extract unique workflows from logs
|
||||
const workflows = useMemo(() => {
|
||||
@@ -29,34 +31,50 @@ export default function Workflow() {
|
||||
return Array.from(uniqueWorkflows.values())
|
||||
}, [logs])
|
||||
|
||||
const getSelectedWorkflowName = () => {
|
||||
if (!workflowId) return 'All workflows'
|
||||
const selected = workflows.find((w) => w.id === workflowId)
|
||||
return selected ? selected.name : 'All workflows'
|
||||
// Get display text for the dropdown button
|
||||
const getSelectedWorkflowsText = () => {
|
||||
if (workflowIds.length === 0) return 'All workflows'
|
||||
if (workflowIds.length === 1) {
|
||||
const selected = workflows.find((w) => w.id === workflowIds[0])
|
||||
return selected ? selected.name : 'All workflows'
|
||||
}
|
||||
return `${workflowIds.length} workflows selected`
|
||||
}
|
||||
|
||||
// Check if a workflow is selected
|
||||
const isWorkflowSelected = (workflowId: string) => {
|
||||
return workflowIds.includes(workflowId)
|
||||
}
|
||||
|
||||
// Clear all selections
|
||||
const clearSelections = () => {
|
||||
setWorkflowIds([])
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="w-full justify-between text-sm font-normal">
|
||||
{getSelectedWorkflowName()}
|
||||
{getSelectedWorkflowsText()}
|
||||
<ChevronDown className="h-4 w-4 ml-2 text-muted-foreground" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" className="w-[180px] max-h-[300px] overflow-y-auto">
|
||||
<DropdownMenuContent align="start" className="w-[220px] max-h-[300px] overflow-y-auto">
|
||||
<DropdownMenuItem
|
||||
key="all"
|
||||
onClick={() => setWorkflowId(null)}
|
||||
onClick={clearSelections}
|
||||
className="flex items-center justify-between p-2 cursor-pointer text-sm"
|
||||
>
|
||||
<span>All workflows</span>
|
||||
{workflowId === null && <Check className="h-4 w-4 text-primary" />}
|
||||
{workflowIds.length === 0 && <Check className="h-4 w-4 text-primary" />}
|
||||
</DropdownMenuItem>
|
||||
|
||||
{workflows.length > 0 && <DropdownMenuSeparator />}
|
||||
|
||||
{workflows.map((workflow) => (
|
||||
<DropdownMenuItem
|
||||
key={workflow.id}
|
||||
onClick={() => setWorkflowId(workflow.id)}
|
||||
onClick={() => toggleWorkflowId(workflow.id)}
|
||||
className="flex items-center justify-between p-2 cursor-pointer text-sm"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
@@ -66,7 +84,7 @@ export default function Workflow() {
|
||||
/>
|
||||
{workflow.name}
|
||||
</div>
|
||||
{workflowId === workflow.id && <Check className="h-4 w-4 text-primary" />}
|
||||
{isWorkflowSelected(workflow.id) && <Check className="h-4 w-4 text-primary" />}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -12,7 +12,7 @@ interface FilterState {
|
||||
// Filter states
|
||||
timeRange: TimeRange
|
||||
level: LogLevel
|
||||
workflowId: string | null
|
||||
workflowIds: string[]
|
||||
searchQuery: string
|
||||
// Loading state
|
||||
loading: boolean
|
||||
@@ -21,7 +21,8 @@ interface FilterState {
|
||||
setLogs: (logs: WorkflowLog[]) => void
|
||||
setTimeRange: (timeRange: TimeRange) => void
|
||||
setLevel: (level: LogLevel) => void
|
||||
setWorkflowId: (workflowId: string | null) => void
|
||||
setWorkflowIds: (workflowIds: string[]) => void
|
||||
toggleWorkflowId: (workflowId: string) => void
|
||||
setSearchQuery: (query: string) => void
|
||||
setLoading: (loading: boolean) => void
|
||||
setError: (error: string | null) => void
|
||||
@@ -34,7 +35,7 @@ export const useFilterStore = create<FilterState>((set, get) => ({
|
||||
filteredLogs: [],
|
||||
timeRange: 'All time',
|
||||
level: 'all',
|
||||
workflowId: null,
|
||||
workflowIds: [],
|
||||
searchQuery: '',
|
||||
loading: true,
|
||||
error: null,
|
||||
@@ -53,8 +54,22 @@ export const useFilterStore = create<FilterState>((set, get) => ({
|
||||
get().applyFilters()
|
||||
},
|
||||
|
||||
setWorkflowId: (workflowId) => {
|
||||
set({ workflowId })
|
||||
setWorkflowIds: (workflowIds) => {
|
||||
set({ workflowIds })
|
||||
get().applyFilters()
|
||||
},
|
||||
|
||||
toggleWorkflowId: (workflowId) => {
|
||||
const currentWorkflowIds = [...get().workflowIds]
|
||||
const index = currentWorkflowIds.indexOf(workflowId)
|
||||
|
||||
if (index === -1) {
|
||||
currentWorkflowIds.push(workflowId)
|
||||
} else {
|
||||
currentWorkflowIds.splice(index, 1)
|
||||
}
|
||||
|
||||
set({ workflowIds: currentWorkflowIds })
|
||||
get().applyFilters()
|
||||
},
|
||||
|
||||
@@ -68,7 +83,7 @@ export const useFilterStore = create<FilterState>((set, get) => ({
|
||||
setError: (error) => set({ error }),
|
||||
|
||||
applyFilters: () => {
|
||||
const { logs, timeRange, level, workflowId, searchQuery } = get()
|
||||
const { logs, timeRange, level, workflowIds, searchQuery } = get()
|
||||
|
||||
let filtered = [...logs]
|
||||
|
||||
@@ -100,8 +115,8 @@ export const useFilterStore = create<FilterState>((set, get) => ({
|
||||
}
|
||||
|
||||
// Apply workflow filter
|
||||
if (workflowId) {
|
||||
filtered = filtered.filter((log) => log.workflowId === workflowId)
|
||||
if (workflowIds.length > 0) {
|
||||
filtered = filtered.filter((log) => workflowIds.includes(log.workflowId))
|
||||
}
|
||||
|
||||
// Apply search query filter
|
||||
|
||||
Reference in New Issue
Block a user