diff --git a/client/modules/IDE/components/NewFileForm.jsx b/client/modules/IDE/components/NewFileForm.jsx index eb0740e1..40725879 100644 --- a/client/modules/IDE/components/NewFileForm.jsx +++ b/client/modules/IDE/components/NewFileForm.jsx @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import React from 'react'; +import { withTranslation } from 'react-i18next'; import { domOnlyProps } from '../../../utils/reduxFormUtils'; import Button from '../../../common/Button'; @@ -35,14 +36,17 @@ class NewFileForm extends React.Component { className="new-file-form__name-input" id="name" type="text" - placeholder="Name" + placeholder={this.props.t('NewFileForm.Placeholder')} maxLength="128" {...domOnlyProps(name)} ref={(element) => { this.fileName = element; }} /> - + {name.touched && name.error && ( {name.error} @@ -59,6 +63,7 @@ NewFileForm.propTypes = { handleSubmit: PropTypes.func.isRequired, createFile: PropTypes.func.isRequired, focusOnModal: PropTypes.func.isRequired, + t: PropTypes.func.isRequired }; -export default NewFileForm; +export default withTranslation()(NewFileForm); diff --git a/client/modules/IDE/components/NewFileModal.jsx b/client/modules/IDE/components/NewFileModal.jsx index 412d9895..791cb0af 100644 --- a/client/modules/IDE/components/NewFileModal.jsx +++ b/client/modules/IDE/components/NewFileModal.jsx @@ -3,6 +3,8 @@ import React from 'react'; import { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; import { reduxForm } from 'redux-form'; +import { withTranslation } from 'react-i18next'; +import i18n from 'i18next'; import NewFileForm from './NewFileForm'; import { closeNewFileModal } from '../actions/ide'; import { createFile } from '../actions/files'; @@ -33,11 +35,11 @@ class NewFileModal extends React.Component {
{ this.modal = element; }}>
-

Create File

+

{this.props.t('NewFileModal.Title')}

@@ -54,16 +56,17 @@ class NewFileModal extends React.Component { NewFileModal.propTypes = { createFile: PropTypes.func.isRequired, - closeNewFileModal: PropTypes.func.isRequired + closeNewFileModal: PropTypes.func.isRequired, + t: PropTypes.func.isRequired }; function validate(formProps) { const errors = {}; if (!formProps.name) { - errors.name = 'Please enter a name'; + errors.name = i18n.t('NewFileModal.EnterName'); } else if (!formProps.name.match(CREATE_FILE_REGEX)) { - errors.name = 'Invalid file type. Valid extensions are .js, .css, .json, .txt, .csv, .tsv, .frag, and .vert.'; + errors.name = i18n.t('NewFileModal.InvalidType'); } return errors; @@ -77,11 +80,11 @@ function mapDispatchToProps(dispatch) { return bindActionCreators({ createFile, closeNewFileModal }, dispatch); } -export default compose( +export default withTranslation()(compose( connect(mapStateToProps, mapDispatchToProps), reduxForm({ form: 'new-file', fields: ['name'], validate }) -)(NewFileModal); +)(NewFileModal)); diff --git a/client/modules/IDE/components/NewFolderForm.jsx b/client/modules/IDE/components/NewFolderForm.jsx index 04c590fe..db307861 100644 --- a/client/modules/IDE/components/NewFolderForm.jsx +++ b/client/modules/IDE/components/NewFolderForm.jsx @@ -1,9 +1,11 @@ import PropTypes from 'prop-types'; import React from 'react'; +import { withTranslation } from 'react-i18next'; import { domOnlyProps } from '../../../utils/reduxFormUtils'; import Button from '../../../common/Button'; + class NewFolderForm extends React.Component { constructor(props) { super(props); @@ -35,13 +37,14 @@ class NewFolderForm extends React.Component { id="name" type="text" maxLength="128" - placeholder="Name" - ref={(element) => { - this.fileName = element; - }} + placeholder={this.props.t('NewFolderForm.Placeholder')} + ref={(element) => { this.fileName = element; }} {...domOnlyProps(name)} /> - +
{name.touched && name.error && ( {name.error} @@ -60,9 +63,10 @@ NewFolderForm.propTypes = { closeModal: PropTypes.func.isRequired, submitting: PropTypes.bool, pristine: PropTypes.bool, + t: PropTypes.func.isRequired }; NewFolderForm.defaultProps = { submitting: false, pristine: true, }; -export default NewFolderForm; +export default withTranslation()(NewFolderForm); diff --git a/client/modules/IDE/components/NewFolderModal.jsx b/client/modules/IDE/components/NewFolderModal.jsx index 13029d6c..bf897afa 100644 --- a/client/modules/IDE/components/NewFolderModal.jsx +++ b/client/modules/IDE/components/NewFolderModal.jsx @@ -1,6 +1,8 @@ import PropTypes from 'prop-types'; import React from 'react'; import { reduxForm } from 'redux-form'; +import { withTranslation } from 'react-i18next'; +import i18n from 'i18next'; import NewFolderForm from './NewFolderForm'; import ExitIcon from '../../../images/exit.svg'; @@ -15,11 +17,11 @@ class NewFolderModal extends React.Component {
{ this.newFolderModal = element; }} >
-

Create Folder

+

{this.props.t('NewFolderModal.Title')}

@@ -32,23 +34,24 @@ class NewFolderModal extends React.Component { } NewFolderModal.propTypes = { - closeModal: PropTypes.func.isRequired + closeModal: PropTypes.func.isRequired, + t: PropTypes.func.isRequired }; function validate(formProps) { const errors = {}; if (!formProps.name) { - errors.name = 'Please enter a name'; + errors.name = i18n.t('NewFolderModal.EnterName'); } else if (formProps.name.trim().length === 0) { - errors.name = 'Folder name cannot contain only spaces'; + errors.name = i18n.t('NewFolderModal.EmptyName'); } else if (formProps.name.match(/\.+/i)) { - errors.name = 'Folder name cannot contain an extension'; + errors.name = i18n.t('NewFolderModal.InvalidExtension'); } return errors; } -export default reduxForm({ +export default withTranslation()(reduxForm({ form: 'new-folder', fields: ['name'], validate -})(NewFolderModal); +})(NewFolderModal)); diff --git a/package-lock.json b/package-lock.json index 04592b99..8abec584 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "p5.js-web-editor", - "version": "1.0.6", + "version": "1.0.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ba2680a8..01f558f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "p5.js-web-editor", - "version": "1.0.6", + "version": "1.0.7", "description": "The web editor for p5.js.", "scripts": { "clean": "rimraf dist", diff --git a/server/controllers/project.controller.js b/server/controllers/project.controller.js index 7f118c23..2a83aa6a 100644 --- a/server/controllers/project.controller.js +++ b/server/controllers/project.controller.js @@ -30,14 +30,15 @@ export function updateProject(req, res) { $set: req.body }, { - new: true + new: true, + runValidators: true } ) .populate('user', 'username') .exec((updateProjectErr, updatedProject) => { if (updateProjectErr) { console.log(updateProjectErr); - res.json({ success: false }); + res.status(400).json({ success: false }); return; } if (req.body.files && updatedProject.files.length !== req.body.files.length) { @@ -50,7 +51,7 @@ export function updateProject(req, res) { updatedProject.save((innerErr, savedProject) => { if (innerErr) { console.log(innerErr); - res.json({ success: false }); + res.status(400).json({ success: false }); return; } res.json(savedProject); diff --git a/server/controllers/project.controller/createProject.js b/server/controllers/project.controller/createProject.js index e4040268..74529c0d 100644 --- a/server/controllers/project.controller/createProject.js +++ b/server/controllers/project.controller/createProject.js @@ -9,7 +9,7 @@ export default function createProject(req, res) { projectValues = Object.assign(projectValues, req.body); function sendFailure() { - res.json({ success: false }); + res.status(400).json({ success: false }); } function populateUserData(newProject) { diff --git a/server/models/project.js b/server/models/project.js index bf8c992e..3581e998 100644 --- a/server/models/project.js +++ b/server/models/project.js @@ -29,7 +29,7 @@ fileSchema.set('toJSON', { const projectSchema = new Schema( { - name: { type: String, default: "Hello p5.js, it's the server" }, + name: { type: String, default: "Hello p5.js, it's the server", maxlength: 128 }, user: { type: Schema.Types.ObjectId, ref: 'User' }, serveSecure: { type: Boolean, default: false }, files: { type: [fileSchema] }, diff --git a/translations/locales/en-US/translations.json b/translations/locales/en-US/translations.json index 56a898f5..d0868580 100644 --- a/translations/locales/en-US/translations.json +++ b/translations/locales/en-US/translations.json @@ -173,5 +173,26 @@ }, "IDEView": { "SubmitFeedback": "Submit Feedback" + }, + "NewFileModal": { + "Title": "Create File", + "CloseButtonARIA": "Close New File Modal", + "EnterName": "Please enter a name", + "InvalidType": "Invalid file type. Valid extensions are .js, .css, .json, .txt, .csv, .tsv, .frag, and .vert." + }, + "NewFileForm": { + "AddFileSubmit": "Add File", + "Placeholder": "Name" +}, + "NewFolderModal": { + "Title": "Create Folder", + "CloseButtonARIA": "Close New Folder Modal", + "EnterName": "Please enter a name", + "EmptyName": "Folder name cannot contain only spaces", + "InvalidExtension": "Folder name cannot contain an extension" + }, + "NewFolderForm": { + "AddFolderSubmit": "Add Folder", + "Placeholder": "Name" } } diff --git a/translations/locales/es-419/translations.json b/translations/locales/es-419/translations.json index 8b8d8f87..398da8dc 100644 --- a/translations/locales/es-419/translations.json +++ b/translations/locales/es-419/translations.json @@ -172,6 +172,27 @@ }, "IDEView": { "SubmitFeedback": "Enviar retroalimentación" + }, + "NewFileModal": { + "Title": "Crear Archivo", + "CloseButtonARIA": "Cerrar diálogo de crear archivo", + "EnterName": "Por favor introduce un nombre", + "InvalidType": "Tipo de archivo inválido. Las extensiones válidas son .js, .css, .json, .txt, .csv, .tsv, .frag y .vert." + }, + "NewFileForm": { + "AddFileSubmit": "Agregar Archivo", + "Placeholder": "Nombre" + }, + "NewFolderModal": { + "Title": "Crear Directorio", + "CloseButtonARIA": "Cerrar Diálogo de Nuevo Directorio", + "EnterName": "Por favor introduce un nombre", + "EmptyName": " El nombre del directorio no debe contener solo espacios vacíos", + "InvalidExtension": "El nombre del directorio no debe contener una extensión" +}, + "NewFolderForm": { + "AddFolderSubmit": "Agregar Directorio", + "Placeholder": "Nombre" } }