Dashboards: Add template variables to selectable options (#75870)

This commit is contained in:
Fabrizio 2023-10-06 16:32:30 +02:00 committed by GitHub
parent c5914d92d4
commit b2ba28ab40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 10 deletions

View File

@ -1,8 +1,9 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { initTemplateSrv } from 'test/helpers/initTemplateSrv';
import { FetchError } from '@grafana/runtime';
import { FetchError, setTemplateSrv } from '@grafana/runtime';
import { TraceqlFilter, TraceqlSearchScope } from '../dataquery.gen';
import { TempoDatasource } from '../datasource';
@ -35,9 +36,11 @@ jest.mock('../language_provider', () => {
});
describe('SearchField', () => {
let templateSrv = initTemplateSrv('key', [{ name: 'templateVariable1' }, { name: 'templateVariable2' }]);
let user: ReturnType<typeof userEvent.setup>;
beforeEach(() => {
setTemplateSrv(templateSrv);
jest.useFakeTimers();
// Need to use delay: null here to work with fakeTimers
// see https://github.com/testing-library/user-event/issues/833
@ -172,6 +175,8 @@ describe('SearchField', () => {
expect(await screen.findByText('span')).toBeInTheDocument();
expect(await screen.findByText('unscoped')).toBeInTheDocument();
expect(screen.queryByText('intrinsic')).not.toBeInTheDocument();
expect(await screen.findByText('$templateVariable1')).toBeInTheDocument();
expect(await screen.findByText('$templateVariable2')).toBeInTheDocument();
}
});
});

View File

@ -3,8 +3,9 @@ import { uniq } from 'lodash';
import React, { useState, useEffect, useMemo } from 'react';
import useAsync from 'react-use/lib/useAsync';
import { SelectableValue } from '@grafana/data';
import { AccessoryButton } from '@grafana/experimental';
import { FetchError, isFetchError } from '@grafana/runtime';
import { FetchError, getTemplateSrv, isFetchError } from '@grafana/runtime';
import { Select, HorizontalGroup, useStyles2 } from '@grafana/ui';
import { createErrorNotification } from '../../../../core/copy/appNotification';
@ -112,13 +113,24 @@ const SearchField = ({
operatorList = numberOperators;
}
/**
* Add to a list of options the current template variables.
*
* @param options a list of options
* @returns the list of given options plus the template variables
*/
const withTemplateVariableOptions = (options: SelectableValue[] | undefined) => {
const templateVariables = getTemplateSrv().getVariables();
return [...(options || []), ...templateVariables.map((v) => ({ label: `$${v.name}`, value: `$${v.name}` }))];
};
return (
<HorizontalGroup spacing={'none'} width={'auto'}>
{!hideScope && (
<Select
className={styles.dropdown}
inputId={`${filter.id}-scope`}
options={scopeOptions}
options={withTemplateVariableOptions(scopeOptions)}
value={filter.scope}
onChange={(v) => {
updateFilter({ ...filter, scope: v?.value });
@ -133,10 +145,12 @@ const SearchField = ({
inputId={`${filter.id}-tag`}
isLoading={isTagsLoading}
// Add the current tag to the list if it doesn't exist in the tags prop, otherwise the field will be empty even though the state has a value
options={(filter.tag !== undefined ? uniq([filter.tag, ...tags]) : tags).map((t) => ({
label: t,
value: t,
}))}
options={withTemplateVariableOptions(
(filter.tag !== undefined ? uniq([filter.tag, ...tags]) : tags).map((t) => ({
label: t,
value: t,
}))
)}
value={filter.tag}
onChange={(v) => {
updateFilter({ ...filter, tag: v?.value });
@ -150,7 +164,7 @@ const SearchField = ({
<Select
className={styles.dropdown}
inputId={`${filter.id}-operator`}
options={operatorList.map(operatorSelectableValue)}
options={withTemplateVariableOptions(operatorList.map(operatorSelectableValue))}
value={filter.operator}
onChange={(v) => {
updateFilter({ ...filter, operator: v?.value });
@ -165,7 +179,7 @@ const SearchField = ({
className={styles.dropdown}
inputId={`${filter.id}-value`}
isLoading={isLoadingValues}
options={options}
options={withTemplateVariableOptions(options)}
value={filter.value}
onChange={(val) => {
if (Array.isArray(val)) {

View File

@ -1,8 +1,9 @@
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { initTemplateSrv } from 'test/helpers/initTemplateSrv';
import { FetchError } from '@grafana/runtime';
import { FetchError, setTemplateSrv } from '@grafana/runtime';
import { TraceqlFilter, TraceqlSearchScope } from '../dataquery.gen';
import { TempoDatasource } from '../datasource';
@ -13,9 +14,11 @@ import TagsInput from './TagsInput';
import { v1Tags, v2Tags } from './utils.test';
describe('TagsInput', () => {
let templateSrv = initTemplateSrv('key', [{ name: 'templateVariable1' }, { name: 'templateVariable2' }]);
let user: ReturnType<typeof userEvent.setup>;
beforeEach(() => {
setTemplateSrv(templateSrv);
jest.useFakeTimers();
// Need to use delay: null here to work with fakeTimers
// see https://github.com/testing-library/user-event/issues/833
@ -37,6 +40,8 @@ describe('TagsInput', () => {
await waitFor(() => {
expect(screen.getByText('foo')).toBeInTheDocument();
expect(screen.getByText('bar')).toBeInTheDocument();
expect(screen.getByText('$templateVariable1')).toBeInTheDocument();
expect(screen.getByText('$templateVariable2')).toBeInTheDocument();
});
});
@ -50,6 +55,8 @@ describe('TagsInput', () => {
await waitFor(() => {
expect(screen.getByText('cluster')).toBeInTheDocument();
expect(screen.getByText('container')).toBeInTheDocument();
expect(screen.getByText('$templateVariable1')).toBeInTheDocument();
expect(screen.getByText('$templateVariable2')).toBeInTheDocument();
});
});
@ -62,6 +69,8 @@ describe('TagsInput', () => {
jest.advanceTimersByTime(1000);
await waitFor(() => {
expect(screen.getByText('db')).toBeInTheDocument();
expect(screen.getByText('$templateVariable1')).toBeInTheDocument();
expect(screen.getByText('$templateVariable2')).toBeInTheDocument();
});
});
@ -76,6 +85,8 @@ describe('TagsInput', () => {
expect(screen.getByText('cluster')).toBeInTheDocument();
expect(screen.getByText('container')).toBeInTheDocument();
expect(screen.getByText('db')).toBeInTheDocument();
expect(screen.getByText('$templateVariable1')).toBeInTheDocument();
expect(screen.getByText('$templateVariable2')).toBeInTheDocument();
});
});
});