misc_pterodactyl-panel/resources/scripts/components/server/files/MassActionsBar.tsx

115 lines
4.9 KiB
TypeScript
Raw Normal View History

import React, { useEffect, useState } from 'react';
2020-07-11 22:37:59 +00:00
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';
2022-02-27 17:44:22 +00:00
import { compressFiles, deleteFiles } from '@/api/server/files';
2020-07-11 22:37:59 +00:00
import { ServerContext } from '@/state/server';
import ConfirmationModal from '@/components/elements/ConfirmationModal';
import RenameFileModal from '@/components/server/files/RenameFileModal';
2020-07-11 22:37:59 +00:00
const MassActionsBar = () => {
2020-08-26 04:39:00 +00:00
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
2020-07-11 22:37:59 +00:00
const { mutate } = useFileManagerSwr();
const { clearFlashes, clearAndAddHttpError } = useFlash();
const [ loading, setLoading ] = useState(false);
const [ loadingMessage, setLoadingMessage ] = useState('');
2020-07-11 22:37:59 +00:00
const [ showConfirm, setShowConfirm ] = useState(false);
const [ showMove, setShowMove ] = useState(false);
2020-07-11 22:37:59 +00:00
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 ]);
2020-07-11 22:37:59 +00:00
const onClickCompress = () => {
setLoading(true);
clearFlashes('files');
setLoadingMessage('Archiving files...');
2020-07-11 22:37:59 +00:00
compressFiles(uuid, directory, selectedFiles)
2020-07-11 22:37:59 +00:00
.then(() => mutate())
.then(() => setSelectedFiles([]))
2020-07-11 22:37:59 +00:00
.catch(error => clearAndAddHttpError({ key: 'files', error }))
.then(() => setLoading(false));
};
const onClickConfirmDeletion = () => {
setLoading(true);
setShowConfirm(false);
clearFlashes('files');
setLoadingMessage('Deleting files...');
2020-07-11 22:37:59 +00:00
deleteFiles(uuid, directory, selectedFiles)
2021-09-10 21:26:02 +00:00
.then(async () => {
await mutate(files => files!.filter(f => selectedFiles.indexOf(f.name) < 0), false);
setSelectedFiles([]);
2020-07-11 22:37:59 +00:00
})
2021-09-10 21:26:02 +00:00
.catch(async (error) => {
await mutate();
2020-07-11 22:37:59 +00:00
clearAndAddHttpError({ key: 'files', error });
})
.then(() => setLoading(false));
};
return (
<Fade timeout={75} in={selectedFiles.length > 0} unmountOnExit>
<div css={tw`pointer-events-none fixed bottom-0 z-20 left-0 right-0 flex justify-center`}>
<SpinnerOverlay visible={loading} size={'large'} fixed>
{loadingMessage}
</SpinnerOverlay>
2020-07-11 22:37:59 +00:00
<ConfirmationModal
visible={showConfirm}
title={'Delete these files?'}
buttonText={'Yes, Delete Files'}
onConfirmed={onClickConfirmDeletion}
onModalDismissed={() => setShowConfirm(false)}
2020-07-11 22:37:59 +00:00
>
Are you sure you want to delete {selectedFiles.length} file(s)?
<br/>
Deleting the file(s) listed below is a permanent operation, you cannot undo this action.
<br/>
<code>
2022-02-27 17:44:22 +00:00
{selectedFiles.slice(0, 15).map(file => (
<li key={file}>{file}<br/></li>))
}
2022-02-27 17:44:22 +00:00
{selectedFiles.length > 15 &&
<li> + {selectedFiles.length - 15} other(s) </li>
}
</code>
2020-07-11 22:37:59 +00:00
</ConfirmationModal>
2020-07-11 23:49:46 +00:00
{showMove &&
<RenameFileModal
files={selectedFiles}
2020-07-11 23:49:46 +00:00
visible
appear
useMoveTerminology
onDismissed={() => setShowMove(false)}
/>
2020-07-11 23:49:46 +00:00
}
<div css={tw`pointer-events-auto rounded p-4 mb-6`} style={{ background: 'rgba(0, 0, 0, 0.35)' }}>
<Button size={'xsmall'} css={tw`mr-4`} onClick={() => setShowMove(true)}>
2020-07-11 22:37:59 +00:00
<FontAwesomeIcon icon={faLevelUpAlt} css={tw`mr-2`}/> Move
</Button>
<Button size={'xsmall'} css={tw`mr-4`} onClick={onClickCompress}>
2020-07-11 22:37:59 +00:00
<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;