|
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'; |
6 | 5 | 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'; |
7 | 9 |
|
| 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); |
8 | 20 |
|
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; |
13 | 31 | }
|
14 | 32 |
|
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 | + }); |
17 | 41 | }
|
18 | 42 |
|
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 | + ); |
55 | 89 | }
|
56 | 90 |
|
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; |
0 commit comments