import { useMemo, useState } from 'react'; import { Cross2Icon } from '@radix-ui/react-icons'; import { Table } from '@tanstack/react-table'; import { RefreshCw, X } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useAuthStore } from '@/stores/authStore'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Input } from '@/components/ui/input'; import { Switch } from '@/components/ui/switch'; import { DataTableFacetedFilter } from '@/components/data-table-faceted-filter'; import { DateRangePicker } from '@/components/date-range-picker'; import { DataTableViewOptions } from './data-table-view-options'; import { useApiKeys } from '@/features/apikeys/data'; import { useMe } from '@/features/auth/data/auth'; import { useQueryChannels } from '@/features/channels/data/channels'; import { RequestStatus } from '../data/schema'; import type { DateTimeRangeValue } from '@/utils/date-range'; interface DataTableToolbarProps { table: Table; dateRange?: DateTimeRangeValue; onDateRangeChange?: (range: DateTimeRangeValue | undefined) => void; onRefresh?: () => void; showRefresh?: boolean; apiKeyFilter?: string[]; onApiKeyFilterChange?: (filters: string[]) => void; autoRefresh?: boolean; onAutoRefreshChange?: (enabled: boolean) => void; } export function DataTableToolbar({ table, dateRange, onDateRangeChange, onRefresh, showRefresh = false, apiKeyFilter, onApiKeyFilterChange, autoRefresh = false, onAutoRefreshChange, }: DataTableToolbarProps) { const { t } = useTranslation(); const [showArchivedApiKeys, setShowArchivedApiKeys] = useState(false); const [showArchivedChannels, setShowArchivedChannels] = useState(false); const hasDateRange = !!dateRange?.from || !!dateRange?.to; const isFiltered = table.getState().columnFilters.length > 0 || hasDateRange; // Handler to toggle show archived API keys and prune hidden IDs from filters const handleToggleShowArchivedApiKeys = (checked: boolean) => { setShowArchivedApiKeys(checked === true); if (checked === false) { // When turning off show archived, prune any archived IDs from the filter const currentFilter = table.getColumn('apiKey')?.getFilterValue() as string[] | undefined; if (currentFilter && currentFilter.length > 0) { // Compute visible IDs from raw data (filtering for non-archived status) const visibleIds = new Set( apiKeysData?.edges ?.filter((edge) => edge.node.status !== 'archived') ?.map((edge) => edge.node.id) ?? [] ); const prunedFilter = currentFilter.filter((id) => visibleIds.has(id)); table .getColumn('apiKey') ?.setFilterValue(prunedFilter.length > 0 ? prunedFilter : undefined); } } }; // Handler to toggle show archived channels and prune hidden IDs from filters const handleToggleShowArchivedChannels = (checked: boolean) => { setShowArchivedChannels(checked === true); if (checked === false) { // When turning off show archived, prune any archived IDs from the filter const currentFilter = table.getColumn('channel')?.getFilterValue() as string[] | undefined; if (currentFilter && currentFilter.length > 0) { // Compute visible IDs from raw data (filtering for non-archived status) const visibleIds = new Set( channelsData?.edges ?.filter((edge) => edge.node.status !== 'archived') ?.map((edge) => edge.node.id) ?? [] ); const prunedFilter = currentFilter.filter((id) => visibleIds.has(id)); table .getColumn('channel') ?.setFilterValue(prunedFilter.length > 0 ? prunedFilter : undefined); } } }; const { user: authUser } = useAuthStore((state) => state.auth); const { data: meData } = useMe(); const user = meData || authUser; const userScopes = user?.scopes || []; const isOwner = user?.isOwner || false; const canViewChannels = isOwner || userScopes.includes('*') || userScopes.includes('read_channels'); const canViewApiKeys = isOwner || userScopes.includes('*') || userScopes.includes('read_api_keys'); const { data: channelsData, isFetching: isFetchingChannels } = useQueryChannels( { first: 100, orderBy: { field: 'CREATED_AT', direction: 'DESC' }, where: showArchivedChannels ? { statusIn: ['enabled', 'disabled', 'archived'], } : { statusIn: ['enabled', 'disabled'], }, }, { disableAutoFetch: !canViewChannels, } ); const { data: apiKeysData, isFetching: isFetchingApiKeys } = useApiKeys( { first: 100, orderBy: { field: 'CREATED_AT', direction: 'DESC' }, where: showArchivedApiKeys ? { statusIn: ['enabled', 'disabled', 'archived'], } : { statusIn: ['enabled', 'disabled'], }, }, { disableAutoFetch: !canViewApiKeys, } ); const channelOptions = useMemo(() => { if (!canViewChannels || !channelsData?.edges) return []; return channelsData.edges.map((edge) => ({ value: edge.node.id, label: edge.node.name, })); }, [canViewChannels, channelsData]); const apiKeyOptions = useMemo(() => { if (!canViewApiKeys || !apiKeysData?.edges) return []; return apiKeysData.edges.map((edge) => ({ value: edge.node.id, label: edge.node.name, })); }, [canViewApiKeys, apiKeysData]); const requestStatuses = [ { value: 'pending' as RequestStatus, label: t('requests.status.pending'), }, { value: 'processing' as RequestStatus, label: t('requests.status.processing'), }, { value: 'completed' as RequestStatus, label: t('requests.status.completed'), }, { value: 'failed' as RequestStatus, label: t('requests.status.failed'), }, ]; const requestSources = [ { value: 'api', label: t('requests.source.api'), }, { value: 'playground', label: t('requests.source.playground'), }, { value: 'test', label: t('requests.source.test'), }, ]; return (
table.getColumn('id')?.setFilterValue(event.target.value)} className='h-8 w-[150px] lg:w-[250px]' /> {table.getColumn('status') && ( )} {/* {table.getColumn('source') && ( )} */} {canViewChannels && table.getColumn('channel') && (channelOptions.length > 0 || isFetchingChannels) && ( e.stopPropagation()} onClick={(e) => e.stopPropagation()} > handleToggleShowArchivedChannels(checked === true)} onPointerDown={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()} />
} /> )} {canViewApiKeys && table.getColumn('apiKey') && (apiKeyOptions.length > 0 || isFetchingApiKeys) && ( e.stopPropagation()} onClick={(e) => e.stopPropagation()} > handleToggleShowArchivedApiKeys(checked === true)} onPointerDown={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()} />
} /> )} {hasDateRange && ( )} {isFiltered && ( )}
{showRefresh && onAutoRefreshChange && (
)} {showRefresh && onRefresh && ( )}
); }