import { Button } from "@/src/components/ui/button"; import React, { type Dispatch, type SetStateAction, useState } from "react"; import { Input } from "@/src/components/ui/input"; import { DataTableColumnVisibilityFilter } from "@/src/components/table/data-table-column-visibility-filter"; import { PopoverFilterBuilder } from "@/src/features/filters/components/filter-builder"; import { type FilterState, type ColumnDefinition, type OrderByState, type TableViewPresetDomain, type TableViewPresetTableName, type TracingSearchType, } from "@langfuse/shared"; import { type RowSelectionState, type ColumnOrderState, type VisibilityState, } from "@tanstack/react-table"; import { type LangfuseColumnDef } from "@/src/components/table/types"; import { DataTableRowHeightSwitch, type RowHeight, } from "@/src/components/table/data-table-row-height-switch"; import { Search, ChevronDown, PanelLeftClose, PanelLeftOpen, } from "lucide-react"; import { Badge } from "@/src/components/ui/badge"; import { usePostHogClientCapture } from "@/src/features/posthog-analytics/usePostHogClientCapture"; import { TimeRangePicker } from "@/src/components/date-picker"; import { type TimeRange, TABLE_AGGREGATION_OPTIONS, } from "@/src/utils/date-range-utils"; import { DataTableSelectAllBanner } from "@/src/components/table/data-table-multi-select-actions/data-table-select-all-banner"; import { cn } from "@/src/utils/tailwind"; import DocPopup from "@/src/components/layouts/doc-popup"; import { TableViewPresetsDrawer } from "@/src/components/table/table-view-presets/components/data-table-view-presets-drawer"; import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from "@/src/components/ui/dropdown-menu"; import { useDataTableControls } from "@/src/components/table/data-table-controls"; import { MultiSelect as MultiSelectFilter } from "@/src/features/filters/components/multi-select"; import { DataTableRefreshButton, type RefreshInterval, } from "@/src/components/table/data-table-refresh-button"; export interface MultiSelect { selectAll: boolean; setSelectAll: Dispatch>; selectedRowIds: string[]; setRowSelection: Dispatch>; pageSize: number; pageIndex: number; totalCount: number | null; } interface SearchConfig { metadataSearchFields?: string[]; updateQuery: (event: string) => void; currentQuery?: string; tableAllowsFullTextSearch?: boolean; setSearchType?: (newSearchType: TracingSearchType[]) => void; searchType?: TracingSearchType[]; customDropdownLabels?: { metadata: string; fullText: string; }; hidePerformanceWarning?: boolean; } interface TableViewControllers { applyViewState: (viewData: TableViewPresetDomain) => void; selectedViewId: string | null; handleSetViewId: (viewId: string | null) => void; } interface TableViewConfig { tableName: TableViewPresetTableName; projectId: string; controllers: TableViewControllers; } interface RefreshConfig { onRefresh: () => void; isRefreshing: boolean; interval: RefreshInterval; setInterval: (interval: RefreshInterval) => void; } interface DataTableToolbarProps { columns: LangfuseColumnDef[]; filterColumnDefinition?: ColumnDefinition[]; searchConfig?: SearchConfig; actionButtons?: React.ReactNode; filterState?: FilterState; setFilterState?: | Dispatch> | ((newState: FilterState) => void); columnVisibility?: VisibilityState; setColumnVisibility?: Dispatch>; columnOrder?: ColumnOrderState; setColumnOrder?: Dispatch>; rowHeight?: RowHeight; setRowHeight?: Dispatch>; columnsWithCustomSelect?: string[]; timeRange?: TimeRange; setTimeRange?: (timeRange: TimeRange) => void; refreshConfig?: RefreshConfig; multiSelect?: MultiSelect; environmentFilter?: { values: string[]; onValueChange: (values: string[]) => void; options: { value: string }[]; }; orderByState?: OrderByState; viewConfig?: TableViewConfig; filterWithAI?: boolean; className?: string; viewModeToggle?: React.ReactNode; } export function DataTableToolbar({ columns, filterColumnDefinition, searchConfig, actionButtons, filterState, setFilterState, columnVisibility, setColumnVisibility, columnOrder, setColumnOrder, rowHeight, setRowHeight, columnsWithCustomSelect, timeRange, setTimeRange, refreshConfig, multiSelect, environmentFilter, className, orderByState, viewConfig, filterWithAI = false, viewModeToggle, }: DataTableToolbarProps) { const [searchString, setSearchString] = useState( searchConfig?.currentQuery ?? "", ); const capture = usePostHogClientCapture(); const { open: controlsPanelOpen, setOpen: setControlsPanelOpen } = useDataTableControls(); // Only show the toggle button when we're using the new sidebar const hasNewSidebar = !filterColumnDefinition && filterState !== undefined; return (
{hasNewSidebar && ( )} {searchConfig && (
{ const newValue = event.currentTarget.value; setSearchString(newValue); // If user cleared the search, update URL immediately if (newValue === "") { searchConfig.updateQuery(""); } }} onKeyDown={(event) => { if (event.key === "Enter") { capture("table:search_submit"); searchConfig.updateQuery(searchString); } }} className="w-full border-none bg-transparent px-0 py-2 text-sm focus-visible:outline-none focus-visible:ring-0" />
{searchConfig.setSearchType && ( { if ( !searchConfig.tableAllowsFullTextSearch && value === "metadata_fulltext" ) return; const newSearchType = value === "metadata_fulltext" ? ["id" as const, "content" as const] : ["id" as const]; searchConfig.setSearchType?.(newSearchType); }} > {searchConfig.customDropdownLabels?.metadata ?? "IDs / Names"} {searchConfig.customDropdownLabels?.fullText ?? "Full Text"} )}
)} {viewModeToggle} {timeRange && setTimeRange && ( )} {refreshConfig && ( )} {environmentFilter && ( )} {!!filterColumnDefinition && !!filterState && !!setFilterState && ( )}
{!!columnVisibility && !!columnOrder && !!viewConfig && ( )} {!!columnVisibility && !!setColumnVisibility && ( )} {!!rowHeight && !!setRowHeight && ( )} {actionButtons}
{multiSelect && multiSelect.pageIndex === 0 && multiSelect.selectedRowIds.length === multiSelect.pageSize && ( )}
); }