Skip to content

Commit c9d1dda

Browse files
MikeShi42cursoragentgithub-actions[bot]
authored
feat: Add Column toggle button to filter panel in DBSearchPage (#1947)
## Summary Adds a column toggle button (+ / - icon) next to the "Show Distribution" button in each filter group header on the search page. Clicking the button adds or removes the filter's field from the `SELECT` statement, and the table reflects the change immediately. ### Changes - **`FilterGroup`** (`DBSearchPageFilters.tsx`): Added `onColumnToggle` and `isColumnDisplayed` props. Renders an `ActionIcon` with `IconPlus` (add) or `IconMinus` (remove) between the distribution toggle and the pin field button. - **`NestedFilterGroup`**: Passes the new column toggle props through to child `FilterGroup` components. - **`DBSearchPage.tsx`**: Passes `toggleColumn` and `displayedColumns` to `DBSearchPageFilters`, reusing the existing `toggleColumn` callback that manages the `SELECT` form field. ### Screenshots or video | Before | After | | :----- | :---- | | Only distribution and pin buttons in filter header | New +/- column button appears between distribution and pin buttons | ### How to test locally or on Vercel 1. Navigate to the Search page 2. Open the filter panel on the left side 3. Find any filter group and hover over the header area — a `+` icon should appear next to the distribution chart icon 4. Click the `+` icon — the field should be added to the `SELECT` input and appear as a column in the results table 5. Click the `-` icon (now shown since the column is displayed) — the field should be removed from `SELECT` and the column disappears ### References - Linear Issue: HDX-3770 Linear Issue: [HDX-3770](https://linear.app/clickhouse/issue/HDX-3770/telstra-add-column-from-filter-panel-in-dbsearchpage) <div><a href="https://cursor.com/agents/bc-11d702b5-a58e-485c-982f-61d990e45091"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-11d702b5-a58e-485c-982f-61d990e45091"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div> Co-authored-by: Cursor Agent <199161495+cursoragent@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent b642ce4 commit c9d1dda

File tree

4 files changed

+59
-1
lines changed

4 files changed

+59
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperdx/app": patch
3+
---
4+
5+
feat: Add column toggle button to filter panel in DBSearchPage

packages/app/src/DBSearchPage.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,8 @@ function DBSearchPage() {
17691769
? searchedSource.durationExpression
17701770
: undefined)
17711771
}
1772+
onColumnToggle={toggleColumn}
1773+
displayedColumns={displayedColumns}
17721774
{...searchFilters}
17731775
/>
17741776
</ErrorBoundary>

packages/app/src/components/DBSearchPageFilters.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ import {
3636
IconChevronRight,
3737
IconChevronUp,
3838
IconFilterOff,
39+
IconMinus,
3940
IconPin,
4041
IconPinFilled,
42+
IconPlus,
4143
IconRefresh,
4244
IconSearch,
4345
IconShadow,
@@ -341,6 +343,8 @@ export type FilterGroupProps = {
341343
isPinned: (value: string | boolean) => boolean;
342344
onFieldPinClick?: VoidFunction;
343345
isFieldPinned?: boolean;
346+
onColumnToggle?: VoidFunction;
347+
isColumnDisplayed?: boolean;
344348
onLoadMore: (key: string) => void;
345349
loadMoreLoading: boolean;
346350
hasLoadedMore: boolean;
@@ -349,7 +353,7 @@ export type FilterGroupProps = {
349353
chartConfig: BuilderChartConfigWithDateRange;
350354
isLive?: boolean;
351355
onRangeChange?: (range: { min: number; max: number }) => void;
352-
distributionKey?: string; // Optional key to use for distribution queries, defaults to name
356+
distributionKey?: string;
353357
};
354358

355359
export const FilterGroup = ({
@@ -365,6 +369,8 @@ export const FilterGroup = ({
365369
onPinClick,
366370
onFieldPinClick,
367371
isFieldPinned,
372+
onColumnToggle,
373+
isColumnDisplayed,
368374
onLoadMore,
369375
loadMoreLoading,
370376
hasLoadedMore,
@@ -641,6 +647,29 @@ export const FilterGroup = ({
641647
)}
642648
</ActionIcon>
643649
</Tooltip>
650+
{onColumnToggle && (
651+
<Tooltip
652+
label={isColumnDisplayed ? 'Remove Column' : 'Add Column'}
653+
position="top"
654+
withArrow
655+
fz="xxs"
656+
color="gray"
657+
>
658+
<ActionIcon
659+
size="xs"
660+
variant="subtle"
661+
color="gray"
662+
onClick={onColumnToggle}
663+
data-testid={`toggle-column-button-${name}`}
664+
>
665+
{isColumnDisplayed ? (
666+
<IconMinus size={14} />
667+
) : (
668+
<IconPlus size={14} />
669+
)}
670+
</ActionIcon>
671+
</Tooltip>
672+
)}
644673
{onFieldPinClick && (
645674
<Tooltip
646675
label={isFieldPinned ? 'Unpin Field' : 'Pin Field'}
@@ -844,6 +873,8 @@ const DBSearchPageFiltersComponent = ({
844873
denoiseResults,
845874
setDenoiseResults,
846875
setFilterRange,
876+
onColumnToggle,
877+
displayedColumns,
847878
}: {
848879
analysisMode: 'results' | 'delta' | 'pattern';
849880
setAnalysisMode: (mode: 'results' | 'delta' | 'pattern') => void;
@@ -854,6 +885,8 @@ const DBSearchPageFiltersComponent = ({
854885
denoiseResults: boolean;
855886
setDenoiseResults: (denoiseResults: boolean) => void;
856887
setFilterRange: (key: string, range: { min: number; max: number }) => void;
888+
onColumnToggle?: (column: string) => void;
889+
displayedColumns?: string[];
857890
} & FilterStateHook) => {
858891
const setFilterValue = useCallback(
859892
(
@@ -1334,6 +1367,8 @@ const DBSearchPageFiltersComponent = ({
13341367
isPinned={(key, value) => isFilterPinned(key, value)}
13351368
onFieldPinClick={key => toggleFieldPin(key)}
13361369
isFieldPinned={key => isFieldPinned(key)}
1370+
onColumnToggle={onColumnToggle}
1371+
displayedColumns={displayedColumns}
13371372
onLoadMore={loadMoreFilterValuesForKey}
13381373
loadMoreLoading={group.children.reduce(
13391374
(acc, child) => {
@@ -1394,6 +1429,12 @@ const DBSearchPageFiltersComponent = ({
13941429
isPinned={value => isFilterPinned(facet.key, value)}
13951430
onFieldPinClick={() => toggleFieldPin(facet.key)}
13961431
isFieldPinned={isFieldPinned(facet.key)}
1432+
onColumnToggle={
1433+
onColumnToggle
1434+
? () => onColumnToggle(facet.key)
1435+
: undefined
1436+
}
1437+
isColumnDisplayed={displayedColumns?.includes(facet.key)}
13971438
onLoadMore={loadMoreFilterValuesForKey}
13981439
loadMoreLoading={loadMoreLoadingKeys.has(facet.key)}
13991440
hasLoadedMore={Boolean(extraFacets[facet.key])}

packages/app/src/components/DBSearchPageFilters/NestedFilterGroup.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export type NestedFilterGroupProps = {
3030
isPinned: (key: string, value: string | boolean) => boolean;
3131
onFieldPinClick?: (key: string) => void;
3232
isFieldPinned?: (key: string) => boolean;
33+
onColumnToggle?: (column: string) => void;
34+
displayedColumns?: string[];
3335
onLoadMore: (key: string) => void;
3436
loadMoreLoading: Record<string, boolean>;
3537
hasLoadedMore: Record<string, boolean>;
@@ -51,6 +53,8 @@ export const NestedFilterGroup = ({
5153
isPinned,
5254
onFieldPinClick,
5355
isFieldPinned,
56+
onColumnToggle,
57+
displayedColumns,
5458
onLoadMore,
5559
loadMoreLoading,
5660
hasLoadedMore,
@@ -153,6 +157,12 @@ export const NestedFilterGroup = ({
153157
isPinned={value => isPinned(child.key, value)}
154158
onFieldPinClick={() => onFieldPinClick?.(child.key)}
155159
isFieldPinned={isFieldPinned?.(child.key)}
160+
onColumnToggle={
161+
onColumnToggle
162+
? () => onColumnToggle(child.key)
163+
: undefined
164+
}
165+
isColumnDisplayed={displayedColumns?.includes(child.key)}
156166
onLoadMore={() => onLoadMore(child.key)}
157167
loadMoreLoading={loadMoreLoading[child.key] || false}
158168
hasLoadedMore={hasLoadedMore[child.key] || false}

0 commit comments

Comments
 (0)