mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
refactor all the URL inputs
This commit is contained in:
parent
1566051545
commit
06dca21d47
@ -38,3 +38,7 @@
|
|||||||
color: var(--font-color-text);
|
color: var(--font-color-text);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info li.success {
|
||||||
|
color: var(--brand-alert-green);
|
||||||
|
}
|
||||||
|
@ -1,37 +1,25 @@
|
|||||||
import React, { ReactElement, useEffect } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { prettySize } from './utils'
|
import { prettySize } from './utils'
|
||||||
import cleanupContentType from '@utils/cleanupContentType'
|
import cleanupContentType from '@utils/cleanupContentType'
|
||||||
import styles from './Info.module.css'
|
import styles from './Info.module.css'
|
||||||
import { useField, useFormikContext } from 'formik'
|
|
||||||
import { FileMetadata } from '@utils/provider'
|
import { FileMetadata } from '@utils/provider'
|
||||||
|
|
||||||
export default function FileInfo({
|
export default function FileInfo({
|
||||||
name,
|
file,
|
||||||
file
|
handleClose
|
||||||
}: {
|
}: {
|
||||||
name: string
|
|
||||||
file: FileMetadata
|
file: FileMetadata
|
||||||
|
handleClose(): void
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { validateField } = useFormikContext()
|
|
||||||
const [field, meta, helpers] = useField(name)
|
|
||||||
|
|
||||||
// On mount, validate the field manually
|
|
||||||
useEffect(() => {
|
|
||||||
validateField(name)
|
|
||||||
}, [name, validateField])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
<h3 className={styles.url}>{(file as any).url}</h3>
|
<h3 className={styles.url}>{(file as any).url}</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>URL confirmed</li>
|
<li className={styles.success}>✓ URL confirmed</li>
|
||||||
{file.contentLength && <li>{prettySize(+file.contentLength)}</li>}
|
{file.contentLength && <li>{prettySize(+file.contentLength)}</li>}
|
||||||
{file.contentType && <li>{cleanupContentType(file.contentType)}</li>}
|
{file.contentType && <li>{cleanupContentType(file.contentType)}</li>}
|
||||||
</ul>
|
</ul>
|
||||||
<button
|
<button className={styles.removeButton} onClick={handleClose}>
|
||||||
className={styles.removeButton}
|
|
||||||
onClick={() => helpers.setValue(undefined)}
|
|
||||||
>
|
|
||||||
×
|
×
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,6 +8,7 @@ import { getFileInfo } from '@utils/provider'
|
|||||||
import { useWeb3 } from '@context/Web3'
|
import { useWeb3 } from '@context/Web3'
|
||||||
import { getOceanConfig } from '@utils/ocean'
|
import { getOceanConfig } from '@utils/ocean'
|
||||||
import { useCancelToken } from '@hooks/useCancelToken'
|
import { useCancelToken } from '@hooks/useCancelToken'
|
||||||
|
import { initialValues } from 'src/components/Publish/_constants'
|
||||||
|
|
||||||
export default function FilesInput(props: InputProps): ReactElement {
|
export default function FilesInput(props: InputProps): ReactElement {
|
||||||
const [field, meta, helpers] = useField(props.name)
|
const [field, meta, helpers] = useField(props.name)
|
||||||
@ -44,17 +45,23 @@ export default function FilesInput(props: InputProps): ReactElement {
|
|||||||
loadFileInfo(url)
|
loadFileInfo(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
helpers.setValue(initialValues.services[0].files)
|
||||||
|
helpers.setTouched(false)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{field?.value && field.value[0].url !== '' && field.value[0].valid ? (
|
{field?.value?.length &&
|
||||||
<FileInfo name={props.name} file={field.value[0]} />
|
field.value[0].url !== '' &&
|
||||||
|
field.value[0].valid ? (
|
||||||
|
<FileInfo file={field.value[0]} handleClose={handleClose} />
|
||||||
) : (
|
) : (
|
||||||
<UrlInput
|
<UrlInput
|
||||||
submitText="Add File"
|
submitText="Validate"
|
||||||
{...props}
|
{...props}
|
||||||
{...field}
|
name={`${field.name}[0].url`}
|
||||||
name={`${props.name}[0].url`}
|
hasError={Boolean(meta.touched && meta.error)}
|
||||||
value={field?.value && field.value[0].url}
|
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
handleButtonClick={handleButtonClick}
|
handleButtonClick={handleButtonClick}
|
||||||
/>
|
/>
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
.error {
|
||||||
|
composes: error from '@shared/FormInput/index.module.css';
|
||||||
|
}
|
||||||
|
|
||||||
|
.restore {
|
||||||
|
font-family: var(--font-family-base);
|
||||||
|
text-transform: none;
|
||||||
|
font-weight: var(--font-weight-base);
|
||||||
|
}
|
@ -1,13 +1,16 @@
|
|||||||
import React, { ReactElement, useState } from 'react'
|
import React, { ReactElement, useState } from 'react'
|
||||||
import { useField } from 'formik'
|
import { ErrorMessage, useField } from 'formik'
|
||||||
import UrlInput from '../URLInput'
|
import UrlInput from '../URLInput'
|
||||||
import { useOcean } from '@context/Ocean'
|
import { useOcean } from '@context/Ocean'
|
||||||
import { InputProps } from '@shared/FormInput'
|
import { InputProps } from '@shared/FormInput'
|
||||||
|
import FileInfo from '../FilesInput/Info'
|
||||||
|
import styles from './index.module.css'
|
||||||
|
import Button from '@shared/atoms/Button'
|
||||||
|
import { initialValues } from 'src/components/Publish/_constants'
|
||||||
|
|
||||||
export default function CustomProvider(props: InputProps): ReactElement {
|
export default function CustomProvider(props: InputProps): ReactElement {
|
||||||
const [field, meta, helpers] = useField(props.name)
|
const [field, meta, helpers] = useField(props.name)
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [isValid, setIsValid] = useState(false)
|
|
||||||
const { ocean, config } = useOcean()
|
const { ocean, config } = useOcean()
|
||||||
|
|
||||||
async function validateProvider(url: string) {
|
async function validateProvider(url: string) {
|
||||||
@ -16,31 +19,60 @@ export default function CustomProvider(props: InputProps): ReactElement {
|
|||||||
try {
|
try {
|
||||||
// TODO: #948 Remove ocean.provider.isValidProvider dependency.
|
// TODO: #948 Remove ocean.provider.isValidProvider dependency.
|
||||||
const isValid = await ocean.provider.isValidProvider(url)
|
const isValid = await ocean.provider.isValidProvider(url)
|
||||||
setIsValid(isValid)
|
helpers.setValue({ url, valid: isValid })
|
||||||
helpers.setError(undefined)
|
helpers.setError(undefined)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setIsValid(false)
|
|
||||||
helpers.setError(
|
helpers.setError(
|
||||||
'Could not validate provider. Please check URL and try again'
|
'Could not validate provider. Please check URL and try again.'
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleButtonClick(e: React.SyntheticEvent, url: string) {
|
async function handleValidateButtonClick(
|
||||||
|
e: React.SyntheticEvent,
|
||||||
|
url: string
|
||||||
|
) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
validateProvider(url)
|
validateProvider(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
function handleFileInfoClose() {
|
||||||
<UrlInput
|
helpers.setValue({ url: '', valid: false })
|
||||||
submitText="Validate"
|
helpers.setTouched(false)
|
||||||
isValid={isValid}
|
}
|
||||||
{...props}
|
|
||||||
{...field}
|
function handleRestore(e: React.SyntheticEvent) {
|
||||||
isLoading={isLoading}
|
e.preventDefault()
|
||||||
handleButtonClick={handleButtonClick}
|
helpers.setValue(initialValues.services[0].providerUrl)
|
||||||
/>
|
}
|
||||||
|
|
||||||
|
return field?.value?.valid ? (
|
||||||
|
<FileInfo file={field.value} handleClose={handleFileInfoClose} />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<UrlInput
|
||||||
|
submitText="Validate"
|
||||||
|
{...props}
|
||||||
|
name={`${field.name}.url`}
|
||||||
|
hasError={Boolean(meta.touched && meta.error)}
|
||||||
|
isLoading={isLoading}
|
||||||
|
handleButtonClick={handleValidateButtonClick}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
style="text"
|
||||||
|
size="small"
|
||||||
|
onClick={handleRestore}
|
||||||
|
className={styles.restore}
|
||||||
|
>
|
||||||
|
Use Default Provider
|
||||||
|
</Button>
|
||||||
|
{typeof meta.error === 'string' && meta.touched && meta.error && (
|
||||||
|
<div className={styles.error}>
|
||||||
|
<ErrorMessage name={field.name} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -11,51 +11,41 @@ export default function URLInput({
|
|||||||
handleButtonClick,
|
handleButtonClick,
|
||||||
isLoading,
|
isLoading,
|
||||||
name,
|
name,
|
||||||
value,
|
hasError,
|
||||||
isValid,
|
|
||||||
...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
|
name: string
|
||||||
value: string
|
hasError: boolean
|
||||||
isValid?: boolean
|
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const [field, meta] = useField(name)
|
const [field, meta] = useField(name)
|
||||||
const isButtonDisabled =
|
const isButtonDisabled = !field?.value || field.value === ''
|
||||||
!field.value || field.value.length === 0 || field.value === ''
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<InputElement
|
<InputElement
|
||||||
className={`${styles.input} ${
|
className={`${styles.input} ${
|
||||||
meta.touched && meta.error ? styles.hasError : ''
|
!isLoading && hasError ? styles.hasError : ''
|
||||||
}`}
|
}`}
|
||||||
{...props}
|
{...props}
|
||||||
name={name}
|
{...field}
|
||||||
value={value}
|
|
||||||
type="url"
|
type="url"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isValid ? (
|
<Button
|
||||||
<Button size="small" disabled className={styles.success}>
|
style="primary"
|
||||||
✓ Valid
|
size="small"
|
||||||
</Button>
|
onClick={(e: React.SyntheticEvent) => {
|
||||||
) : (
|
e.preventDefault()
|
||||||
<Button
|
handleButtonClick(e, field.value)
|
||||||
style="primary"
|
}}
|
||||||
size="small"
|
disabled={isButtonDisabled}
|
||||||
onClick={(e: React.SyntheticEvent) => {
|
>
|
||||||
e.preventDefault()
|
{isLoading ? <Loader /> : submitText}
|
||||||
handleButtonClick(e, field.value)
|
</Button>
|
||||||
}}
|
|
||||||
disabled={isButtonDisabled}
|
|
||||||
>
|
|
||||||
{isLoading ? <Loader /> : submitText}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
|
||||||
{meta.touched && meta.error && (
|
{meta.touched && meta.error && (
|
||||||
|
@ -54,8 +54,8 @@ export default function ServicesFields(): ReactElement {
|
|||||||
if (!values?.user?.chainId) return
|
if (!values?.user?.chainId) return
|
||||||
|
|
||||||
const config = getOceanConfig(values.user.chainId)
|
const config = getOceanConfig(values.user.chainId)
|
||||||
config && setFieldValue('services[0].providerUrl', config.providerUri)
|
config && setFieldValue('services[0].providerUrl.url', config.providerUri)
|
||||||
setTouched({ services: [{ providerUrl: true }] })
|
setTouched({ services: [{ providerUrl: { url: true } }] })
|
||||||
}, [values.user.chainId, setFieldValue, setTouched])
|
}, [values.user.chainId, setFieldValue, setTouched])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -62,7 +62,10 @@ export const initialValues: FormPublishData = {
|
|||||||
dataTokenOptions: { name: '', symbol: '' },
|
dataTokenOptions: { name: '', symbol: '' },
|
||||||
timeout: '',
|
timeout: '',
|
||||||
access: '',
|
access: '',
|
||||||
providerUrl: 'https://provider.mainnet.oceanprotocol.com'
|
providerUrl: {
|
||||||
|
url: 'https://provider.mainnet.oceanprotocol.com',
|
||||||
|
valid: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
pricing: {
|
pricing: {
|
||||||
|
@ -15,7 +15,7 @@ export interface FormPublishService {
|
|||||||
timeout: string
|
timeout: string
|
||||||
dataTokenOptions: DataTokenOptions
|
dataTokenOptions: DataTokenOptions
|
||||||
access: 'Download' | 'Compute' | string
|
access: 'Download' | 'Compute' | string
|
||||||
providerUrl?: string
|
providerUrl?: { url: string; valid: boolean }
|
||||||
algorithmPrivacy?: boolean
|
algorithmPrivacy?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ const validationService = {
|
|||||||
files: Yup.array<{ url: string; valid: boolean }[]>()
|
files: Yup.array<{ url: string; valid: boolean }[]>()
|
||||||
.of(
|
.of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
url: Yup.string().required('Required'),
|
url: Yup.string().url('Must be a valid URL.').required('Required'),
|
||||||
valid: Yup.boolean().isTrue().required('File must be valid.')
|
valid: Yup.boolean().isTrue().required('File must be valid.')
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -31,7 +31,7 @@ const validationService = {
|
|||||||
links: Yup.array<{ url: string; valid: boolean }[]>()
|
links: Yup.array<{ url: string; valid: boolean }[]>()
|
||||||
.of(
|
.of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
url: Yup.string(),
|
url: Yup.string().url('Must be a valid URL.'),
|
||||||
// TODO: require valid file only when URL is given
|
// TODO: require valid file only when URL is given
|
||||||
valid: Yup.boolean()
|
valid: Yup.boolean()
|
||||||
// valid: Yup.boolean().isTrue('File must be valid.')
|
// valid: Yup.boolean().isTrue('File must be valid.')
|
||||||
@ -46,7 +46,10 @@ const validationService = {
|
|||||||
access: Yup.string()
|
access: Yup.string()
|
||||||
.matches(/compute|download/g)
|
.matches(/compute|download/g)
|
||||||
.required('Required'),
|
.required('Required'),
|
||||||
providerUrl: Yup.string().url().required('Required')
|
providerUrl: Yup.object().shape({
|
||||||
|
url: Yup.string().url('Must be a valid URL.').required('Required'),
|
||||||
|
valid: Yup.boolean().isTrue().required('Valid Provider is required.')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationPricing = {
|
const validationPricing = {
|
||||||
|
Loading…
Reference in New Issue
Block a user