Skip to content

Commit

Permalink
Add Query Field Picker for Initial Request (#227)
Browse files Browse the repository at this point in the history
* Add Query Field Picker

* Allow to select query field from any queries

* Formatting

---------

Co-authored-by: Mikhail <mikhail@volkovlabs.io>
  • Loading branch information
asimonok and mikhail-vl authored Aug 18, 2023
1 parent 46ecd0e commit 6a0d092
Show file tree
Hide file tree
Showing 13 changed files with 477 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Add clearing errors before initial and update requests (#232)
- Add URL encode to variables (#231)
- Allow empty section name (#228)
- Add Query Field Picker for Initial Request (#227)

## 3.1.0 (2023-08-13)

Expand Down
7 changes: 6 additions & 1 deletion src/__mocks__/@grafana/ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const DateTimePicker = jest.fn(({ onChange, ...restProps }) => {
/**
* Mock Select component
*/
const Select = jest.fn(({ options, onChange, value, isMulti, ...restProps }) => (
const Select = jest.fn(({ options, onChange, value, isMulti, isClearable, ...restProps }) => (
<select
onChange={(event: any) => {
if (onChange) {
Expand All @@ -64,6 +64,11 @@ const Select = jest.fn(({ options, onChange, value, isMulti, ...restProps }) =>
multiple={isMulti}
{...restProps}
>
{isClearable && (
<option key="clear" value="">
Clear
</option>
)}
{options.map(({ label, value }: any) => (
<option key={value} value={value}>
{label}
Expand Down
35 changes: 33 additions & 2 deletions src/components/ElementEditor/ElementEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
StringElementOptions,
TestIds,
} from '../../constants';
import { LocalFormElement } from '../../types';
import { LocalFormElement, QueryField } from '../../types';
import { FormatNumberValue, GetElementWithNewType, ToNumberValue } from '../../utils';
import { ElementDateEditor } from '../ElementDateEditor';
import { Styles } from './styles';
Expand Down Expand Up @@ -59,7 +59,17 @@ interface Props {
/**
* Initial Request Method
*/
initialMethod: RequestMethod;
initialMethod?: RequestMethod;

/**
* Query Fields
*/
queryFields: QueryField[];

/**
* Is Query Fields Enabled
*/
isQueryFieldsEnabled: boolean;
}

/**
Expand All @@ -71,6 +81,8 @@ export const ElementEditor: React.FC<Props> = ({
onChangeOption,
layoutSectionOptions,
initialMethod,
isQueryFieldsEnabled,
queryFields,
}) => {
/**
* Styles
Expand Down Expand Up @@ -415,6 +427,25 @@ export const ElementEditor: React.FC<Props> = ({
</InlineFieldRow>
)}

{isQueryFieldsEnabled && (
<InlineFieldRow>
<InlineField grow={true} label="Query Field" labelWidth={14} tooltip="Specify a field name from the Query">
<Select
value={element.queryField?.value}
options={queryFields}
onChange={(item) => {
onChange({
...element,
queryField: item,
});
}}
aria-label={TestIds.formElementsEditor.fieldFromQueryPicker}
isClearable={true}
/>
</InlineField>
</InlineFieldRow>
)}

{(element.type === FormElementType.RADIO ||
element.type === FormElementType.SELECT ||
element.type === FormElementType.MULTISELECT ||
Expand Down
117 changes: 117 additions & 0 deletions src/components/FormElementsEditor/FormElementsEditor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '../../constants';
import { getFormElementsEditorSelectors } from '../../utils';
import { FormElementsEditor } from './FormElementsEditor';
import { toDataFrame } from '@grafana/data';

/**
* Mock timers
Expand Down Expand Up @@ -434,6 +435,76 @@ describe('Form Elements Editor', () => {
expect(elementSelectors.buttonRemoveOption()).toBeInTheDocument();
});

/**
* Field Name Disabled
*/
it('Should not allow to select field name if initial method is not Datasource', () => {
const elements = [
{
...FormElementDefault,
id: 'element',
type: FormElementType.STRING,
},
];

render(
getComponent({
value: elements,
onChange,
context: {
options: {
initial: {
method: RequestMethod.QUERY,
},
},
},
})
);
expect(selectors.root()).toBeInTheDocument();

/**
* Make Element is opened
*/
const elementSelectors = openElement('element', FormElementType.STRING);

expect(elementSelectors.fieldNamePicker(true)).not.toBeInTheDocument();
});

/**
* Query Field Name Disabled
*/
it('Should not allow to select query field name if initial method is not Query', () => {
const elements = [
{
...FormElementDefault,
id: 'element',
type: FormElementType.STRING,
},
];

render(
getComponent({
value: elements,
onChange,
context: {
options: {
initial: {
method: RequestMethod.DATASOURCE,
},
},
},
})
);
expect(selectors.root()).toBeInTheDocument();

/**
* Make Element is opened
*/
const elementSelectors = openElement('element', FormElementType.STRING);

expect(elementSelectors.fieldFromQueryPicker(true)).not.toBeInTheDocument();
});

/**
* Two elements
*/
Expand Down Expand Up @@ -1081,6 +1152,52 @@ describe('Form Elements Editor', () => {
expect(elementSelectors.fieldNamePicker()).toHaveValue('metric');
});

it('Should update query field name', async () => {
const elements = [{ ...FormElementDefault, id: 'id' }];
const context = {
options: {
initial: {
method: RequestMethod.QUERY,
},
},
data: [
toDataFrame({
fields: [
{
name: 'field1',
values: [],
},
{
name: 'field2',
values: [],
},
],
}),
],
};

render(getComponent({ value: elements, onChange, context }));

/**
* Open id element
*/
const elementSelectors = openElement('id', FormElementDefault.type);

/**
* Change query field name
*/
await act(() => fireEvent.change(elementSelectors.fieldFromQueryPicker(), { target: { value: 'field1' } }));

expect(elementSelectors.fieldFromQueryPicker()).toHaveValue('field1');

/**
* Clear query field name
*/
await act(() => fireEvent.change(elementSelectors.fieldFromQueryPicker(), { target: { value: '' } }));

expect(elementSelectors.fieldFromQueryPicker()).toHaveValue('');
});

it('Should update showIf', async () => {
const element = { ...FormElementDefault, id: 'id', type: FormElementType.TEXTAREA, rows: 2 };
const elements = [element];
Expand Down
16 changes: 12 additions & 4 deletions src/components/FormElementsEditor/FormElementsEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
} from 'react-beautiful-dnd';
import { SelectableValue, StandardEditorProps } from '@grafana/data';
import { Button, Icon, IconButton, useTheme2 } from '@grafana/ui';
import { TestIds } from '../../constants';
import { useFormElements } from '../../hooks';
import { FormElement, LayoutSection, LocalFormElement } from '../../types';
import { RequestMethod, TestIds } from '../../constants';
import { useFormElements, useQueryFields } from '../../hooks';
import { FormElement, LayoutSection, LocalFormElement, PanelOptions } from '../../types';
import { GetElementUniqueId, GetLayoutUniqueId, Reorder } from '../../utils';
import { Collapse } from '../Collapse';
import { ElementEditor } from '../ElementEditor';
Expand All @@ -31,7 +31,7 @@ const getItemStyle = (isDragging: boolean, draggableStyle: DraggingStyle | NotDr
/**
* Properties
*/
interface Props extends StandardEditorProps<FormElement[]> {}
interface Props extends StandardEditorProps<FormElement[], null, PanelOptions> {}

/**
* Form Elements Editor
Expand Down Expand Up @@ -61,6 +61,12 @@ export const FormElementsEditor: React.FC<Props> = ({ value, onChange, context }
onElementRemove,
} = useFormElements(onChange, value);

/**
* Query Fields
*/
const isQueryFieldsEnabled = context.options?.initial?.method === RequestMethod.QUERY;
const queryFields = useQueryFields({ data: context.data, isEnabled: isQueryFieldsEnabled });

/**
* Add Elements
*/
Expand Down Expand Up @@ -165,6 +171,8 @@ export const FormElementsEditor: React.FC<Props> = ({ value, onChange, context }
layoutSectionOptions={layoutSectionOptions}
initialMethod={context.options?.initial?.method}
onChangeOption={onChangeElementOption}
queryFields={queryFields}
isQueryFieldsEnabled={isQueryFieldsEnabled}
/>
</Collapse>
</div>
Expand Down
Loading

0 comments on commit 6a0d092

Please sign in to comment.