Skip to content

Commit 6f5fff5

Browse files
committed
Migrate NewFolderForm to final-form
1 parent a684f40 commit 6f5fff5

File tree

4 files changed

+112
-129
lines changed

4 files changed

+112
-129
lines changed

client/modules/IDE/actions/files.js

Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -73,51 +73,35 @@ export function submitFile(formProps, files, parentId, projectId) {
7373
});
7474
}
7575

76-
export function createFolder(formProps) {
77-
return (dispatch, getState) => {
78-
const state = getState();
79-
const { parentId } = state.ide;
80-
if (state.project.id) {
81-
const postParams = {
82-
name: createUniqueName(formProps.name, parentId, state.files),
83-
content: '',
84-
children: [],
85-
parentId,
86-
fileType: 'folder'
87-
};
88-
apiClient.post(`/projects/${state.project.id}/files`, postParams)
89-
.then((response) => {
90-
dispatch({
91-
type: ActionTypes.CREATE_FILE,
92-
...response.data.updatedFile,
93-
parentId
94-
});
95-
dispatch(setProjectSavedTime(response.data.project.updatedAt));
96-
dispatch(closeNewFolderModal());
97-
})
98-
.catch((error) => {
99-
const { response } = error;
100-
dispatch({
101-
type: ActionTypes.ERROR,
102-
error: response.data
103-
});
104-
});
105-
} else {
106-
const id = objectID().toHexString();
107-
dispatch({
108-
type: ActionTypes.CREATE_FILE,
109-
name: createUniqueName(formProps.name, parentId, state.files),
110-
id,
111-
_id: id,
112-
content: '',
113-
// TODO pass parent id from File Tree
114-
parentId,
115-
fileType: 'folder',
116-
children: []
117-
});
118-
dispatch(closeNewFolderModal());
119-
}
76+
export function submitFolder(formProps, files, parentId, projectId) {
77+
if (projectId) {
78+
const postParams = {
79+
name: createUniqueName(formProps.name, parentId, files),
80+
content: '',
81+
children: [],
82+
parentId,
83+
fileType: 'folder'
84+
};
85+
return apiClient.post(`/projects/${projectId}/files`, postParams)
86+
.then(response => ({
87+
file: response.data.updatedFile,
88+
updatedAt: response.data.project.updatedAt
89+
}));
90+
}
91+
const id = objectID().toHexString();
92+
const file = {
93+
type: ActionTypes.CREATE_FILE,
94+
name: createUniqueName(formProps.name, parentId, files),
95+
id,
96+
_id: id,
97+
content: '',
98+
// TODO pass parent id from File Tree
99+
fileType: 'folder',
100+
children: []
120101
};
102+
return Promise.resolve({
103+
file
104+
});
121105
}
122106

123107
export function updateFileName(id, name) {

client/modules/IDE/components/NewFileForm.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ function NewFileForm() {
2424
if (updatedAt) dispatch(setProjectSavedTime(updatedAt));
2525
dispatch(closeNewFileModal());
2626
dispatch(setUnsavedChanges(true));
27-
// reset form
2827
}).catch((error) => {
2928
const { response } = error;
3029
dispatch(createError(response.data));
Lines changed: 82 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,91 @@
1-
import PropTypes from 'prop-types';
2-
import React from 'react';
3-
import { withTranslation } from 'react-i18next';
4-
import { domOnlyProps } from '../../../utils/reduxFormUtils';
5-
1+
import React, { useRef, useEffect } from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { Form, Field } from 'react-final-form';
4+
import { useDispatch, useSelector } from 'react-redux';
65
import Button from '../../../common/Button';
6+
import { submitFolder, createFile } from '../actions/files';
7+
import { setProjectSavedTime } from '../actions/project';
8+
import { closeNewFolderModal, setUnsavedChanges } from '../actions/ide';
79

10+
function NewFolderForm() {
11+
const folderNameInput = useRef(null);
12+
useEffect(() => {
13+
folderNameInput.current.focus();
14+
});
15+
const { t } = useTranslation();
16+
const dispatch = useDispatch();
17+
const files = useSelector(state => state.files);
18+
const parentId = useSelector(state => state.ide.parentId);
19+
const projectId = useSelector(state => state.project.id);
820

9-
class NewFolderForm extends React.Component {
10-
constructor(props) {
11-
super(props);
12-
this.createFolder = this.props.createFolder.bind(this);
21+
function validate(formProps) {
22+
const errors = {};
23+
if (!formProps.name) {
24+
errors.name = t('NewFolderModal.EnterName');
25+
} else if (formProps.name.trim().length === 0) {
26+
errors.name = t('NewFolderModal.EmptyName');
27+
} else if (formProps.name.match(/\.+/i)) {
28+
errors.name = t('NewFolderModal.InvalidExtension');
29+
}
30+
return errors;
1331
}
1432

15-
componentDidMount() {
16-
this.fileName.focus();
33+
function handleCreateFolder(formProps) {
34+
submitFolder(formProps, files, parentId, projectId).then((response) => {
35+
const { file, updatedAt } = response;
36+
dispatch(createFile(file, parentId));
37+
if (updatedAt) dispatch(setProjectSavedTime(updatedAt));
38+
dispatch(closeNewFolderModal());
39+
dispatch(setUnsavedChanges(true));
40+
});
1741
}
1842

19-
render() {
20-
const {
21-
fields: { name },
22-
handleSubmit,
23-
} = this.props;
24-
return (
25-
<form
26-
className="new-folder-form"
27-
onSubmit={(data) => {
28-
handleSubmit(this.createFolder)(data);
29-
}}
30-
>
31-
<div className="new-folder-form__input-wrapper">
32-
<label className="new-folder-form__name-label" htmlFor="name">
33-
Name:
34-
</label>
35-
<input
36-
className="new-folder-form__name-input"
37-
id="name"
38-
type="text"
39-
maxLength="128"
40-
placeholder={this.props.t('NewFolderForm.Placeholder')}
41-
ref={(element) => { this.fileName = element; }}
42-
{...domOnlyProps(name)}
43-
/>
44-
<Button
45-
type="submit"
46-
>{this.props.t('NewFolderForm.AddFolderSubmit')}
47-
</Button>
48-
</div>
49-
{name.touched && name.error && (
50-
<span className="form-error">{name.error}</span>
51-
)}
52-
</form>
53-
);
54-
}
43+
return (
44+
<Form
45+
fields={['name']}
46+
validate={validate}
47+
onSubmit={handleCreateFolder}
48+
>
49+
{({
50+
handleSubmit, invalid, submitting, touched, errors
51+
}) => (
52+
<form
53+
className="new-folder-form"
54+
onSubmit={handleSubmit}
55+
>
56+
<div className="new-folder-form__input-wrapper">
57+
<Field name="name">
58+
{field => (
59+
<React.Fragment>
60+
<label className="new-folder-form__name-label" htmlFor="name">
61+
Name:
62+
</label>
63+
<input
64+
className="new-folder-form__name-input"
65+
id="name"
66+
type="text"
67+
maxLength="128"
68+
placeholder={t('NewFolderForm.Placeholder')}
69+
ref={folderNameInput}
70+
{...field.input}
71+
/>
72+
</React.Fragment>
73+
)}
74+
</Field>
75+
<Button
76+
type="submit"
77+
disabled={invalid || submitting}
78+
>{t('NewFolderForm.AddFolderSubmit')}
79+
</Button>
80+
</div>
81+
{touched.name && errors.name && (
82+
<span className="form-error">{errors.name}</span>
83+
)}
84+
</form>
85+
86+
)}
87+
</Form>
88+
);
5589
}
5690

57-
NewFolderForm.propTypes = {
58-
fields: PropTypes.shape({
59-
name: PropTypes.objectOf(PropTypes.shape()).isRequired
60-
}).isRequired,
61-
handleSubmit: PropTypes.func.isRequired,
62-
createFolder: PropTypes.func.isRequired,
63-
closeModal: PropTypes.func.isRequired,
64-
submitting: PropTypes.bool,
65-
pristine: PropTypes.bool,
66-
t: PropTypes.func.isRequired
67-
};
68-
NewFolderForm.defaultProps = {
69-
submitting: false,
70-
pristine: true,
71-
};
72-
export default withTranslation()(NewFolderForm);
91+
export default NewFolderForm;

client/modules/IDE/components/NewFolderModal.jsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
3-
import { reduxForm } from 'redux-form';
43
import { withTranslation } from 'react-i18next';
5-
import i18n from 'i18next';
64
import NewFolderForm from './NewFolderForm';
7-
85
import ExitIcon from '../../../images/exit.svg';
96

107
class NewFolderModal extends React.Component {
@@ -43,7 +40,7 @@ class NewFolderModal extends React.Component {
4340
<ExitIcon focusable="false" aria-hidden="true" />
4441
</button>
4542
</div>
46-
<NewFolderForm {...this.props} />
43+
<NewFolderForm />
4744
</div>
4845
</section>
4946
);
@@ -55,20 +52,4 @@ NewFolderModal.propTypes = {
5552
t: PropTypes.func.isRequired
5653
};
5754

58-
function validate(formProps) {
59-
const errors = {};
60-
if (!formProps.name) {
61-
errors.name = i18n.t('NewFolderModal.EnterName');
62-
} else if (formProps.name.trim().length === 0) {
63-
errors.name = i18n.t('NewFolderModal.EmptyName');
64-
} else if (formProps.name.match(/\.+/i)) {
65-
errors.name = i18n.t('NewFolderModal.InvalidExtension');
66-
}
67-
68-
return errors;
69-
}
70-
export default withTranslation()(reduxForm({
71-
form: 'new-folder',
72-
fields: ['name'],
73-
validate
74-
})(NewFolderModal));
55+
export default withTranslation()(NewFolderModal);

0 commit comments

Comments
 (0)