in frontend/src/js/components/Uploads/UploadFiles.tsx [220:360]
export default function UploadFiles(props: Props) {
let target: WorkspaceTarget | undefined = undefined;
const appDispatch = useDispatch();
const [state, dispatch] = useReducer(reducer, { files: new Map() });
const currentUpload = getCurrentlyUploading(state);
const isUploading = currentUpload !== undefined;
const completeCount = [...state.files.values()].filter(({ state }) => state.description === 'uploaded').length;
const isComplete = [...state.files.values()].some(({ state }) => state.description === 'uploaded');
const isEditDisabled = isUploading || isComplete;
function dismissAndResetModal() {
setOpen(false);
dispatch({ type: "Reset", state: { files: new Map(), target: undefined } });
}
const [open, setOpen] = useState(false);
const [focusedWorkspaceFolder, setFocusedWorkspaceFolder] = useState<TreeNode<WorkspaceEntry> | null>(null);
async function onSubmit() {
const { username, workspace, collections, getResource } = props;
if (!collections) {
throw new Error('No collections when submitting upload dialog');
}
try {
target = await getUploadTarget(username, workspace, collections, focusedWorkspaceFolder);
if (isComplete) {
dismissAndResetModal();
history.push(`/workspaces/${target.workspace.id}`);
} else {
await uploadFiles(target, state.files, dispatch).then(() => {
getResource(workspace.id);
});
}
} catch(error) {
appDispatch({
type: AppActionType.APP_SHOW_ERROR,
message: `Error uploading files ${error}`,
error: error,
});
}
}
function onDismiss() {
setOpen(false);
setFocusedWorkspaceFolder(null);
dispatch({ type: "Reset", state: { files: new Map(), target: undefined } });
}
function onClick() {
setOpen(true);
if (props.focusedWorkspaceEntry) {
const { focusedWorkspaceEntry } = props;
// Set the folder we are focused on. If we are focused on a leaf, then
// the focused leaf is the parent of that folder.
if (isTreeNode(focusedWorkspaceEntry)) {
setFocusedWorkspaceFolder(focusedWorkspaceEntry);
}
else if (isTreeLeaf(focusedWorkspaceEntry)) {
const rootNodeId = props.workspace.rootNode.id;
const parentId = focusedWorkspaceEntry.data.maybeParentId;
if (parentId && parentId !== rootNodeId) {
const focusedUploadFolder = props.expandedNodes && props.expandedNodes.find(node => node.id === parentId);
if (focusedUploadFolder) {
setFocusedWorkspaceFolder(focusedUploadFolder);
}
}
}
}
}
const focusedWorkspaceRelativePath = (focusedWorkspaceFolder && props.workspace.rootNode)
? displayRelativePath(props.workspace.rootNode, focusedWorkspaceFolder.id)
: null;
return (
<React.Fragment>
<button
className='btn file-upload__button'
onClick={onClick}
>
<MdFileUpload className='file-upload__icon'/>
Upload to workspace
</button>
<Modal isOpen={open} dismiss={onDismiss} isDismissable={!isUploading}>
<Form onSubmit={onSubmit}>
<h2 className='form__title'>Upload Files (limit {MAX_FILE_UPLOAD_SIZE_MBYTES}MB per file)</h2>
{ focusedWorkspaceRelativePath ? <div className='form__row'>Uploading to folder {focusedWorkspaceRelativePath}</div> : false}
<Form.Field>
<FilePicker
disabled={isEditDisabled}
onAddFiles={(files) => {
dispatch({ type: "Add_Files", files })
}}
/>
</Form.Field>
<Form.Field>
<FileList
files={state.files}
disabled={isEditDisabled}
removeByPath={(path: string) => {
dispatch({ type: "Remove_Path", path })
}}
/>
</Form.Field>
{currentUpload ? <FileUploadProgressBar file={currentUpload.file} uploadState={currentUpload.uploadState} /> : false}
{ !isComplete ?
<Button
type="submit"
primary
disabled={state.files.size === 0 || isUploading}
loading={isUploading}
>
{'Upload'}
</Button>
: false }
{isComplete && !isUploading ?
<Button
type="button"
onClick={() => dismissAndResetModal()}
>
Close
</Button>
: false}
{isUploading ?
<span>Uploaded {completeCount}/{state.files.size}</span>
: false}
</Form>
</Modal>
</React.Fragment>
);
}