1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

file input validation fixes

This commit is contained in:
Matthias Kretschmann 2021-11-23 15:34:43 +00:00
parent c484a5b40c
commit a313f39494
Signed by: m
GPG Key ID: 606EEEF3C479A91F
7 changed files with 94 additions and 46 deletions

View File

@ -92,10 +92,11 @@
}, },
{ {
"name": "providerUrl", "name": "providerUrl",
"label": "Custom Provider URL", "label": "Provider URL",
"type": "providerUrl", "type": "providerUrl",
"help": "Enter the URL for your custom provider or leave blank to use the default provider. [Learn more](https://github.com/oceanprotocol/provider/).", "help": "Enter the URL for your custom [provider](https://github.com/oceanprotocol/provider/) or leave as is to use the default one. If you change your provider URL after adding your file, please add & validate your file again.",
"placeholder": "e.g. https://provider.polygon.oceanprotocol.com/" "placeholder": "e.g. https://provider.oceanprotocol.com/",
"required": true
}, },
{ {
"name": "files", "name": "files",

View File

@ -2,7 +2,7 @@ import React, { ReactElement, useState, useEffect } from 'react'
import { useField } from 'formik' import { useField } from 'formik'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import FileInfo from './Info' import FileInfo from './Info'
import CustomInput from '../URLInput/Input' import UrlInput from '../URLInput/Input'
import { InputProps } from '@shared/FormInput' import { InputProps } from '@shared/FormInput'
import { getFileInfo } from '@utils/provider' import { getFileInfo } from '@utils/provider'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
@ -61,13 +61,15 @@ export default function FilesInput(props: InputProps): ReactElement {
return ( return (
<> <>
{field?.value && field.value[0] && typeof field.value === 'object' ? ( {field?.value && field.value[0].url !== '' && field.value[0].valid ? (
<FileInfo name={props.name} file={field.value[0]} /> <FileInfo name={props.name} file={field.value[0]} />
) : ( ) : (
<CustomInput <UrlInput
submitText="Add File" submitText="Add File"
{...props} {...props}
{...field} {...field}
name={`${props.name}[0].url`}
value={field?.value && field.value[0].url}
isLoading={isLoading} isLoading={isLoading}
handleButtonClick={handleButtonClick} handleButtonClick={handleButtonClick}
/> />

View File

@ -1,3 +1,12 @@
.input { .input {
composes: input from '@shared/FormInput/InputElement.module.css'; composes: input from '@shared/FormInput/InputElement.module.css';
} }
.hasError {
color: var(--brand-alert-red);
border-color: var(--brand-alert-red);
}
.error {
composes: error from '@shared/FormInput/index.module.css';
}

View File

@ -1,40 +1,59 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Button from '@shared/atoms/Button' import Button from '@shared/atoms/Button'
import { FieldInputProps, useField } from 'formik' import { ErrorMessage, FieldInputProps, useField } from 'formik'
import Loader from '@shared/atoms/Loader' import Loader from '@shared/atoms/Loader'
import styles from './Input.module.css' import styles from './Input.module.css'
import InputGroup from '@shared/FormInput/InputGroup' import InputGroup from '@shared/FormInput/InputGroup'
import InputElement from '@shared/FormInput/InputElement'
export default function URLInput({ export default function URLInput({
submitText, submitText,
handleButtonClick, handleButtonClick,
isLoading, isLoading,
name,
value,
...props ...props
}: { }: {
submitText: string submitText: string
handleButtonClick(e: React.SyntheticEvent, data: string): void handleButtonClick(e: React.SyntheticEvent, data: string): void
isLoading: boolean isLoading: boolean
name: string
value: string
}): ReactElement { }): ReactElement {
const [field, meta] = useField(props as FieldInputProps<any>) const [field, meta] = useField(name)
const isButtonDisabled = const isButtonDisabled =
!field.value || field.value.length === 0 || field.value === '' !field.value || field.value.length === 0 || field.value === ''
return ( return (
<>
<InputGroup> <InputGroup>
<input <InputElement
className={styles.input} className={`${styles.input} ${
meta.touched && meta.error ? styles.hasError : ''
}`}
{...props} {...props}
name={name}
value={value}
type="url" type="url"
onBlur={(e: React.SyntheticEvent) => handleButtonClick(e, field.value)}
/> />
<Button <Button
style="primary" style="primary"
size="small" size="small"
onClick={(e: React.SyntheticEvent) => e.preventDefault()} onClick={(e: React.SyntheticEvent) => {
e.preventDefault()
handleButtonClick(e, field.value)
}}
disabled={isButtonDisabled} disabled={isButtonDisabled}
> >
{isLoading ? <Loader /> : submitText} {isLoading ? <Loader /> : submitText}
</Button> </Button>
</InputGroup> </InputGroup>
{meta.touched && meta.error && (
<div className={styles.error}>
<ErrorMessage name={field.name} />
</div>
)}
</>
) )
} }

View File

@ -44,7 +44,6 @@ export const initialValues: FormPublishData = {
author: '', author: '',
description: '', description: '',
tags: '', tags: '',
links: [],
termsAndConditions: false, termsAndConditions: false,
dockerImage: '', dockerImage: '',
dockerImageCustom: '', dockerImageCustom: '',
@ -53,7 +52,8 @@ export const initialValues: FormPublishData = {
}, },
services: [ services: [
{ {
files: undefined, files: [{ url: '' }],
links: [{ url: '' }],
dataTokenOptions: { name: '', symbol: '' }, dataTokenOptions: { name: '', symbol: '' },
timeout: '', timeout: '',
access: '', access: '',
@ -94,10 +94,23 @@ const validationMetadata = {
} }
const validationService = { const validationService = {
files: Yup.array<string[]>() files: Yup.array<{ url: string; valid: boolean }[]>()
.required('Enter a valid URL and click "ADD FILE"') .of(
Yup.object().shape({
url: Yup.string().required('Required'),
valid: Yup.boolean().isTrue().required('File must be valid.')
})
)
.min(1, (param) => `At least one file is required`)
.required('Enter a valid URL and click "ADD FILE"'),
links: Yup.array<{ url: string; valid: boolean }[]>()
.of(
Yup.object().shape({
url: Yup.string().required('Required'),
valid: Yup.boolean().isTrue().required('File must be valid.')
})
)
.nullable(), .nullable(),
links: Yup.array<string[]>().nullable(),
dataTokenOptions: Yup.object().shape({ dataTokenOptions: Yup.object().shape({
name: Yup.string(), name: Yup.string(),
symbol: Yup.string() symbol: Yup.string()

View File

@ -2,13 +2,16 @@ import { DataTokenOptions } from '@utils/datatokens'
import { NftOptions } from '@utils/nft' import { NftOptions } from '@utils/nft'
import { ReactElement } from 'react' import { ReactElement } from 'react'
export interface FormPublishService { interface FileMetadata {
files: {
url: string url: string
valid: boolean valid?: boolean
contentLength: string contentLength?: string
contentType: string contentType?: string
}[] }
export interface FormPublishService {
files: FileMetadata[]
links?: FileMetadata[]
timeout: string timeout: string
dataTokenOptions: DataTokenOptions dataTokenOptions: DataTokenOptions
access: 'Download' | 'Compute' | string access: 'Download' | 'Compute' | string
@ -30,7 +33,6 @@ export interface FormPublishData {
author: string author: string
termsAndConditions: boolean termsAndConditions: boolean
tags?: string tags?: string
links?: string[]
dockerImage?: string dockerImage?: string
dockerImageCustom?: string dockerImageCustom?: string
dockerImageCustomTag?: string dockerImageCustomTag?: string

View File

@ -42,21 +42,17 @@ export async function transformPublishFormToDdo(
name, name,
description, description,
tags, tags,
links,
author, author,
termsAndConditions, termsAndConditions,
dockerImageCustom, dockerImageCustom,
dockerImageCustomTag, dockerImageCustomTag,
dockerImageCustomEntrypoint dockerImageCustomEntrypoint
} = metadata } = metadata
const { access, files, providerUrl, timeout } = services[0] const { access, files, links, providerUrl, timeout } = services[0]
const filesTransformed = files?.length && files[0].valid && [...files[0].url] // Transform from files[0].url to string[] assuming only 1 file
const filesTransformed = files?.length && files[0].valid && [files[0].url]
const filesEncrypted = const linksTransformed = links?.length && links[0].valid && [links[0].url]
files?.length &&
files[0].valid &&
(await getEncryptedFileUrls(filesTransformed, providerUrl, did, accountId))
const newMetadata: Metadata = { const newMetadata: Metadata = {
created: currentTime, created: currentTime,
@ -67,7 +63,7 @@ export async function transformPublishFormToDdo(
tags: transformTags(tags), tags: transformTags(tags),
author, author,
license: 'https://market.oceanprotocol.com/terms', license: 'https://market.oceanprotocol.com/terms',
links, links: linksTransformed,
additionalInformation: { additionalInformation: {
termsAndConditions termsAndConditions
}, },
@ -85,9 +81,15 @@ export async function transformPublishFormToDdo(
}) })
} }
// Encypt just created string[] of urls
const filesEncrypted =
files?.length &&
files[0].valid &&
(await getEncryptedFileUrls(filesTransformed, providerUrl, did, accountId))
const newService: Service = { const newService: Service = {
type: access, type: access,
files: filesEncrypted, files: filesEncrypted || '',
datatokenAddress, datatokenAddress,
serviceEndpoint: providerUrl, serviceEndpoint: providerUrl,
timeout: mapTimeoutStringToSeconds(timeout), timeout: mapTimeoutStringToSeconds(timeout),