diff --git a/frontend/src/admin/AdminDomainModal.js b/frontend/src/admin/AdminDomainModal.js index f4c1632065..5644a80f99 100644 --- a/frontend/src/admin/AdminDomainModal.js +++ b/frontend/src/admin/AdminDomainModal.js @@ -6,7 +6,6 @@ import { Button, FormControl, FormErrorMessage, - FormLabel, Grid, IconButton, Input, @@ -26,6 +25,7 @@ import { array, bool, func, object, string } from 'prop-types' import { Field, FieldArray, Formik } from 'formik' import { useMutation } from '@apollo/client' +import { DomainField } from '../domains/DomainField' import { CREATE_DOMAIN, UPDATE_DOMAIN } from '../graphql/mutations' export function AdminDomainModal({ @@ -193,30 +193,11 @@ export function AdminDomainModal({ - - {({ field, form }) => ( - - - New Domain URL: - - - - - {form.errors.domainUrl} - - - )} - + const adminDomainList = loading ? ( @@ -279,7 +260,7 @@ export function AdminDomains({ orgSlug, domainsPerPage, orgId }) { { // Submit update role mutation if (mutation === 'update') { @@ -170,7 +158,7 @@ export function UserListModal({ variables: { orgId: orgId, role: values.role, - userName: values.userName, + userName: values.email, }, }) } else if (mutation === 'create') { @@ -178,7 +166,7 @@ export function UserListModal({ variables: { orgId: orgId, requestedRole: values.role, - userName: values.userName, + userName: values.email, preferredLang: 'ENGLISH', }, }) @@ -204,36 +192,7 @@ export function UserListModal({ {editingUserName} ) : ( - - {({ field, form }) => ( - - - - User: - - - - - - - - {form.errors.userName} - - - )} - + )} diff --git a/frontend/src/admin/__tests__/AdminDomains.test.js b/frontend/src/admin/__tests__/AdminDomains.test.js index aa4e8938c5..dc78efdc36 100644 --- a/frontend/src/admin/__tests__/AdminDomains.test.js +++ b/frontend/src/admin/__tests__/AdminDomains.test.js @@ -229,7 +229,7 @@ describe('', () => { }, ] - const { getByText, getByRole, findByRole } = render( + const { getByText, getByRole } = render( ', () => { , ) - const domainUrlInput = await findByRole('textbox', { + const domainUrlInput = getByRole('textbox', { name: 'Search by Domain URL', }) diff --git a/frontend/src/auth/CreateUserPage.js b/frontend/src/auth/CreateUserPage.js index 366f6dca64..e5016e5d32 100644 --- a/frontend/src/auth/CreateUserPage.js +++ b/frontend/src/auth/CreateUserPage.js @@ -9,11 +9,9 @@ import { useToast, } from '@chakra-ui/react' import { useMutation } from '@apollo/client' -import { object, string } from 'yup' import { Link as RouteLink, useParams } from 'react-router-dom' import { Formik } from 'formik' import { t, Trans } from '@lingui/macro' -import { i18n } from '@lingui/core' import { ArrowForwardIcon, CheckCircleIcon } from '@chakra-ui/icons' import { LanguageSelect } from './LanguageSelect' @@ -22,7 +20,7 @@ import { EmailField } from '../components/EmailField' import { DisplayNameField } from '../components/DisplayNameField' import { PasswordConfirmation } from '../components/PasswordConfirmation' import { LoadingMessage } from '../components/LoadingMessage' -import { fieldRequirements } from '../utilities/fieldRequirements' +import { createValidationSchema } from '../utilities/fieldRequirements' import { useUserVar } from '../utilities/userState' import { activate } from '../utilities/i18n.config' import TermsConditionsPage from '../termsConditions/TermsConditionsPage' @@ -34,30 +32,6 @@ export default function CreateUserPage() { const userOrgToken = useParams().userOrgToken || '' const [showVerifyMessage, setShowVerifyMessage] = useState(false) - const validationSchema = object().shape({ - email: string() - .required(i18n._(fieldRequirements.email.required.message)) - .email(i18n._(fieldRequirements.email.email.message)), - displayName: string().required( - i18n._(fieldRequirements.displayName.required.message), - ), - password: string() - .required(i18n._(fieldRequirements.password.required.message)) - .min( - fieldRequirements.password.min.minLength, - i18n._(fieldRequirements.password.min.message), - ), - confirmPassword: string() - .required(i18n._(fieldRequirements.confirmPassword.required.message)) - .oneOf( - fieldRequirements.confirmPassword.oneOf.types, - i18n._(fieldRequirements.confirmPassword.oneOf.message), - ), - lang: string() - .required(i18n._(fieldRequirements.lang.required.message)) - .oneOf(fieldRequirements.lang.oneOf.types), - }) - const [signUp, { loading }] = useMutation(SIGN_UP, { onError(error) { toast({ @@ -159,7 +133,13 @@ export default function CreateUserPage() { return ( - {meta.error} + {meta.error} ) diff --git a/frontend/src/createOrganization/CreateOrganizationField.js b/frontend/src/createOrganization/CreateOrganizationField.js index b6fccb9687..c2e1a1eac9 100644 --- a/frontend/src/createOrganization/CreateOrganizationField.js +++ b/frontend/src/createOrganization/CreateOrganizationField.js @@ -1,36 +1,25 @@ import React from 'react' import { func, object, oneOfType, shape, string } from 'prop-types' -import { - FormControl, - FormErrorMessage, - FormLabel, - Input, -} from '@chakra-ui/react' -import { useField } from 'formik' + +import { FormField } from '../components/FormField' function OrganizationCreateField({ name, label, language, forwardedRef, + inputProps, ...props }) { - const [field, meta] = useField(name) - return ( - - - {label} ({language}) - - - {meta.error} - + ) } @@ -38,6 +27,7 @@ OrganizationCreateField.propTypes = { name: string.isRequired, label: string, language: string, + inputProps: object, forwardedRef: oneOfType([func, shape({ current: object })]), } diff --git a/frontend/src/createOrganization/CreateOrganizationPage.js b/frontend/src/createOrganization/CreateOrganizationPage.js index 001fa8db96..62ef18e5be 100644 --- a/frontend/src/createOrganization/CreateOrganizationPage.js +++ b/frontend/src/createOrganization/CreateOrganizationPage.js @@ -12,14 +12,16 @@ import { t, Trans } from '@lingui/macro' import { useMutation } from '@apollo/client' import { Formik } from 'formik' import { Link as RouteLink, useHistory } from 'react-router-dom' -import { object, string } from 'yup' import { useLingui } from '@lingui/react' import { CreateOrganizationField } from './CreateOrganizationField' import { InfoButton, InfoBox, InfoPanel } from '../components/InfoPanel' import { LoadingMessage } from '../components/LoadingMessage' -import { fieldRequirements } from '../utilities/fieldRequirements' +import { + getRequirment, + schemaToValidation, +} from '../utilities/fieldRequirements' import { CREATE_ORGANIZATION } from '../graphql/mutations' export default function CreateOrganizationPage() { @@ -31,43 +33,22 @@ export default function CreateOrganizationPage() { isVisible: false, }) - const validationSchema = object().shape({ - nameEN: string().required(i18n._(fieldRequirements.field.required.message)), - nameFR: string().required(i18n._(fieldRequirements.field.required.message)), - acronymEN: string() - .matches( - fieldRequirements.acronym.matches.regex, - i18n._(fieldRequirements.acronym.matches.message), - ) - .max( - fieldRequirements.acronym.max.maxLength, - i18n._(fieldRequirements.acronym.max.message), - ) - .required(i18n._(fieldRequirements.field.required.message)), - acronymFR: string() - .matches( - fieldRequirements.acronym.matches.regex, - i18n._(fieldRequirements.acronym.matches.message), - ) - .max( - fieldRequirements.acronym.max.maxLength, - i18n._(fieldRequirements.acronym.max.message), - ) - .required(i18n._(fieldRequirements.field.required.message)), - cityEN: string().required(i18n._(fieldRequirements.field.required.message)), - cityFR: string().required(i18n._(fieldRequirements.field.required.message)), - provinceEN: string().required( - i18n._(fieldRequirements.field.required.message), - ), - provinceFR: string().required( - i18n._(fieldRequirements.field.required.message), - ), - countryEN: string().required( - i18n._(fieldRequirements.field.required.message), - ), - countryFR: string().required( - i18n._(fieldRequirements.field.required.message), - ), + const fieldRequirement = getRequirment('field') + const acronymRequirement = getRequirment('acronym').required( + i18n._(t`This field cannot be empty`), + ) + + const validationSchema = schemaToValidation({ + nameEN: fieldRequirement, + nameFR: fieldRequirement, + acronymEN: acronymRequirement, + acronymFR: acronymRequirement, + cityEN: fieldRequirement, + cityFR: fieldRequirement, + provinceEN: fieldRequirement, + provinceFR: fieldRequirement, + countryEN: fieldRequirement, + countryFR: fieldRequirement, }) const [createOrganization, { loading }] = useMutation(CREATE_ORGANIZATION, { diff --git a/frontend/src/createOrganization/__tests__/CreateOrganizationField.test.js b/frontend/src/createOrganization/__tests__/CreateOrganizationField.test.js index 31791ee9ad..fcdde00ae5 100644 --- a/frontend/src/createOrganization/__tests__/CreateOrganizationField.test.js +++ b/frontend/src/createOrganization/__tests__/CreateOrganizationField.test.js @@ -47,8 +47,8 @@ describe('', () => { , ) - const createOrgInput = getByRole('textbox', { name: /Create Org Field/ }) - fireEvent.blur(createOrgInput) + const input = getByRole('textbox', { name: /Create Org Field/ }) + fireEvent.blur(input) await waitFor(() => { expect(getByText(/sadness/)).toBeInTheDocument() diff --git a/frontend/src/domains/DomainField.js b/frontend/src/domains/DomainField.js index e679b85fb3..f0f86ba0dd 100644 --- a/frontend/src/domains/DomainField.js +++ b/frontend/src/domains/DomainField.js @@ -1,44 +1,43 @@ import React from 'react' import { func, object, oneOfType, shape, string } from 'prop-types' -import { t, Trans } from '@lingui/macro' -import { - FormControl, - FormErrorMessage, - FormLabel, - Input, - InputGroup, -} from '@chakra-ui/react' -import { useField } from 'formik' +import { t } from '@lingui/macro' -function DomainField({ name, label, forwardedRef, ...props }) { - const [field, meta] = useField(name) - - const labelText = label === undefined ? Domain URL: : label +import { FormField } from '../components/FormField' +function DomainField({ + name, + label, + placeholder, + forwardedRef, + inputProps, + ...props +}) { return ( - - - {labelText} - - - - - {meta.error} - + ) } DomainField.propTypes = { - name: string.isRequired, + name: string, label: string, + placeholder: string, + inputProps: object, forwardedRef: oneOfType([func, shape({ current: object })]), } +DomainField.defaultProps = { + name: 'domainURL', + label: t`Domain URL:`, + placeholder: t`Domain URL`, +} + const withForwardedRef = React.forwardRef((props, ref) => { return }) diff --git a/frontend/src/domains/ScanDomain.js b/frontend/src/domains/ScanDomain.js index 8482e7fe22..0aea352998 100644 --- a/frontend/src/domains/ScanDomain.js +++ b/frontend/src/domains/ScanDomain.js @@ -1,6 +1,5 @@ import React from 'react' import { t, Trans } from '@lingui/macro' -import { i18n } from '@lingui/core' import { Formik } from 'formik' import { Accordion, @@ -24,7 +23,6 @@ import { } from '@chakra-ui/react' import { WarningTwoIcon } from '@chakra-ui/icons' import { useMutation, useQuery } from '@apollo/client' -import { object, string } from 'yup' import { DomainField } from './DomainField' import { StatusBadge } from './StatusBadge' @@ -32,17 +30,12 @@ import { StatusBadge } from './StatusBadge' import { ScanCategoryDetails } from '../guidance/ScanCategoryDetails' import { LoadingMessage } from '../components/LoadingMessage' import { StatusIcon } from '../components/StatusIcon' -import { fieldRequirements } from '../utilities/fieldRequirements' +import { createValidationSchema } from '../utilities/fieldRequirements' import { GET_ONE_TIME_SCANS } from '../graphql/queries' import { REQUEST_SCAN } from '../graphql/mutations' export function ScanDomain() { const toast = useToast() - const validationSchema = object().shape({ - domain: string().required( - i18n._(fieldRequirements.domainUrl.required.message), - ), - }) const [requestScan, { loading }] = useMutation(REQUEST_SCAN, { onError(error) { @@ -156,12 +149,12 @@ export function ScanDomain() { return ( requestScan({ variables: { - domainUrl: values.domain.toLowerCase(), + domainUrl: values.domainUrl.toLowerCase(), }, }) } @@ -182,13 +175,14 @@ export function ScanDomain() { > Request a domain to be scanned: - +