mirror of
https://github.com/grafana/grafana.git
synced 2025-09-20 01:39:53 +08:00
Transformations: Add time filtering to filter by value (#101591)
* WIP - time filtering * Replace variable test * Change tests * Validator is already tested * Change test to match evaluation * Add line to docs * Revert "Add line to docs" This reverts commit 783f247c33e854e00a72a42c5d04eee3aa923a5a. * Put transformations docs update in the right place, cannot build without an update, WIP * Run build * Use regex test and rewind * Does this help * make config optional
This commit is contained in:
@ -461,13 +461,13 @@ The available conditions for string fields are:
|
||||
- **Contains substring** - Match if the value contains the specified substring (case insensitive).
|
||||
- **Does not contain substring** - Match if the value doesn't contain the specified substring (case insensitive).
|
||||
|
||||
The available conditions for number fields are:
|
||||
The available conditions for number and time fields are:
|
||||
|
||||
- **Greater** - Match if the value is greater than the specified value.
|
||||
- **Lower** - Match if the value is lower than the specified value.
|
||||
- **Greater or equal** - Match if the value is greater or equal.
|
||||
- **Lower or equal** - Match if the value is lower or equal.
|
||||
- **Range** - Match a range between a specified minimum and maximum, min and max included.
|
||||
- **Range** - Match a range between a specified minimum and maximum, min and max included. A time field will pre-populate with variables to filter by selected time.
|
||||
|
||||
Consider the following dataset:
|
||||
|
||||
|
@ -14,14 +14,25 @@ const isBetweenValueMatcher: ValueMatcherInfo<RangeValueMatcherOptions> = {
|
||||
if (isNaN(value)) {
|
||||
return false;
|
||||
}
|
||||
return value > options.from && value < options.to;
|
||||
|
||||
// if it is a time, it is interpolated as a string, so convert before comparing
|
||||
const fromVal = typeof options.from !== 'number' ? parseInt(options.from, 10) : options.from;
|
||||
const toVal = typeof options.to !== 'number' ? parseInt(options.to, 10) : options.to;
|
||||
|
||||
return value > fromVal && value < toVal;
|
||||
};
|
||||
},
|
||||
getOptionsDisplayText: (options) => {
|
||||
return `Matches all rows where field value is between ${options.from} and ${options.to}.`;
|
||||
},
|
||||
isApplicable: (field) => field.type === FieldType.number,
|
||||
getDefaultOptions: () => ({ from: 0, to: 100 }),
|
||||
isApplicable: (field) => field.type === FieldType.number || field.type === FieldType.time,
|
||||
getDefaultOptions: (field) => {
|
||||
if (field.type === FieldType.time) {
|
||||
return { from: '$__from', to: '$__to' };
|
||||
} else {
|
||||
return { from: 0, to: 100 };
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const getRangeValueMatchers = (): ValueMatcherInfo[] => [isBetweenValueMatcher];
|
||||
|
@ -18,4 +18,4 @@ export const updateConfig = (update: Partial<GrafanaBootConfig>) => {
|
||||
};
|
||||
|
||||
// The `enable_alpha` flag is not exposed directly, this is equivalent
|
||||
export const hasAlphaPanels = Boolean(config.panels?.debug?.state === PluginState.alpha);
|
||||
export const hasAlphaPanels = Boolean(config?.panels?.debug?.state === PluginState.alpha);
|
||||
|
@ -70,7 +70,7 @@ export const expressionTypes: Array<SelectableValue<ExpressionQueryType>> = [
|
||||
},
|
||||
].filter((expr) => {
|
||||
if (expr.value === ExpressionQueryType.sql) {
|
||||
return config.featureToggles?.sqlExpressions;
|
||||
return config?.featureToggles?.sqlExpressions;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
@ -380,13 +380,13 @@ The available conditions for string fields are:
|
||||
- **Contains substring** - Match if the value contains the specified substring (case insensitive).
|
||||
- **Does not contain substring** - Match if the value doesn't contain the specified substring (case insensitive).
|
||||
|
||||
The available conditions for number fields are:
|
||||
The available conditions for number and time fields are:
|
||||
|
||||
- **Greater** - Match if the value is greater than the specified value.
|
||||
- **Lower** - Match if the value is lower than the specified value.
|
||||
- **Greater or equal** - Match if the value is greater or equal.
|
||||
- **Lower or equal** - Match if the value is lower or equal.
|
||||
- **Range** - Match a range between a specified minimum and maximum, min and max included.
|
||||
- **Range** - Match a range between a specified minimum and maximum, min and max included. A time field will pre-populate with variables to filter by selected time.
|
||||
|
||||
Consider the following dataset:
|
||||
|
||||
|
@ -27,19 +27,19 @@ describe('validator', () => {
|
||||
expect(numberOrVariableValidator('1')).toBe(true);
|
||||
});
|
||||
|
||||
it('validats a string that is a negative integer', () => {
|
||||
it('validates a string that is a negative integer', () => {
|
||||
expect(numberOrVariableValidator('-1')).toBe(true);
|
||||
});
|
||||
|
||||
it('validats a string that is zero', () => {
|
||||
it('validates a string that is zero', () => {
|
||||
expect(numberOrVariableValidator('0')).toBe(true);
|
||||
});
|
||||
|
||||
it('validats a string that is a float', () => {
|
||||
it('validates a string that is a float', () => {
|
||||
expect(numberOrVariableValidator('1.2')).toBe(true);
|
||||
});
|
||||
|
||||
it('validats a string that is a negative float', () => {
|
||||
it('validates a string that is a negative float', () => {
|
||||
expect(numberOrVariableValidator('-1.2')).toBe(true);
|
||||
});
|
||||
|
||||
@ -51,8 +51,8 @@ describe('validator', () => {
|
||||
expect(numberOrVariableValidator('$foo')).toBe(true);
|
||||
});
|
||||
|
||||
it('fails a string that has multiple variables', () => {
|
||||
expect(numberOrVariableValidator('$foo$asd')).toBe(false);
|
||||
it('validates a string that has multiple variables', () => {
|
||||
expect(numberOrVariableValidator('$foo$asd')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -12,6 +12,8 @@ import {
|
||||
import { t } from '@grafana/i18n';
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
|
||||
import { variableRegex } from '../variables/utils';
|
||||
|
||||
export const getAllFieldNamesFromDataFrames = (frames: DataFrame[], withBaseFieldNames = false) => {
|
||||
// get full names
|
||||
let names = frames.flatMap((frame) => frame.fields.map((field) => getFieldDisplayName(field, frame, frames)));
|
||||
@ -77,7 +79,9 @@ export const numberOrVariableValidator = (value: string | number) => {
|
||||
if (!Number.isNaN(Number(value))) {
|
||||
return true;
|
||||
}
|
||||
if (/^\$[A-Za-z0-9_]+$/.test(value)) {
|
||||
const variableFound = variableRegex.test(value);
|
||||
variableRegex.lastIndex = 0;
|
||||
if (variableFound) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user