From b2ba28ab40313cb592cbe350ded2b69e259eb61e Mon Sep 17 00:00:00 2001 From: Fabrizio <135109076+fabrizio-grafana@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:32:30 +0200 Subject: [PATCH] Dashboards: Add template variables to selectable options (#75870) --- .../SearchTraceQLEditor/SearchField.test.tsx | 7 ++++- .../tempo/SearchTraceQLEditor/SearchField.tsx | 30 ++++++++++++++----- .../SearchTraceQLEditor/TagsInput.test.tsx | 13 +++++++- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx index b46ed26216d..7fbd097a83a 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx @@ -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; 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(); } }); }); diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.tsx b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.tsx index 9be6a1e2ba2..3f4858b5ed4 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.tsx +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.tsx @@ -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 ( {!hideScope && ( { 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)) { diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TagsInput.test.tsx b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TagsInput.test.tsx index 7cb9ee97c75..ac20fc2e768 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TagsInput.test.tsx +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TagsInput.test.tsx @@ -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; 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(); }); }); });