Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/scenes/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export {
} from './variables/variants/MultiValueVariable';
export { LocalValueVariable } from './variables/variants/LocalValueVariable';
export { IntervalVariable } from './variables/variants/IntervalVariable';
export { AdHocFiltersVariable } from './variables/adhoc/AdHocFiltersVariable';
export { AdHocFiltersVariable, GROUP_BY_OPERATOR_VALUE } from './variables/adhoc/AdHocFiltersVariable';
export type { AdHocFilterWithLabels } from './variables/adhoc/AdHocFiltersVariable';
export type {
AdHocFiltersController,
Expand Down
10 changes: 10 additions & 0 deletions packages/scenes/src/locales/en-US/grafana-scenes.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
"subTitle": "The url did not match any page",
"title": "Not found"
},
"group-by-pill": {
"clear-all": "Clear all group by values",
"edit-group-by": "Edit group by values",
"prefix": "Group by:",
"remove-value": "Remove {{label}}"
},
"lazy-loader": {
"placeholder": "\u00a0"
},
Expand Down Expand Up @@ -100,6 +106,10 @@
"placeholder-select-value": "Select value"
}
},
"adhoc": {
"group-by-operator-description": "Group by this label instead of filtering",
"group-by-operator-label": "Group by"
},
"adhoc-filters-combobox-renderer": {
"collapse": "Collapse",
"collapse-filters": "Collapse filters"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ import { FloatingFocusManager, FloatingPortal, UseFloatingOptions } from '@float
import { Spinner, Text, useStyles2 } from '@grafana/ui';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { css, cx } from '@emotion/css';
import { AdHocFilterWithLabels, isFilterComplete, isMultiValueOperator, OPERATORS } from '../AdHocFiltersVariable';
import {
AdHocFilterWithLabels,
GROUP_BY_OPERATOR_VALUE,
isFilterComplete,
isMultiValueOperator,
OPERATORS,
} from '../AdHocFiltersVariable';
import { AdHocFiltersController } from '../controller/AdHocFiltersController';
import { useVirtualizer } from '@tanstack/react-virtual';
import {
Expand Down Expand Up @@ -459,6 +465,21 @@ export const AdHocCombobox = forwardRef(function AdHocCombobox(
}
const selectedItem = filteredDropDownItems[activeIndex];

// Handle "Group by" operator selection
if (filterInputType === 'operator' && selectedItem.value === GROUP_BY_OPERATOR_VALUE) {
if (!isAlwaysWip && filter) {
// Editing an existing filter: remove it first
controller.removeFilter(filter);
}
controller.addGroupByValue?.(filter!.key, filter!.keyLabel);
handleResetWip();
handleChangeViewMode?.();
setOpen(false);
setInputValue('');
focusOnWipInputRef?.();
return;
}

if (multiValueEdit) {
handleLocalMultiValueChange(selectedItem);
setInputValue('');
Expand Down Expand Up @@ -508,8 +529,10 @@ export const AdHocCombobox = forwardRef(function AdHocCombobox(
controller,
filter,
filterInputType,
isAlwaysWip,
populateInputOnEdit,
handleChangeViewMode,
handleResetWip,
refs.domReference,
isLastFilter,
focusOnWipInputRef,
Expand Down Expand Up @@ -776,6 +799,21 @@ export const AdHocCombobox = forwardRef(function AdHocCombobox(
event.stopPropagation();
}

// Handle "Group by" operator selection via click
if (filterInputType === 'operator' && item.value === GROUP_BY_OPERATOR_VALUE) {
event.stopPropagation();
if (!isAlwaysWip && filter) {
controller.removeFilter(filter);
}
controller.addGroupByValue?.(filter!.key, filter!.keyLabel);
handleResetWip();
handleChangeViewMode?.();
setOpen(false);
setInputValue('');
focusOnWipInputRef?.();
return;
}

if (isMultiValueEdit) {
event.preventDefault();
event.stopPropagation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useMeasure } from 'react-use';
import { AdHocFiltersController } from '../controller/AdHocFiltersController';
import { AdHocFilterPill } from './AdHocFilterPill';
import { AdHocFiltersAlwaysWipCombobox } from './AdHocFiltersAlwaysWipCombobox';
import { GroupByPill } from './GroupByPill';

const MAX_VISIBLE_FILTERS = 5;

Expand All @@ -15,7 +16,9 @@ interface Props {
}

export const AdHocFiltersComboboxRenderer = memo(function AdHocFiltersComboboxRenderer({ controller }: Props) {
const { originFilters, filters, readOnly, collapsible, valueRecommendations } = controller.useState();
const { originFilters, filters, readOnly, collapsible, valueRecommendations, forceEditGroupBy } =
controller.useState();
const groupByVariable = controller.getGroupByVariable?.();
const styles = useStyles2(getStyles);
const theme = useTheme2();
const [collapsed, setCollapsed] = useState(true);
Expand Down Expand Up @@ -85,6 +88,17 @@ export const AdHocFiltersComboboxRenderer = memo(function AdHocFiltersComboboxRe

{valueRecommendations && <valueRecommendations.Component model={valueRecommendations} />}

{/* Single GroupBy pill showing all group-by values — rendered first */}
{groupByVariable && (
<GroupByPill
groupByVariable={groupByVariable}
controller={controller}
readOnly={readOnly}
focusOnWipInputRef={focusOnWipInputRef.current}
forceEdit={forceEditGroupBy}
/>
)}

{filtersToRender.map((filter, index) => (
<AdHocFilterPill
key={`${filter.origin ? 'origin-' : ''}${index}-${filter.key}`}
Expand Down
Loading