diff --git a/zubhub_frontend/zubhub/docker-compose.prod.yml b/zubhub_frontend/zubhub/docker-compose.prod.yml index e0c527af6..16bc8b02a 100644 --- a/zubhub_frontend/zubhub/docker-compose.prod.yml +++ b/zubhub_frontend/zubhub/docker-compose.prod.yml @@ -5,9 +5,15 @@ services: container_name: zubhub_frontend build: context: . +<<<<<<< HEAD + dockerfile: Dockerfile + volumes: + - ./nginx/default.conf:/etc/nginx/conf.d/default.conf +======= dockerfile: Dockerfile.prod volumes: - ./nginx/prod/default.conf:/etc/nginx/conf.d/default.conf +>>>>>>> e27329f26fe2cff77464c3965a2859d1d6c0b01f restart: on-failure ports: - "80" diff --git a/zubhub_frontend/zubhub/docker-compose.yml b/zubhub_frontend/zubhub/docker-compose.yml index 7db4ee546..a2dcab6a4 100644 --- a/zubhub_frontend/zubhub/docker-compose.yml +++ b/zubhub_frontend/zubhub/docker-compose.yml @@ -10,4 +10,8 @@ services: - ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf restart: on-failure ports: +<<<<<<< HEAD + - "80:80" +======= - "3000:3000" +>>>>>>> e27329f26fe2cff77464c3965a2859d1d6c0b01f diff --git a/zubhub_frontend/zubhub/package-lock.json b/zubhub_frontend/zubhub/package-lock.json index b1c50af10..20d60cf5d 100644 --- a/zubhub_frontend/zubhub/package-lock.json +++ b/zubhub_frontend/zubhub/package-lock.json @@ -3424,6 +3424,11 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "blueimp-canvas-to-blob": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.28.0.tgz", + "integrity": "sha512-5q+YHzgGsuHQ01iouGgJaPJXod2AzTxJXmVv90PpGrRxU7G7IqgPqWXz+PBmt3520jKKi6irWbNV87DicEa7wg==" + }, "bn.js": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", @@ -4175,6 +4180,15 @@ } } }, + "compressorjs": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/compressorjs/-/compressorjs-1.0.7.tgz", + "integrity": "sha512-ca+H8CGrn0LG103//VQmXBbNdvzvHiW26LGdWncp4RmLNbNQjaaFWIUxMN9++hbhGobLtofkHoxzzXGisNyD3w==", + "requires": { + "blueimp-canvas-to-blob": "^3.28.0", + "is-blob": "^2.1.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -7709,6 +7723,11 @@ "binary-extensions": "^2.0.0" } }, + "is-blob": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-blob/-/is-blob-2.1.0.tgz", + "integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==" + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -16428,6 +16447,14 @@ "microevent.ts": "~0.1.1" } }, + "workerize-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/workerize-loader/-/workerize-loader-1.3.0.tgz", + "integrity": "sha512-utWDc8K6embcICmRBUUkzanPgKBb8yM1OHfh6siZfiMsswE8wLCa9CWS+L7AARz0+Th4KH4ZySrqer/OJ9WuWw==", + "requires": { + "loader-utils": "^2.0.0" + } + }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", diff --git a/zubhub_frontend/zubhub/package.json b/zubhub_frontend/zubhub/package.json index c24a548ff..472e0d408 100644 --- a/zubhub_frontend/zubhub/package.json +++ b/zubhub_frontend/zubhub/package.json @@ -12,6 +12,7 @@ "@testing-library/user-event": "^12.2.2", "aws-sdk": "^2.813.0", "classnames": "^2.2.6", + "compressorjs": "^1.0.7", "date-fns": "^2.16.1", "formik": "^2.2.5", "nanoid": "^3.1.20", @@ -27,6 +28,7 @@ "redux-thunk": "^2.3.0", "slick-carousel": "^1.8.1", "web-vitals": "^0.2.4", + "workerize-loader": "^1.3.0", "yup": "^0.29.3" }, "scripts": { @@ -55,6 +57,6 @@ ] }, "devDependencies": { - "prettier": "2.2.1" + "prettier": "^2.2.1" } } diff --git a/zubhub_frontend/zubhub/src/assets/js/Compress.js b/zubhub_frontend/zubhub/src/assets/js/Compress.js new file mode 100644 index 000000000..f4aec897c --- /dev/null +++ b/zubhub_frontend/zubhub/src/assets/js/Compress.js @@ -0,0 +1,39 @@ +import Compressor from 'compressorjs'; + +const Compress = (images, state, handleSetState) => { + let compressed = []; + + for (let index = 0; index < images.length; index += 1) { + let image = images[index]; + + if (image && image.type.split('/')[1] !== 'gif') { + new Compressor(image, { + quality: 0.6, + convertSize: 100000, + success: result => { + compressed.push(result); + shouldSetImages(compressed, images, state, handleSetState); + }, + error: error => { + console.warn(error.message); + compressed.push(image); + shouldSetImages(compressed, images, state, handleSetState); + }, + }); + } else { + compressed.push(image); + shouldSetImages(compressed, images, state, handleSetState); + } + } +}; + +const shouldSetImages = (compressed, images, state, handleSetState) => { + if (compressed.length === images.length) { + const { image_upload } = state; + image_upload.images_to_upload = compressed; + + handleSetState(image_upload); + } +}; + +export default Compress; diff --git a/zubhub_frontend/zubhub/src/assets/js/removeMetaDataWorker.js b/zubhub_frontend/zubhub/src/assets/js/removeMetaDataWorker.js new file mode 100644 index 000000000..166abf3f2 --- /dev/null +++ b/zubhub_frontend/zubhub/src/assets/js/removeMetaDataWorker.js @@ -0,0 +1,62 @@ +export const removeMetaData = imageArr => { + let newImageArr = []; + + for (let index = 0; index < imageArr.length; index++) { + let fr = new FileReader(); + fr.onload = process; + fr.mainFile = imageArr[index]; + fr.readAsArrayBuffer(imageArr[index]); + } + + function process() { + let dv = new DataView(this.result); + let offset = 0, + recess = 0; + let pieces = []; + let i = 0; + if (dv.getUint16(offset) === 0xffd8) { + offset += 2; + let app1 = dv.getUint16(offset); + offset += 2; + while (offset < dv.byteLength) { + if (app1 === 0xffe1) { + pieces[i] = { recess: recess, offset: offset - 2 }; + recess = offset + dv.getUint16(offset); + i++; + } else if (app1 === 0xffda) { + break; + } + offset += dv.getUint16(offset); + app1 = dv.getUint16(offset); + offset += 2; + } + + if (pieces.length > 0) { + let newPieces = []; + pieces.forEach(function (v) { + newPieces.push(this.result.slice(v.recess, v.offset)); + }, this); + newPieces.push(this.result.slice(recess)); + newImageArr.push( + new Blob(newPieces, { type: imageArr[newImageArr.length].type }), + ); + + if (newImageArr.length === imageArr.length) { + postMessage(newImageArr); + } + } else { + newImageArr.push(this.mainFile); + + if (newImageArr.length === imageArr.length) { + postMessage(newImageArr); + } + } + } else { + newImageArr.push(this.mainFile); + + if (newImageArr.length === imageArr.length) { + postMessage(newImageArr); + } + } + } +}; diff --git a/zubhub_frontend/zubhub/src/assets/js/styles/views/signup/signupStyles.js b/zubhub_frontend/zubhub/src/assets/js/styles/views/signup/signupStyles.js index 751895f43..6b0e75171 100644 --- a/zubhub_frontend/zubhub/src/assets/js/styles/views/signup/signupStyles.js +++ b/zubhub_frontend/zubhub/src/assets/js/styles/views/signup/signupStyles.js @@ -42,6 +42,11 @@ const styles = theme => ({ }, }, }, + DOBInputStyle: { + '&.MuiOutlinedInput-root fieldset legend': { + width: '75.5px !important', + }, + }, secondaryLink: { color: '#00B8C4', '&:hover': { diff --git a/zubhub_frontend/zubhub/src/store/actions/authActions.js b/zubhub_frontend/zubhub/src/store/actions/authActions.js index 877810508..e391e3c76 100644 --- a/zubhub_frontend/zubhub/src/store/actions/authActions.js +++ b/zubhub_frontend/zubhub/src/store/actions/authActions.js @@ -17,27 +17,14 @@ export const login = props => { return API.login(props.values) .then(res => { if (!res.key) { - res = Object.keys(res) - .map(key => res[key]) - .join('\n'); - throw new Error(res); + throw new Error(JSON.stringify(res)); } dispatch({ type: 'SET_AUTH_USER', payload: { token: res.key }, }); }) - .then(() => props.history.push('/profile')) - .catch(error => { - if (error.message.startsWith('Unexpected')) { - return { - error: - 'An error occured while performing this action. Please try again later', - }; - } else { - return { error: error.message }; - } - }); + .then(() => props.history.push('/profile')); }; }; @@ -85,95 +72,61 @@ export const signup = props => { return API.signup(props.values) .then(res => { if (!res.key) { - res = Object.keys(res) - .map(key => res[key]) - .join('\n'); - throw new Error(res); + throw new Error(JSON.stringify(res)); } dispatch({ type: 'SET_AUTH_USER', payload: { token: res.key }, }); }) - .then(() => props.history.push('/profile')) - .catch(error => { - if (error.message.startsWith('Unexpected')) { - return { - error: - 'An error occured while performing this action. Please try again later', - }; - } else { - return { error: error.message }; - } - }); + .then(() => props.history.push('/profile')); }; }; export const send_email_confirmation = (props, key) => { return () => { - return API.send_email_confirmation(key) - .then(res => { + return API.send_email_confirmation(key).then(res => { + if (res.detail !== 'ok') { + throw new Error(res.detail); + } else { toast.success('Congratulations!, your email has been confirmed!'); setTimeout(() => { props.history.push('/'); }, 4000); - }) - .catch(error => { - if (error.message.startsWith('Unexpected')) { - return { - error: - 'An error occured while performing this action. Please try again later', - }; - } else { - return { error: error.message }; - } - }); + } + }); }; }; export const send_password_reset_link = props => { return () => { - return API.send_password_reset_link(props.values.email) - .then(res => { + return API.send_password_reset_link(props.values.email).then(res => { + if (res.detail !== 'Password reset e-mail has been sent.') { + throw new Error(JSON.stringify(res)); + } else { toast.success('We just sent a password reset link to your email!'); setTimeout(() => { props.history.push('/'); }, 4000); - }) - .catch(error => { - if (error.message.startsWith('Unexpected')) { - return { - error: - 'An error occured while performing this action. Please try again later', - }; - } else { - return { error: error.message }; - } - }); + } + }); }; }; export const password_reset_confirm = props => { return () => { - return API.password_reset_confirm(props) - .then(res => { + return API.password_reset_confirm(props).then(res => { + if (res.detail !== 'Password has been reset with the new password.') { + throw new Error(JSON.stringify(res)); + } else { toast.success( 'Congratulations! your password reset was successful! you will now be redirected to login', ); setTimeout(() => { props.history.push('/login'); }, 4000); - }) - .catch(error => { - if (error.message.startsWith('Unexpected')) { - return { - error: - 'An error occured while performing this action. Please try again later', - }; - } else { - return { error: error.message }; - } - }); + } + }); }; }; diff --git a/zubhub_frontend/zubhub/src/store/actions/projectActions.js b/zubhub_frontend/zubhub/src/store/actions/projectActions.js index 2254c7a7b..e7d3176f4 100644 --- a/zubhub_frontend/zubhub/src/store/actions/projectActions.js +++ b/zubhub_frontend/zubhub/src/store/actions/projectActions.js @@ -13,28 +13,14 @@ export const set_projects = projects => { export const create_project = props => { return dispatch => { - return API.create_project(props) - .then(res => { - if (!res.comments) { - res = Object.keys(res) - .map(key => res[key]) - .join('\n'); - throw new Error(res); - } else { - toast.success('Your project was created successfully!!'); - return props.history.push('/profile'); - } - }) - .catch(error => { - if (error.message.startsWith('Unexpected')) { - return { - error: - 'An error occured while performing this action. Please try again later', - }; - } else { - return { error: error.message }; - } - }); + return API.create_project(props).then(res => { + if (!res.id) { + throw new Error(JSON.stringify(res)); + } else { + toast.success('Your project was created successfully!!'); + return props.history.push('/profile'); + } + }); }; }; diff --git a/zubhub_frontend/zubhub/src/views/PageWrapper.jsx b/zubhub_frontend/zubhub/src/views/PageWrapper.jsx index d090c93c9..75cbe3c5e 100644 --- a/zubhub_frontend/zubhub/src/views/PageWrapper.jsx +++ b/zubhub_frontend/zubhub/src/views/PageWrapper.jsx @@ -170,6 +170,48 @@ function PageWrapper(props) { + + + + Projects + + + + + + + Followers + + + + + + + Following + + + { - props.setFieldValue(e.currentTarget.name, refs.imageEl.current); +const handleImageFieldChange = (refs, props, state, handleSetState) => { refs.imageCountEl.current.innerText = refs.imageEl.current.files.length; refs.imageCountEl.current.style.fontSize = '0.8rem'; + + props.setFieldValue('project_images', refs.imageEl.current).then(errors => { + if (!errors['project_images']) { + removeMetaData(refs.imageEl.current.files, state, handleSetState); + } + }); +}; + +const removeMetaData = (images, state, handleSetState) => { + const newWorker = worker(); + newWorker.removeMetaData(images); + newWorker.addEventListener('message', e => { + Compress(e.data, state, handleSetState); + }); }; const handleImageButtonClick = (e, props, refs) => { @@ -117,7 +132,7 @@ function CreateProject(props) { useStateUpdateCallback(() => { if ( - state.image_upload.images_to_upload === + state.image_upload.images_to_upload.length === state.image_upload.successful_uploads ) { handleSetState(upload_project()); @@ -213,12 +228,33 @@ function CreateProject(props) { const { image_upload } = state; image_upload.upload_dialog = false; handleSetState({ image_upload }); - return props.create_project({ - ...props.values, - token: props.auth.token, - images: state.image_upload.uploaded_images_url, - video: props.values.video ? props.values.video : '', - }); + return props + .create_project({ + ...props.values, + token: props.auth.token, + images: state.image_upload.uploaded_images_url, + video: props.values.video ? props.values.video : '', + }) + .catch(error => { + const messages = JSON.parse(error.message); + if (typeof messages === 'object') { + let non_field_errors; + Object.keys(messages).forEach(key => { + if (key === 'non_field_errors') { + non_field_errors = { error: messages[key][0] }; + } else { + props.setFieldTouched(key, true, false); + props.setFieldError(key, messages[key][0]); + } + }); + if (non_field_errors) return non_field_errors; + } else { + return { + error: + 'An error occured while performing this action. Please try again later', + }; + } + }); }; const init_project = e => { @@ -231,35 +267,30 @@ function CreateProject(props) { props.setFieldTouched('project_images'); props.setFieldTouched('video'); props.setFieldTouched('materials_used'); - props.validateField('title'); - props.validateField('description'); - props.validateField('project_images'); - props.validateField('video'); - props.validateField('materials_used'); - - if ( - props.errors['title'] || - props.errors['description'] || - props.errors['project_images'] || - props.errors['video'] || - props.errors['materials_used'] - ) { - return; - } else if (refs.imageEl.current.files.length === 0) { - handleSetState(upload_project()); - } else { - const project_images = refs.imageEl.current.files; - const { image_upload } = state; - image_upload.images_to_upload = project_images.length; - image_upload.upload_dialog = true; - image_upload.upload_percent = 0; - handleSetState({ image_upload }); + image_field_touched = true; + video_field_touched = true; + + props.validateForm().then(errors => { + if (Object.keys(errors).length > 0) { + return; + } else if (refs.imageEl.current.files.length === 0) { + handleSetState(upload_project()); + } else { + const { image_upload } = state; + image_upload.upload_dialog = true; + image_upload.upload_percent = 0; + handleSetState({ image_upload }); - for (let index = 0; index < project_images.length; index++) { - upload(project_images[index]); + for ( + let index = 0; + index < image_upload.images_to_upload.length; + index++ + ) { + upload(image_upload.images_to_upload[index]); + } } - } + }); } }; @@ -378,6 +409,17 @@ function CreateProject(props) { labelWidth={90} /> + + Tell us something interesting about the project! You + can share what it is about, what inspired you to + make it, your making process, fun and challenging + moments you experienced, etc. + +
{props.touched['description'] && props.errors['description']}
@@ -425,7 +467,14 @@ function CreateProject(props) { id="project_images" name="project_images" multiple - onChange={e => handleImageFieldChange(e, refs, props)} + onChange={e => + handleImageFieldChange( + refs, + props, + state, + handleSetState, + ) + } onBlur={props.handleBlur} /> @@ -460,6 +509,14 @@ function CreateProject(props) { labelWidth={90} /> + + YouTube, Vimeo, Google Drive links are supported + +
{props.touched['video'] && props.errors['video']}
@@ -668,6 +725,19 @@ export default connect( : true; }, ) + .test('not_an_image', 'only images are allowed', value => { + if (value) { + let not_an_image = false; + for (let index = 0; index < value.files.length; index++) { + if (value.files[index].type.split('/')[0] !== 'image') { + not_an_image = true; + } + } + return not_an_image ? false : true; + } else { + return true; + } + }) .test('too_many_images', 'too many images uploaded', value => { if (value) { return value.files.length > 10 ? false : true; @@ -677,12 +747,12 @@ export default connect( }) .test( 'image_size_too_large', - 'one or more of your image is greater than 3mb', + 'one or more of your image is greater than 10mb', value => { if (value) { let image_size_too_large = false; for (let index = 0; index < value.files.length; index++) { - if (value.files[index].size / 1000 > 3072) { + if (value.files[index].size / 1000 > 10240) { image_size_too_large = true; } } diff --git a/zubhub_frontend/zubhub/src/views/email_confirm/EmailConfirm.jsx b/zubhub_frontend/zubhub/src/views/email_confirm/EmailConfirm.jsx index f5d22e46b..c67fd2e06 100644 --- a/zubhub_frontend/zubhub/src/views/email_confirm/EmailConfirm.jsx +++ b/zubhub_frontend/zubhub/src/views/email_confirm/EmailConfirm.jsx @@ -31,7 +31,16 @@ const getUsernameAndKey = queryString => { const confirmEmail = (e, props, state) => { e.preventDefault(); - return props.send_email_confirmation(props, state.key); + return props.send_email_confirmation(props, state.key).catch(error => { + if (error.message.startsWith('Unexpected')) { + return { + error: + 'An error occured while performing this action. Please try again later', + }; + } else { + return { error: error.message }; + } + }); }; function EmailConfirm(props) { diff --git a/zubhub_frontend/zubhub/src/views/login/Login.jsx b/zubhub_frontend/zubhub/src/views/login/Login.jsx index 9cc98a2de..5bb75a3ca 100644 --- a/zubhub_frontend/zubhub/src/views/login/Login.jsx +++ b/zubhub_frontend/zubhub/src/views/login/Login.jsx @@ -45,7 +45,26 @@ const handleMouseDownPassword = e => { const login = (e, props) => { e.preventDefault(); - return props.login(props); + return props.login(props).catch(error => { + const messages = JSON.parse(error.message); + if (typeof messages === 'object') { + let non_field_errors; + Object.keys(messages).forEach(key => { + if (key === 'non_field_errors') { + non_field_errors = { error: messages[key][0] }; + } else { + props.setFieldTouched(key, true, false); + props.setFieldError(key, messages[key][0]); + } + }); + return non_field_errors; + } else { + return { + error: + 'An error occured while performing this action. Please try again later', + }; + } + }); }; function Login(props) { diff --git a/zubhub_frontend/zubhub/src/views/password_reset/PasswordReset.jsx b/zubhub_frontend/zubhub/src/views/password_reset/PasswordReset.jsx index 5156b237f..cf1ff7ba3 100644 --- a/zubhub_frontend/zubhub/src/views/password_reset/PasswordReset.jsx +++ b/zubhub_frontend/zubhub/src/views/password_reset/PasswordReset.jsx @@ -30,7 +30,26 @@ const useStyles = makeStyles(styles); const sendPasswordResetLink = (e, props) => { e.preventDefault(); - return props.send_password_reset_link(props); + return props.send_password_reset_link(props).catch(error => { + const messages = JSON.parse(error.message); + let non_field_errors; + if (typeof messages === 'object') { + Object.keys(messages).forEach(key => { + if (key !== 'email') { + non_field_errors = { error: messages[key][0] }; + } else { + props.setFieldTouched(key, true, false); + props.setFieldError(key, messages[key][0]); + } + }); + return non_field_errors; + } else { + return { + error: + 'An error occured while performing this action. Please try again later', + }; + } + }); }; function PasswordReset(props) { diff --git a/zubhub_frontend/zubhub/src/views/password_reset_confirm/PasswordResetConfirm.jsx b/zubhub_frontend/zubhub/src/views/password_reset_confirm/PasswordResetConfirm.jsx index 1f510d032..b87775979 100644 --- a/zubhub_frontend/zubhub/src/views/password_reset_confirm/PasswordResetConfirm.jsx +++ b/zubhub_frontend/zubhub/src/views/password_reset_confirm/PasswordResetConfirm.jsx @@ -44,7 +44,28 @@ const getUidAndToken = queryString => { const resetPassword = (e, props) => { e.preventDefault(); const { uid, token } = getUidAndToken(props.location.search); - return props.password_reset_confirm({ ...props.values, uid, token }); + return props + .password_reset_confirm({ ...props.values, uid, token }) + .catch(error => { + const messages = JSON.parse(error.message); + if (typeof messages === 'object') { + let non_field_errors; + Object.keys(messages).forEach(key => { + if (key !== 'new_password1' && key !== 'new_password2') { + non_field_errors = { error: messages[key][0] }; + } else { + props.setFieldTouched(key, true, false); + props.setFieldError(key, messages[key][0]); + } + }); + return non_field_errors; + } else { + return { + error: + 'An error occured while performing this action. Please try again later', + }; + } + }); }; const handleClickShowPassword = (field, state) => { diff --git a/zubhub_frontend/zubhub/src/views/profile/Profile.jsx b/zubhub_frontend/zubhub/src/views/profile/Profile.jsx index bbfa64ad3..23feb32f4 100644 --- a/zubhub_frontend/zubhub/src/views/profile/Profile.jsx +++ b/zubhub_frontend/zubhub/src/views/profile/Profile.jsx @@ -64,9 +64,16 @@ const updateProfile = (e, props, state, newUserNameEL) => { username: username.value, }) .then(res => { + if (!res.id) { + res = Object.keys(res) + .map(key => res[key]) + .join('\n'); + throw new Error(res); + } username.value = ''; return { ...res, ...handleToggleEditProfileModal(state) }; - }); + }) + .catch(error => ({ dialogError: error.message })); } else { return handleToggleEditProfileModal(state); } @@ -128,6 +135,7 @@ function Profile(props) { openEditProfileModal: false, loading: true, profile: {}, + dialogError: null, }); React.useEffect(() => { @@ -142,7 +150,13 @@ function Profile(props) { } }; - const { results: projects, profile, loading, openEditProfileModal } = state; + const { + results: projects, + profile, + loading, + openEditProfileModal, + dialogError, + } = state; if (loading) { return ; @@ -327,6 +341,16 @@ function Profile(props) { aria-labelledby="edit user profile" > Edit User Profile + + {dialogError !== null && ( + + {dialogError} + + )} + {' '} { if (props.values.location.length < 1) { props.validateField('location'); } else { - return props.signup(props); + return props.signup(props).catch(error => { + const messages = JSON.parse(error.message); + if (typeof messages === 'object') { + let non_field_errors; + Object.keys(messages).forEach(key => { + if (key === 'non_field_errors') { + non_field_errors = { error: messages[key][0] }; + } else if (key === 'location') { + props.setFieldTouched('user_location', true, false); + props.setFieldError('user_location', messages[key][0]); + } else { + props.setFieldTouched(key, true, false); + props.setFieldError(key, messages[key][0]); + } + }); + return non_field_errors; + } else { + return { + error: + 'An error occured while performing this action. Please try again later', + }; + } + }); } }; @@ -228,7 +250,10 @@ function Signup(props) { Date Of Birth