fileField.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import {Fragment, useState} from 'react';
  2. import omit from 'lodash/omit';
  3. import InputField, {InputFieldProps} from 'sentry/components/forms/inputField';
  4. import Input from 'sentry/components/input';
  5. export interface FileFieldProps extends Omit<InputFieldProps, 'type' | 'accept'> {
  6. accept?: string[];
  7. // TODO(dcramer): multiple is native to the file input type, but not yet supported
  8. // multiple?: boolean;
  9. }
  10. // XXX(dcramer): This stores files in memory - serialized into the forms values
  11. // which is not ideal, but is compatible with the API-side SerializedFileField.
  12. // TODO(dcramer): it'd be nice if the form api supported a validation state, so
  13. // async controls like this would could finish their work and disable submission.
  14. // Until that is done though if you try to submit the form while this is uploading
  15. // you will just submit the form without the field.
  16. export default function FileField({accept, ...props}: FileFieldProps) {
  17. const [isUploading, setUploading] = useState(false);
  18. const handleFile = (onChange, e) => {
  19. const file = e.target.files[0];
  20. const reader = new FileReader();
  21. setUploading(true);
  22. reader.addEventListener(
  23. 'load',
  24. () => {
  25. onChange([file.name, (reader.result as string).split(',')[1]], e);
  26. setUploading(false);
  27. },
  28. false
  29. );
  30. reader.readAsDataURL(file);
  31. };
  32. return (
  33. <InputField
  34. {...props}
  35. accept={accept?.join(', ')}
  36. field={({onChange, ...fieldProps}) => {
  37. return (
  38. <Fragment>
  39. <Input
  40. {...omit(fieldProps, 'value', 'onBlur', 'onKeyDown')}
  41. type="file"
  42. onChange={e => handleFile(onChange, e)}
  43. />
  44. {isUploading ? (
  45. <div>This is a janky upload indicator. Wait to hit save!</div>
  46. ) : (
  47. ''
  48. )}
  49. </Fragment>
  50. );
  51. }}
  52. />
  53. );
  54. }