From e533e5fe2ab1805b4bf4d5f0b60c0543dbaa9976 Mon Sep 17 00:00:00 2001 From: Villena Guillaume Date: Wed, 14 Apr 2021 08:15:15 +0200 Subject: [PATCH] AsyncSegment: Allow custom "no options" messages (#32674) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added support for custom user function for mapping custom noOptions messages * Added new scenario in SegmentAsync.story.tsx Co-authored-by: Hugo Häggmark --- .../components/Segment/SegmentAsync.story.tsx | 61 +++++++++++++++++++ .../src/components/Segment/SegmentAsync.tsx | 4 +- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx b/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx index 245927289fb..fb3bcf10612 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import { AsyncState } from 'react-use/lib/useAsync'; import { action } from '@storybook/addon-actions'; import { SelectableValue } from '@grafana/data'; import { SegmentAsync, Icon } from '@grafana/ui'; @@ -15,6 +16,9 @@ const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(t const loadOptions = (options: any): Promise>> => new Promise((res) => setTimeout(() => res(options), 2000)); +const loadOptionsErr = (): Promise>> => + new Promise((_, rej) => setTimeout(() => rej(Error('Could not find data')), 2000)); + const SegmentFrame = ({ loadOptions, children }: any) => ( <>
@@ -124,6 +128,63 @@ export const CustomLabel = () => { ); }; +export const CustomStateMessageHandler = () => { + const stateToTextFunction = (state: AsyncState>>) => { + if (state.loading) { + return "You're going too fast for me, please wait..."; + } + + if (state.error) { + return 'Outch ! We encountered an error...'; + } + + if (!Array.isArray(state.value) || state.value.length === 0) { + return 'It is empty :)'; + } + + return ''; + }; + + const [value, setValue] = useState(options[0]); + return ( + <> + loadOptions(groupedOptions)}> + loadOptions(groupedOptions)} + onChange={({ value }) => { + setValue(value); + action('Segment value changed')(value); + }} + /> + + loadOptions([])}> + loadOptions([])} + onChange={({ value }) => { + setValue(value); + action('Segment value changed')(value); + }} + /> + + loadOptionsErr()}> + loadOptionsErr()} + onChange={({ value }) => { + setValue(value); + action('Segment value changed')(value); + }} + /> + + + ); +}; + export const HtmlAttributes = () => { const [value, setValue] = useState(options[0]); return ( diff --git a/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx b/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx index f23e01d6215..39fa85443c0 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx @@ -14,6 +14,7 @@ export interface SegmentAsyncProps extends SegmentProps, Omit; loadOptions: (query?: string) => Promise>>; onChange: (item: SelectableValue) => void; + noOptionMessageHandler?: (state: AsyncState>>) => string; } export function SegmentAsync({ @@ -25,6 +26,7 @@ export function SegmentAsync({ allowCustomValue, disabled, placeholder, + noOptionMessageHandler = mapStateToNoOptionsMessage, ...rest }: React.PropsWithChildren>) { const [state, fetchOptions] = useAsyncFn(loadOptions, [loadOptions]); @@ -64,7 +66,7 @@ export function SegmentAsync({ value={value && !_.isObject(value) ? { value } : value} options={state.value ?? []} width={width} - noOptionsMessage={mapStateToNoOptionsMessage(state)} + noOptionsMessage={noOptionMessageHandler(state)} allowCustomValue={allowCustomValue} onClickOutside={() => { setExpanded(false);