@@ -4,20 +4,28 @@ import {
44 getFilterBroadcastTarget ,
55 getFilterVariableName ,
66 getPendingFilterValuesVariables ,
7+ isAdhocFilter ,
78 isFilterGlobalRequirement ,
89 isFilterRequired ,
910 isFilterVariableEnabled ,
1011 isQueryExpressionFilter ,
1112 isStaticListFilter ,
1213} from '@hyperdx/common-utils/dist/filters' ;
1314import {
15+ AdhocFilterCondition ,
1416 ChartVariable ,
1517 DashboardFilter ,
1618} from '@hyperdx/common-utils/dist/types' ;
1719import { isFilterSingleSelect } from '@hyperdx/common-utils/dist/variables' ;
18- import { Group , Stack , Text , Tooltip } from '@mantine/core' ;
19- import { IconAlertTriangle , IconHelp , IconRefresh } from '@tabler/icons-react' ;
20+ import { Group , Stack , Text } from '@mantine/core' ;
21+ import { IconRefresh } from '@tabler/icons-react' ;
2022
23+ import { AdhocDashboardFilter } from './components/AdhocDashboardFilter/AdhocDashboardFilter' ;
24+ import {
25+ DashboardFilterLabel ,
26+ FilterCaution ,
27+ FilterEffect ,
28+ } from './components/DashboardFilterLabel' ;
2129import { FilterLinkToggle } from './components/FilterLinkToggle' ;
2230import { VirtualMultiSelect } from './components/VirtualMultiSelect/VirtualMultiSelect' ;
2331import { useDashboardFilterValues } from './hooks/useDashboardFilterValues' ;
@@ -65,9 +73,7 @@ export const getRequiredFilterTooltip = (filter: DashboardFilter): string =>
6573 * Describe what a filter does with the value you pick: broadcast it as a
6674 * condition, expose it as a variable, both, or neither.
6775 */
68- export const getFilterEffect = (
69- filter : DashboardFilter ,
70- ) : { hasEffect : boolean ; tooltip : string } => {
76+ export const getFilterEffect = ( filter : DashboardFilter ) : FilterEffect => {
7177 const parts : string [ ] = [ ] ;
7278
7379 const broadcast = getFilterBroadcastTarget ( filter ) ;
@@ -99,25 +105,6 @@ export const getFilterEffect = (
99105 return { hasEffect : true , tooltip : parts . join ( ', ' ) } ;
100106} ;
101107
102- /** One of the caution icons a filter's label row can carry, with its tooltip. */
103- const FilterCaution = ( {
104- label,
105- testId,
106- variant = 'warning' ,
107- } : {
108- label : string ;
109- testId : string ;
110- variant ?: 'warning' | 'danger' ;
111- } ) => (
112- < Tooltip label = { label } withinPortal multiline maw = { 400 } >
113- < IconAlertTriangle
114- size = { 12 }
115- color = { `var(--color-text-${ variant } )` }
116- data-testid = { testId }
117- />
118- </ Tooltip >
119- ) ;
120-
121108const DashboardFilterSelect = ( {
122109 filter,
123110 onChange,
@@ -134,25 +121,7 @@ const DashboardFilterSelect = ({
134121
135122 return (
136123 < Stack gap = { 2 } >
137- < Group gap = { 4 } align = "center" wrap = "nowrap" >
138- < Text size = "xs" c = "dimmed" >
139- { filter . name }
140- </ Text >
141- < Tooltip label = { effect . tooltip } withinPortal >
142- { effect . hasEffect ? (
143- < IconHelp
144- size = { 12 }
145- color = "var(--color-text-muted)"
146- data-testid = { `dashboard-filter-help-${ filter . name } ` }
147- />
148- ) : (
149- < IconAlertTriangle
150- size = { 12 }
151- color = "var(--color-text-warning)"
152- data-testid = { `dashboard-filter-no-effect-${ filter . name } ` }
153- />
154- ) }
155- </ Tooltip >
124+ < DashboardFilterLabel name = { filter . name } effect = { effect } >
156125 { isMissingRequiredValue && (
157126 < FilterCaution
158127 label = { getRequiredFilterTooltip ( filter ) }
@@ -175,7 +144,7 @@ const DashboardFilterSelect = ({
175144 variant = "danger"
176145 />
177146 ) }
178- </ Group >
147+ </ DashboardFilterLabel >
179148 < div style = { { width : 250 } } >
180149 < VirtualMultiSelect
181150 placeholder = { value . length === 0 ? filter . name : undefined }
@@ -203,6 +172,11 @@ interface DashboardFilterProps {
203172 filters : DashboardFilter [ ] ;
204173 selectionByFilterId : ReadonlyMap < string , FilterSelection > ;
205174 onSetFilterValue : ( filterId : string , values : string [ ] ) => void ;
175+ adhocConditionsByFilterId ?: ReadonlyMap < string , AdhocFilterCondition [ ] > ;
176+ onSetAdhocConditions ?: (
177+ filterId : string ,
178+ conditions : AdhocFilterCondition [ ] ,
179+ ) => void ;
206180 dateRange : [ Date , Date ] ;
207181 /**
208182 * The dashboard's variables and their current selections. Defined only when
@@ -217,6 +191,8 @@ const DashboardFilters = ({
217191 dateRange,
218192 selectionByFilterId,
219193 onSetFilterValue,
194+ adhocConditionsByFilterId,
195+ onSetAdhocConditions,
220196 variables,
221197} : DashboardFilterProps ) => {
222198 // "Link" mode (opt-in, off by default): each dropdown's values are narrowed by
@@ -248,6 +224,20 @@ const DashboardFilters = ({
248224 return (
249225 < Group align = "start" >
250226 { filters . map ( filter => {
227+ if ( isAdhocFilter ( filter ) ) {
228+ return (
229+ < AdhocDashboardFilter
230+ key = { filter . id }
231+ filter = { filter }
232+ conditions = { adhocConditionsByFilterId ?. get ( filter . id ) ?? [ ] }
233+ onChange = { conditions =>
234+ onSetAdhocConditions ?.( filter . id , conditions )
235+ }
236+ dateRange = { dateRange }
237+ effect = { getFilterEffect ( filter ) }
238+ />
239+ ) ;
240+ }
251241 const queriedFilterValues = filterValuesById ?. get ( filter . id ) ;
252242 const included = selectionByFilterId . get ( filter . id ) ?. included ;
253243 const selectedValues = included
0 commit comments