diff --git a/client/modules/IDE/actions/files.js b/client/modules/IDE/actions/files.js
index c8a656c83c..faf3e18134 100644
--- a/client/modules/IDE/actions/files.js
+++ b/client/modules/IDE/actions/files.js
@@ -1,10 +1,10 @@
import objectID from 'bson-objectid';
import blobUtil from 'blob-util';
-import { reset } from 'redux-form';
import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
import { setUnsavedChanges, closeNewFolderModal, closeNewFileModal } from './ide';
import { setProjectSavedTime } from './project';
+import { createError } from './ide';
function appendToFilename(filename, string) {
@@ -36,106 +36,117 @@ export function updateFileContent(id, content) {
};
}
-export function createFile(formProps) {
+export function createFile(file, parentId) {
+ return {
+ type: ActionTypes.CREATE_FILE,
+ ...file,
+ parentId
+ };
+}
+
+export function submitFile(formProps, files, parentId, projectId) {
+ if (projectId) {
+ const postParams = {
+ name: createUniqueName(formProps.name, parentId, files),
+ url: formProps.url,
+ content: formProps.content || '',
+ parentId,
+ children: []
+ };
+ return apiClient.post(`/projects/${projectId}/files`, postParams)
+ .then(response => ({
+ file: response.data.updatedFile,
+ updatedAt: response.data.project.updatedAt
+ }));
+ }
+ const id = objectID().toHexString();
+ const file = {
+ name: createUniqueName(formProps.name, parentId, files),
+ id,
+ _id: id,
+ url: formProps.url,
+ content: formProps.content || '',
+ children: []
+ };
+ return Promise.resolve({
+ file
+ });
+}
+
+export function handleCreateFile(formProps) {
return (dispatch, getState) => {
const state = getState();
+ const { files } = state;
const { parentId } = state.ide;
- if (state.project.id) {
- const postParams = {
- name: createUniqueName(formProps.name, parentId, state.files),
- url: formProps.url,
- content: formProps.content || '',
- parentId,
- children: []
- };
- apiClient.post(`/projects/${state.project.id}/files`, postParams)
- .then((response) => {
- dispatch({
- type: ActionTypes.CREATE_FILE,
- ...response.data.updatedFile,
- parentId
- });
- dispatch(setProjectSavedTime(response.data.project.updatedAt));
- dispatch(closeNewFileModal());
- dispatch(reset('new-file'));
- // dispatch({
- // type: ActionTypes.HIDE_MODAL
- // });
- dispatch(setUnsavedChanges(true));
- })
- .catch((error) => {
- const { response } = error;
- dispatch({
- type: ActionTypes.ERROR,
- error: response.data
- });
- });
- } else {
- const id = objectID().toHexString();
- dispatch({
- type: ActionTypes.CREATE_FILE,
- name: createUniqueName(formProps.name, parentId, state.files),
- id,
- _id: id,
- url: formProps.url,
- content: formProps.content || '',
- parentId,
- children: []
+ const projectId = state.project.id;
+ return new Promise((resolve) => {
+ submitFile(formProps, files, parentId, projectId).then((response) => {
+ const { file, updatedAt } = response;
+ dispatch(createFile(file, parentId));
+ if (updatedAt) dispatch(setProjectSavedTime(updatedAt));
+ dispatch(closeNewFileModal());
+ dispatch(setUnsavedChanges(true));
+ resolve();
+ }).catch((error) => {
+ const { response } = error;
+ dispatch(createError(response.data));
+ resolve({ error });
});
- dispatch(reset('new-file'));
- // dispatch({
- // type: ActionTypes.HIDE_MODAL
- // });
- dispatch(setUnsavedChanges(true));
- dispatch(closeNewFileModal());
- }
+ });
+ };
+}
+
+export function submitFolder(formProps, files, parentId, projectId) {
+ if (projectId) {
+ const postParams = {
+ name: createUniqueName(formProps.name, parentId, files),
+ content: '',
+ children: [],
+ parentId,
+ fileType: 'folder'
+ };
+ return apiClient.post(`/projects/${projectId}/files`, postParams)
+ .then(response => ({
+ file: response.data.updatedFile,
+ updatedAt: response.data.project.updatedAt
+ }));
+ }
+ const id = objectID().toHexString();
+ const file = {
+ type: ActionTypes.CREATE_FILE,
+ name: createUniqueName(formProps.name, parentId, files),
+ id,
+ _id: id,
+ content: '',
+ // TODO pass parent id from File Tree
+ fileType: 'folder',
+ children: []
};
+ return Promise.resolve({
+ file
+ });
}
-export function createFolder(formProps) {
+export function handleCreateFolder(formProps) {
return (dispatch, getState) => {
const state = getState();
+ const { files } = state;
const { parentId } = state.ide;
- if (state.project.id) {
- const postParams = {
- name: createUniqueName(formProps.name, parentId, state.files),
- content: '',
- children: [],
- parentId,
- fileType: 'folder'
- };
- apiClient.post(`/projects/${state.project.id}/files`, postParams)
- .then((response) => {
- dispatch({
- type: ActionTypes.CREATE_FILE,
- ...response.data.updatedFile,
- parentId
- });
- dispatch(setProjectSavedTime(response.data.project.updatedAt));
- dispatch(closeNewFolderModal());
- })
- .catch((error) => {
- const { response } = error;
- dispatch({
- type: ActionTypes.ERROR,
- error: response.data
- });
- });
- } else {
- const id = objectID().toHexString();
- dispatch({
- type: ActionTypes.CREATE_FILE,
- name: createUniqueName(formProps.name, parentId, state.files),
- id,
- _id: id,
- content: '',
- // TODO pass parent id from File Tree
- parentId,
- fileType: 'folder',
- children: []
+ const projectId = state.project.id;
+ return new Promise((resolve) => {
+ submitFolder(formProps, files, parentId, projectId).then((response) => {
+ const { file, updatedAt } = response;
+ dispatch(createFile(file, parentId));
+ if (updatedAt) dispatch(setProjectSavedTime(updatedAt));
+ dispatch(closeNewFolderModal());
+ dispatch(setUnsavedChanges(true));
+ resolve();
+ }).catch((error) => {
+ const { response } = error;
+ dispatch(createError(response.data));
+ resolve({ error });
});
- dispatch(closeNewFolderModal());
- }
+ });
};
}
diff --git a/client/modules/IDE/actions/ide.js b/client/modules/IDE/actions/ide.js
index 239dc6c757..e18d9d747c 100644
--- a/client/modules/IDE/actions/ide.js
+++ b/client/modules/IDE/actions/ide.js
@@ -278,3 +278,10 @@ export function stopSketch() {
dispatch(stopVisualSketch());
};
}
+
+export function createError(error) {
+ return {
+ type: ActionTypes.ERROR,
+ error
+ };
+}
diff --git a/client/modules/IDE/components/NewFileForm.jsx b/client/modules/IDE/components/NewFileForm.jsx
index 712520dd53..abc48ecf88 100644
--- a/client/modules/IDE/components/NewFileForm.jsx
+++ b/client/modules/IDE/components/NewFileForm.jsx
@@ -1,69 +1,82 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import { withTranslation } from 'react-i18next';
-import { domOnlyProps } from '../../../utils/reduxFormUtils';
+import React, { useEffect, useRef } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Form, Field } from 'react-final-form';
+import { useDispatch } from 'react-redux';
+import { handleCreateFile } from '../actions/files';
+import { CREATE_FILE_REGEX } from '../../../../server/utils/fileUtils';
import Button from '../../../common/Button';
-class NewFileForm extends React.Component {
- constructor(props) {
- super(props);
- this.createFile = this.props.createFile.bind(this);
- }
+function NewFileForm() {
+ const fileNameInput = useRef(null);
+ const { t } = useTranslation();
+ const dispatch = useDispatch();
- componentDidMount() {
- this.fileName.focus();
+ function onSubmit(formProps) {
+ return dispatch(handleCreateFile(formProps));
}
- render() {
- const {
- fields: { name },
- handleSubmit,
- } = this.props;
- return (
-
- );
+ function validate(formProps) {
+ const errors = {};
+
+ if (!formProps.name) {
+ errors.name = t('NewFileModal.EnterName');
+ } else if (!formProps.name.match(CREATE_FILE_REGEX)) {
+ errors.name = t('NewFileModal.InvalidType');
+ }
+
+ return errors;
}
-}
-NewFileForm.propTypes = {
- fields: PropTypes.shape({
- name: PropTypes.objectOf(PropTypes.shape()).isRequired
- }).isRequired,
- handleSubmit: PropTypes.func.isRequired,
- createFile: PropTypes.func.isRequired,
- focusOnModal: PropTypes.func.isRequired,
- t: PropTypes.func.isRequired
-};
+ useEffect(() => {
+ fileNameInput.current.focus();
+ });
+
+ return (
+
+ )}
+
+ );
+}
-export default withTranslation()(NewFileForm);
+export default NewFileForm;
diff --git a/client/modules/IDE/components/NewFileModal.jsx b/client/modules/IDE/components/NewFileModal.jsx
index 3cb9904df3..c140244d57 100644
--- a/client/modules/IDE/components/NewFileModal.jsx
+++ b/client/modules/IDE/components/NewFileModal.jsx
@@ -1,15 +1,10 @@
import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
-import { bindActionCreators, compose } from 'redux';
-import { reduxForm } from 'redux-form';
+import { bindActionCreators } from 'redux';
import { withTranslation } from 'react-i18next';
-import i18n from 'i18next';
import NewFileForm from './NewFileForm';
import { closeNewFileModal } from '../actions/ide';
-import { createFile } from '../actions/files';
-import { CREATE_FILE_REGEX } from '../../../../server/utils/fileUtils';
-
import ExitIcon from '../../../images/exit.svg';
@@ -59,7 +54,6 @@ class NewFileModal extends React.Component {
@@ -68,36 +62,16 @@ class NewFileModal extends React.Component {
}
NewFileModal.propTypes = {
- createFile: PropTypes.func.isRequired,
closeNewFileModal: PropTypes.func.isRequired,
t: PropTypes.func.isRequired
};
-function validate(formProps) {
- const errors = {};
-
- if (!formProps.name) {
- errors.name = i18n.t('NewFileModal.EnterName');
- } else if (!formProps.name.match(CREATE_FILE_REGEX)) {
- errors.name = i18n.t('NewFileModal.InvalidType');
- }
-
- return errors;
-}
-
function mapStateToProps() {
return {};
}
function mapDispatchToProps(dispatch) {
- return bindActionCreators({ createFile, closeNewFileModal }, dispatch);
+ return bindActionCreators({ closeNewFileModal }, dispatch);
}
-export default withTranslation()(compose(
- connect(mapStateToProps, mapDispatchToProps),
- reduxForm({
- form: 'new-file',
- fields: ['name'],
- validate
- })
-)(NewFileModal));
+export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(NewFileModal));
diff --git a/client/modules/IDE/components/NewFolderForm.jsx b/client/modules/IDE/components/NewFolderForm.jsx
index cc602489c6..44c272f237 100644
--- a/client/modules/IDE/components/NewFolderForm.jsx
+++ b/client/modules/IDE/components/NewFolderForm.jsx
@@ -1,72 +1,80 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import { withTranslation } from 'react-i18next';
-import { domOnlyProps } from '../../../utils/reduxFormUtils';
-
+import React, { useRef, useEffect } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Form, Field } from 'react-final-form';
+import { useDispatch } from 'react-redux';
import Button from '../../../common/Button';
+import { handleCreateFolder } from '../actions/files';
+function NewFolderForm() {
+ const folderNameInput = useRef(null);
+ useEffect(() => {
+ folderNameInput.current.focus();
+ });
+ const { t } = useTranslation();
+ const dispatch = useDispatch();
-class NewFolderForm extends React.Component {
- constructor(props) {
- super(props);
- this.createFolder = this.props.createFolder.bind(this);
+ function validate(formProps) {
+ const errors = {};
+ if (!formProps.name) {
+ errors.name = t('NewFolderModal.EnterName');
+ } else if (formProps.name.trim().length === 0) {
+ errors.name = t('NewFolderModal.EmptyName');
+ } else if (formProps.name.match(/\.+/i)) {
+ errors.name = t('NewFolderModal.InvalidExtension');
+ }
+ return errors;
}
- componentDidMount() {
- this.fileName.focus();
+ function onSubmit(formProps) {
+ return dispatch(handleCreateFolder(formProps));
}
- render() {
- const {
- fields: { name },
- handleSubmit,
- } = this.props;
- return (
-
- );
- }
+ return (
+
+
+ )}
+
+ );
}
-NewFolderForm.propTypes = {
- fields: PropTypes.shape({
- name: PropTypes.objectOf(PropTypes.shape()).isRequired
- }).isRequired,
- handleSubmit: PropTypes.func.isRequired,
- createFolder: PropTypes.func.isRequired,
- closeModal: PropTypes.func.isRequired,
- submitting: PropTypes.bool,
- pristine: PropTypes.bool,
- t: PropTypes.func.isRequired
-};
-NewFolderForm.defaultProps = {
- submitting: false,
- pristine: true,
-};
-export default withTranslation()(NewFolderForm);
+export default NewFolderForm;
diff --git a/client/modules/IDE/components/NewFolderModal.jsx b/client/modules/IDE/components/NewFolderModal.jsx
index fce0ba50c2..ab66b2f1ae 100644
--- a/client/modules/IDE/components/NewFolderModal.jsx
+++ b/client/modules/IDE/components/NewFolderModal.jsx
@@ -1,10 +1,7 @@
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';
class NewFolderModal extends React.Component {
@@ -43,7 +40,7 @@ class NewFolderModal extends React.Component {
-
+
);
@@ -55,20 +52,4 @@ NewFolderModal.propTypes = {
t: PropTypes.func.isRequired
};
-function validate(formProps) {
- const errors = {};
- if (!formProps.name) {
- errors.name = i18n.t('NewFolderModal.EnterName');
- } else if (formProps.name.trim().length === 0) {
- errors.name = i18n.t('NewFolderModal.EmptyName');
- } else if (formProps.name.match(/\.+/i)) {
- errors.name = i18n.t('NewFolderModal.InvalidExtension');
- }
-
- return errors;
-}
-export default withTranslation()(reduxForm({
- form: 'new-folder',
- fields: ['name'],
- validate
-})(NewFolderModal));
+export default withTranslation()(NewFolderModal);
diff --git a/client/modules/User/actions.js b/client/modules/User/actions.js
index 0ce673acae..363a4e4d90 100644
--- a/client/modules/User/actions.js
+++ b/client/modules/User/actions.js
@@ -12,22 +12,8 @@ export function authError(error) {
};
}
-export function signUpUser(previousPath, formValues) {
- return (dispatch) => {
- apiClient.post('/signup', formValues)
- .then((response) => {
- dispatch({
- type: ActionTypes.AUTH_USER,
- user: response.data
- });
- dispatch(justOpenedProject());
- browserHistory.push(previousPath);
- })
- .catch((error) => {
- const { response } = error;
- dispatch(authError(response.data.error));
- });
- };
+export function signUpUser(formValues) {
+ return apiClient.post('/signup', formValues);
}
export function loginUser(formValues) {
@@ -41,6 +27,13 @@ export function loginUserSuccess(user) {
};
}
+export function authenticateUser(user) {
+ return {
+ type: ActionTypes.AUTH_USER,
+ user
+ };
+}
+
export function loginUserFailure(error) {
return {
type: ActionTypes.AUTH_ERROR,
@@ -48,26 +41,52 @@ export function loginUserFailure(error) {
};
}
-export function validateAndLoginUser(previousPath, formProps, dispatch) {
- return new Promise((resolve, reject) => {
- loginUser(formProps)
- .then((response) => {
- dispatch({
- type: ActionTypes.AUTH_USER,
- user: response.data
- });
- dispatch({
- type: ActionTypes.SET_PREFERENCES,
- preferences: response.data.preferences
+export function setPreferences(preferences) {
+ return {
+ type: ActionTypes.SET_PREFERENCES,
+ preferences
+ };
+}
+
+export function validateAndLoginUser(formProps) {
+ return (dispatch, getState) => {
+ const state = getState();
+ const { previousPath } = state.ide;
+ return new Promise((resolve) => {
+ loginUser(formProps)
+ .then((response) => {
+ dispatch(loginUserSuccess(response.data));
+ dispatch(setPreferences(response.data.preferences));
+ dispatch(setLanguage(response.data.preferences.language, { persistPreference: false }));
+ dispatch(justOpenedProject());
+ browserHistory.push(previousPath);
+ resolve();
+ })
+ .catch(error =>
+ resolve({ password: error.response.data.message, _error: 'Login failed!' }));
+ });
+ };
+}
+
+export function validateAndSignUpUser(formValues) {
+ return (dispatch, getState) => {
+ const state = getState();
+ const { previousPath } = state.ide;
+ return new Promise((resolve) => {
+ signUpUser(formValues)
+ .then((response) => {
+ dispatch(authenticateUser(response.data));
+ dispatch(justOpenedProject());
+ browserHistory.push(previousPath);
+ resolve();
+ })
+ .catch((error) => {
+ const { response } = error;
+ dispatch(authError(response.data.error));
+ resolve({ error });
});
- setLanguage(response.data.preferences.language, { persistPreference: false });
- dispatch(justOpenedProject());
- browserHistory.push(previousPath);
- resolve();
- })
- .catch(error =>
- reject({ password: error.response.data.message, _error: 'Login failed!' })); // eslint-disable-line
- });
+ });
+ };
}
export function getUser() {
@@ -125,22 +144,21 @@ export function logoutUser() {
}
export function initiateResetPassword(formValues) {
- return (dispatch) => {
+ return dispatch => new Promise((resolve) => {
dispatch({
type: ActionTypes.RESET_PASSWORD_INITIATE
});
- apiClient.post('/reset-password', formValues)
- .then(() => {
- // do nothing
- })
+ return apiClient.post('/reset-password', formValues)
+ .then(() => resolve())
.catch((error) => {
const { response } = error;
dispatch({
type: ActionTypes.ERROR,
message: response.data
});
+ resolve({ error });
});
- };
+ });
}
export function initiateVerification() {
@@ -202,17 +220,20 @@ export function validateResetPasswordToken(token) {
};
}
-export function updatePassword(token, formValues) {
- return (dispatch) => {
+export function updatePassword(formValues, token) {
+ return dispatch => new Promise(resolve =>
apiClient.post(`/reset-password/${token}`, formValues)
.then((response) => {
dispatch(loginUserSuccess(response.data));
browserHistory.push('/');
+ resolve();
})
- .catch(() => dispatch({
- type: ActionTypes.INVALID_RESET_PASSWORD_TOKEN
+ .catch((error) => {
+ dispatch({
+ type: ActionTypes.INVALID_RESET_PASSWORD_TOKEN
+ });
+ resolve({ error });
}));
- };
}
export function updateSettingsSuccess(user) {
@@ -222,19 +243,22 @@ export function updateSettingsSuccess(user) {
};
}
+export function submitSettings(formValues) {
+ return apiClient.put('/account', formValues);
+}
+
export function updateSettings(formValues) {
return dispatch =>
- apiClient.put('/account', formValues)
- .then((response) => {
+ new Promise(resolve =>
+ submitSettings(formValues).then((response) => {
dispatch(updateSettingsSuccess(response.data));
- browserHistory.push('/');
dispatch(showToast(5500));
dispatch(setToastText('Toast.SettingsSaved'));
- })
- .catch((error) => {
+ resolve();
+ }).catch((error) => {
const { response } = error;
- Promise.reject(new Error(response.data.error));
- });
+ resolve({ error });
+ }));
}
export function createApiKeySuccess(user) {
diff --git a/client/modules/User/components/AccountForm.jsx b/client/modules/User/components/AccountForm.jsx
index 4432efbf7a..4ff2ef4b3f 100644
--- a/client/modules/User/components/AccountForm.jsx
+++ b/client/modules/User/components/AccountForm.jsx
@@ -1,136 +1,161 @@
-import PropTypes from 'prop-types';
import React from 'react';
-import { withTranslation } from 'react-i18next';
-import { domOnlyProps } from '../../../utils/reduxFormUtils';
+import { Form, Field } from 'react-final-form';
+import { useSelector, useDispatch } from 'react-redux';
+import { useTranslation } from 'react-i18next';
import Button from '../../../common/Button';
+import { validateSettings } from '../../../utils/reduxFormUtils';
+import { updateSettings, initiateVerification } from '../actions';
+import apiClient from '../../../utils/apiClient';
-function AccountForm(props) {
- const {
- fields: {
- username, email, currentPassword, newPassword
- },
- user,
- handleSubmit,
- initiateVerification,
- submitting,
- invalid,
- pristine,
- t
- } = props;
+function asyncValidate(fieldToValidate, value) {
+ if (!value || value.trim().length === 0) return `Please enter a ${fieldToValidate}.`;
+ const queryParams = {};
+ queryParams[fieldToValidate] = value;
+ queryParams.check_type = fieldToValidate;
+ return apiClient.get('/signup/duplicate_check', { params: queryParams })
+ .then((response) => {
+ if (response.data.exists) {
+ return response.data.message;
+ }
+ return '';
+ });
+}
+
+function AccountForm() {
+ const { t } = useTranslation();
+ const user = useSelector(state => state.user);
+ const dispatch = useDispatch();
const handleInitiateVerification = (evt) => {
evt.preventDefault();
- initiateVerification();
+ dispatch(initiateVerification());
};
+ function validateUsername(username) {
+ if (username === user.username) return '';
+ return asyncValidate('username', username);
+ }
+
+ function validateEmail(email) {
+ if (email === user.email) return '';
+ return asyncValidate('email', email);
+ }
+
+ function onSubmit(formProps) {
+ return dispatch(updateSettings(formProps));
+ }
+
return (
-
+
+ )}
+
);
}
-AccountForm.propTypes = {
- fields: PropTypes.shape({
- username: PropTypes.objectOf(PropTypes.shape()).isRequired,
- email: PropTypes.objectOf(PropTypes.shape()).isRequired,
- currentPassword: PropTypes.objectOf(PropTypes.shape()).isRequired,
- newPassword: PropTypes.objectOf(PropTypes.shape()).isRequired,
- }).isRequired,
- user: PropTypes.shape({
- verified: PropTypes.string.isRequired,
- emailVerificationInitiate: PropTypes.bool.isRequired,
- }).isRequired,
- handleSubmit: PropTypes.func.isRequired,
- initiateVerification: PropTypes.func.isRequired,
- updateSettings: PropTypes.func.isRequired,
- submitting: PropTypes.bool,
- invalid: PropTypes.bool,
- pristine: PropTypes.bool,
- t: PropTypes.func.isRequired
-};
-
-AccountForm.defaultProps = {
- submitting: false,
- pristine: true,
- invalid: false,
-};
-
-export default withTranslation()(AccountForm);
+export default AccountForm;
diff --git a/client/modules/User/components/LoginForm.jsx b/client/modules/User/components/LoginForm.jsx
index 3c969ddd7a..9c2ec6b949 100644
--- a/client/modules/User/components/LoginForm.jsx
+++ b/client/modules/User/components/LoginForm.jsx
@@ -1,75 +1,78 @@
import PropTypes from 'prop-types';
import React from 'react';
import { withTranslation } from 'react-i18next';
+import { Form, Field } from 'react-final-form';
+import { useDispatch } from 'react-redux';
import Button from '../../../common/Button';
-
-import { domOnlyProps } from '../../../utils/reduxFormUtils';
+import { validateLogin } from '../../../utils/reduxFormUtils';
+import { validateAndLoginUser } from '../actions';
function LoginForm(props) {
- const {
- fields: { email, password },
- handleSubmit,
- submitting,
- pristine,
- } = props;
+ const dispatch = useDispatch();
+ function onSubmit(formProps) {
+ return dispatch(validateAndLoginUser(formProps));
+ }
+
return (
-
+ {({
+ handleSubmit, pristine, submitting, invalid
+ }) => (
+
+ )}
+
);
}
LoginForm.propTypes = {
- fields: PropTypes.shape({
- email: PropTypes.objectOf(PropTypes.shape()).isRequired,
- password: PropTypes.objectOf(PropTypes.shape()).isRequired,
- }).isRequired,
- handleSubmit: PropTypes.func.isRequired,
- validateAndLoginUser: PropTypes.func.isRequired,
- submitting: PropTypes.bool,
- pristine: PropTypes.bool,
- invalid: PropTypes.bool,
- previousPath: PropTypes.string.isRequired,
t: PropTypes.func.isRequired
};
-LoginForm.defaultProps = {
- submitting: false,
- pristine: true,
- invalid: false,
-};
-
export default withTranslation()(LoginForm);
diff --git a/client/modules/User/components/NewPasswordForm.jsx b/client/modules/User/components/NewPasswordForm.jsx
index 1a1e0386c1..dfd1661676 100644
--- a/client/modules/User/components/NewPasswordForm.jsx
+++ b/client/modules/User/components/NewPasswordForm.jsx
@@ -1,70 +1,77 @@
import PropTypes from 'prop-types';
import React from 'react';
-import { withTranslation } from 'react-i18next';
-import { domOnlyProps } from '../../../utils/reduxFormUtils';
+import { Form, Field } from 'react-final-form';
+import { useDispatch } from 'react-redux';
+import { useTranslation } from 'react-i18next';
+import { validateNewPassword } from '../../../utils/reduxFormUtils';
+import { updatePassword } from '../actions';
import Button from '../../../common/Button';
function NewPasswordForm(props) {
- const {
- fields: { password, confirmPassword }, handleSubmit, submitting, invalid, pristine,
- t
- } = props;
+ const { resetPasswordToken } = props;
+ const { t } = useTranslation();
+ const dispatch = useDispatch();
+
+ function onSubmit(formProps) {
+ return dispatch(updatePassword(formProps, resetPasswordToken));
+ }
+
return (
-
+ {({
+ handleSubmit, submitting, invalid, pristine
+ }) => (
+
+ )}
+
);
}
NewPasswordForm.propTypes = {
- fields: PropTypes.shape({
- password: PropTypes.objectOf(PropTypes.shape()).isRequired,
- confirmPassword: PropTypes.objectOf(PropTypes.shape()).isRequired,
- }).isRequired,
- handleSubmit: PropTypes.func.isRequired,
- updatePassword: PropTypes.func.isRequired,
- submitting: PropTypes.bool,
- invalid: PropTypes.bool,
- pristine: PropTypes.bool,
- params: PropTypes.shape({
- reset_password_token: PropTypes.string,
- }).isRequired,
- t: PropTypes.func.isRequired
-};
-
-NewPasswordForm.defaultProps = {
- invalid: false,
- pristine: true,
- submitting: false,
+ resetPasswordToken: PropTypes.string.isRequired,
};
-export default withTranslation()(NewPasswordForm);
+export default NewPasswordForm;
diff --git a/client/modules/User/components/ResetPasswordForm.jsx b/client/modules/User/components/ResetPasswordForm.jsx
index 82b399cd9e..c8f008e7bd 100644
--- a/client/modules/User/components/ResetPasswordForm.jsx
+++ b/client/modules/User/components/ResetPasswordForm.jsx
@@ -1,59 +1,59 @@
-import PropTypes from 'prop-types';
import React from 'react';
-import { withTranslation } from 'react-i18next';
-import { domOnlyProps } from '../../../utils/reduxFormUtils';
+import { useTranslation } from 'react-i18next';
+import { Form, Field } from 'react-final-form';
+import { useDispatch, useSelector } from 'react-redux';
+import { validateResetPassword } from '../../../utils/reduxFormUtils';
+import { initiateResetPassword } from '../actions';
import Button from '../../../common/Button';
function ResetPasswordForm(props) {
- const {
- fields: { email }, handleSubmit, submitting, invalid, pristine, t
- } = props;
+ const { t } = useTranslation();
+ const resetPasswordInitiate = useSelector(state => state.user.resetPasswordInitiate);
+ const dispatch = useDispatch();
+
+ function onSubmit(formProps) {
+ dispatch(initiateResetPassword(formProps));
+ }
+
return (
-
+ {({
+ handleSubmit, submitting, pristine, invalid
+ }) => (
+
+ )}
+
);
}
-ResetPasswordForm.propTypes = {
- fields: PropTypes.shape({
- email: PropTypes.objectOf(PropTypes.shape()).isRequired
- }).isRequired,
- handleSubmit: PropTypes.func.isRequired,
- initiateResetPassword: PropTypes.func.isRequired,
- submitting: PropTypes.bool,
- invalid: PropTypes.bool,
- pristine: PropTypes.bool,
- user: PropTypes.shape({
- resetPasswordInitiate: PropTypes.bool
- }).isRequired,
- t: PropTypes.func.isRequired
-};
-
-ResetPasswordForm.defaultProps = {
- submitting: false,
- pristine: true,
- invalid: false,
-};
-
-export default withTranslation()(ResetPasswordForm);
+export default ResetPasswordForm;
diff --git a/client/modules/User/components/SignupForm.jsx b/client/modules/User/components/SignupForm.jsx
index b8e7b710f8..301d2503b0 100644
--- a/client/modules/User/components/SignupForm.jsx
+++ b/client/modules/User/components/SignupForm.jsx
@@ -1,106 +1,136 @@
import PropTypes from 'prop-types';
import React from 'react';
import { withTranslation } from 'react-i18next';
-
-import { domOnlyProps } from '../../../utils/reduxFormUtils';
+import { Form, Field } from 'react-final-form';
+import { useDispatch } from 'react-redux';
+import { validateSignup } from '../../../utils/reduxFormUtils';
+import { validateAndSignUpUser } from '../actions';
import Button from '../../../common/Button';
+import apiClient from '../../../utils/apiClient';
+
+function asyncValidate(fieldToValidate, value) {
+ if (!value || value.trim().length === 0) return `Please enter a ${fieldToValidate}.`;
+ const queryParams = {};
+ queryParams[fieldToValidate] = value;
+ queryParams.check_type = fieldToValidate;
+ return apiClient.get('/signup/duplicate_check', { params: queryParams })
+ .then((response) => {
+ if (response.data.exists) {
+ return response.data.message;
+ }
+ return '';
+ });
+}
+
+function validateUsername(username) {
+ return asyncValidate('username', username);
+}
+
+function validateEmail(email) {
+ return asyncValidate('email', email);
+}
function SignupForm(props) {
- const {
- fields: {
- username, email, password, confirmPassword
- },
- handleSubmit,
- submitting,
- invalid,
- pristine,
- } = props;
+ const dispatch = useDispatch();
+ function onSubmit(formProps) {
+ return dispatch(validateAndSignUpUser(formProps));
+ }
+
return (
-
+ {({
+ handleSubmit, pristine, submitting, invalid
+ }) => (
+
+
+ )}
+
);
}
SignupForm.propTypes = {
- fields: PropTypes.shape({
- username: PropTypes.objectOf(PropTypes.shape()).isRequired,
- email: PropTypes.objectOf(PropTypes.shape()).isRequired,
- password: PropTypes.objectOf(PropTypes.shape()).isRequired,
- confirmPassword: PropTypes.objectOf(PropTypes.shape()).isRequired,
- }).isRequired,
- handleSubmit: PropTypes.func.isRequired,
- signUpUser: PropTypes.func.isRequired,
- submitting: PropTypes.bool,
- invalid: PropTypes.bool,
- pristine: PropTypes.bool,
- previousPath: PropTypes.string.isRequired,
t: PropTypes.func.isRequired
};
-SignupForm.defaultProps = {
- submitting: false,
- pristine: true,
- invalid: false,
-};
-
export default withTranslation()(SignupForm);
diff --git a/client/modules/User/pages/AccountView.jsx b/client/modules/User/pages/AccountView.jsx
index fa0bd75a15..54bedf3168 100644
--- a/client/modules/User/pages/AccountView.jsx
+++ b/client/modules/User/pages/AccountView.jsx
@@ -1,27 +1,26 @@
import PropTypes from 'prop-types';
import React from 'react';
-import { reduxForm } from 'redux-form';
+import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import { Helmet } from 'react-helmet';
import { withTranslation } from 'react-i18next';
import { withRouter, browserHistory } from 'react-router';
import { parse } from 'query-string';
-import { updateSettings, initiateVerification, createApiKey, removeApiKey } from '../actions';
+import { createApiKey, removeApiKey } from '../actions';
import AccountForm from '../components/AccountForm';
-import apiClient from '../../../utils/apiClient';
-import { validateSettings } from '../../../utils/reduxFormUtils';
import SocialAuthButton from '../components/SocialAuthButton';
import APIKeyForm from '../components/APIKeyForm';
import Nav from '../../../components/Nav';
import ErrorModal from '../../IDE/components/ErrorModal';
import Overlay from '../../App/components/Overlay';
+import Toast from '../../IDE/components/Toast';
function SocialLoginPanel(props) {
const { user } = props;
return (
-
+
{/* eslint-disable-next-line react/prop-types */}
{props.t('AccountView.SocialLogin')}
@@ -67,6 +66,7 @@ class AccountView extends React.Component {
{this.props.t('AccountView.Title')}
+ {this.props.toast.isVisible && }
@@ -118,34 +118,17 @@ function mapStateToProps(state) {
previousPath: state.ide.previousPath,
user: state.user,
apiKeys: state.user.apiKeys,
- theme: state.preferences.theme
+ theme: state.preferences.theme,
+ toast: state.toast
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
- updateSettings, initiateVerification, createApiKey, removeApiKey
+ createApiKey, removeApiKey
}, dispatch);
}
-function asyncValidate(formProps, dispatch, props) {
- const fieldToValidate = props.form._active;
- if (fieldToValidate) {
- const queryParams = {};
- queryParams[fieldToValidate] = formProps[fieldToValidate];
- queryParams.check_type = fieldToValidate;
- return apiClient.get('/signup/duplicate_check', { params: queryParams })
- .then((response) => {
- if (response.data.exists) {
- const error = {};
- error[fieldToValidate] = response.data.message;
- throw error;
- }
- });
- }
- return Promise.resolve(true).then(() => {});
-}
-
AccountView.propTypes = {
previousPath: PropTypes.string.isRequired,
theme: PropTypes.string.isRequired,
@@ -153,13 +136,10 @@ AccountView.propTypes = {
location: PropTypes.shape({
search: PropTypes.string.isRequired,
pathname: PropTypes.string.isRequired
+ }).isRequired,
+ toast: PropTypes.shape({
+ isVisible: PropTypes.bool.isRequired,
}).isRequired
};
-export default withTranslation()(withRouter(reduxForm({
- form: 'updateAllSettings',
- fields: ['username', 'email', 'currentPassword', 'newPassword'],
- validate: validateSettings,
- asyncValidate,
- asyncBlurFields: ['username', 'email', 'currentPassword']
-}, mapStateToProps, mapDispatchToProps)(AccountView)));
+export default withTranslation()(withRouter(connect(mapStateToProps, mapDispatchToProps)(AccountView)));
diff --git a/client/modules/User/pages/DashboardView.jsx b/client/modules/User/pages/DashboardView.jsx
index 4d3476e3cc..f4e461203f 100644
--- a/client/modules/User/pages/DashboardView.jsx
+++ b/client/modules/User/pages/DashboardView.jsx
@@ -1,16 +1,12 @@
import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
import { browserHistory } from 'react-router';
import { withTranslation } from 'react-i18next';
-import { updateSettings, initiateVerification, createApiKey, removeApiKey } from '../actions';
import Button from '../../../common/Button';
-
import Nav from '../../../components/Nav';
import Overlay from '../../App/components/Overlay';
-
import AssetList from '../../IDE/components/AssetList';
import AssetSize from '../../IDE/components/AssetSize';
import CollectionList from '../../IDE/components/CollectionList';
@@ -159,12 +155,6 @@ function mapStateToProps(state) {
};
}
-function mapDispatchToProps(dispatch) {
- return bindActionCreators({
- updateSettings, initiateVerification, createApiKey, removeApiKey
- }, dispatch);
-}
-
DashboardView.propTypes = {
location: PropTypes.shape({
pathname: PropTypes.string.isRequired,
@@ -180,4 +170,4 @@ DashboardView.propTypes = {
t: PropTypes.func.isRequired
};
-export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(DashboardView));
+export default withTranslation()(connect(mapStateToProps)(DashboardView));
diff --git a/client/modules/User/pages/LoginView.jsx b/client/modules/User/pages/LoginView.jsx
index cfd278cb65..606ef4d5e1 100644
--- a/client/modules/User/pages/LoginView.jsx
+++ b/client/modules/User/pages/LoginView.jsx
@@ -1,95 +1,40 @@
-import PropTypes from 'prop-types';
import React from 'react';
-import { reduxForm } from 'redux-form';
-import { Link, browserHistory } from 'react-router';
+import { Link } from 'react-router';
import { Helmet } from 'react-helmet';
-import { withTranslation } from 'react-i18next';
-import { validateAndLoginUser } from '../actions';
+import { useTranslation } from 'react-i18next';
import LoginForm from '../components/LoginForm';
-import { validateLogin } from '../../../utils/reduxFormUtils';
import SocialAuthButton from '../components/SocialAuthButton';
import Nav from '../../../components/Nav';
-import ResponsiveForm from '../components/ResponsiveForm';
-class LoginView extends React.Component {
- constructor(props) {
- super(props);
- this.closeLoginPage = this.closeLoginPage.bind(this);
- this.gotoHomePage = this.gotoHomePage.bind(this);
- }
-
- closeLoginPage() {
- browserHistory.push(this.props.previousPath);
- }
-
- gotoHomePage() {
- browserHistory.push('/');
- }
-
- render() {
- if (this.props.user.authenticated) {
- this.gotoHomePage();
- return null;
- }
- return (
-
-
-
-
- {this.props.t('LoginView.Title')}
-
-
-
{this.props.t('LoginView.Login')}
-
-
{this.props.t('LoginView.LoginOr')}
-
-
-
-
-
- {this.props.t('LoginView.DontHaveAccount')}
- {this.props.t('LoginView.SignUp')}
-
-
- {this.props.t('LoginView.ForgotPassword')}
- {this.props.t('LoginView.ResetPassword')}
-
+function LoginView() {
+ const { t } = useTranslation();
+ return (
+
+
+
+
+ {t('LoginView.Title')}
+
+
+
{t('LoginView.Login')}
+
+
{t('LoginView.LoginOr')}
+
+
+
-
-
- );
- }
-}
-
-function mapStateToProps(state) {
- return {
- user: state.user,
- previousPath: state.ide.previousPath
- };
+
+ {t('LoginView.DontHaveAccount')}
+ {t('LoginView.SignUp')}
+
+
+ {t('LoginView.ForgotPassword')}
+ {t('LoginView.ResetPassword')}
+
+
+
+
+ );
}
-function mapDispatchToProps() {
- return {
- validateAndLoginUser
- };
-}
-
-LoginView.propTypes = {
- previousPath: PropTypes.string.isRequired,
- user: PropTypes.shape({
- authenticated: PropTypes.bool
- }),
- t: PropTypes.func.isRequired,
-};
-
-LoginView.defaultProps = {
- user: {
- authenticated: false
- },
-};
-
-export default withTranslation()(reduxForm({
- form: 'login',
- fields: ['email', 'password'],
- validate: validateLogin
-}, mapStateToProps, mapDispatchToProps)(LoginView));
+export default LoginView;
diff --git a/client/modules/User/pages/NewPasswordView.jsx b/client/modules/User/pages/NewPasswordView.jsx
index d1b27106bd..3ef0ae8bca 100644
--- a/client/modules/User/pages/NewPasswordView.jsx
+++ b/client/modules/User/pages/NewPasswordView.jsx
@@ -1,19 +1,26 @@
import PropTypes from 'prop-types';
-import React from 'react';
-import { reduxForm } from 'redux-form';
+import React, { useEffect } from 'react';
import classNames from 'classnames';
-import { bindActionCreators } from 'redux';
+import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet';
-import { withTranslation } from 'react-i18next';
-import i18next from 'i18next';
+import { useTranslation } from 'react-i18next';
import NewPasswordForm from '../components/NewPasswordForm';
-import * as UserActions from '../actions';
+import { validateResetPasswordToken } from '../actions';
import Nav from '../../../components/Nav';
function NewPasswordView(props) {
+ const { t } = useTranslation();
+ const resetPasswordToken = props.params.reset_password_token;
+ const resetPasswordInvalid = useSelector(state => state.user.resetPasswordInvalid);
+ const dispatch = useDispatch();
+
+ useEffect(() => {
+ dispatch(validateResetPasswordToken(resetPasswordToken));
+ }, [resetPasswordToken]);
+
const newPasswordClass = classNames({
'new-password': true,
- 'new-password--invalid': props.user.resetPasswordInvalid,
+ 'new-password--invalid': resetPasswordInvalid,
'form-container': true,
'user': true
});
@@ -22,13 +29,13 @@ function NewPasswordView(props) {
- {props.t('NewPasswordView.Title')}
+ {t('NewPasswordView.Title')}
-
{props.t('NewPasswordView.Description')}
-
+
{t('NewPasswordView.Description')}
+
- {props.t('NewPasswordView.TokenInvalidOrExpired')}
+ {t('NewPasswordView.TokenInvalidOrExpired')}
@@ -39,43 +46,7 @@ function NewPasswordView(props) {
NewPasswordView.propTypes = {
params: PropTypes.shape({
reset_password_token: PropTypes.string,
- }).isRequired,
- validateResetPasswordToken: PropTypes.func.isRequired,
- user: PropTypes.shape({
- resetPasswordInvalid: PropTypes.bool
- }).isRequired,
- t: PropTypes.func.isRequired
+ }).isRequired
};
-function validate(formProps) {
- const errors = {};
-
- if (!formProps.password) {
- errors.password = i18next.t('NewPasswordView.EmptyPassword');
- }
- if (!formProps.confirmPassword) {
- errors.confirmPassword = i18next.t('NewPasswordView.PasswordConfirmation');
- }
-
- if (formProps.password !== formProps.confirmPassword) {
- errors.password = i18next.t('NewPasswordView.PasswordMismatch');
- }
-
- return errors;
-}
-
-function mapStateToProps(state) {
- return {
- user: state.user
- };
-}
-
-function mapDispatchToProps(dispatch) {
- return bindActionCreators(UserActions, dispatch);
-}
-
-export default withTranslation()(reduxForm({
- form: 'new-password',
- fields: ['password', 'confirmPassword'],
- validate
-}, mapStateToProps, mapDispatchToProps)(NewPasswordView));
+export default NewPasswordView;
diff --git a/client/modules/User/pages/ResetPasswordView.jsx b/client/modules/User/pages/ResetPasswordView.jsx
index 46d0b51782..ec3ac65fea 100644
--- a/client/modules/User/pages/ResetPasswordView.jsx
+++ b/client/modules/User/pages/ResetPasswordView.jsx
@@ -1,21 +1,18 @@
-
-import PropTypes from 'prop-types';
import React from 'react';
import { Link } from 'react-router';
import classNames from 'classnames';
-import { bindActionCreators } from 'redux';
-import { reduxForm } from 'redux-form';
+import { useSelector } from 'react-redux';
import { Helmet } from 'react-helmet';
-import { withTranslation } from 'react-i18next';
-import * as UserActions from '../actions';
+import { useTranslation } from 'react-i18next';
import ResetPasswordForm from '../components/ResetPasswordForm';
-import { validateResetPassword } from '../../../utils/reduxFormUtils';
import Nav from '../../../components/Nav';
-function ResetPasswordView(props) {
+function ResetPasswordView() {
+ const { t } = useTranslation();
+ const resetPasswordInitiate = useSelector(state => state.user.resetPasswordInitiate);
const resetPasswordClass = classNames({
'reset-password': true,
- 'reset-password--submitted': props.user.resetPasswordInitiate,
+ 'reset-password--submitted': resetPasswordInitiate,
'form-container': true,
'user': true
});
@@ -24,18 +21,18 @@ function ResetPasswordView(props) {
- {props.t('ResetPasswordView.Title')}
+ {t('ResetPasswordView.Title')}
-
{props.t('ResetPasswordView.Reset')}
-
+
{t('ResetPasswordView.Reset')}
+
- {props.t('ResetPasswordView.Submitted')}
+ {t('ResetPasswordView.Submitted')}
- {props.t('ResetPasswordView.Login')}
- {props.t('ResetPasswordView.LoginOr')}
- {props.t('ResetPasswordView.SignUp')}
+ {t('ResetPasswordView.Login')}
+ {t('ResetPasswordView.LoginOr')}
+ {t('ResetPasswordView.SignUp')}
@@ -43,26 +40,4 @@ function ResetPasswordView(props) {
);
}
-ResetPasswordView.propTypes = {
- resetPasswordReset: PropTypes.func.isRequired,
- user: PropTypes.shape({
- resetPasswordInitiate: PropTypes.bool
- }).isRequired,
- t: PropTypes.func.isRequired
-};
-
-function mapStateToProps(state) {
- return {
- user: state.user
- };
-}
-
-function mapDispatchToProps(dispatch) {
- return bindActionCreators(UserActions, dispatch);
-}
-
-export default withTranslation()(reduxForm({
- form: 'reset-password',
- fields: ['email'],
- validate: validateResetPassword
-}, mapStateToProps, mapDispatchToProps)(ResetPasswordView));
+export default ResetPasswordView;
diff --git a/client/modules/User/pages/SignupView.jsx b/client/modules/User/pages/SignupView.jsx
index 55ef1ae1fd..e878cd5072 100644
--- a/client/modules/User/pages/SignupView.jsx
+++ b/client/modules/User/pages/SignupView.jsx
@@ -1,131 +1,37 @@
-import PropTypes from 'prop-types';
import React from 'react';
-import { bindActionCreators } from 'redux';
-import { Link, browserHistory } from 'react-router';
+import { Link } from 'react-router';
import { Helmet } from 'react-helmet';
-import { reduxForm } from 'redux-form';
-import { withTranslation } from 'react-i18next';
-import * as UserActions from '../actions';
+import { useTranslation } from 'react-i18next';
import SignupForm from '../components/SignupForm';
-import apiClient from '../../../utils/apiClient';
-import { validateSignup } from '../../../utils/reduxFormUtils';
import SocialAuthButton from '../components/SocialAuthButton';
import Nav from '../../../components/Nav';
-import ResponsiveForm from '../components/ResponsiveForm';
-class SignupView extends React.Component {
- gotoHomePage = () => {
- browserHistory.push('/');
- }
-
- render() {
- if (this.props.user.authenticated) {
- this.gotoHomePage();
- return null;
- }
- return (
-
-
-
-
- {this.props.t('SignupView.Title')}
-
-
-
{this.props.t('SignupView.Description')}
-
-
{this.props.t('SignupView.Or')}
-
-
-
-
-
- {this.props.t('SignupView.AlreadyHave')}
- {this.props.t('SignupView.Login')}
-
+function SignupView() {
+ const { t } = useTranslation();
+ return (
+
+
+
+
+ {t('SignupView.Title')}
+
+
+
{t('SignupView.Description')}
+
+
{t('SignupView.Or')}
+
+
+
-
-
- );
- }
-}
-
-function asyncErrorsSelector(formName, state) {
- const form = state.form[formName];
- if (!form) {
- return {};
- }
-
- const fieldNames = Object.keys(form).filter(key => !key.startsWith('_'));
- return fieldNames.reduce((asyncErrors, fieldName) => {
- if (form[fieldName].asyncError) {
- return { ...asyncErrors, [fieldName]: form[fieldName].asyncError };
- }
- return asyncErrors;
- }, {});
-}
-
-function mapStateToProps(state) {
- return {
- user: state.user,
- previousPath: state.ide.previousPath,
- asyncErrors: asyncErrorsSelector('signup', state)
- };
-}
-
-function mapDispatchToProps(dispatch) {
- return bindActionCreators(UserActions, dispatch);
-}
-
-function asyncValidate(formProps, dispatch, props) {
- const errors = {};
- return Promise.resolve(true)
- .then(() => {
- const fieldToValidate = props.form._active;
- if (fieldToValidate) {
- const queryParams = {};
- queryParams[fieldToValidate] = formProps[fieldToValidate];
- queryParams.check_type = fieldToValidate;
- return apiClient.get('/signup/duplicate_check', { params: queryParams })
- .then((response) => {
- if (response.data.exists) {
- errors[fieldToValidate] = response.data.message;
- }
- });
- }
- return null;
- })
- .then(() => {
- const err = { ...errors, ...props.asyncErrors };
- if (Object.keys(err).length > 0) {
- throw err;
- }
- });
+
+ {t('SignupView.AlreadyHave')}
+ {t('SignupView.Login')}
+
+
+
+
+ );
}
-function onSubmitFail(errors) {
- console.log(errors);
-}
-
-SignupView.propTypes = {
- previousPath: PropTypes.string.isRequired,
- user: PropTypes.shape({
- authenticated: PropTypes.bool
- }),
- t: PropTypes.func.isRequired,
-};
-
-SignupView.defaultProps = {
- user: {
- authenticated: false
- },
-};
-
-export default withTranslation()(reduxForm({
- form: 'signup',
- fields: ['username', 'email', 'password', 'confirmPassword'],
- onSubmitFail,
- validate: validateSignup,
- asyncValidate,
- asyncBlurFields: ['username', 'email']
-}, mapStateToProps, mapDispatchToProps)(SignupView));
+export default SignupView;
diff --git a/client/reducers.js b/client/reducers.js
index 121c6cd6f0..f61d2585d6 100644
--- a/client/reducers.js
+++ b/client/reducers.js
@@ -1,5 +1,4 @@
import { combineReducers } from 'redux';
-import { reducer as form } from 'redux-form';
import files from './modules/IDE/reducers/files';
import ide from './modules/IDE/reducers/ide';
import preferences from './modules/IDE/reducers/preferences';
@@ -16,7 +15,6 @@ import loading from './modules/IDE/reducers/loading';
import collections from './modules/IDE/reducers/collections';
const rootReducer = combineReducers({
- form,
ide,
files,
preferences,
diff --git a/client/utils/reduxFormUtils.js b/client/utils/reduxFormUtils.js
index 27d23a9d69..9339433a96 100644
--- a/client/utils/reduxFormUtils.js
+++ b/client/utils/reduxFormUtils.js
@@ -62,11 +62,7 @@ export function validateLogin(formProps) {
return errors;
}
-export function validateSignup(formProps) {
- const errors = {};
-
- validateNameEmail(formProps, errors);
-
+function validatePasswords(formProps, errors) {
if (!formProps.password) {
errors.password = i18n.t('ReduxFormUtils.errorEmptyPassword');
}
@@ -80,6 +76,19 @@ export function validateSignup(formProps) {
if (formProps.password !== formProps.confirmPassword && formProps.confirmPassword) {
errors.confirmPassword = i18n.t('ReduxFormUtils.errorPasswordMismatch');
}
+}
+
+export function validateNewPassword(formProps) {
+ const errors = {};
+ validatePasswords(formProps, errors);
+ return errors;
+}
+
+export function validateSignup(formProps) {
+ const errors = {};
+
+ validateNameEmail(formProps, errors);
+ validatePasswords(formProps, errors);
return errors;
}
diff --git a/package-lock.json b/package-lock.json
index bb206b068b..54cd215242 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9080,160 +9080,159 @@
"dev": true
},
"@webassemblyjs/ast": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
- "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
+ "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
"requires": {
- "@webassemblyjs/helper-module-context": "1.8.5",
- "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
- "@webassemblyjs/wast-parser": "1.8.5"
+ "@webassemblyjs/helper-module-context": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/wast-parser": "1.9.0"
}
},
"@webassemblyjs/floating-point-hex-parser": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz",
- "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ=="
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
+ "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA=="
},
"@webassemblyjs/helper-api-error": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz",
- "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA=="
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
+ "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw=="
},
"@webassemblyjs/helper-buffer": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz",
- "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q=="
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
+ "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA=="
},
"@webassemblyjs/helper-code-frame": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz",
- "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
+ "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
"requires": {
- "@webassemblyjs/wast-printer": "1.8.5"
+ "@webassemblyjs/wast-printer": "1.9.0"
}
},
"@webassemblyjs/helper-fsm": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz",
- "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow=="
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
+ "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw=="
},
"@webassemblyjs/helper-module-context": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
- "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
+ "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
"requires": {
- "@webassemblyjs/ast": "1.8.5",
- "mamacro": "^0.0.3"
+ "@webassemblyjs/ast": "1.9.0"
}
},
"@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz",
- "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ=="
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
+ "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw=="
},
"@webassemblyjs/helper-wasm-section": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz",
- "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
+ "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
"requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/helper-buffer": "1.8.5",
- "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
- "@webassemblyjs/wasm-gen": "1.8.5"
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-buffer": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/wasm-gen": "1.9.0"
}
},
"@webassemblyjs/ieee754": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz",
- "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
+ "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
"requires": {
"@xtuc/ieee754": "^1.2.0"
}
},
"@webassemblyjs/leb128": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz",
- "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
+ "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
"requires": {
"@xtuc/long": "4.2.2"
}
},
"@webassemblyjs/utf8": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz",
- "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw=="
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
+ "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w=="
},
"@webassemblyjs/wasm-edit": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz",
- "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
+ "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
"requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/helper-buffer": "1.8.5",
- "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
- "@webassemblyjs/helper-wasm-section": "1.8.5",
- "@webassemblyjs/wasm-gen": "1.8.5",
- "@webassemblyjs/wasm-opt": "1.8.5",
- "@webassemblyjs/wasm-parser": "1.8.5",
- "@webassemblyjs/wast-printer": "1.8.5"
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-buffer": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/helper-wasm-section": "1.9.0",
+ "@webassemblyjs/wasm-gen": "1.9.0",
+ "@webassemblyjs/wasm-opt": "1.9.0",
+ "@webassemblyjs/wasm-parser": "1.9.0",
+ "@webassemblyjs/wast-printer": "1.9.0"
}
},
"@webassemblyjs/wasm-gen": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz",
- "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
+ "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
"requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
- "@webassemblyjs/ieee754": "1.8.5",
- "@webassemblyjs/leb128": "1.8.5",
- "@webassemblyjs/utf8": "1.8.5"
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/ieee754": "1.9.0",
+ "@webassemblyjs/leb128": "1.9.0",
+ "@webassemblyjs/utf8": "1.9.0"
}
},
"@webassemblyjs/wasm-opt": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz",
- "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
+ "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
"requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/helper-buffer": "1.8.5",
- "@webassemblyjs/wasm-gen": "1.8.5",
- "@webassemblyjs/wasm-parser": "1.8.5"
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-buffer": "1.9.0",
+ "@webassemblyjs/wasm-gen": "1.9.0",
+ "@webassemblyjs/wasm-parser": "1.9.0"
}
},
"@webassemblyjs/wasm-parser": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz",
- "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
+ "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
"requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/helper-api-error": "1.8.5",
- "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
- "@webassemblyjs/ieee754": "1.8.5",
- "@webassemblyjs/leb128": "1.8.5",
- "@webassemblyjs/utf8": "1.8.5"
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-api-error": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/ieee754": "1.9.0",
+ "@webassemblyjs/leb128": "1.9.0",
+ "@webassemblyjs/utf8": "1.9.0"
}
},
"@webassemblyjs/wast-parser": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz",
- "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==",
- "requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/floating-point-hex-parser": "1.8.5",
- "@webassemblyjs/helper-api-error": "1.8.5",
- "@webassemblyjs/helper-code-frame": "1.8.5",
- "@webassemblyjs/helper-fsm": "1.8.5",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
+ "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/floating-point-hex-parser": "1.9.0",
+ "@webassemblyjs/helper-api-error": "1.9.0",
+ "@webassemblyjs/helper-code-frame": "1.9.0",
+ "@webassemblyjs/helper-fsm": "1.9.0",
"@xtuc/long": "4.2.2"
}
},
"@webassemblyjs/wast-printer": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz",
- "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
+ "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
"requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/wast-parser": "1.8.5",
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/wast-parser": "1.9.0",
"@xtuc/long": "4.2.2"
}
},
@@ -9884,13 +9883,21 @@
}
},
"asn1.js": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
- "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"requires": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
}
},
"assert": {
@@ -11030,8 +11037,7 @@
},
"kind-of": {
"version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+ "resolved": ""
}
}
},
@@ -11097,9 +11103,9 @@
}
},
"bl": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
- "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
+ "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
@@ -11134,9 +11140,9 @@
"integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw=="
},
"bn.js": {
- "version": "4.11.8",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
- "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
+ "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ=="
},
"body-parser": {
"version": "1.19.0",
@@ -11263,26 +11269,50 @@
}
},
"browserify-rsa": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
- "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+ "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
"requires": {
- "bn.js": "^4.1.0",
+ "bn.js": "^5.0.0",
"randombytes": "^2.0.1"
}
},
"browserify-sign": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
- "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+ "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
"requires": {
- "bn.js": "^4.1.1",
- "browserify-rsa": "^4.0.0",
- "create-hash": "^1.1.0",
- "create-hmac": "^1.1.2",
- "elliptic": "^6.0.0",
- "inherits": "^2.0.1",
- "parse-asn1": "^5.0.0"
+ "bn.js": "^5.1.1",
+ "browserify-rsa": "^4.0.1",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.3",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.5",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ }
}
},
"browserify-zlib": {
@@ -12806,12 +12836,19 @@
}
},
"create-ecdh": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
- "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+ "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
"requires": {
"bn.js": "^4.1.0",
- "elliptic": "^6.0.0"
+ "elliptic": "^6.5.3"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
}
},
"create-emotion": {
@@ -13880,11 +13917,6 @@
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
"dev": true
},
- "deep-equal": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
- "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
- },
"deep-extend": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
@@ -14092,6 +14124,13 @@
"bn.js": "^4.1.0",
"miller-rabin": "^4.0.0",
"randombytes": "^2.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
}
},
"dir-glob": {
@@ -14402,6 +14441,13 @@
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
}
},
"emoji-regex": {
@@ -14454,9 +14500,9 @@
}
},
"enhanced-resolve": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz",
- "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
+ "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
"requires": {
"graceful-fs": "^4.1.2",
"memory-fs": "^0.5.0",
@@ -15269,9 +15315,9 @@
"dev": true
},
"events": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
- "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg=="
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
+ "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg=="
},
"eventsource": {
"version": "1.0.7",
@@ -16214,6 +16260,29 @@
"repeat-string": "^1.5.2"
}
},
+ "final-form": {
+ "version": "4.20.1",
+ "resolved": "https://registry.npmjs.org/final-form/-/final-form-4.20.1.tgz",
+ "integrity": "sha512-IIsOK3JRxJrN72OBj7vFWZxtGt3xc1bYwJVPchjVWmDol9DlzMSAOPB+vwe75TUYsw1JaH0fTQnIgwSQZQ9Acg==",
+ "requires": {
+ "@babel/runtime": "^7.10.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.12.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
+ "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
+ }
+ },
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@@ -17388,8 +17457,7 @@
},
"ini": {
"version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "resolved": "",
"optional": true
},
"is-fullwidth-code-point": {
@@ -18331,12 +18399,35 @@
}
},
"hash-base": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
- "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
"requires": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ }
}
},
"hash-sum": {
@@ -19275,9 +19366,9 @@
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"inline-style-parser": {
"version": "0.1.1",
@@ -19726,7 +19817,8 @@
"is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
- "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
},
"is-redirect": {
"version": "1.0.0",
@@ -25857,11 +25949,6 @@
"tmpl": "1.0.x"
}
},
- "mamacro": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz",
- "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA=="
- },
"map-age-cleaner": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
@@ -26276,6 +26363,13 @@
"requires": {
"bn.js": "^4.0.0",
"brorand": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
}
},
"mime": {
@@ -29104,13 +29198,12 @@
}
},
"parse-asn1": {
- "version": "5.1.5",
- "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
- "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
+ "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
"requires": {
- "asn1.js": "^4.0.0",
+ "asn1.js": "^5.2.0",
"browserify-aes": "^1.0.0",
- "create-hash": "^1.1.0",
"evp_bytestokey": "^1.0.0",
"pbkdf2": "^3.0.3",
"safe-buffer": "^5.1.1"
@@ -29374,9 +29467,9 @@
"integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
},
"pbkdf2": {
- "version": "3.0.17",
- "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
- "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
+ "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
"requires": {
"create-hash": "^1.1.2",
"create-hmac": "^1.1.4",
@@ -31555,6 +31648,13 @@
"parse-asn1": "^5.0.0",
"randombytes": "^2.0.1",
"safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
}
},
"pug": {
@@ -32318,6 +32418,29 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
},
+ "react-final-form": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/react-final-form/-/react-final-form-6.5.2.tgz",
+ "integrity": "sha512-c5l45FYOoxtfpvsvMFh3w2WW8KNxbuebBUrM16rUrooQkewTs0Zahmv0TuKFX5jsC9BKn5Fo84j3ZVXQdURS4w==",
+ "requires": {
+ "@babel/runtime": "^7.12.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.12.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
+ "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
+ }
+ },
"react-focus-lock": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.3.1.tgz",
@@ -32461,14 +32584,6 @@
"react-base16-styling": "^0.5.1"
}
},
- "react-lazy-cache": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/react-lazy-cache/-/react-lazy-cache-3.0.1.tgz",
- "integrity": "sha1-DcZNON8XZ+93Z4xclBkAZMsRsM0=",
- "requires": {
- "deep-equal": "^1.0.1"
- }
- },
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
@@ -33232,19 +33347,6 @@
"base16": "^1.0.0"
}
},
- "redux-form": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-5.4.0.tgz",
- "integrity": "sha512-Ssftdf3Or6nwEBl1SqgPbZdxhmZC8AejHTTLnt1R6SfCqyoHgPnPyxu8NuewS2KvDN925nwRT9dGxeIYDgtAWQ==",
- "requires": {
- "deep-equal": "^1.0.1",
- "hoist-non-react-statics": "^2.3.1",
- "invariant": "^2.0.0",
- "is-promise": "^2.1.0",
- "prop-types": "^15.5.8",
- "react-lazy-cache": "^3.0.1"
- }
- },
"redux-thunk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
@@ -34782,9 +34884,12 @@
}
},
"serialize-javascript": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
- "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ=="
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
+ "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
},
"serve-favicon": {
"version": "2.5.0",
@@ -35239,8 +35344,7 @@
},
"kind-of": {
"version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+ "resolved": ""
}
}
},
@@ -36501,15 +36605,15 @@
}
},
"terser-webpack-plugin": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
- "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
+ "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
"requires": {
"cacache": "^12.0.2",
"find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0",
"schema-utils": "^1.0.0",
- "serialize-javascript": "^2.1.2",
+ "serialize-javascript": "^4.0.0",
"source-map": "^0.6.1",
"terser": "^4.1.2",
"webpack-sources": "^1.4.0",
@@ -36596,9 +36700,9 @@
"dev": true
},
"timers-browserify": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
- "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
+ "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==",
"requires": {
"setimmediate": "^1.0.4"
}
@@ -37672,19 +37776,151 @@
}
},
"watchpack": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
- "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
+ "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
"requires": {
- "chokidar": "^2.0.2",
+ "chokidar": "^3.4.1",
"graceful-fs": "^4.1.2",
- "neo-async": "^2.5.0"
+ "neo-async": "^2.5.0",
+ "watchpack-chokidar2": "^2.0.1"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "optional": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "binary-extensions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+ "optional": true
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "optional": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "chokidar": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
+ "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
+ "optional": true,
+ "requires": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.5.0"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "optional": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "fsevents": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "optional": true
+ },
+ "glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "optional": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "optional": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "optional": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "optional": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "optional": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "optional": true
+ },
+ "readdirp": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+ "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
+ "optional": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "optional": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
+ }
+ },
+ "watchpack-chokidar2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz",
+ "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==",
+ "optional": true,
+ "requires": {
+ "chokidar": "^2.1.8"
},
"dependencies": {
"anymatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
"integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "optional": true,
"requires": {
"micromatch": "^3.1.4",
"normalize-path": "^2.1.1"
@@ -37694,6 +37930,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "optional": true,
"requires": {
"remove-trailing-separator": "^1.0.1"
}
@@ -37703,17 +37940,20 @@
"arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "optional": true
},
"array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "optional": true
},
"braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "optional": true,
"requires": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
@@ -37731,6 +37971,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@@ -37741,6 +37982,7 @@
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
"integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "optional": true,
"requires": {
"anymatch": "^2.0.0",
"async-each": "^1.0.1",
@@ -37760,6 +38002,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "optional": true,
"requires": {
"ms": "2.0.0"
}
@@ -37768,6 +38011,7 @@
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
"integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "optional": true,
"requires": {
"debug": "^2.3.3",
"define-property": "^0.2.5",
@@ -37782,6 +38026,7 @@
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "optional": true,
"requires": {
"is-descriptor": "^0.1.0"
}
@@ -37790,6 +38035,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@@ -37798,6 +38044,7 @@
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
"integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "optional": true,
"requires": {
"kind-of": "^3.0.2"
},
@@ -37806,6 +38053,7 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@@ -37816,6 +38064,7 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
"integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "optional": true,
"requires": {
"kind-of": "^3.0.2"
},
@@ -37824,6 +38073,7 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@@ -37834,6 +38084,7 @@
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
"integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "optional": true,
"requires": {
"is-accessor-descriptor": "^0.1.6",
"is-data-descriptor": "^0.1.4",
@@ -37843,7 +38094,8 @@
"kind-of": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "optional": true
}
}
},
@@ -37851,6 +38103,7 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
"integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "optional": true,
"requires": {
"array-unique": "^0.3.2",
"define-property": "^1.0.0",
@@ -37866,6 +38119,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
"integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "optional": true,
"requires": {
"is-descriptor": "^1.0.0"
}
@@ -37874,6 +38128,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@@ -37884,6 +38139,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "optional": true,
"requires": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
@@ -37895,6 +38151,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@@ -37905,6 +38162,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "optional": true,
"requires": {
"is-glob": "^3.1.0",
"path-dirname": "^1.0.0"
@@ -37914,6 +38172,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
"integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "optional": true,
"requires": {
"is-extglob": "^2.1.0"
}
@@ -37924,6 +38183,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
"integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "optional": true,
"requires": {
"kind-of": "^6.0.0"
}
@@ -37932,6 +38192,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
"integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "optional": true,
"requires": {
"kind-of": "^6.0.0"
}
@@ -37940,6 +38201,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
"integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "optional": true,
"requires": {
"is-accessor-descriptor": "^1.0.0",
"is-data-descriptor": "^1.0.0",
@@ -37949,12 +38211,14 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "optional": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "optional": true,
"requires": {
"is-extglob": "^2.1.1"
}
@@ -37963,6 +38227,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "optional": true,
"requires": {
"kind-of": "^3.0.2"
},
@@ -37971,6 +38236,7 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@@ -37980,17 +38246,20 @@
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "optional": true
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
- "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "optional": true
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "optional": true,
"requires": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
@@ -38010,12 +38279,14 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "optional": true
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "optional": true
}
}
},
@@ -38099,44 +38370,44 @@
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
},
"webpack": {
- "version": "4.41.6",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.6.tgz",
- "integrity": "sha512-yxXfV0Zv9WMGRD+QexkZzmGIh54bsvEs+9aRWxnN8erLWEOehAKUTeNBoUbA6HPEZPlRo7KDi2ZcNveoZgK9MA==",
- "requires": {
- "@webassemblyjs/ast": "1.8.5",
- "@webassemblyjs/helper-module-context": "1.8.5",
- "@webassemblyjs/wasm-edit": "1.8.5",
- "@webassemblyjs/wasm-parser": "1.8.5",
- "acorn": "^6.2.1",
+ "version": "4.44.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz",
+ "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-module-context": "1.9.0",
+ "@webassemblyjs/wasm-edit": "1.9.0",
+ "@webassemblyjs/wasm-parser": "1.9.0",
+ "acorn": "^6.4.1",
"ajv": "^6.10.2",
"ajv-keywords": "^3.4.1",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^4.1.0",
+ "enhanced-resolve": "^4.3.0",
"eslint-scope": "^4.0.3",
"json-parse-better-errors": "^1.0.2",
"loader-runner": "^2.4.0",
"loader-utils": "^1.2.3",
"memory-fs": "^0.4.1",
"micromatch": "^3.1.10",
- "mkdirp": "^0.5.1",
+ "mkdirp": "^0.5.3",
"neo-async": "^2.6.1",
"node-libs-browser": "^2.2.1",
"schema-utils": "^1.0.0",
"tapable": "^1.1.3",
"terser-webpack-plugin": "^1.4.3",
- "watchpack": "^1.6.0",
+ "watchpack": "^1.7.4",
"webpack-sources": "^1.4.1"
},
"dependencies": {
"acorn": {
- "version": "6.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
- "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA=="
+ "version": "6.4.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+ "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ=="
},
"ajv": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
- "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -38145,9 +38416,9 @@
}
},
"ajv-keywords": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
- "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ=="
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
},
"arr-diff": {
"version": "4.0.0",
@@ -38320,9 +38591,9 @@
}
},
"fast-deep-equal": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
- "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fill-range": {
"version": "4.0.0",
diff --git a/package.json b/package.json
index 774257b4e3..dff0d41522 100644
--- a/package.json
+++ b/package.json
@@ -167,6 +167,7 @@
"express": "^4.17.1",
"express-basic-auth": "^1.2.0",
"express-session": "^1.17.0",
+ "final-form": "^4.20.1",
"friendly-words": "^1.1.10",
"htmlhint": "^0.10.1",
"i18next": "^19.4.5",
@@ -199,6 +200,7 @@
"raw-loader": "^4.0.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
+ "react-final-form": "^6.5.2",
"react-helmet": "^5.1.3",
"react-hot-loader": "^4.12.19",
"react-i18next": "^11.5.0",
@@ -212,7 +214,6 @@
"redux-devtools": "^3.4.2",
"redux-devtools-dock-monitor": "^1.1.3",
"redux-devtools-log-monitor": "^1.4.0",
- "redux-form": "^5.3.3",
"redux-thunk": "^2.3.0",
"request": "^2.88.2",
"request-promise": "^4.2.5",
diff --git a/server/controllers/user.controller.js b/server/controllers/user.controller.js
index a8f21f16ed..dac4015dce 100644
--- a/server/controllers/user.controller.js
+++ b/server/controllers/user.controller.js
@@ -95,7 +95,8 @@ export function createUser(req, res, next) {
export function duplicateUserCheck(req, res) {
const checkType = req.query.check_type;
const value = req.query[checkType];
- User.findByEmailOrUsername(value, { caseInsensitive: true }, (err, user) => {
+ const options = { caseInsensitive: true, valueType: checkType };
+ User.findByEmailOrUsername(value, options, (err, user) => {
if (user) {
return res.json({
exists: true,
diff --git a/server/models/user.js b/server/models/user.js
index 4ab738d0be..8e25b9e675 100644
--- a/server/models/user.js
+++ b/server/models/user.js
@@ -194,19 +194,25 @@ userSchema.statics.findByUsername = function findByUsername(username, options, c
*
* Queries User collection using email or username with optional callback.
* This function will determine automatically whether the data passed is
- * a username or email.
+ * a username or email, unless you specify options.valueType
*
* @param {string} value - Email or username
* @param {Object} [options] - Optional options
* @param {boolean} options.caseInsensitive - Does a caseInsensitive query rather than
* default query for username or email, defaults
* to false
+ * @param {("email"|"username")} options.valueType - Prevents automatic type inferrence
* @callback [cb] - Optional error-first callback that passes User document
* @return {Promise