Skip to content

Commit

Permalink
Multiple include: Fields & Metadata (#1091)
Browse files Browse the repository at this point in the history
* feat: multiple field includes

---------

Co-authored-by: Matias Chomicki <matyax@gmail.com>
  • Loading branch information
gtk-grafana and matyax authored Feb 24, 2025
1 parent 8f090a0 commit df09c78
Show file tree
Hide file tree
Showing 21 changed files with 1,162 additions and 168 deletions.
2 changes: 1 addition & 1 deletion src/Components/IndexScene/LevelsVariableScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class LevelsVariableScene extends SceneObjectBase<LevelsVariableSceneStat
hideSelectedOptions={false}
value={options?.filter((v) => v.selected)}
options={options?.map((val) => ({
value: val.text,
value: val.value,
label: val.text,
}))}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ describe('addToFilters and addAdHocFilter', () => {
it('allows to clear a filter', () => {
const lookupVariable = jest.spyOn(sceneGraph, 'lookupVariable').mockReturnValue(adHocVariable);
jest.spyOn(sceneGraph, 'getAncestor').mockReturnValue(serviceScene);
addToFilters('existing', 'existingValue', 'clear', scene);
addToFilters('existing', 'existingValue', 'clear', scene, VAR_FIELDS);
expect(lookupVariable).toHaveBeenCalledWith(VAR_FIELDS_AND_METADATA, expect.anything());
expect(adHocVariable.state.filters).toEqual([]);
});
Expand Down Expand Up @@ -231,7 +231,7 @@ describe('addToFilters and addAdHocFilter', () => {
it.each(['=', '!='])('allows to add an %s filter', (operator: string) => {
const lookupVariable = jest.spyOn(sceneGraph, 'lookupVariable').mockReturnValue(adHocVariable);
jest.spyOn(sceneGraph, 'getAncestor').mockReturnValue(serviceScene);
addAdHocFilter({ key: 'key', value: 'value', operator }, scene);
addAdHocFilter({ key: 'key', value: 'value', operator }, scene, VAR_FIELDS);

expect(lookupVariable).toHaveBeenCalledWith(VAR_FIELDS_AND_METADATA, expect.anything());
expect(adHocVariable.state.filters).toEqual([
Expand Down
27 changes: 12 additions & 15 deletions src/Components/ServiceScene/Breakdowns/AddToFiltersButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { FilterOp, NumericFilterOp } from '../../../services/filterTypes';
import { addToFavorites } from '../../../services/favorites';
import { areArraysEqual } from '../../../services/comparison';
import { logger } from '../../../services/logger';
import { isFilterMetadata } from '../../../services/filters';

export interface AddToFiltersButtonState extends SceneObjectState {
frame: DataFrame;
Expand Down Expand Up @@ -70,7 +71,7 @@ export type NumericFilterType = NumericFilterOp.gt | NumericFilterOp.gte | Numer
*/
export type FilterType = 'include' | 'clear' | 'exclude' | 'toggle';

export function addAdHocFilter(filter: AdHocVariableFilter, scene: SceneObject, variableType?: InterpolatedFilterType) {
export function addAdHocFilter(filter: AdHocVariableFilter, scene: SceneObject, variableType: InterpolatedFilterType) {
const type: FilterType = filter.operator === '=' ? 'include' : 'exclude';
addToFilters(filter.key, filter.value, type, scene, variableType);
}
Expand All @@ -82,18 +83,14 @@ export type AdHocFilterTypes = InterpolatedFilterType | typeof VAR_LABELS_REPLIC
export function clearFilters(
key: string,
scene: SceneObject,
variableType?: InterpolatedFilterType,
variableType: InterpolatedFilterType,
value?: string,
operator?: FilterType
) {
if (!variableType) {
variableType = resolveVariableTypeForField(key, scene);
}

const variable = getUIAdHocVariable(variableType, key, scene);

let filters = variable.state.filters.filter((filter) => {
const fieldValue = getValueFromAdHocVariableFilter(variable, filter);
const fieldValue = getValueFromAdHocVariableFilter(variableType, filter);
if (value && operator) {
return !(filter.key === key && fieldValue.value === value && filter.operator === operator);
}
Expand Down Expand Up @@ -200,29 +197,28 @@ export function addToFilters(
value: string,
operator: FilterType,
scene: SceneObject,
variableType?: InterpolatedFilterType
variableType: InterpolatedFilterType
) {
if (!variableType) {
variableType = resolveVariableTypeForField(key, scene);
}

if (variableType === VAR_LABELS) {
addToFavorites(key, value, scene);
}

const variable = getUIAdHocVariable(variableType, key, scene);

let valueObject: string | undefined = undefined;
let valueLabel = value;
if (variableType === VAR_FIELDS) {
valueObject = JSON.stringify({
value,
parser: getParserForField(key, scene),
});
} else if (variableType === VAR_LEVELS && operator === 'exclude') {
valueLabel = `!${value}`;
}

// If the filter exists, filter it
let filters = variable.state.filters.filter((filter) => {
const fieldValue = getValueFromAdHocVariableFilter(variable, filter);
const fieldValue = getValueFromAdHocVariableFilter(variableType, filter);

// if we're including, we want to remove all filters that have this key
if (operator === 'include') {
Expand All @@ -244,7 +240,7 @@ export function addToFilters(
key,
operator: operator === 'exclude' ? FilterOp.NotEqual : FilterOp.Equal,
value: valueObject ? valueObject : value,
valueLabels: [value],
valueLabels: [valueLabel],
},
];
}
Expand Down Expand Up @@ -326,7 +322,8 @@ export class AddToFiltersButton extends SceneObjectBase<AddToFiltersButtonState>

// Check if the filter is already there
const filterInSelectedFilters = variable.state.filters.find((f) => {
const value = getValueFromAdHocVariableFilter(variable, f);
const isMetadata = isFilterMetadata(filter);
const value = getValueFromAdHocVariableFilter(isMetadata ? VAR_METADATA : VAR_FIELDS, f);
return f.key === filter.name && value.value === filter.value;
});

Expand Down
Loading

0 comments on commit df09c78

Please sign in to comment.