Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation for new shared folder #1390

Merged
merged 18 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { t, Trans } from "@lingui/macro"
import { CSFTheme } from "../../../Themes/types"
import { useFileBrowser } from "../../../Contexts/FileBrowserContext"
import { useFilesApi } from "../../../Contexts/FilesApiContext"
import { folderNameValidator } from "../../../Utils/validationSchema"
import { nameValidator } from "../../../Utils/validationSchema"
import { getPathWithFile } from "../../../Utils/pathUtils"


Expand Down Expand Up @@ -108,7 +108,7 @@ const CreateFolderModal: React.FC<ICreateFolderModalProps> = ({
initialValues={{
name: ""
}}
validationSchema={folderNameValidator}
validationSchema={nameValidator}
validateOnChange={false}
onSubmit={async (values, helpers) => {
if (!bucket) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useEffect } from "react"
import { SharedFolderModalMode } from "./types"
import { useCreateOrEditSharedFolder } from "./hooks/useCreateOrEditSharedFolder"
import { useLookupSharedFolderUser } from "./hooks/useLookupUser"
import { nameValidator } from "../../../Utils/validationSchema"

const useStyles = makeStyles(
({ breakpoints, constants, typography, zIndex, palette }: CSFTheme) => {
Expand Down Expand Up @@ -108,6 +109,10 @@ const useStyles = makeStyles(
footer: {
width: "100%",
padding: `${constants.generalUnit * 2}px ${constants.generalUnit}px`
},
errorText: {
textAlign: "center",
color: palette.error.main
}
})
}
Expand All @@ -127,6 +132,7 @@ const CreateOrEditSharedFolderModal = ({ mode, isModalOpen, onClose, bucketToEdi
const [sharedFolderName, setSharedFolderName] = useState("")
const { sharedFolderReaders, sharedFolderWriters, onNewUsers, handleLookupUser, usersError, setUsersError } = useLookupSharedFolderUser()
const [hasPermissionsChanged, setHasPermissionsChanged] = useState(false)
const [nameError, setNameError] = useState("")

useEffect(() => {
setSharedFolderName("")
Expand Down Expand Up @@ -166,6 +172,22 @@ const CreateOrEditSharedFolderModal = ({ mode, isModalOpen, onClose, bucketToEdi
.finally(onClose)
}, [handleEditSharedFolder, sharedFolderWriters, sharedFolderReaders, onClose, bucketToEdit])

const onNameChange = useCallback((value?: string | number) => {
if (value === undefined) return

const trimmedValue = value.toString().trim()
setSharedFolderName(trimmedValue)

nameValidator
.validate({ name: trimmedValue })
.then(() => {
setNameError("")
})
.catch((e: Error) => {
setNameError(e.message)
})
}, [])

return (
<CustomModal
className={classes.modalRoot}
Expand Down Expand Up @@ -196,9 +218,19 @@ const CreateOrEditSharedFolderModal = ({ mode, isModalOpen, onClose, bucketToEdi
labelClassName={classes.inputLabel}
label={t`Shared Folder Name`}
value={sharedFolderName}
onChange={(value) => {setSharedFolderName(value?.toString() || "")}}
onChange={onNameChange}
autoFocus
state={nameError ? "error" : "normal"}
/>
{nameError && (
<Typography
component="p"
variant="body1"
className={classes.errorText}
>
{nameError}
</Typography>
)}
</div>
}
<div className={classes.modalFlexItem}>
Expand Down Expand Up @@ -275,7 +307,7 @@ const CreateOrEditSharedFolderModal = ({ mode, isModalOpen, onClose, bucketToEdi
className={classes.okButton}
loading={isCreatingSharedFolder || isEditingSharedFolder}
onClick={mode === "create" ? onCreateSharedFolder : onEditSharedFolder}
disabled={mode === "create" ? !!usersError : !hasPermissionsChanged || !!usersError}
disabled={mode === "create" ? (!!usersError || !!nameError) : !hasPermissionsChanged || !!usersError}
>
{mode === "create"
? <Trans>Create</Trans>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ const SharedFileBrowser = () => {
deleteItems,
downloadFile: handleDownload,
moveItems,
renameItem: renameItem,
renameItem,
viewFolder,
loadingCurrentPath,
showUploadsInTable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { CSFTheme } from "../../../../../Themes/types"
import { FileSystemItem } from "../../../../../Contexts/FilesContext"
import { ConnectDragPreview } from "react-dnd"
import { Form, FormikProvider, useFormik } from "formik"
import { renameSchema } from "../../../../../Utils/validationSchema"
import { nameValidator } from "../../../../../Utils/validationSchema"

const useStyles = makeStyles(({ breakpoints, constants, palette }: CSFTheme) => {
return createStyles({
Expand Down Expand Up @@ -160,7 +160,7 @@ const FileSystemGridItem = React.forwardRef(
initialValues:{
fileName: name
},
validationSchema: renameSchema,
validationSchema: nameValidator,
onSubmit:(values) => {
const newName = values.fileName?.trim()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { useFileBrowser } from "../../../../../Contexts/FileBrowserContext"
import { getPathWithFile } from "../../../../../Utils/pathUtils"
import { BucketUser } from "@chainsafe/files-api-client"
import { useMemo } from "react"
import { renameSchema } from "../../../../../Utils/validationSchema"
import { nameValidator } from "../../../../../Utils/validationSchema"

const useStyles = makeStyles(({ breakpoints, constants }: CSFTheme) => {
return createStyles({
Expand Down Expand Up @@ -156,7 +156,7 @@ const FileSystemItem = ({
initialValues:{
fileName: name
},
validationSchema:renameSchema,
validationSchema: nameValidator,
onSubmit:(values) => {
const newName = values.fileName?.trim()

Expand Down Expand Up @@ -433,7 +433,7 @@ const FileSystemItem = ({
menuItems,
onFolderOrFileClicks,
preview,
renameSchema,
renameSchema: nameValidator,
selected,
setEditing,
resetSelectedFiles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import dayjs from "dayjs"
import { FileSystemItem } from "../../../../../Contexts/FilesContext"
import { ConnectDragPreview } from "react-dnd"
import { Form, FormikProvider, useFormik } from "formik"
import { renameSchema } from "../../../../../Utils/validationSchema"
import { nameValidator } from "../../../../../Utils/validationSchema"

const useStyles = makeStyles(({ breakpoints, constants, palette }: CSFTheme) => {
const desktopGridSettings = "50px 69px 3fr 190px 100px 45px !important"
Expand Down Expand Up @@ -145,7 +145,7 @@ const FileSystemTableItem = React.forwardRef(
initialValues:{
fileName: name
},
validationSchema: renameSchema,
validationSchema: nameValidator,
onSubmit:(values) => {
const newName = values.fileName?.trim()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { Form, FormikProvider, useFormik } from "formik"
import clsx from "clsx"
import { BucketKeyPermission } from "../../../../../Contexts/FilesContext"
import UserBubble from "../../../../Elements/UserBubble"
import { renameSchema } from "../../../../../Utils/validationSchema"
import { nameValidator } from "../../../../../Utils/validationSchema"

const useStyles = makeStyles(({ breakpoints, constants, palette }: CSFTheme) => {

Expand Down Expand Up @@ -210,12 +210,12 @@ const SharedFolderRow = ({ bucket, handleRename, openSharedFolder, handleDeleteS

const formik = useFormik({
initialValues:{
fileName: name
name
},
enableReinitialize: true,
validationSchema: renameSchema,
validationSchema: nameValidator,
onSubmit:(values, { resetForm }) => {
const newName = values.fileName?.trim()
const newName = values.name?.trim()

newName && handleRename && handleRename(bucket, newName)
setIsRenaming(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,15 @@ const InitialScreen = ({ className }: IInitialScreen) => {
setIsConnecting(false)
}

const onSubmitEmail = useCallback((values) => {
const onSubmitEmail = useCallback((values: {email: string}) => {
setIsConnecting(true)
setErrorEmail("")
const trimmedEmail = values.email.trim()

filesApiClient
.getIdentityEmailToken({ email: values.email })
.getIdentityEmailToken({ email: trimmedEmail })
.then(() => {
setEmail(values.email)
setEmail(trimmedEmail)
setLoginMode("email")
})
.catch((e) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,31 +88,13 @@ interface IPasswordlessEmail {

const PasswordlessEmail = ({ resetLogin, email }: IPasswordlessEmail) => {
const classes = useStyles()
// const [isSubmitEmailLoading, setIsSubmitEmailLoading] = useState(false)
const [isSubmitResendEmailLoading, setIsSubmitResendEmailLoading] = useState(false)
const [isSubmitNonceLoading, setIsSubmitNonceLoading] = useState(false)
// const [page, setPage] = useState<"confirmEmail" | "confirmVerificationCode">("confirmEmail")
// const [email, setEmail] = useState<string | undefined>()
const [hasEmailResent, setHasEmailResent] = useState(false)
const { filesApiClient } = useFilesApi()
const { login } = useThresholdKey()
const [error, setError] = useState<string | undefined>()

// const onSubmitEmail = useCallback((values) => {
// setIsSubmitEmailLoading(true)
// setError(undefined)
// filesApiClient.getIdentityEmailToken({ email: values.email })
// .then(() => {
// setEmail(values.email)
// setPage("confirmVerificationCode")
// setIsSubmitEmailLoading(false)
// }).catch ((e) => {
// setError(t`Something went wrong!`)
// setIsSubmitEmailLoading(false)
// console.error(e)
// })
// }, [filesApiClient])

const onSubmitNonce = useCallback((values) => {
if (!email) return
setIsSubmitNonceLoading(true)
Expand Down
33 changes: 6 additions & 27 deletions packages/files-ui/src/Utils/validationSchema.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,28 @@
import { t } from "@lingui/macro"
import { object, string } from "yup"

const whitespaceOnlyRegex = new RegExp("^\\s+$")

export const renameSchema = object().shape({
fileName: string()
.min(1, t`Please enter a name`)
.max(65, t`Name too long`)
.required(t`A name is required`)
.test(
"Invalid character in name",
t`Name cannot contain '/' character`,
(val: string | null | undefined) => !val?.includes("/")
)
.test(
"Only whitespace",
t`Name cannot only contain whitespace characters`,
(val) => !!val && !whitespaceOnlyRegex.test(val)
)
})

export const folderNameValidator = object().shape({
export const nameValidator = object().shape({
name: string()
.trim()
.min(1, t`Please enter a name`)
.max(65, t`Name too long`)
.required("Folder name is required")
.required("A name is required")
.test(
"Invalid name",
"Folder name cannot contain '/' character",
"A name cannot contain '/' character",
(val: string | null | undefined) => !val?.includes("/")
)
.test(
"Only whitespace",
t`Folder name cannot only contain whitepsace characters`,
(val) => !!val && !whitespaceOnlyRegex.test(val)
)
})

export const emailValidation = object().shape({
email: string()
.trim()
.email("Please enter a valid email")
.required(t`Email is required`)
})

export const nonceValidation = object().shape({
nonce: string()
.trim()
.required(t`Verification code is required`)
})
12 changes: 0 additions & 12 deletions packages/files-ui/src/locales/de/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ msgstr "Es wird ein Sicherungsgeheimsatz generiert und für Ihr Konto verwendet.
msgid "A file with the same name already exists"
msgstr "Es existiert bereits eine Datei mit demselben Namen"

msgid "A name is required"
msgstr "Ein Name ist erforderlich"

msgid "Account"
msgstr "Konto"

Expand Down Expand Up @@ -277,9 +274,6 @@ msgstr "Vorname"
msgid "Folder"
msgstr "Ordner"

msgid "Folder name cannot only contain whitepsace characters"
msgstr ""

msgid "Folder name is already in use"
msgstr ""

Expand Down Expand Up @@ -391,12 +385,6 @@ msgstr "Meine Dateien"
msgid "Name"
msgstr "Name"

msgid "Name cannot contain '/' character"
msgstr "Name darf kein /-Zeichen enthalten"

msgid "Name cannot only contain whitespace characters"
msgstr ""

msgid "Name too long"
msgstr "Name zu lang"

Expand Down
12 changes: 0 additions & 12 deletions packages/files-ui/src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ msgstr "A backup secret phrase will be generated and used for your account.<0/>W
msgid "A file with the same name already exists"
msgstr "A file with the same name already exists"

msgid "A name is required"
msgstr "A name is required"

msgid "Account"
msgstr "Account"

Expand Down Expand Up @@ -280,9 +277,6 @@ msgstr "First name"
msgid "Folder"
msgstr "Folder"

msgid "Folder name cannot only contain whitepsace characters"
msgstr "Folder name cannot only contain whitepsace characters"

msgid "Folder name is already in use"
msgstr "Folder name is already in use"

Expand Down Expand Up @@ -394,12 +388,6 @@ msgstr "My Files"
msgid "Name"
msgstr "Name"

msgid "Name cannot contain '/' character"
msgstr "Name cannot contain '/' character"

msgid "Name cannot only contain whitespace characters"
msgstr "Name cannot only contain whitespace characters"

msgid "Name too long"
msgstr "Name too long"

Expand Down
Loading