12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import {useState} from 'react';
- import SelectAsyncControl, {
- Result,
- SelectAsyncControlProps,
- } from 'sentry/components/forms/controls/selectAsyncControl';
- // projects can be passed as a direct prop as well
- import {GeneralSelectValue} from 'sentry/components/forms/controls/selectControl';
- import FormField from 'sentry/components/forms/formField';
- // XXX(epurkhiser): This is wrong, it should not be inheriting these props
- import {InputFieldProps} from './inputField';
- export interface SelectAsyncFieldProps
- extends Omit<InputFieldProps, 'highlighted' | 'visible' | 'required' | 'value'>,
- SelectAsyncControlProps {
- /**
- * Similar to onChange, except it provides the entire option object (including label) when a
- * change is made to the field. Occurs after onChange.
- */
- onChangeOption?: (option: GeneralSelectValue, event: any) => void;
- }
- function SelectAsyncField({onChangeOption, ...props}: SelectAsyncFieldProps) {
- const [results, setResults] = useState<Result[]>([]);
- const [latestSelection, setLatestSelection] = useState<
- GeneralSelectValue | undefined
- >();
- return (
- <FormField {...props}>
- {({
- required: _required,
- children: _children,
- onBlur,
- onChange,
- onResults,
- value,
- ...fieldProps
- }) => {
- const {defaultOptions} = props;
- // We don't use defaultOptions if it is undefined or a boolean
- const options = typeof defaultOptions === 'object' ? defaultOptions : [];
- // The propsValue is the `id` of the object (user, team, etc), and
- // react-select expects a full value object: {value: "id", label: "name"}
- const resolvedValue =
- // When rendering the selected value, first look at the API results...
- results.find(({value: v}) => v === value) ??
- // Then at the defaultOptions passed in props...
- options?.find(({value: v}) => v === value) ??
- // Then at the latest value selected in the form
- (latestSelection as GeneralSelectValue);
- return (
- <SelectAsyncControl
- {...fieldProps}
- onChange={(option, e) => {
- const resultValue = !option
- ? option
- : props.multiple && Array.isArray(option)
- ? // List of optionObjs
- option.map(({value: val}) => val)
- : !Array.isArray(option)
- ? option.value
- : option;
- setLatestSelection(option);
- onChange?.(resultValue, e);
- onChangeOption?.(option, e);
- onBlur?.(resultValue, e);
- }}
- onResults={data => {
- const newResults = onResults(data);
- const resultSelection = newResults.find(result => result.value === value);
- setResults(newResults);
- if (resultSelection) {
- setLatestSelection(resultSelection);
- }
- return newResults;
- }}
- onSelectResetsInput
- onCloseResetsInput={false}
- onBlurResetsInput={false}
- value={resolvedValue}
- />
- );
- }}
- </FormField>
- );
- }
- export default SelectAsyncField;
|