c28cba92e2
This allows entire components to be unmounted when the modal is hidden without affecting the fade in/out of the modal itself. This also makes it easier to programatically dismiss a modal without having to copy the visibility all over the place, and makes working with props much simpler in those modal components
104 lines
4.4 KiB
TypeScript
104 lines
4.4 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import tw from 'twin.macro';
|
|
import Button from '@/components/elements/Button';
|
|
import Fade from '@/components/elements/Fade';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
import { faFileArchive, faLevelUpAlt, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
|
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
|
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
|
|
import useFlash from '@/plugins/useFlash';
|
|
import compressFiles from '@/api/server/files/compressFiles';
|
|
import useServer from '@/plugins/useServer';
|
|
import { ServerContext } from '@/state/server';
|
|
import ConfirmationModal from '@/components/elements/ConfirmationModal';
|
|
import deleteFiles from '@/api/server/files/deleteFiles';
|
|
import RenameFileModal from '@/components/server/files/RenameFileModal';
|
|
|
|
const MassActionsBar = () => {
|
|
const { uuid } = useServer();
|
|
const { mutate } = useFileManagerSwr();
|
|
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
|
const [ loading, setLoading ] = useState(false);
|
|
const [ loadingMessage, setLoadingMessage ] = useState('');
|
|
const [ showConfirm, setShowConfirm ] = useState(false);
|
|
const [ showMove, setShowMove ] = useState(false);
|
|
const directory = ServerContext.useStoreState(state => state.files.directory);
|
|
|
|
const selectedFiles = ServerContext.useStoreState(state => state.files.selectedFiles);
|
|
const setSelectedFiles = ServerContext.useStoreActions(actions => actions.files.setSelectedFiles);
|
|
|
|
useEffect(() => {
|
|
if (!loading) setLoadingMessage('');
|
|
}, [ loading ]);
|
|
|
|
const onClickCompress = () => {
|
|
setLoading(true);
|
|
clearFlashes('files');
|
|
setLoadingMessage('Archiving files...');
|
|
|
|
compressFiles(uuid, directory, selectedFiles)
|
|
.then(() => mutate())
|
|
.then(() => setSelectedFiles([]))
|
|
.catch(error => clearAndAddHttpError({ key: 'files', error }))
|
|
.then(() => setLoading(false));
|
|
};
|
|
|
|
const onClickConfirmDeletion = () => {
|
|
setLoading(true);
|
|
setShowConfirm(false);
|
|
clearFlashes('files');
|
|
setLoadingMessage('Deleting files...');
|
|
|
|
deleteFiles(uuid, directory, selectedFiles)
|
|
.then(() => {
|
|
mutate(files => files.filter(f => selectedFiles.indexOf(f.name) < 0), false);
|
|
setSelectedFiles([]);
|
|
})
|
|
.catch(error => {
|
|
mutate();
|
|
clearAndAddHttpError({ key: 'files', error });
|
|
})
|
|
.then(() => setLoading(false));
|
|
};
|
|
|
|
return (
|
|
<Fade timeout={75} in={selectedFiles.length > 0} unmountOnExit>
|
|
<div css={tw`fixed bottom-0 z-50 left-0 right-0 flex justify-center`}>
|
|
<SpinnerOverlay visible={loading} size={'large'} fixed>
|
|
{loadingMessage}
|
|
</SpinnerOverlay>
|
|
<ConfirmationModal
|
|
visible={showConfirm}
|
|
title={'Delete these files?'}
|
|
buttonText={'Yes, Delete Files'}
|
|
onConfirmed={onClickConfirmDeletion}
|
|
onModalDismissed={() => setShowConfirm(false)}
|
|
>
|
|
Deleting files is a permanent operation, you cannot undo this action.
|
|
</ConfirmationModal>
|
|
{showMove &&
|
|
<RenameFileModal
|
|
files={selectedFiles}
|
|
visible
|
|
appear
|
|
useMoveTerminology
|
|
onDismissed={() => setShowMove(false)}
|
|
/>
|
|
}
|
|
<div css={tw`rounded p-4 mb-6`} style={{ background: 'rgba(0, 0, 0, 0.35)' }}>
|
|
<Button size={'xsmall'} css={tw`mr-4`} onClick={() => setShowMove(true)}>
|
|
<FontAwesomeIcon icon={faLevelUpAlt} css={tw`mr-2`}/> Move
|
|
</Button>
|
|
<Button size={'xsmall'} css={tw`mr-4`} onClick={onClickCompress}>
|
|
<FontAwesomeIcon icon={faFileArchive} css={tw`mr-2`}/> Archive
|
|
</Button>
|
|
<Button size={'xsmall'} color={'red'} isSecondary onClick={() => setShowConfirm(true)}>
|
|
<FontAwesomeIcon icon={faTrashAlt} css={tw`mr-2`}/> Delete
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Fade>
|
|
);
|
|
};
|
|
|
|
export default MassActionsBar;
|