Commit 81c3dac7 authored by tom's avatar tom

async select for compiler version

parent 7c00d780
import { Code } from '@chakra-ui/react'; import { Checkbox, Code } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
import type { ControllerRenderProps } from 'react-hook-form'; import type { ControllerRenderProps } from 'react-hook-form';
...@@ -13,44 +13,76 @@ import FancySelect from 'ui/shared/FancySelect/FancySelect'; ...@@ -13,44 +13,76 @@ import FancySelect from 'ui/shared/FancySelect/FancySelect';
import ContractVerificationFormRow from '../ContractVerificationFormRow'; import ContractVerificationFormRow from '../ContractVerificationFormRow';
const OPTIONS_LIMIT = 50;
interface Props { interface Props {
isVyper?: boolean; isVyper?: boolean;
} }
const ContractVerificationFieldCompiler = ({ isVyper }: Props) => { const ContractVerificationFieldCompiler = ({ isVyper }: Props) => {
const { formState, control } = useFormContext<FormFields>(); const [ isNightly, setIsNightly ] = React.useState(false);
const { formState, control, getValues, resetField } = useFormContext<FormFields>();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const config = queryClient.getQueryData<SmartContractVerificationConfig>(getResourceKey('contract_verification_config')); const config = queryClient.getQueryData<SmartContractVerificationConfig>(getResourceKey('contract_verification_config'));
const handleCheckboxChange = React.useCallback(() => {
if (isNightly) {
const field = getValues('compiler');
field?.value.includes('nightly') && resetField('compiler', { defaultValue: null });
}
setIsNightly(prev => !prev);
}, [ getValues, isNightly, resetField ]);
const options = React.useMemo(() => ( const options = React.useMemo(() => (
(isVyper ? config?.vyper_compiler_versions : config?.solidity_compiler_versions)?.map((option) => ({ label: option, value: option })) || [] (isVyper ? config?.vyper_compiler_versions : config?.solidity_compiler_versions)?.map((option) => ({ label: option, value: option })) || []
), [ config?.solidity_compiler_versions, config?.vyper_compiler_versions, isVyper ]); ), [ config?.solidity_compiler_versions, config?.vyper_compiler_versions, isVyper ]);
const loadOptions = React.useCallback(async(inputValue: string) => {
return options
.filter(({ label }) => !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()))
.filter(({ label }) => isNightly ? true : !label.includes('nightly'))
.slice(0, OPTIONS_LIMIT);
}, [ isNightly, options ]);
const renderControl = React.useCallback(({ field }: {field: ControllerRenderProps<FormFields, 'compiler'>}) => { const renderControl = React.useCallback(({ field }: {field: ControllerRenderProps<FormFields, 'compiler'>}) => {
const error = 'compiler' in formState.errors ? formState.errors.compiler : undefined; const error = 'compiler' in formState.errors ? formState.errors.compiler : undefined;
return ( return (
<FancySelect <FancySelect
{ ...field } { ...field }
options={ options } loadOptions={ loadOptions }
defaultOptions
size={ isMobile ? 'md' : 'lg' } size={ isMobile ? 'md' : 'lg' }
placeholder="Compiler" placeholder="Compiler"
isDisabled={ formState.isSubmitting } isDisabled={ formState.isSubmitting }
error={ error } error={ error }
isRequired isRequired
isAsync
/> />
); );
}, [ formState.errors, formState.isSubmitting, isMobile, options ]); }, [ formState.errors, formState.isSubmitting, isMobile, loadOptions ]);
return ( return (
<ContractVerificationFormRow> <ContractVerificationFormRow>
<Controller <>
name="compiler" <Controller
control={ control } name="compiler"
render={ renderControl } control={ control }
rules={{ required: true }} render={ renderControl }
/> rules={{ required: true }}
/>
{ !isVyper && (
<Checkbox
size="lg"
mt={ 3 }
onChange={ handleCheckboxChange }
isDisabled={ formState.isSubmitting }
>
Include nightly builds
</Checkbox>
) }
</>
{ isVyper ? null : ( { isVyper ? null : (
<> <>
<span>The compiler version is specified in </span> <span>The compiler version is specified in </span>
......
import { FormControl, useToken, useColorMode } from '@chakra-ui/react'; import { FormControl, useToken, useColorMode } from '@chakra-ui/react';
import type { Size, CSSObjectWithLabel, OptionsOrGroups, GroupBase, SingleValue, MultiValue } from 'chakra-react-select'; import type { CSSObjectWithLabel, GroupBase, SingleValue, MultiValue, AsyncProps, Props as SelectProps } from 'chakra-react-select';
import { Select } from 'chakra-react-select'; import { Select, AsyncSelect } from 'chakra-react-select';
import React from 'react'; import React from 'react';
import type { FieldError, FieldErrorsImpl, Merge } from 'react-hook-form'; import type { FieldError, FieldErrorsImpl, Merge } from 'react-hook-form';
...@@ -9,20 +9,23 @@ import type { Option } from './types'; ...@@ -9,20 +9,23 @@ import type { Option } from './types';
import { getChakraStyles } from 'ui/shared/FancySelect/utils'; import { getChakraStyles } from 'ui/shared/FancySelect/utils';
import InputPlaceholder from 'ui/shared/InputPlaceholder'; import InputPlaceholder from 'ui/shared/InputPlaceholder';
interface Props { interface CommonProps {
size?: Size; // we don't have styles for sm select/input with floating label yet
options: OptionsOrGroups<Option, GroupBase<Option>>;
placeholder: string;
name: string;
onChange: (newValue: SingleValue<Option> | MultiValue<Option>) => void;
onBlur?: () => void;
isDisabled?: boolean;
isRequired?: boolean;
error?: Merge<FieldError, FieldErrorsImpl<Option>> | undefined; error?: Merge<FieldError, FieldErrorsImpl<Option>> | undefined;
value?: SingleValue<Option> | MultiValue<Option>;
} }
const FancySelect = ({ size = 'md', options, placeholder, name, onChange, onBlur, isDisabled, isRequired, error, value }: Props) => { interface RegularSelectProps extends SelectProps<Option, boolean, GroupBase<Option>>, CommonProps {
isAsync?: false;
onChange: (newValue: SingleValue<Option> | MultiValue<Option>) => void;
}
interface AsyncSelectProps extends AsyncProps<Option, boolean, GroupBase<Option>>, CommonProps {
isAsync: true;
onChange: (newValue: SingleValue<Option> | MultiValue<Option>) => void;
}
type Props = RegularSelectProps | AsyncSelectProps;
const FancySelect = (props: Props) => {
const menuZIndex = useToken('zIndices', 'dropdown'); const menuZIndex = useToken('zIndices', 'dropdown');
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
...@@ -32,34 +35,30 @@ const FancySelect = ({ size = 'md', options, placeholder, name, onChange, onBlur ...@@ -32,34 +35,30 @@ const FancySelect = ({ size = 'md', options, placeholder, name, onChange, onBlur
const chakraStyles = React.useMemo(() => getChakraStyles(colorMode), [ colorMode ]); const chakraStyles = React.useMemo(() => getChakraStyles(colorMode), [ colorMode ]);
const SelectComponent = props.isAsync ? AsyncSelect : Select;
return ( return (
<FormControl <FormControl
variant="floating" variant="floating"
size={ size } size={ props.size || 'md' }
isRequired={ isRequired } isRequired={ props.isRequired }
{ ...(error ? { 'aria-invalid': true } : {}) } { ...(props.error ? { 'aria-invalid': true } : {}) }
{ ...(isDisabled ? { 'aria-disabled': true } : {}) } { ...(props.isDisabled ? { 'aria-disabled': true } : {}) }
{ ...(value ? { 'data-active': true } : {}) } { ...(props.value ? { 'data-active': true } : {}) }
> >
<Select <SelectComponent
{ ...props }
size={ props.size || 'md' }
menuPortalTarget={ window.document.body } menuPortalTarget={ window.document.body }
placeholder="" placeholder=""
name={ name }
options={ options }
size={ size }
styles={ styles } styles={ styles }
chakraStyles={ chakraStyles } chakraStyles={ chakraStyles }
isInvalid={ Boolean(props.error) }
useBasicStyles useBasicStyles
onChange={ onChange }
onBlur={ onBlur }
isDisabled={ isDisabled }
isRequired={ isRequired }
isInvalid={ Boolean(error) }
value={ value }
/> />
<InputPlaceholder <InputPlaceholder
text={ placeholder } text={ typeof props.placeholder === 'string' ? props.placeholder : '' }
error={ error } error={ props.error }
isFancy isFancy
/> />
</FormControl> </FormControl>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment