ReportFilterBar() — supabase Function Reference
Architecture documentation for the ReportFilterBar() function in ReportFilterBar.tsx from the supabase codebase.
Entity Profile
Relationship Graph
Source Code
apps/studio/components/interfaces/Reports/ReportFilterBar.tsx lines 82–370
const ReportFilterBar = ({
filters,
isLoading = false,
onAddFilter,
onDatepickerChange,
hideDatepicker = false,
onRemoveFilters,
onRefresh,
datepickerHelpers,
initialDatePickerValue,
className,
selectedProduct,
showDatabaseSelector = true,
}: ReportFilterBarProps) => {
const { ref } = useParams()
const { data: loadBalancers } = useLoadBalancersQuery({ projectRef: ref })
const filterKeys = [
'request.path',
'request.method',
'request.search',
'request.headers.x_client_info',
'request.headers.user_agent',
'response.status_code',
]
const [showAdder, setShowAdder] = useState(false)
const [currentProductFilter, setCurrentProductFilter] = useState<
null | (typeof PRODUCT_FILTERS)[number]
>(null)
const [addFilterValues, setAddFilterValues] = useState<ReportFilterItem>({
key: filterKeys[0],
compare: 'is',
value: '',
})
const resetFilterValues = () => {
setAddFilterValues({
key: filterKeys[0],
compare: 'is',
value: '',
})
}
const handleDatepickerChange = (vals: DatePickerValue) => {
onDatepickerChange && onDatepickerChange(vals)
setSelectedRange(vals)
}
const handleProductFilterChange = async (
nextProductFilter: null | (typeof PRODUCT_FILTERS)[number]
) => {
const toRemove = PRODUCT_FILTERS.map(
(productFilter) =>
({
key: productFilter.filterKey,
compare: 'matches',
value: productFilter.filterValue,
}) as ReportFilterItem
)
onRemoveFilters(toRemove)
if (nextProductFilter) {
onAddFilter({
key: nextProductFilter.filterKey,
compare: 'matches',
value: nextProductFilter.filterValue,
})
}
setCurrentProductFilter(nextProductFilter)
}
useEffect(() => {
if (selectedProduct) {
handleProductFilterChange(PRODUCT_FILTERS.find((p) => p.key === selectedProduct) ?? null)
}
}, [])
const getInitialDatePickerValue = () => {
if (initialDatePickerValue) {
return initialDatePickerValue
}
const defaultHelper = datepickerHelpers.find((h) => h.default) || datepickerHelpers[0]
return {
to: defaultHelper.calcTo(),
from: defaultHelper.calcFrom(),
isHelper: true,
text: defaultHelper.text,
}
}
const [selectedRange, setSelectedRange] = useState<DatePickerValue>(getInitialDatePickerValue())
// Sync selectedRange when initialDatePickerValue changes
useEffect(() => {
if (initialDatePickerValue) {
setSelectedRange(initialDatePickerValue)
}
}, [initialDatePickerValue])
return (
<div className={cn('flex items-center justify-between', className)}>
<div className="flex flex-row justify-start items-center flex-wrap gap-2">
{onRefresh && (
<ButtonTooltip
type="default"
disabled={isLoading}
icon={<RefreshCw className={isLoading ? 'animate-spin' : ''} />}
className="w-7"
tooltip={{ content: { side: 'bottom', text: 'Refresh report' } }}
onClick={() => onRefresh()}
/>
)}
{!hideDatepicker && (
<LogsDatePicker
onSubmit={handleDatepickerChange}
value={selectedRange}
helpers={datepickerHelpers}
/>
)}
{!selectedProduct && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
type="default"
className="inline-flex flex-row gap-2"
iconRight={<ChevronDown size={14} />}
>
<span>
{currentProductFilter === null ? 'All Requests' : currentProductFilter.label}
</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="bottom" align="start">
<DropdownMenuItem onClick={() => handleProductFilterChange(null)}>
<Network size={14} strokeWidth={1.5} className="mr-2" />
All Requests
</DropdownMenuItem>
<DropdownMenuSeparator />
{PRODUCT_FILTERS.map((productFilter) => {
const Icon = productFilter.icon
return (
<DropdownMenuItem
key={productFilter.key}
className="space-x-2"
disabled={productFilter.key === currentProductFilter?.key}
onClick={() => handleProductFilterChange(productFilter)}
>
{productFilter.key === 'graphql' ? (
<SVG
src={`${BASE_PATH}/img/graphql.svg`}
className="w-[14px] h-[14px] mr-2"
preProcessor={(code) =>
code.replace(/svg/, 'svg class="m-auto text-color-inherit"')
}
/>
) : Icon !== null ? (
<Icon size={14} strokeWidth={1.5} className="mr-2" />
) : null}
<div className="flex flex-col">
<p
className={cn(
productFilter.key === currentProductFilter?.key ? 'font-bold' : '',
'inline-block'
)}
>
{productFilter.label}
</p>
</div>
</DropdownMenuItem>
)
})}
</DropdownMenuContent>
</DropdownMenu>
)}
{filters
.filter(
(filter) =>
filter.value !== currentProductFilter?.filterValue ||
filter.key !== currentProductFilter?.filterKey
)
.map((filter) => (
<div
key={`${filter.key}-${filter.compare}-${filter.value}`}
className="text-xs rounded-md font-mono bg-surface-300 px-2 h-[26px] flex flex-row justify-center gap-1 items-center"
>
<span className="">{filter.key}</span>
<span className="text-foreground-lighter">{filter.compare}</span>
<span className="">{filter.value}</span>
<Button
type="text"
size="tiny"
className="!p-0 !space-x-0"
onClick={() => onRemoveFilters([filter])}
icon={<X className="text-foreground-light" />}
>
<span className="sr-only">Remove</span>
</Button>
</div>
))}
<Popover open={showAdder} onOpenChange={(openValue) => setShowAdder(openValue)}>
<PopoverTrigger>
<Button
asChild
type="default"
size="tiny"
icon={<Plus className={`text-foreground-light `} />}
>
<span>Add filter</span>
</Button>
</PopoverTrigger>
<PopoverContent align={filters.length > 0 ? 'end' : 'start'} className="p-0 w-60">
<div className="flex flex-col gap-3 p-3">
<Select
size="tiny"
value={addFilterValues.key}
onChange={(e) => {
setAddFilterValues((prev) => ({ ...prev, key: e.target.value }))
}}
label="Attribute Filter"
className="gap-[2px]"
>
{filterKeys.map((key) => (
<Select.Option key={key} value={key}>
{key}
</Select.Option>
))}
</Select>
<Select
size="tiny"
value={addFilterValues.compare}
onChange={(e) => {
setAddFilterValues((prev) => ({
...prev,
compare: e.target.value as ReportFilterItem['compare'],
}))
}}
label="Comparison"
className="gap-[2px]"
>
{['is', 'matches'].map((value) => (
<Select.Option key={value} value={value}>
{value}
</Select.Option>
))}
</Select>
<Input
size="tiny"
label="Value"
className="gap-[2px]"
placeholder={
addFilterValues.compare === 'matches'
? 'Provide a regex expression'
: 'Provide a string'
}
onChange={(e) => {
setAddFilterValues((prev) => ({ ...prev, value: e.target.value }))
}}
/>
</div>
<div className="flex items-center justify-end gap-2 border-t border-default p-2">
<Button
type="primary"
size="tiny"
onClick={() => {
onAddFilter(addFilterValues)
setShowAdder(false)
resetFilterValues()
}}
>
Add filter
</Button>
</div>
</PopoverContent>
</Popover>
</div>
{showDatabaseSelector && (
<DatabaseSelector
additionalOptions={
(loadBalancers ?? []).length > 0
? [{ id: `${ref}-all`, name: 'API Load Balancer' }]
: []
}
/>
)}
</div>
)
}
Domain
Subdomains
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free