diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a0981e..6db54f31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Update jest selectors to use npm package (#209) - Add onChange to update elements in local state within custom code (#214) - Update ESLint configuration (#215) +- Add Multi Select element (#217) ## 3.0.0 (2023-07-15) diff --git a/src/components/ElementEditor/ElementEditor.tsx b/src/components/ElementEditor/ElementEditor.tsx index f19734ee..afed45e1 100644 --- a/src/components/ElementEditor/ElementEditor.tsx +++ b/src/components/ElementEditor/ElementEditor.tsx @@ -337,6 +337,7 @@ export const ElementEditor: React.FC = ({ element, onChange, onChangeOpti {(element.type === FormElementType.RADIO || element.type === FormElementType.SELECT || + element.type === FormElementType.MULTISELECT || element.type === FormElementType.DISABLED) && (
{element.options?.map((option, index) => ( diff --git a/src/components/FormElements/FormElements.test.tsx b/src/components/FormElements/FormElements.test.tsx index d1d26196..389ff99c 100644 --- a/src/components/FormElements/FormElements.test.tsx +++ b/src/components/FormElements/FormElements.test.tsx @@ -46,11 +46,15 @@ jest.mock('@grafana/ui', () => ({ /** * Mock Select component */ - Select: jest.fn().mockImplementation(({ options, onChange, value, ...restProps }) => ( + Select: jest.fn().mockImplementation(({ options, onChange, value, isMulti, ...restProps }) => ( { + onChange={(event) => { onChangeElement({ ...element, - value: event?.value, + value: Array.isArray(event) ? event.map(({ value }) => value) : event.value, }); }} width={ApplyWidth(element.width)} diff --git a/src/components/FormElementsEditor/FormElementsEditor.test.tsx b/src/components/FormElementsEditor/FormElementsEditor.test.tsx index 8f465e59..bd4e9326 100644 --- a/src/components/FormElementsEditor/FormElementsEditor.test.tsx +++ b/src/components/FormElementsEditor/FormElementsEditor.test.tsx @@ -450,6 +450,33 @@ describe('Form Elements Editor', () => { expect(elementSelectors.buttonRemoveOption()).toBeInTheDocument(); }); + /** + * Multi Select + */ + it('Should find component with Multi Select', () => { + const elements = [ + { + ...FormElementDefault, + id: 'select', + type: FormElementType.MULTISELECT, + options: [{ id: 'id', label: 'label', type: FormElementType.NUMBER }], + }, + ]; + + render(getComponent({ value: elements, onChange })); + expect(selectors.root()).toBeInTheDocument(); + + /** + * Make Select Element is opened + */ + const elementSelectors = openElement('select', FormElementType.MULTISELECT); + + expect(elementSelectors.fieldType()).toBeInTheDocument(); + expect(elementSelectors.fieldOptionType()).toBeInTheDocument(); + expect(elementSelectors.fieldOptionLabel()).toBeInTheDocument(); + expect(elementSelectors.buttonRemoveOption()).toBeInTheDocument(); + }); + /** * Two elements */ diff --git a/src/constants/form-element.ts b/src/constants/form-element.ts index a0b6884c..e91b6c74 100644 --- a/src/constants/form-element.ts +++ b/src/constants/form-element.ts @@ -14,6 +14,7 @@ export const enum FormElementType { RADIO = 'radio', SECRET = 'secret', SELECT = 'select', + MULTISELECT = 'multiselect', SLIDER = 'slider', STRING = 'string', TEXTAREA = 'textarea', @@ -59,6 +60,10 @@ export const FormElementTypeOptions: SelectableValue[] = [ value: FormElementType.SELECT, label: 'Select with Custom options', }, + { + value: FormElementType.MULTISELECT, + label: 'Multi Select with Custom options', + }, { value: FormElementType.STRING, label: 'String Input', diff --git a/src/types/form-element.ts b/src/types/form-element.ts index 67d12d09..7b7e1cf9 100644 --- a/src/types/form-element.ts +++ b/src/types/form-element.ts @@ -208,6 +208,7 @@ export type FormElement = FormElementBase & | ({ type: FormElementType.NUMBER } & NumberOptions) | ({ type: FormElementType.TEXTAREA } & TextareaOptions) | ({ type: FormElementType.SELECT } & SelectOptions) + | ({ type: FormElementType.MULTISELECT } & SelectOptions) | ({ type: FormElementType.RADIO } & SelectOptions) | ({ type: FormElementType.DISABLED } & SelectOptions) | { type: FormElementType.PASSWORD } diff --git a/src/utils/form-element.ts b/src/utils/form-element.ts index cd40841c..74137c6b 100644 --- a/src/utils/form-element.ts +++ b/src/utils/form-element.ts @@ -77,6 +77,7 @@ export const GetElementWithNewType = ( }; } case FormElementType.SELECT: + case FormElementType.MULTISELECT: case FormElementType.DISABLED: case FormElementType.RADIO: { return {