fix: add the ability to select multiple workflows in logs

This commit is contained in:
Waleed Latif
2025-03-10 00:51:13 -07:00
parent 744396c56c
commit 56d37e2d2d
2 changed files with 52 additions and 19 deletions

View File

@@ -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>

View File

@@ -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