From 5bf854315041d6ce0ba3cf8493067c9e75f4eec9 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 24 Nov 2021 12:29:14 +0000 Subject: [PATCH] refactor all the URL inputs * only act on user action, we were firing events left and right on every keystroke * remove all local state management, the field has the value already * add success state for provider input --- .../@shared/FormFields/CustomProvider.tsx | 53 +++++++------------ .../@shared/FormFields/FilesInput/index.tsx | 29 +++------- .../{Input.module.css => index.module.css} | 5 ++ .../URLInput/{Input.tsx => index.tsx} | 35 +++++++----- src/components/Publish/Services/index.tsx | 16 +++++- src/components/Publish/_constants.tsx | 2 +- 6 files changed, 68 insertions(+), 72 deletions(-) rename src/components/@shared/FormFields/URLInput/{Input.module.css => index.module.css} (75%) rename src/components/@shared/FormFields/URLInput/{Input.tsx => index.tsx} (64%) diff --git a/src/components/@shared/FormFields/CustomProvider.tsx b/src/components/@shared/FormFields/CustomProvider.tsx index 77c107024..56413ad14 100644 --- a/src/components/@shared/FormFields/CustomProvider.tsx +++ b/src/components/@shared/FormFields/CustomProvider.tsx @@ -1,56 +1,41 @@ -import React, { ReactElement, useState, useEffect } from 'react' +import React, { ReactElement, useState } from 'react' import { useField } from 'formik' -import { toast } from 'react-toastify' -import CustomInput from './URLInput/Input' +import UrlInput from './URLInput' import { useOcean } from '@context/Ocean' import { InputProps } from '@shared/FormInput' export default function CustomProvider(props: InputProps): ReactElement { const [field, meta, helpers] = useField(props.name) const [isLoading, setIsLoading] = useState(false) - const [providerUrl, setProviderUrl] = useState() + const [isValid, setIsValid] = useState(false) const { ocean, config } = useOcean() - function loadProvider() { - if (!providerUrl) return - async function validateProvider() { - let valid: boolean - try { - setIsLoading(true) - valid = await ocean.provider.isValidProvider(providerUrl) - } catch (error) { - valid = false - console.error(error.message) - } finally { - valid - ? toast.success('Perfect! That provider URL looks good 🐳') - : toast.error( - 'Could not validate provider. Please check URL and try again' - ) + async function validateProvider(url: string) { + setIsLoading(true) - setIsLoading(false) - } + try { + const isValid = await ocean.provider.isValidProvider(url) + setIsValid(isValid) + helpers.setError(undefined) + } catch (error) { + setIsValid(false) + helpers.setError( + 'Could not validate provider. Please check URL and try again' + ) + } finally { + setIsLoading(false) } - validateProvider() } - useEffect(() => { - loadProvider() - }, [providerUrl, config?.providerUri]) - async function handleButtonClick(e: React.SyntheticEvent, url: string) { - helpers.setTouched(false) e.preventDefault() - if (providerUrl === url) { - loadProvider() - } - - setProviderUrl(url) + validateProvider(url) } return ( - () const { chainId } = useWeb3() const newCancelToken = useCancelToken() - function loadFileInfo() { + function loadFileInfo(url: string) { const config = getOceanConfig(chainId || 1) async function validateUrl() { try { setIsLoading(true) const checkedFile = await getFileInfo( - fileUrl, + url, config?.providerUri, newCancelToken() ) - checkedFile && helpers.setValue([{ url: fileUrl, ...checkedFile[0] }]) + checkedFile && helpers.setValue([{ url, ...checkedFile[0] }]) } catch (error) { toast.error('Could not fetch file info. Please check URL and try again') console.error(error.message) @@ -36,27 +35,13 @@ export default function FilesInput(props: InputProps): ReactElement { } } - fileUrl && validateUrl() + validateUrl() } - useEffect(() => { - loadFileInfo() - }, [fileUrl]) - async function handleButtonClick(e: React.SyntheticEvent, url: string) { - // hack so the onBlur-triggered validation does not show, - // like when this field is required - helpers.setTouched(false) - // File example 'https://oceanprotocol.com/tech-whitepaper.pdf' e.preventDefault() - - // In the case when the user re-add the same URL after it was removed (by accident or intentionally) - if (fileUrl === url) { - loadFileInfo() - } - - setFileUrl(url) + loadFileInfo(url) } return ( diff --git a/src/components/@shared/FormFields/URLInput/Input.module.css b/src/components/@shared/FormFields/URLInput/index.module.css similarity index 75% rename from src/components/@shared/FormFields/URLInput/Input.module.css rename to src/components/@shared/FormFields/URLInput/index.module.css index 7cc9b6283..dce4c726f 100644 --- a/src/components/@shared/FormFields/URLInput/Input.module.css +++ b/src/components/@shared/FormFields/URLInput/index.module.css @@ -10,3 +10,8 @@ .error { composes: error from '@shared/FormInput/index.module.css'; } + +.success { + background: var(--brand-alert-green); + opacity: 1 !important; +} diff --git a/src/components/@shared/FormFields/URLInput/Input.tsx b/src/components/@shared/FormFields/URLInput/index.tsx similarity index 64% rename from src/components/@shared/FormFields/URLInput/Input.tsx rename to src/components/@shared/FormFields/URLInput/index.tsx index e87af81f0..9ae46aa16 100644 --- a/src/components/@shared/FormFields/URLInput/Input.tsx +++ b/src/components/@shared/FormFields/URLInput/index.tsx @@ -1,8 +1,8 @@ import React, { ReactElement } from 'react' import Button from '@shared/atoms/Button' -import { ErrorMessage, FieldInputProps, useField } from 'formik' +import { ErrorMessage, useField } from 'formik' import Loader from '@shared/atoms/Loader' -import styles from './Input.module.css' +import styles from './index.module.css' import InputGroup from '@shared/FormInput/InputGroup' import InputElement from '@shared/FormInput/InputElement' @@ -12,6 +12,7 @@ export default function URLInput({ isLoading, name, value, + isValid, ...props }: { submitText: string @@ -19,6 +20,7 @@ export default function URLInput({ isLoading: boolean name: string value: string + isValid?: boolean }): ReactElement { const [field, meta] = useField(name) const isButtonDisabled = @@ -36,17 +38,24 @@ export default function URLInput({ value={value} type="url" /> - + + {isValid ? ( + + ) : ( + + )} {meta.touched && meta.error && ( diff --git a/src/components/Publish/Services/index.tsx b/src/components/Publish/Services/index.tsx index e06a3e589..41a48d345 100644 --- a/src/components/Publish/Services/index.tsx +++ b/src/components/Publish/Services/index.tsx @@ -6,6 +6,8 @@ import IconCompute from '@images/compute.svg' import content from '../../../../content/publish/form.json' import { getFieldContent } from '../_utils' import { FormPublishData } from '../_types' +import { useWeb3 } from '@context/Web3' +import { getOceanConfig } from '@utils/ocean' const accessTypeOptionsTitles = getFieldContent( 'access', @@ -14,7 +16,8 @@ const accessTypeOptionsTitles = getFieldContent( export default function ServicesFields(): ReactElement { // connect with Form state, use for conditional field rendering - const { values, setFieldValue } = useFormikContext() + const { values, setFieldValue, setTouched } = + useFormikContext() const accessTypeOptions = [ { @@ -44,7 +47,16 @@ export default function ServicesFields(): ReactElement { 'services[0].access', values.services[0].algorithmPrivacy === true ? 'compute' : 'download' ) - }, [values.services[0].algorithmPrivacy]) + }, [values.services[0].algorithmPrivacy, setFieldValue]) + + // Auto-change default providerUrl on user network change + useEffect(() => { + if (!values?.user?.chainId) return + + const config = getOceanConfig(values.user.chainId) + config && setFieldValue('services[0].providerUrl', config.providerUri) + setTouched({ services: [{ providerUrl: true }] }) + }, [values.user.chainId, setFieldValue, setTouched]) return ( <> diff --git a/src/components/Publish/_constants.tsx b/src/components/Publish/_constants.tsx index d1a5c8064..522c3f289 100644 --- a/src/components/Publish/_constants.tsx +++ b/src/components/Publish/_constants.tsx @@ -56,7 +56,7 @@ export const initialValues: FormPublishData = { dataTokenOptions: { name: '', symbol: '' }, timeout: '', access: '', - providerUrl: 'https://provider.oceanprotocol.com' + providerUrl: 'https://provider.mainnet.oceanprotocol.com' } ], pricing: {