import React, { FC, ChangeEvent, useState } from 'react' import { useSelector, useDispatch } from 'react-redux' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faUpload } from '@fortawesome/free-solid-svg-icons' import { BlockBlobClient, AnonymousCredential } from '@azure/storage-blob' import { useTheme } from '../../hooks' import { setFieldValue } from '../../actions/forms' import { showNotification } from '../../actions/notifications' import { getFieldValue } from '../../selectors/forms' import { apiFetch } from '../../api/fetch' import { MEDIA_DEFAULT_MAX_SIZE } from '../../constants' import { AppState, AppThunkDispatch, SasResponse, NotificationType } from '../../types' import Progress from '../../components/progress' import FieldLabel from '../../components/controls/field-label' interface Props { name: string label: string help?: string previewWidth?: number maxSize?: number } const FileField: FC = props => { const theme = useTheme() const value = useSelector(state => getFieldValue(state, props.name, '')) const dispatch = useDispatch() const { name, label, help, previewWidth = 128, maxSize = MEDIA_DEFAULT_MAX_SIZE } = props const [progress, setProgress] = useState(0) const [uploading, setUploading] = useState(false) const [uploaded, setUploaded] = useState(false) const handleChange = async (event: ChangeEvent) => { if (event.target.files) { const file = event.target.files[0] if (file.size > maxSize) { const maxSizeString = Math.round(maxSize / 1024 / 1024) dispatch(showNotification(NotificationType.Error, `Files must be less than ${maxSizeString} MBs`)) return } const ext = file.name.substring(file.name.lastIndexOf('.')) const { sas, blobUrl, id } = await apiFetch({ path: '/v1/sas' }) const filename = `${id}${ext}` setUploading(true) try { const blockBlobClient = new BlockBlobClient(`${blobUrl}/${filename}?${sas}`, new AnonymousCredential()) await blockBlobClient.uploadBrowserData(file, { onProgress: p => { setProgress((p.loadedBytes / file.size) * 100) } }) await apiFetch({ path: '/v1/media', method: 'post', body: { name: filename, size: file.size, type: file.type, originalName: file.name, } }) dispatch(setFieldValue(name, `${blobUrl}/${filename}`)) setUploaded(true) } catch (err) { console.error(err) dispatch(showNotification(NotificationType.Error, `Upload error: ${err}`)) } setUploading(false) } } const handleDelete = async () => { if (uploaded) { await apiFetch({ path: `/v1/media?name=${value}`, method: 'delete', }) } dispatch(setFieldValue(name, '')) } if (uploading) { return (
{label}
) } return (
{label} {value &&
{value.split('/').pop()}    ( handleDelete()}>Delete)
} {!value &&

{help}

}
) } export default FileField