-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Expand file tree
/
Copy pathNewButton.tsx
More file actions
132 lines (121 loc) · 5.19 KB
/
NewButton.tsx
File metadata and controls
132 lines (121 loc) · 5.19 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import React, { useContext, useEffect, useState } from 'react';
import { NavLink } from 'react-router-dom';
import { Button } from '@/components/elements/button/index';
import { ServerContext } from '@/state/server';
import DropdownMenu, { DropdownButtonRow } from '@/components/elements/DropdownMenu';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faChevronDown, faFile, faFolder } from '@fortawesome/free-solid-svg-icons';
import tw from 'twin.macro';
import { Form, Formik, FormikHelpers } from 'formik';
import Field from '@/components/elements/Field';
import { join } from 'pathe';
import { object, string } from 'yup';
import createDirectory from '@/api/server/files/createDirectory';
import { FileObject } from '@/api/server/files/loadDirectory';
import { useFlashKey } from '@/plugins/useFlash';
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
import FlashMessageRender from '@/components/FlashMessageRender';
import { Dialog, DialogWrapperContext } from '@/components/elements/dialog';
import Code from '@/components/elements/Code';
import asDialog from '@/hoc/asDialog';
interface Values {
directoryName: string;
}
const schema = object().shape({
directoryName: string().required('A valid directory name must be provided.'),
});
const generateDirectoryData = (name: string): FileObject => ({
key: `dir_${name.split('/', 1)[0] ?? name}`,
name: name.replace(/^(\/*)/, '').split('/', 1)[0] ?? name,
mode: 'drwxr-xr-x',
modeBits: '0755',
size: 0,
isFile: false,
isSymlink: false,
mimetype: '',
createdAt: new Date(),
modifiedAt: new Date(),
isArchiveType: () => false,
isEditable: () => false,
});
const NewDirectoryDialog = asDialog({
title: 'Create Directory',
})(() => {
const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid);
const directory = ServerContext.useStoreState((state) => state.files.directory);
const { mutate } = useFileManagerSwr();
const { close } = useContext(DialogWrapperContext);
const { clearAndAddHttpError } = useFlashKey('files:directory-modal');
useEffect(() => {
return () => {
clearAndAddHttpError();
};
}, []);
const submit = ({ directoryName }: Values, { setSubmitting }: FormikHelpers<Values>) => {
createDirectory(uuid, directory, directoryName)
.then(() => mutate((data) => [...data, generateDirectoryData(directoryName)], false))
.then(() => close())
.catch((error) => {
setSubmitting(false);
clearAndAddHttpError(error);
});
};
return (
<Formik onSubmit={submit} validationSchema={schema} initialValues={{ directoryName: '' }}>
{({ submitForm, values }) => (
<>
<FlashMessageRender key={'files:directory-modal'} />
<Form css={tw`m-0`}>
<Field autoFocus id={'directoryName'} name={'directoryName'} label={'Name'} />
<p css={tw`mt-2 text-sm md:text-base break-all`}>
<span css={tw`text-neutral-200`}>This directory will be created as </span>
<Code>
/home/container/
<span css={tw`text-cyan-200`}>
{join(directory, values.directoryName).replace(/^(\.\.\/|\/)+/, '')}
</span>
</Code>
</p>
</Form>
<Dialog.Footer>
<Button.Text className={'w-full sm:w-auto'} onClick={close}>
Cancel
</Button.Text>
<Button className={'w-full sm:w-auto'} onClick={submitForm}>
Create
</Button>
</Dialog.Footer>
</>
)}
</Formik>
);
});
const NewButton = () => {
const id = ServerContext.useStoreState((state) => state.server.data!.id);
const [openDirectoryDialog, setOpenDirectoryDialog] = useState(false);
return (
<>
<NewDirectoryDialog open={openDirectoryDialog} onClose={() => setOpenDirectoryDialog(false)} />
<DropdownMenu
renderToggle={(onClick) => (
<Button onClick={onClick}>
New
<FontAwesomeIcon icon={faChevronDown} css={tw`ml-2`} />
</Button>
)}
>
<NavLink to={`/server/${id}/files/new${window.location.hash}`}>
<DropdownButtonRow css={tw`justify-start !w-full`}>
<FontAwesomeIcon icon={faFile} css={tw`mr-3`} />
File
</DropdownButtonRow>
</NavLink>
<DropdownButtonRow onClick={() => setOpenDirectoryDialog(true)} css={tw`justify-start !w-full`}>
<FontAwesomeIcon icon={faFolder} css={tw`mr-3`} />
Folder
</DropdownButtonRow>
</DropdownMenu>
</>
);
};
export default NewButton;