mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
kinda make file input work
This commit is contained in:
parent
b3e4940d08
commit
482a307f80
@ -16,7 +16,7 @@
|
|||||||
"label": "Files",
|
"label": "Files",
|
||||||
"placeholder": "e.g. https://file.com/file.json",
|
"placeholder": "e.g. https://file.com/file.json",
|
||||||
"help": "Please provide a URL to your data set file.",
|
"help": "Please provide a URL to your data set file.",
|
||||||
"type": "url",
|
"type": "files",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import React from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import slugify from '@sindresorhus/slugify'
|
import slugify from '@sindresorhus/slugify'
|
||||||
import styles from './InputElement.module.css'
|
import styles from './InputElement.module.css'
|
||||||
import { InputProps } from '.'
|
import { InputProps } from '.'
|
||||||
|
import FilesInput from '../../molecules/FilesInput'
|
||||||
|
|
||||||
export default function InputElement(props: InputProps) {
|
export default function InputElement(props: InputProps): ReactElement {
|
||||||
const { type, options, rows, name } = props
|
const { type, options, rows, name } = props
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -52,6 +53,8 @@ export default function InputElement(props: InputProps) {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
case 'files':
|
||||||
|
return <FilesInput name={name} {...props} />
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
.field {
|
.field {
|
||||||
margin-bottom: var(--spacer);
|
margin-bottom: var(--spacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field .field {
|
||||||
|
margin-bottom: calc(var(--spacer) / 2);
|
||||||
|
}
|
||||||
|
@ -35,7 +35,7 @@ export interface InputProps {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Input(props: InputProps) {
|
export default function Input(props: InputProps): ReactElement {
|
||||||
const {
|
const {
|
||||||
required,
|
required,
|
||||||
name,
|
name,
|
||||||
@ -54,6 +54,11 @@ export default function Input(props: InputProps) {
|
|||||||
|
|
||||||
{help && <Help>{help}</Help>}
|
{help && <Help>{help}</Help>}
|
||||||
{additionalComponent && additionalComponent}
|
{additionalComponent && additionalComponent}
|
||||||
|
|
||||||
|
{/* TODO: Make field errors show up here */}
|
||||||
|
{/* {meta && meta.touched && meta.error ? (
|
||||||
|
<div className="error">{meta.error}</div>
|
||||||
|
) : null} */}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
40
src/components/molecules/FilesInput/Info.module.css
Normal file
40
src/components/molecules/FilesInput/Info.module.css
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
.info {
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: calc(var(--spacer) / 2);
|
||||||
|
border: 1px solid var(--brand-grey-lighter);
|
||||||
|
background-color: var(--brand-grey-dimmed);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.url {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
line-height: var(--line-height);
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-all;
|
||||||
|
padding-right: calc(var(--spacer) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info ul {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info li {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
margin-right: calc(var(--spacer) / 2);
|
||||||
|
color: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.removeButton {
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -0.2rem;
|
||||||
|
right: 0;
|
||||||
|
font-size: var(--font-size-h3);
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--brand-grey);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
27
src/components/molecules/FilesInput/Info.tsx
Normal file
27
src/components/molecules/FilesInput/Info.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React, { ReactElement } from 'react'
|
||||||
|
import { File } from '@oceanprotocol/squid'
|
||||||
|
import { prettySize } from '../../../utils'
|
||||||
|
import cleanupContentType from '../../../utils/cleanupContentType'
|
||||||
|
import styles from './Info.module.css'
|
||||||
|
|
||||||
|
export default function FileInfo({
|
||||||
|
file,
|
||||||
|
removeItem
|
||||||
|
}: {
|
||||||
|
file: File
|
||||||
|
removeItem(): void
|
||||||
|
}): ReactElement {
|
||||||
|
return (
|
||||||
|
<div className={styles.info}>
|
||||||
|
<h3 className={styles.url}>{file.url}</h3>
|
||||||
|
<ul>
|
||||||
|
<li>URL confirmed</li>
|
||||||
|
{file.contentLength && <li>{prettySize(+file.contentLength)}</li>}
|
||||||
|
{file.contentType && <li>{cleanupContentType(file.contentType)}</li>}
|
||||||
|
</ul>
|
||||||
|
<button className={styles.removeButton} onClick={() => removeItem()}>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
31
src/components/molecules/FilesInput/Input.tsx
Normal file
31
src/components/molecules/FilesInput/Input.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React, { ReactElement } from 'react'
|
||||||
|
import isUrl from 'is-url-superb'
|
||||||
|
import Button from '../../atoms/Button'
|
||||||
|
import Input from '../../atoms/Input'
|
||||||
|
import { useField, FormikProps } from 'formik'
|
||||||
|
import { File } from '@oceanprotocol/squid'
|
||||||
|
|
||||||
|
export default function FileInput({
|
||||||
|
handleButtonClick,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
handleButtonClick(e: React.SyntheticEvent, data: string): void
|
||||||
|
props: FormikProps<File>
|
||||||
|
}): ReactElement {
|
||||||
|
const [field, meta, helpers] = useField(props)
|
||||||
|
console.log(field)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Input type="url" name="url" placeholder="e.g." {...field} />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
onClick={(e: React.SyntheticEvent) => handleButtonClick(e, field.value)}
|
||||||
|
// disabled={!isUrl(field && field.value)}
|
||||||
|
>
|
||||||
|
Add File
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
57
src/components/molecules/FilesInput/index.tsx
Normal file
57
src/components/molecules/FilesInput/index.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import React, { ReactElement, useState } from 'react'
|
||||||
|
import isUrl from 'is-url-superb'
|
||||||
|
import { useField, FormikProps } from 'formik'
|
||||||
|
import { File } from '@oceanprotocol/squid'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import Input from '../../atoms/Input'
|
||||||
|
import Button from '../../atoms/Button'
|
||||||
|
import Loader from '../../atoms/Loader'
|
||||||
|
import styles from './index.module.css'
|
||||||
|
import FileInfo from './Info'
|
||||||
|
import FileInput from './Input'
|
||||||
|
import shortid from 'shortid'
|
||||||
|
import { getFileInfo } from '../../../utils'
|
||||||
|
|
||||||
|
interface Values {
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FilesInput(props: FormikProps<File>): ReactElement {
|
||||||
|
const [field, meta, helpers] = useField(props)
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [file, setFile] = useState<File>()
|
||||||
|
|
||||||
|
const handleButtonClick = async (e: React.SyntheticEvent, url: string) => {
|
||||||
|
// File example 'https://oceanprotocol.com/tech-whitepaper.pdf'
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true)
|
||||||
|
const newFileInfo = await getFileInfo(url)
|
||||||
|
newFileInfo && setFile(newFileInfo)
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('Could not fetch file info. Please check url and try again')
|
||||||
|
console.error(error.message)
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeItem() {
|
||||||
|
setFile(undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{file ? (
|
||||||
|
<FileInfo file={file} removeItem={removeItem} />
|
||||||
|
) : (
|
||||||
|
<FileInput
|
||||||
|
{...props}
|
||||||
|
{...field}
|
||||||
|
handleButtonClick={handleButtonClick}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render } from '@testing-library/react'
|
import { render } from '@testing-library/react'
|
||||||
import Form, { transformErrors } from '../../../src/components/molecules/Form'
|
import Form, {
|
||||||
|
transformErrors
|
||||||
|
} from '../../../src/components/molecules/FilesInput'
|
||||||
import {
|
import {
|
||||||
publishFormData,
|
publishFormData,
|
||||||
PublishFormDataInterface,
|
PublishFormDataInterface,
|
||||||
@ -8,7 +10,7 @@ import {
|
|||||||
PublishFormUiSchema
|
PublishFormUiSchema
|
||||||
} from '../../../src/models/PublishForm'
|
} from '../../../src/models/PublishForm'
|
||||||
import testFormData from '../__fixtures__/testFormData'
|
import testFormData from '../__fixtures__/testFormData'
|
||||||
import { transformPublishFormToMetadata } from '../../../src/components/pages/Publish/PublishForm'
|
import { transformPublishFormToMetadata } from '../../../src/components/pages/Publish/utils'
|
||||||
import { MetaDataMarket } from '../../../src/@types/MetaData'
|
import { MetaDataMarket } from '../../../src/@types/MetaData'
|
||||||
|
|
||||||
describe('PublishForm', () => {
|
describe('PublishForm', () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user