Commit 220e9c9f authored by tom's avatar tom

file input and multi-part file methos

parent ca47d79c
import { GridItem, Text, Button, Box } from '@chakra-ui/react';
import React from 'react';
import type { ControllerRenderProps, Control } from 'react-hook-form';
import { Controller } from 'react-hook-form';
import type { FormFields } from '../types';
import FileInput from 'ui/shared/forms/FileInput';
import FileSnippet from 'ui/shared/forms/FileSnippet';
interface Props {
control: Control<FormFields>;
}
const ContractVerificationFieldSources = ({ control }: Props) => {
const renderFiles = React.useCallback((files: Array<File>) => {
return (
<Box display="grid" gridTemplateColumns={{ base: '1fr', lg: '1fr 1fr' }} columnGap={ 3 } rowGap={ 3 }>
{ files.map((file, index) => <FileSnippet key={ file.name + index } file={ file } maxW="initial"/>) }
</Box>
);
}, []);
const renderControl = React.useCallback(({ field }: {field: ControllerRenderProps<FormFields, 'sources'>}) => (
<>
<FileInput<FormFields, 'sources'> accept=".sol,.yul" multiple field={ field }>
<Button variant="outline" size="sm" display={ field.value && field.value.length > 0 ? 'none' : 'block' }>
Upload file
</Button>
</FileInput>
{ field.value && field.value.length > 0 && renderFiles(field.value) }
</>
), [ renderFiles ]);
return (
<>
<GridItem mt="30px">
<Text fontWeight={ 500 } mb={ 4 }>Sources *.sol or *.yul files</Text>
<Controller
name="sources"
control={ control }
render={ renderControl }
/>
</GridItem>
<GridItem/>
</>
);
};
export default React.memo(ContractVerificationFieldSources);
......@@ -4,16 +4,24 @@ import type { Control } from 'react-hook-form';
import type { FormFields } from '../types';
import ContractVerificationMethod from '../ContractVerificationMethod';
import ContractVerificationFieldCompiler from '../fields/ContractVerificationFieldCompiler';
import ContractVerificationFieldEvmVersion from '../fields/ContractVerificationFieldEvmVersion';
import ContractVerificationFieldLibraries from '../fields/ContractVerificationFieldLibraries';
import ContractVerificationFieldOptimization from '../fields/ContractVerificationFieldOptimization';
import ContractVerificationFieldSources from '../fields/ContractVerificationFieldSources';
interface Props {
control: Control<FormFields>;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const ContractVerificationMultiPartFile = ({ control }: Props) => {
return (
<ContractVerificationMethod title="New Solidity/Yul Smart Contract Verification">
ContractVerificationMultiPartFile
<ContractVerificationFieldCompiler control={ control }/>
<ContractVerificationFieldEvmVersion control={ control }/>
<ContractVerificationFieldOptimization control={ control }/>
<ContractVerificationFieldSources control={ control }/>
<ContractVerificationFieldLibraries control={ control }/>
</ContractVerificationMethod>
);
};
......
......@@ -28,6 +28,11 @@ export interface FormFieldsSourcify {
export interface FormFieldsMultiPartFile {
method: 'multi_part_file';
compiler: string;
evm_version: string;
is_optimization_enabled: boolean;
optimization_runs: string;
sources: Array<File>;
}
export interface FormFieldsVyperContract {
......
import { InputGroup, VisuallyHiddenInput } from '@chakra-ui/react';
import type { ChangeEvent } from 'react';
import React from 'react';
import type { ControllerRenderProps, FieldValues, Path } from 'react-hook-form';
interface Props<V extends FieldValues, N extends Path<V>> {
children: React.ReactNode;
field: ControllerRenderProps<V, N>;
accept?: string;
multiple?: boolean;
}
const FileInput = <Values extends FieldValues, Names extends Path<Values>>({ children, accept, multiple, field }: Props<Values, Names>) => {
const ref = React.useRef<HTMLInputElement>(null);
const handleInputChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
const fileList = event.target.files;
if (!fileList) {
return;
}
const files = Array.from(fileList);
field.onChange(files);
}, [ field ]);
const handleClick = React.useCallback(() => {
ref.current?.click();
}, []);
return (
<InputGroup onClick={ handleClick }>
<VisuallyHiddenInput
type="file"
onChange={ handleInputChange }
ref={ ref }
accept={ accept }
multiple={ multiple }
/>
{ children }
</InputGroup>
);
};
export default FileInput;
import { Box, Flex, Icon, Text, useColorModeValue, chakra } from '@chakra-ui/react';
import React from 'react';
import crossIcon from 'icons/cross.svg';
import imageIcon from 'icons/image.svg';
import { shortenNumberWithLetter } from 'lib/formatters';
interface Props {
file: File;
className?: string;
index?: number;
onRemove?: (index?: number) => void;
}
const FileSnippet = ({ file, className, index, onRemove }: Props) => {
const handleRemove = React.useCallback(() => {
onRemove?.(index);
}, [ index, onRemove ]);
return (
<Flex
p={ 3 }
borderWidth="2px"
borderRadius="md"
borderColor={ useColorModeValue('blackAlpha.100', 'whiteAlpha.200') }
maxW="300px"
overflow="hidden"
className={ className }
>
<Icon as={ imageIcon } boxSize="50px" color={ useColorModeValue('gray.600', 'gray.400') } mr={ 2 }/>
<Box width="calc(100% - 58px - 24px)" >
<Text fontWeight={ 600 } overflow="hidden" textOverflow="ellipsis" whiteSpace="nowrap">{ file.name }</Text>
<Text variant="secondary" mt={ 1 }>{ shortenNumberWithLetter(file.size) }B</Text>
</Box>
<Icon
as={ crossIcon }
boxSize={ 6 }
color="link"
_hover={{ color: 'link_hovered' }}
cursor="pointer"
ml="auto"
onClick={ handleRemove }
/>
</Flex>
);
};
export default React.memo(chakra(FileSnippet));
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