113 lines
4.8 KiB
TypeScript
113 lines
4.8 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
|
|
import compressFiles from '@/api/server/files/compressFiles';
|
|
import deleteFiles from '@/api/server/files/deleteFiles';
|
|
import { Button } from '@/components/elements/button';
|
|
import { Dialog } from '@/components/elements/dialog';
|
|
import Portal from '@/components/elements/Portal';
|
|
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
|
import RenameFileModal from '@/components/server/files/RenameFileModal';
|
|
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
|
|
import useFlash from '@/plugins/useFlash';
|
|
import { ServerContext } from '@/state/server';
|
|
import FadeTransition from '@/components/elements/transitions/FadeTransition';
|
|
|
|
const MassActionsBar = () => {
|
|
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
|
|
|
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(async () => {
|
|
await mutate(files => files!.filter(f => selectedFiles.indexOf(f.name) < 0), false);
|
|
setSelectedFiles([]);
|
|
})
|
|
.catch(async error => {
|
|
await mutate();
|
|
clearAndAddHttpError({ key: 'files', error });
|
|
})
|
|
.then(() => setLoading(false));
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className="pointer-events-none fixed bottom-0 left-0 right-0 z-20 flex justify-center">
|
|
<SpinnerOverlay visible={loading} size={'large'} fixed>
|
|
{loadingMessage}
|
|
</SpinnerOverlay>
|
|
<Dialog.Confirm
|
|
title={'Delete Files'}
|
|
open={showConfirm}
|
|
confirm={'Delete'}
|
|
onClose={() => setShowConfirm(false)}
|
|
onConfirmed={onClickConfirmDeletion}
|
|
>
|
|
<p className="mb-2">
|
|
Are you sure you want to delete
|
|
<span className="font-semibold text-slate-50">{selectedFiles.length} files</span>? This is a
|
|
permanent action and the files cannot be recovered.
|
|
</p>
|
|
{selectedFiles.slice(0, 15).map(file => (
|
|
<li key={file}>{file}</li>
|
|
))}
|
|
{selectedFiles.length > 15 && <li>and {selectedFiles.length - 15} others</li>}
|
|
</Dialog.Confirm>
|
|
{showMove && (
|
|
<RenameFileModal
|
|
files={selectedFiles}
|
|
visible
|
|
appear
|
|
useMoveTerminology
|
|
onDismissed={() => setShowMove(false)}
|
|
/>
|
|
)}
|
|
<Portal>
|
|
<div className="fixed bottom-0 z-50 mb-6 flex w-full justify-center">
|
|
<FadeTransition duration="duration-75" show={selectedFiles.length > 0} appear unmount>
|
|
<div className="pointer-events-auto flex items-center space-x-4 rounded bg-black/50 p-4">
|
|
<Button onClick={() => setShowMove(true)}>Move</Button>
|
|
<Button onClick={onClickCompress}>Archive</Button>
|
|
<Button.Danger variant={Button.Variants.Secondary} onClick={() => setShowConfirm(true)}>
|
|
Delete
|
|
</Button.Danger>
|
|
</div>
|
|
</FadeTransition>
|
|
</div>
|
|
</Portal>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default MassActionsBar;
|