diff --git a/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js b/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js index bc4de66769..bd01dd88fd 100644 --- a/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js +++ b/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js @@ -15,7 +15,13 @@ import { Grid, GridItem } from '@strapi/design-system/Grid'; import { Typography } from '@strapi/design-system/Typography'; import EyeStriked from '@strapi/icons/EyeStriked'; import Eye from '@strapi/icons/Eye'; -import { Form, useQuery, useNotification } from '@strapi/helper-plugin'; +import { + Form, + useQuery, + useNotification, + useTracking, + getYupInnerErrors, +} from '@strapi/helper-plugin'; import { useHistory } from 'react-router-dom'; import PropTypes from 'prop-types'; import { Formik } from 'formik'; @@ -41,12 +47,14 @@ const PasswordInput = styled(TextInput)` } `; -const Register = ({ fieldsToDisable, noSignin, onSubmit, schema }) => { +const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => { const toggleNotification = useNotification(); const { push } = useHistory(); const [passwordShown, setPasswordShown] = useState(false); const [confirmPasswordShown, setConfirmPasswordShown] = useState(false); + const [submitCount, setSubmitCount] = useState(0); const [userInfo, setUserInfo] = useState({}); + const { trackUsage } = useTracking(); const { formatMessage } = useIntl(); const query = useQuery(); const registrationToken = query.get('registrationToken'); @@ -97,225 +105,218 @@ const Register = ({ fieldsToDisable, noSignin, onSubmit, schema }) => { registrationToken: registrationToken || undefined, news: false, }} - onSubmit={(data, formik) => { - if (registrationToken) { - // We need to pass the registration token in the url param to the api in order to submit another admin user - onSubmit({ userInfo: omit(data, ['registrationToken']), registrationToken }, formik); - } else { - onSubmit(data, formik); + onSubmit={async (data, formik) => { + try { + await schema.validate(data, { abortEarly: false }); + + if (submitCount > 0 && authType === 'register-admin') { + trackUsage('didSubmitWithErrorsFirstAdmin', { count: submitCount.toString() }); + } + + if (registrationToken) { + // We need to pass the registration token in the url param to the api in order to submit another admin user + onSubmit( + { userInfo: omit(data, ['registrationToken']), registrationToken }, + formik + ); + } else { + onSubmit(data, formik); + } + } catch (err) { + const errors = getYupInnerErrors(err); + setSubmitCount(submitCount + 1); + + formik.setErrors(errors); } }} - validationSchema={schema} + // Leaving this part commented when we remove the tracking for the submitCount + // validationSchema={schema} validateOnChange={false} > - {({ values, errors, handleChange }) => ( -
-
- - - - - {formatMessage({ - id: 'Auth.form.welcome.title', - defaultMessage: 'Welcome!', - })} - - - - - {formatMessage({ - id: 'Auth.form.register.subtitle', - defaultMessage: - 'Your credentials are only used to authenticate yourself on the admin panel. All saved data will be stored in your own database.', - })} - - - - - - - { + return ( + +
+ + + + + {formatMessage({ + id: 'Auth.form.welcome.title', + defaultMessage: 'Welcome!', })} - /> - - - + + + + {formatMessage({ + id: 'Auth.form.register.subtitle', + defaultMessage: + 'Your credentials are only used to authenticate yourself on the admin panel. All saved data will be stored in your own database.', })} - /> - - - - { - e.preventDefault(); - setPasswordShown(prev => !prev); - }} - label={formatMessage( - passwordShown - ? { - id: 'Auth.form.password.show-password', - defaultMessage: 'Show password', - } - : { - id: 'Auth.form.password.hide-password', - defaultMessage: 'Hide password', - } - )} - > - {passwordShown ? : } - - } - hint={formatMessage({ - id: 'Auth.form.password.hint', - defaultMessage: - 'Password must contain at least 8 characters, 1 uppercase, 1 lowercase and 1 number', - })} - required - label={formatMessage({ - id: 'Auth.form.password.label', - defaultMessage: 'Password', - })} - type={passwordShown ? 'text' : 'password'} - /> - { - e.preventDefault(); - setConfirmPasswordShown(prev => !prev); - }} - label={formatMessage( - confirmPasswordShown - ? { - id: 'Auth.form.password.show-password', - defaultMessage: 'Show password', - } - : { - id: 'Auth.form.password.hide-password', - defaultMessage: 'Hide password', - } - )} - > - {confirmPasswordShown ? : } - - } - required - label={formatMessage({ - id: 'Auth.form.confirmPassword.label', - defaultMessage: 'Confirmation Password', - })} - type={confirmPasswordShown ? 'text' : 'password'} - /> - { - handleChange({ target: { value: checked, name: 'news' } }); - }} - value={values.news} - name="news" - aria-label="news" - > - {formatMessage( - { - id: 'Auth.form.register.news.label', - defaultMessage: - 'Keep me updated about the new features and upcoming improvements (by doing this you accept the {terms} and the {policy}).', - }, - { - terms: ( - - {formatMessage({ - id: 'Auth.privacy-policy-agreement.terms', - defaultMessage: 'terms', - })} - - ), - policy: ( - - {formatMessage({ - id: 'Auth.privacy-policy-agreement.policy', - defaultMessage: 'policy', - })} - - ), + + + + + + + + + + + + + + { + e.preventDefault(); + setPasswordShown(prev => !prev); + }} + label={formatMessage( + passwordShown + ? { + id: 'Auth.form.password.show-password', + defaultMessage: 'Show password', + } + : { + id: 'Auth.form.password.hide-password', + defaultMessage: 'Hide password', + } + )} + > + {passwordShown ? : } + } - )} - - - -
- - )} + hint={formatMessage({ + id: 'Auth.form.password.hint', + defaultMessage: + 'Password must contain at least 8 characters, 1 uppercase, 1 lowercase and 1 number', + })} + required + label={formatMessage({ + id: 'Auth.form.password.label', + defaultMessage: 'Password', + })} + type={passwordShown ? 'text' : 'password'} + /> + { + e.preventDefault(); + setConfirmPasswordShown(prev => !prev); + }} + label={formatMessage( + confirmPasswordShown + ? { + id: 'Auth.form.password.show-password', + defaultMessage: 'Show password', + } + : { + id: 'Auth.form.password.hide-password', + defaultMessage: 'Hide password', + } + )} + > + {confirmPasswordShown ? : } + + } + required + label={formatMessage({ + id: 'Auth.form.confirmPassword.label', + defaultMessage: 'Confirmation Password', + })} + type={confirmPasswordShown ? 'text' : 'password'} + /> + { + handleChange({ target: { value: checked, name: 'news' } }); + }} + value={values.news} + name="news" + aria-label="news" + > + {formatMessage( + { + id: 'Auth.form.register.news.label', + defaultMessage: + 'Keep me updated about the new features and upcoming improvements (by doing this you accept the {terms} and the {policy}).', + }, + { + terms: ( + + {formatMessage({ + id: 'Auth.privacy-policy-agreement.terms', + defaultMessage: 'terms', + })} + + ), + policy: ( + + {formatMessage({ + id: 'Auth.privacy-policy-agreement.policy', + defaultMessage: 'policy', + })} + + ), + } + )} + + +
+
+ + ); + }} {!noSignin && ( @@ -341,10 +342,14 @@ Register.defaultProps = { }; Register.propTypes = { + authType: PropTypes.string.isRequired, fieldsToDisable: PropTypes.array, noSignin: PropTypes.bool, onSubmit: PropTypes.func, - schema: PropTypes.shape({ type: PropTypes.string.isRequired }).isRequired, + schema: PropTypes.shape({ + validate: PropTypes.func.isRequired, + type: PropTypes.string.isRequired, + }).isRequired, }; export default Register; diff --git a/packages/core/admin/admin/src/pages/AuthPage/index.js b/packages/core/admin/admin/src/pages/AuthPage/index.js index 5ddcaf9fdf..063d4c0ce0 100644 --- a/packages/core/admin/admin/src/pages/AuthPage/index.js +++ b/packages/core/admin/admin/src/pages/AuthPage/index.js @@ -4,7 +4,7 @@ import camelCase from 'lodash/camelCase'; import get from 'lodash/get'; import omit from 'lodash/omit'; import { Redirect, useRouteMatch, useHistory } from 'react-router-dom'; -import { auth, useQuery, useGuidedTour } from '@strapi/helper-plugin'; +import { auth, useQuery, useGuidedTour, useTracking } from '@strapi/helper-plugin'; import PropTypes from 'prop-types'; import forms from 'ee_else_ce/pages/AuthPage/utils/forms'; import persistStateToLocaleStorage from '../../components/GuidedTour/utils/persistStateToLocaleStorage'; @@ -17,6 +17,7 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => { const { push } = useHistory(); const { changeLocale } = useLocalesProvider(); const { setSkipped } = useGuidedTour(); + const { trackUsage } = useTracking(); const { params: { authType }, } = useRouteMatch('/auth/:authType'); @@ -146,6 +147,8 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => { const registerRequest = async (body, requestURL, { setSubmitting, setErrors }) => { try { + trackUsage('willCreateFirstAdmin'); + const { data: { data: { token, user }, @@ -189,6 +192,8 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => { // Redirect to the homePage push('/'); } catch (err) { + trackUsage('didNotCreateFirstAdmin'); + if (err.response) { const { data } = err.response; const apiErrors = formatAPIErrors(data); @@ -249,6 +254,7 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => { return (