forked from pterodactyl/panel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMassActionsBar.tsx
More file actions
113 lines (103 loc) · 4.81 KB
/
MassActionsBar.tsx
File metadata and controls
113 lines (103 loc) · 4.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import React, { useEffect, useState } from 'react';
import tw from 'twin.macro';
import { Button } from '@/components/elements/button/index';
import Fade from '@/components/elements/Fade';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
import useFlash from '@/plugins/useFlash';
import compressFiles from '@/api/server/files/compressFiles';
import { ServerContext } from '@/state/server';
import deleteFiles from '@/api/server/files/deleteFiles';
import RenameFileModal from '@/components/server/files/RenameFileModal';
import Portal from '@/components/elements/Portal';
import { Dialog } from '@/components/elements/dialog';
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(() => {
mutate((files) => files.filter((f) => selectedFiles.indexOf(f.name) < 0), false);
setSelectedFiles([]);
})
.catch((error) => {
mutate();
clearAndAddHttpError({ key: 'files', error });
})
.then(() => setLoading(false));
};
return (
<>
<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>
<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-gray-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={'pointer-events-none fixed bottom-0 mb-6 flex justify-center w-full z-50'}>
<Fade timeout={75} in={selectedFiles.length > 0} unmountOnExit>
<div css={tw`flex items-center space-x-4 pointer-events-auto rounded p-4 bg-black/50`}>
<Button onClick={() => setShowMove(true)}>Move</Button>
<Button onClick={onClickCompress}>Archive</Button>
<Button.Danger variant={Button.Variants.Secondary} onClick={() => setShowConfirm(true)}>
Delete
</Button.Danger>
</div>
</Fade>
</div>
</Portal>
</div>
</>
);
};
export default MassActionsBar;