Unified logs add facet count to filter options if operator is eq (#47121)

## Context

Changes are mainly within the `FilterBar` component in UI patterns

Supports a `count` option in `filterProperties` for `FilterBar` - which
will render as a filter option but only if the operator is set to
`eq`(opting for this as we don't have the numbers up front for the `neq`
operator)

<img width="389" height="319" alt="image"
src="https://github.com/user-attachments/assets/1d6e7dae-5350-4110-910b-88a5517fbb6e"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Filter options in Unified Logs now display item counts for log type,
method, level, and other enum filters, providing visibility into result
distribution across filter choices.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Joshen Lim authored and GitHub committed 2026-06-22 13:29:26 +08:00
1 parent e9a976aa74
commit 2207d7f665
4 files changed
+38 -9

No files matched your search

@@ -275,13 +275,20 @@ export const UnifiedLogs = () => {
// For hardcoded enum fields, keep the predefined options (facets only used for counts)
if (field.value === 'log_type' || field.value === 'method' || field.value === 'level') {
return field
const fieldWithCounts = {
...field,
options: field.options.map((x) => {
return { ...x, count: facetsField.rows.find((y) => y.value === x.value)?.total ?? 0 }
}),
}
return fieldWithCounts
}
// For dynamic fields, use faceted options
const options: Option[] = facetsField.rows.map(({ value }) => ({
const options: Option[] = facetsField.rows.map(({ value, total }) => ({
label: `${value}`,
value,
count: total,
}))
return { ...field, options }
@@ -25,7 +25,7 @@ export function CommandListItem({
role="option"
onClick={() => onSelect(item)}
className={cn(
'relative flex items-center justify-between gap-2 px-2 py-1.5 text-xs cursor-pointer select-none outline-hidden text-foreground',
'relative flex items-center justify-between gap-2 px-2 h-[28px] text-xs cursor-pointer select-none outline-hidden text-foreground',
isHighlighted && 'bg-surface-300',
!isHighlighted && 'hover:bg-surface-200'
)}
@@ -35,6 +35,9 @@ export function CommandListItem({
{includeIcon && item.icon}
<span className="truncate">{getActionItemLabel(item)}</span>
</span>
{item.count !== undefined && (
<code className="text-code-inline text-foreground-light">{item.count}</code>
)}
{item.operatorSymbol && <OperatorSymbolBadge symbol={item.operatorSymbol} />}
</div>
)
@@ -156,7 +156,14 @@ export function buildValueItems(
} else if (loadingOptions[property.name]) {
items.push({ value: 'loading', label: 'Loading options...' })
} else if (Array.isArray(property.options)) {
items.push(...getArrayOptionItems(property.options, inputValue, hasTypedSinceFocus))
items.push(
...getArrayOptionItems({
options: property.options,
inputValue,
hasTypedSinceFocus,
showCount: activeCondition?.operator === '=',
})
)
} else if (propertyOptionsCache[property.name]) {
items.push(...getCachedOptionItems(propertyOptionsCache[property.name].options))
}
@@ -164,11 +171,17 @@ export function buildValueItems(
return items
}
function getArrayOptionItems(
options: any[],
inputValue: string,
function getArrayOptionItems({
options,
inputValue,
hasTypedSinceFocus,
showCount,
}: {
options: any[]
inputValue: string
hasTypedSinceFocus: boolean
): MenuItem[] {
showCount?: boolean
}): MenuItem[] {
const items: MenuItem[] = []
const normalizedInput = inputValue.toLowerCase()
@@ -182,7 +195,11 @@ function getArrayOptionItems(
}
} else if (isFilterOptionObject(option)) {
if (!shouldFilter || option.label.toLowerCase().includes(normalizedInput)) {
items.push({ value: option.value, label: option.label })
items.push({
value: option.value,
label: option.label,
count: showCount ? option.count : undefined,
})
}
} else if (isCustomOptionObject(option)) {
if (!shouldFilter || (option.label?.toLowerCase().includes(normalizedInput) ?? true)) {
@@ -9,6 +9,7 @@ export type CustomOptionProps = {
export type FilterOptionObject = {
label: string
value: string
count?: number
}
export type CustomOptionObject = {
@@ -89,6 +90,7 @@ export type FilterBarAction = {
export type MenuItem = {
value: string
label: string
count?: number
icon?: React.ReactNode
isCustom?: boolean
customOption?: (props: CustomOptionProps) => React.ReactElement