Repository navigation
feat: ad hoc filter finishing touches #3658
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --- | ||
| '@hyperdx/common-utils': patch | ||
| '@hyperdx/app': patch | ||
| '@hyperdx/api': patch | ||
| --- | ||
|
|
||
| feat: Ad hoc dashboard filter finishing touches | ||
|
|
||
| - Add an `IN` operator for SQL and a `=|` operator for PromQL. Conditions on the | ||
| same key are OR'd into one `IN (...)` or `=~"a|b"` condition. | ||
| - Ad hoc filters always broadcast (`isBroadcastEnabled: true`), and their | ||
| variable name is only a unique identifier. It is no longer declared as a | ||
| `$variable`. | ||
| - Warn when another ad hoc filter already applies to the same sources. | ||
| - Collapse the filter input to three conditions behind a "+N more" toggle. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ import { | |
| import { getVariableReferences } from '@hyperdx/common-utils/dist/variables'; | ||
| import { | ||
| ActionIcon, | ||
| Button, | ||
| CloseButton, | ||
| Group, | ||
| Popover, | ||
|
|
@@ -39,6 +40,9 @@ import { | |
| notifyAdhocFilterFull, | ||
| } from './notifications'; | ||
|
|
||
| // Series with many labels (common in PromQL) would otherwise grow the input tall. | ||
| const MAX_COLLAPSED_CONDITIONS = 3; | ||
|
|
||
| type AdhocDashboardFilterProps = { | ||
| filter: AdhocDashboardFilterType; | ||
| conditions: AdhocFilterCondition[]; | ||
|
|
@@ -62,7 +66,12 @@ export function AdhocDashboardFilter({ | |
| unsatisfiedRequiredFilters, | ||
| }: AdhocDashboardFilterProps) { | ||
| const [isAdding, setIsAdding] = useState(false); | ||
| const [isExpanded, setIsExpanded] = useState(false); | ||
| const isAtLimit = conditions.length >= ADHOC_FILTER_MAX_CONDITIONS; | ||
| const hiddenCount = isExpanded | ||
| ? 0 | ||
| : Math.max(0, conditions.length - MAX_COLLAPSED_CONDITIONS); | ||
| const languageName = filter.sourceType === 'promql' ? 'PromQL' : 'SQL'; | ||
|
|
||
| // The `where` narrowing the suggestions, and what it is still waiting on. | ||
| // Blocked only by the required filters it references: a global requirement | ||
|
|
@@ -153,45 +162,57 @@ export function AdhocDashboardFilter({ | |
| borderRadius: 'var(--mantine-radius-sm)', | ||
| }} | ||
| > | ||
| {conditions.map((condition, index) => { | ||
| const operator = getFilterOperatorDisplay( | ||
| filter.sourceType, | ||
| condition.operator, | ||
| ); | ||
| return ( | ||
| <FilterPill | ||
| key={JSON.stringify(condition)} | ||
| field={condition.key} | ||
| operator={operator.label} | ||
| value={condition.value} | ||
| isExcluded={operator.isExcluded} | ||
| isInvalid={ | ||
| !isAdhocConditionSupported(filter.sourceType, condition) | ||
| } | ||
| invalidReason={`Filter not applied: PromQL has no ${condition.operator} operator. Remove this condition and add it again with a supported operator.`} | ||
| onRemove={() => remove(index)} | ||
| // Editing would look up suggestions; removing still works. | ||
| renderPopover={ | ||
| isDisabled | ||
| ? undefined | ||
| : close => ( | ||
| <AdhocConditionEditor | ||
| filter={filter} | ||
| dateRange={dateRange} | ||
| suggestionsWhere={suggestionsWhere} | ||
| initial={condition} | ||
| onSubmit={next => { | ||
| if (!isStorable(next)) return; | ||
| replace(index, next); | ||
| close(); | ||
| }} | ||
| /> | ||
| ) | ||
| } | ||
| data-testid="adhoc-condition-pill" | ||
| /> | ||
| ); | ||
| })} | ||
| {conditions | ||
| .slice(0, conditions.length - hiddenCount) | ||
|
knudtty marked this conversation as resolved.
Resolved
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 minor — New conditions and invalid conditions get hidden behind the "+N more" toggle When the filter is collapsed and already has 3 or more conditions, a new condition from the add popover or from click-to-filter is appended at the end. The slice hides it at once, so the user only sees the counter go up and never sees the chip they just added. Conditions past the first three that are marked invalid ( Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond |
||
| .map((condition, index) => { | ||
| const operator = getFilterOperatorDisplay( | ||
| filter.sourceType, | ||
| condition.operator, | ||
| ); | ||
| return ( | ||
| <FilterPill | ||
| key={JSON.stringify(condition)} | ||
| field={condition.key} | ||
| operator={operator.label} | ||
| value={condition.value} | ||
| isExcluded={operator.isExcluded} | ||
| isInvalid={ | ||
| !isAdhocConditionSupported(filter.sourceType, condition) | ||
| } | ||
| invalidReason={`Filter not applied: ${languageName} has no ${condition.operator} operator. Remove this condition and add it again with a supported operator.`} | ||
| onRemove={() => remove(index)} | ||
| // Editing would look up suggestions; removing still works. | ||
| renderPopover={ | ||
| isDisabled | ||
| ? undefined | ||
| : close => ( | ||
| <AdhocConditionEditor | ||
| filter={filter} | ||
| dateRange={dateRange} | ||
| suggestionsWhere={suggestionsWhere} | ||
| initial={condition} | ||
| onSubmit={next => { | ||
| if (!isStorable(next)) return; | ||
| replace(index, next); | ||
| close(); | ||
| }} | ||
| /> | ||
| ) | ||
| } | ||
| data-testid="adhoc-condition-pill" | ||
| /> | ||
| ); | ||
| })} | ||
| {conditions.length > MAX_COLLAPSED_CONDITIONS && ( | ||
| <Button | ||
| variant="subtle" | ||
| size="compact-xs" | ||
| onClick={() => setIsExpanded(!isExpanded)} | ||
| data-testid={`adhoc-filter-toggle-more-${filter.name}`} | ||
| > | ||
| {isExpanded ? 'Show less' : `+${hiddenCount} more`} | ||
| </Button> | ||
| )} | ||
| {conditions.length === 0 && ( | ||
| <Text | ||
| size="xs" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔵 minor — New and invalid conditions are hidden while the filter is collapsed
New conditions are appended to the end of the list, and the list is cut at the first three. Once a filter holds three or more conditions, a condition the user adds with "+" or by clicking a tile value is hidden right away; the only sign of it is the "+N more" count going up. An invalid (
data-invalid) chip past the third position is hidden the same way, so its "Filter not applied" warning never shows. Fix: expand the list when a condition is added (setisExpandedin the add andonChangepaths), or always show invalid chips. At minimum, mark the "+N more" button when a hidden chip is invalid.Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond