Skip to content

Commit d07ee9a

Browse files
committed
Add create directory button
1 parent ba0757f commit d07ee9a

File tree

3 files changed

+142
-25
lines changed

3 files changed

+142
-25
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import http from '@/api/http';
2+
3+
export default (uuid: string, root: string, name: string): Promise<void> => {
4+
return new Promise((resolve, reject) => {
5+
http.post(`/api/client/servers/${uuid}/files/create-folder`, { root, name })
6+
.then(() => resolve())
7+
.catch(reject);
8+
});
9+
};

resources/scripts/components/server/files/FileManagerContainer.tsx

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ import { CSSTransition } from 'react-transition-group';
88
import Spinner from '@/components/elements/Spinner';
99
import FileObjectRow from '@/components/server/files/FileObjectRow';
1010
import FileManagerBreadcrumbs from '@/components/server/files/FileManagerBreadcrumbs';
11+
import { FileObject } from '@/api/server/files/loadDirectory';
12+
import NewDirectoryButton from '@/components/server/files/NewDirectoryButton';
13+
14+
const sortFiles = (files: FileObject[]): FileObject[] => {
15+
return files.sort((a, b) => a.name.localeCompare(b.name))
16+
.sort((a, b) => a.isFile === b.isFile ? 0 : (a.isFile ? 1 : -1));
17+
};
1118

1219
export default () => {
1320
const [ loading, setLoading ] = useState(true);
@@ -37,34 +44,46 @@ export default () => {
3744
loading ?
3845
<Spinner size={'large'} centered={true}/>
3946
:
40-
!files.length ?
41-
<p className={'text-sm text-neutral-600 text-center'}>
42-
This directory seems to be empty.
43-
</p>
44-
:
45-
<CSSTransition classNames={'fade'} timeout={250} appear={true} in={true}>
46-
<div>
47-
{files.length > 250 ?
48-
<React.Fragment>
49-
<div className={'rounded bg-yellow-400 mb-px p-3'}>
50-
<p className={'text-yellow-900 text-sm text-center'}>
51-
This directory is too large to display in the browser, limiting
52-
the output to the first 250 files.
53-
</p>
54-
</div>
55-
{
56-
files.slice(0, 250).map(file => (
47+
<React.Fragment>
48+
{!files.length ?
49+
<p className={'text-sm text-neutral-600 text-center'}>
50+
This directory seems to be empty.
51+
</p>
52+
:
53+
<CSSTransition classNames={'fade'} timeout={250} appear={true} in={true}>
54+
<React.Fragment>
55+
<div>
56+
{files.length > 250 ?
57+
<React.Fragment>
58+
<div className={'rounded bg-yellow-400 mb-px p-3'}>
59+
<p className={'text-yellow-900 text-sm text-center'}>
60+
This directory is too large to display in the browser,
61+
limiting
62+
the output to the first 250 files.
63+
</p>
64+
</div>
65+
{
66+
sortFiles(files.slice(0, 250)).map(file => (
67+
<FileObjectRow key={file.uuid} file={file}/>
68+
))
69+
}
70+
</React.Fragment>
71+
:
72+
sortFiles(files).map(file => (
5773
<FileObjectRow key={file.uuid} file={file}/>
5874
))
5975
}
60-
</React.Fragment>
61-
:
62-
files.map(file => (
63-
<FileObjectRow key={file.uuid} file={file}/>
64-
))
65-
}
66-
</div>
67-
</CSSTransition>
76+
</div>
77+
</React.Fragment>
78+
</CSSTransition>
79+
}
80+
<div className={'flex justify-end mt-8'}>
81+
<NewDirectoryButton/>
82+
<button className={'btn btn-sm btn-primary'}>
83+
New File
84+
</button>
85+
</div>
86+
</React.Fragment>
6887
}
6988
</React.Fragment>
7089
</div>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React, { useState } from 'react';
2+
import Modal from '@/components/elements/Modal';
3+
import { ServerContext } from '@/state/server';
4+
import { Form, Formik, FormikActions } from 'formik';
5+
import Field from '@/components/elements/Field';
6+
import { join } from 'path';
7+
import { object, string } from 'yup';
8+
import createDirectory from '@/api/server/files/createDirectory';
9+
import v4 from 'uuid/v4';
10+
11+
interface Values {
12+
directoryName: string;
13+
}
14+
15+
const schema = object().shape({
16+
directoryName: string().required('A valid directory name must be provided.'),
17+
});
18+
19+
export default () => {
20+
const [ visible, setVisible ] = useState(false);
21+
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
22+
const directory = ServerContext.useStoreState(state => state.files.directory);
23+
const pushFile = ServerContext.useStoreActions(actions => actions.files.pushFile);
24+
25+
const submit = (values: Values, { setSubmitting }: FormikActions<Values>) => {
26+
createDirectory(uuid, directory, values.directoryName)
27+
.then(() => {
28+
pushFile({
29+
uuid: v4(),
30+
name: values.directoryName,
31+
mode: '0644',
32+
size: 0,
33+
isFile: false,
34+
isEditable: false,
35+
isSymlink: false,
36+
mimetype: '',
37+
createdAt: new Date(),
38+
modifiedAt: new Date(),
39+
});
40+
setVisible(false);
41+
})
42+
.catch(error => {
43+
console.error(error);
44+
setSubmitting(false);
45+
});
46+
};
47+
48+
return (
49+
<React.Fragment>
50+
<Formik
51+
onSubmit={submit}
52+
validationSchema={schema}
53+
initialValues={{ directoryName: '' }}
54+
>
55+
{({ resetForm, isSubmitting, values }) => (
56+
<Modal
57+
visible={visible}
58+
dismissable={!isSubmitting}
59+
showSpinnerOverlay={isSubmitting}
60+
onDismissed={() => {
61+
setVisible(false);
62+
resetForm();
63+
}}
64+
>
65+
<Form className={'m-0'}>
66+
<Field
67+
id={'directoryName'}
68+
name={'directoryName'}
69+
label={'Directory Name'}
70+
/>
71+
<p className={'text-xs mt-2 text-neutral-400'}>
72+
<span className={'text-neutral-200'}>This directory will be created as</span>
73+
&nbsp;/home/container/<span className={'text-cyan-200'}>{join(directory, values.directoryName).replace(/^(\.\.\/|\/)+/, '')}</span>
74+
</p>
75+
<div className={'flex justify-end'}>
76+
<button className={'btn btn-sm btn-primary mt-8'}>
77+
Create Directory
78+
</button>
79+
</div>
80+
</Form>
81+
</Modal>
82+
)}
83+
</Formik>
84+
<button className={'btn btn-sm btn-secondary mr-2'} onClick={() => setVisible(true)}>
85+
Create Directory
86+
</button>
87+
</React.Fragment>
88+
);
89+
};

0 commit comments

Comments
 (0)