mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
TextPanel: Fix suggestions for existing panels (#42195)
Closes #42118 Co-authored-by: kay delaney <kay@grafana.com> Co-authored-by: Josh Hunt <josh@trtr.co> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com> Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>
This commit is contained in:
parent
db122e9b2c
commit
df22828d7d
@ -2,7 +2,7 @@ import React, { useMemo, useState } from 'react';
|
||||
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||
import { CustomScrollbar, FilterInput, RadioButtonGroup, useStyles2 } from '@grafana/ui';
|
||||
import { getPanelFrameCategory } from './getPanelFrameOptions';
|
||||
import { getVizualizationOptions } from './getVizualizationOptions';
|
||||
import { getVisualizationOptions } from './getVisualizationOptions';
|
||||
import { css } from '@emotion/css';
|
||||
import { OptionsPaneCategory } from './OptionsPaneCategory';
|
||||
import { getFieldOverrideCategories } from './getFieldOverrideElements';
|
||||
@ -21,7 +21,7 @@ export const OptionsPaneOptions: React.FC<OptionPaneRenderProps> = (props) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const [panelFrameOptions, vizOptions, libraryPanelOptions] = useMemo(
|
||||
() => [getPanelFrameCategory(props), getVizualizationOptions(props), getLibraryPanelOptionsCategory(props)],
|
||||
() => [getPanelFrameCategory(props), getVisualizationOptions(props), getLibraryPanelOptionsCategory(props)],
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[panel.configRev, props.data, props.instanceState, searchQuery]
|
||||
|
@ -0,0 +1,161 @@
|
||||
import { EventBusSrv, FieldType, getDefaultTimeRange, LoadingState, toDataFrame } from '@grafana/data';
|
||||
import { getStandardEditorContext } from './getVisualizationOptions';
|
||||
|
||||
describe('getStandardEditorContext', () => {
|
||||
it('defaults the series data to an empty array', () => {
|
||||
const editorContext = getStandardEditorContext({
|
||||
data: undefined,
|
||||
replaceVariables: jest.fn(),
|
||||
options: {},
|
||||
eventBus: new EventBusSrv(),
|
||||
instanceState: {},
|
||||
});
|
||||
|
||||
expect(editorContext.data).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns suggestions for empty data', () => {
|
||||
const editorContext = getStandardEditorContext({
|
||||
data: undefined,
|
||||
replaceVariables: jest.fn(),
|
||||
options: {},
|
||||
eventBus: new EventBusSrv(),
|
||||
instanceState: {},
|
||||
});
|
||||
|
||||
expect(editorContext.getSuggestions).toBeDefined();
|
||||
expect(editorContext.getSuggestions?.()).toEqual([
|
||||
{
|
||||
documentation: 'Name of the series',
|
||||
label: 'Name',
|
||||
origin: 'series',
|
||||
value: '__series.name',
|
||||
},
|
||||
{
|
||||
documentation: 'Field name of the clicked datapoint (in ms epoch)',
|
||||
label: 'Name',
|
||||
origin: 'field',
|
||||
value: '__field.name',
|
||||
},
|
||||
{
|
||||
documentation: 'Adds current variables',
|
||||
label: 'All variables',
|
||||
origin: 'template',
|
||||
value: '__all_variables',
|
||||
},
|
||||
{
|
||||
documentation: 'Adds current time range',
|
||||
label: 'Time range',
|
||||
origin: 'built-in',
|
||||
value: '__url_time_range',
|
||||
},
|
||||
{
|
||||
documentation: "Adds current time range's from value",
|
||||
label: 'Time range: from',
|
||||
origin: 'built-in',
|
||||
value: '__from',
|
||||
},
|
||||
{
|
||||
documentation: "Adds current time range's to value",
|
||||
label: 'Time range: to',
|
||||
origin: 'built-in',
|
||||
value: '__to',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns suggestions for non-empty data', () => {
|
||||
const series = [
|
||||
toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time },
|
||||
{ name: 'score', type: FieldType.number },
|
||||
],
|
||||
}),
|
||||
];
|
||||
|
||||
const panelData = {
|
||||
series,
|
||||
timeRange: getDefaultTimeRange(),
|
||||
state: LoadingState.Done,
|
||||
};
|
||||
|
||||
const editorContext = getStandardEditorContext({
|
||||
data: panelData,
|
||||
replaceVariables: jest.fn(),
|
||||
options: {},
|
||||
eventBus: new EventBusSrv(),
|
||||
instanceState: {},
|
||||
});
|
||||
|
||||
expect(editorContext.getSuggestions).toBeDefined();
|
||||
expect(editorContext.getSuggestions?.()).toEqual([
|
||||
{
|
||||
documentation: 'Name of the series',
|
||||
label: 'Name',
|
||||
origin: 'series',
|
||||
value: '__series.name',
|
||||
},
|
||||
{
|
||||
documentation: 'Field name of the clicked datapoint (in ms epoch)',
|
||||
label: 'Name',
|
||||
origin: 'field',
|
||||
value: '__field.name',
|
||||
},
|
||||
{
|
||||
documentation: 'Formatted value for time on the same row',
|
||||
label: 'time',
|
||||
origin: 'fields',
|
||||
value: '__data.fields.time',
|
||||
},
|
||||
{
|
||||
documentation: 'Formatted value for score on the same row',
|
||||
label: 'score',
|
||||
origin: 'fields',
|
||||
value: '__data.fields.score',
|
||||
},
|
||||
{
|
||||
documentation: 'Enter the field order',
|
||||
label: 'Select by index',
|
||||
origin: 'fields',
|
||||
value: '__data.fields[0]',
|
||||
},
|
||||
{
|
||||
documentation: 'the numeric field value',
|
||||
label: 'Show numeric value',
|
||||
origin: 'fields',
|
||||
value: '__data.fields.score.numeric',
|
||||
},
|
||||
{
|
||||
documentation: 'the text value',
|
||||
label: 'Show text value',
|
||||
origin: 'fields',
|
||||
value: '__data.fields.score.text',
|
||||
},
|
||||
{
|
||||
documentation: 'Adds current variables',
|
||||
label: 'All variables',
|
||||
origin: 'template',
|
||||
value: '__all_variables',
|
||||
},
|
||||
{
|
||||
documentation: 'Adds current time range',
|
||||
label: 'Time range',
|
||||
origin: 'built-in',
|
||||
value: '__url_time_range',
|
||||
},
|
||||
{
|
||||
documentation: "Adds current time range's from value",
|
||||
label: 'Time range: from',
|
||||
origin: 'built-in',
|
||||
value: '__from',
|
||||
},
|
||||
{
|
||||
documentation: "Adds current time range's to value",
|
||||
label: 'Time range: to',
|
||||
origin: 'built-in',
|
||||
value: '__to',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
@ -1,9 +1,15 @@
|
||||
import React from 'react';
|
||||
import { StandardEditorContext, VariableSuggestionsScope } from '@grafana/data';
|
||||
import {
|
||||
EventBus,
|
||||
InterpolateFunction,
|
||||
PanelData,
|
||||
StandardEditorContext,
|
||||
VariableSuggestionsScope,
|
||||
} from '@grafana/data';
|
||||
import { get as lodashGet } from 'lodash';
|
||||
import { getDataLinksVariableSuggestions } from 'app/features/panel/panellinks/link_srv';
|
||||
import { OptionPaneRenderProps } from './types';
|
||||
import { updateDefaultFieldConfigValue, setOptionImmutably } from './utils';
|
||||
import { setOptionImmutably, updateDefaultFieldConfigValue } from './utils';
|
||||
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
||||
import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor';
|
||||
import {
|
||||
@ -16,22 +22,48 @@ import { getOptionOverrides } from './state/getOptionOverrides';
|
||||
|
||||
type categoryGetter = (categoryNames?: string[]) => OptionsPaneCategoryDescriptor;
|
||||
|
||||
export function getVizualizationOptions(props: OptionPaneRenderProps): OptionsPaneCategoryDescriptor[] {
|
||||
interface GetStandardEditorContextProps {
|
||||
data: PanelData | undefined;
|
||||
replaceVariables: InterpolateFunction;
|
||||
options: Record<string, unknown>;
|
||||
eventBus: EventBus;
|
||||
instanceState: OptionPaneRenderProps['instanceState'];
|
||||
}
|
||||
|
||||
export function getStandardEditorContext({
|
||||
data,
|
||||
replaceVariables,
|
||||
options,
|
||||
eventBus,
|
||||
instanceState,
|
||||
}: GetStandardEditorContextProps): StandardEditorContext<unknown, unknown> {
|
||||
const dataSeries = data?.series ?? [];
|
||||
|
||||
const context: StandardEditorContext<unknown, unknown> = {
|
||||
data: dataSeries,
|
||||
replaceVariables,
|
||||
options,
|
||||
eventBus,
|
||||
getSuggestions: (scope?: VariableSuggestionsScope) => getDataLinksVariableSuggestions(dataSeries, scope),
|
||||
instanceState,
|
||||
};
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
export function getVisualizationOptions(props: OptionPaneRenderProps): OptionsPaneCategoryDescriptor[] {
|
||||
const { plugin, panel, onPanelOptionsChanged, onFieldConfigsChange, data, dashboard, instanceState } = props;
|
||||
const currentOptions = panel.getOptions();
|
||||
const currentFieldConfig = panel.fieldConfig;
|
||||
const categoryIndex: Record<string, OptionsPaneCategoryDescriptor> = {};
|
||||
|
||||
const context: StandardEditorContext<any, any> = {
|
||||
data: data?.series || [],
|
||||
const context = getStandardEditorContext({
|
||||
data,
|
||||
replaceVariables: panel.replaceVariables,
|
||||
options: currentOptions,
|
||||
eventBus: dashboard.events,
|
||||
getSuggestions: (scope?: VariableSuggestionsScope) => {
|
||||
return data ? getDataLinksVariableSuggestions(data.series, scope) : [];
|
||||
},
|
||||
instanceState,
|
||||
};
|
||||
});
|
||||
|
||||
const getOptionsPaneCategory = (categoryNames?: string[]): OptionsPaneCategoryDescriptor => {
|
||||
const categoryName = (categoryNames && categoryNames[0]) ?? `${plugin.meta.name}`;
|
Loading…
Reference in New Issue
Block a user