diff --git a/.betterer.results b/.betterer.results index 6311022a3ec..02d1f01333c 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1749,8 +1749,7 @@ exports[`better eslint`] = { [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] ], "public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.tsx:5381": [ - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"] + [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] ], "public/app/features/dashboard-scene/settings/variables/components/QueryVariableForm.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] diff --git a/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.test.tsx b/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.test.tsx index bca55beadec..e0572105472 100644 --- a/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.test.tsx +++ b/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.test.tsx @@ -45,6 +45,7 @@ describe('GroupByVariableForm', () => { onAllowCustomValueChange: onAllowCustomValueChangeMock, onDataSourceChange: onDataSourceChangeMock, onDefaultOptionsChange: onDefaultOptionsChangeMock, + datasourceSupported: true, }; function setup(props?: Partial) { @@ -130,4 +131,27 @@ describe('GroupByVariableForm', () => { expect(onDefaultOptionsChangeMock).toHaveBeenCalledTimes(1); expect(onDefaultOptionsChangeMock).toHaveBeenCalledWith(undefined); }); + + it('should render only datasource picker and alert when not supported', async () => { + const mockOnAllowCustomValueChange = jest.fn(); + const { renderer } = await setup({ + ...defaultProps, + datasourceSupported: false, + onAllowCustomValueChange: mockOnAllowCustomValueChange, + }); + + const dataSourcePicker = renderer.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.GroupByVariable.dataSourceSelect + ); + + const allowCustomValueCheckbox = renderer.queryByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch + ); + + const alertText = renderer.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.GroupByVariable.infoText); + + expect(dataSourcePicker).toBeInTheDocument(); + expect(allowCustomValueCheckbox).not.toBeInTheDocument(); + expect(alertText).toBeInTheDocument(); + }); }); diff --git a/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.tsx b/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.tsx index 749f4a66eca..e122abb2f7e 100644 --- a/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.tsx +++ b/public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.tsx @@ -3,8 +3,9 @@ import { FormEvent, useCallback } from 'react'; import { DataSourceInstanceSettings, MetricFindValue, readCSV } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { Trans, useTranslate } from '@grafana/i18n'; +import { EditorField } from '@grafana/plugin-ui'; import { DataSourceRef } from '@grafana/schema'; -import { Alert, CodeEditor, Field, Switch } from '@grafana/ui'; +import { Alert, Box, CodeEditor, Field, Switch } from '@grafana/ui'; import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker'; import { VariableCheckboxField } from './VariableCheckboxField'; @@ -18,6 +19,8 @@ export interface GroupByVariableFormProps { defaultOptions?: MetricFindValue[]; allowCustomValue: boolean; onAllowCustomValueChange: (event: FormEvent) => void; + inline?: boolean; + datasourceSupported: boolean; } export function GroupByVariableForm({ @@ -28,6 +31,8 @@ export function GroupByVariableForm({ onDefaultOptionsChange, allowCustomValue, onAllowCustomValueChange, + inline, + datasourceSupported, }: GroupByVariableFormProps) { const updateDefaultOptions = useCallback( (csvContent: string) => { @@ -45,70 +50,85 @@ export function GroupByVariableForm({ return ( <> - - Group by options - - - - + {!inline && ( + + Group by options + + )} + + + + + + - {infoText ? ( + {!datasourceSupported ? ( ) : null} - - { - if (defaultOptions === undefined) { - onDefaultOptionsChange([]); - } else { - onDefaultOptionsChange(undefined); - } - }} - /> - + {datasourceSupported && ( + <> + + { + if (defaultOptions === undefined) { + onDefaultOptionsChange([]); + } else { + onDefaultOptionsChange(undefined); + } + }} + /> + - {defaultOptions !== undefined && ( - `${o.text},${o.value}`).join('\n')} - onBlur={updateDefaultOptions} - onSave={updateDefaultOptions} - showMiniMap={false} - showLineNumbers={true} - /> + {defaultOptions !== undefined && ( + `${o.text},${o.value}`).join('\n')} + onBlur={updateDefaultOptions} + onSave={updateDefaultOptions} + showMiniMap={false} + showLineNumbers={true} + /> + )} + )} - + {datasourceSupported && !inline && onAllowCustomValueChange && ( + + )} ); } diff --git a/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.test.tsx b/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.test.tsx index 7185d4bb00b..aa31e257e05 100644 --- a/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.test.tsx +++ b/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.test.tsx @@ -1,13 +1,14 @@ -import { act, render } from '@testing-library/react'; +import { act, render, waitFor, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MetricFindValue, VariableSupportType } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { GroupByVariable } from '@grafana/scenes'; import { mockDataSource } from 'app/features/alerting/unified/mocks'; +import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; import { LegacyVariableQueryEditor } from 'app/features/variables/editor/LegacyVariableQueryEditor'; -import { GroupByVariableEditor } from './GroupByVariableEditor'; +import { getGroupByVariableOptions, GroupByVariableEditor } from './GroupByVariableEditor'; const defaultDatasource = mockDataSource({ name: 'Default Test Data Source', @@ -31,6 +32,7 @@ jest.mock('@grafana/runtime', () => ({ query: jest.fn(), editor: jest.fn().mockImplementation(LegacyVariableQueryEditor), }, + getTagKeys: () => [], }), getList: () => [defaultDatasource, promDatasource], getInstanceSettings: () => ({ ...defaultDatasource }), @@ -43,8 +45,8 @@ describe('GroupByVariableEditor', () => { const dataSourcePicker = renderer.getByTestId( selectors.pages.Dashboard.Settings.Variables.Edit.GroupByVariable.dataSourceSelect ); - const infoText = renderer.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.GroupByVariable.infoText); - const allowCustomValueCheckbox = renderer.getByTestId( + + const allowCustomValueCheckbox = renderer.queryByTestId( selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch ); @@ -52,8 +54,6 @@ describe('GroupByVariableEditor', () => { expect(allowCustomValueCheckbox).toBeChecked(); expect(dataSourcePicker).toBeInTheDocument(); expect(dataSourcePicker.getAttribute('placeholder')).toBe('Default Test Data Source'); - expect(infoText).toBeInTheDocument(); - expect(infoText).toHaveTextContent('This data source does not support group by variable yet.'); }); it('should update the variable data source when data source picker is changed', async () => { @@ -87,6 +87,31 @@ describe('GroupByVariableEditor', () => { expect(variable.state.defaultOptions).toEqual(undefined); }); + + it('should return an OptionsPaneItemDescriptor that renders Editor', async () => { + const variable = new GroupByVariable({ + name: 'test', + datasource: { uid: defaultDatasource.uid, type: defaultDatasource.type }, + }); + + const result = getGroupByVariableOptions(variable); + + expect(result.length).toBe(1); + const descriptor = result[0]; + + // Mock the parent property that OptionsPaneItem expects + descriptor.parent = new OptionsPaneCategoryDescriptor({ + id: 'mock-parent-id', + title: 'Mock Parent', + }); + + render(descriptor.render()); + + await waitFor(() => { + // Check that some part of the component renders + expect(screen.getByText(/data source does not support/i)).toBeInTheDocument(); + }); + }); }); async function setup(defaultOptions?: MetricFindValue[]) { diff --git a/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.tsx b/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.tsx index 759a886059b..67df8b473a0 100644 --- a/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.tsx +++ b/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.tsx @@ -1,26 +1,30 @@ +import { noop } from 'lodash'; import { FormEvent } from 'react'; import { useAsync } from 'react-use'; import { DataSourceInstanceSettings, MetricFindValue, getDataSourceRef } from '@grafana/data'; import { getDataSourceSrv } from '@grafana/runtime'; -import { GroupByVariable } from '@grafana/scenes'; +import { GroupByVariable, SceneVariable } from '@grafana/scenes'; +import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; import { GroupByVariableForm } from '../components/GroupByVariableForm'; interface GroupByVariableEditorProps { variable: GroupByVariable; onRunQuery: () => void; + inline?: boolean; } export function GroupByVariableEditor(props: GroupByVariableEditorProps) { - const { variable, onRunQuery } = props; + const { variable, onRunQuery, inline } = props; const { datasource: datasourceRef, defaultOptions, allowCustomValue = true } = variable.useState(); const { value: datasource } = useAsync(async () => { return await getDataSourceSrv().get(datasourceRef); }, [variable.state]); - const message = datasource?.getTagKeys + const supported = datasource?.getTagKeys !== undefined; + const message = supported ? 'Group by dimensions are applied automatically to all queries that target this data source' : 'This data source does not support group by variable yet.'; @@ -49,6 +53,21 @@ export function GroupByVariableEditor(props: GroupByVariableEditorProps) { onDefaultOptionsChange={onDefaultOptionsChange} allowCustomValue={allowCustomValue} onAllowCustomValueChange={onAllowCustomValueChange} + inline={inline} + datasourceSupported={supported} /> ); } + +export function getGroupByVariableOptions(variable: SceneVariable): OptionsPaneItemDescriptor[] { + if (!(variable instanceof GroupByVariable)) { + console.warn('getAdHocFilterOptions: variable is not an AdHocFiltersVariable'); + return []; + } + + return [ + new OptionsPaneItemDescriptor({ + render: () => , + }), + ]; +} diff --git a/public/app/features/dashboard-scene/settings/variables/utils.ts b/public/app/features/dashboard-scene/settings/variables/utils.ts index 576ea3456b9..a43c6e9d8f3 100644 --- a/public/app/features/dashboard-scene/settings/variables/utils.ts +++ b/public/app/features/dashboard-scene/settings/variables/utils.ts @@ -27,7 +27,7 @@ import { AdHocFiltersVariableEditor, getAdHocFilterOptions } from './editors/AdH import { ConstantVariableEditor, getConstantVariableOptions } from './editors/ConstantVariableEditor'; import { CustomVariableEditor, getCustomVariableOptions } from './editors/CustomVariableEditor'; import { DataSourceVariableEditor, getDataSourceVariableOptions } from './editors/DataSourceVariableEditor'; -import { GroupByVariableEditor } from './editors/GroupByVariableEditor'; +import { getGroupByVariableOptions, GroupByVariableEditor } from './editors/GroupByVariableEditor'; import { getIntervalVariableOptions, IntervalVariableEditor } from './editors/IntervalVariableEditor'; import { getQueryVariableOptions, QueryVariableEditor } from './editors/QueryVariableEditor'; import { TextBoxVariableEditor, getTextBoxVariableOptions } from './editors/TextBoxVariableEditor'; @@ -87,6 +87,7 @@ export const EDITABLE_VARIABLES: Record