1
0
mirror of https://github.com/oceanprotocol/commons.git synced 2023-03-15 18:03:00 +01:00

more error output in UI

This commit is contained in:
Matthias Kretschmann 2019-09-20 13:51:24 +02:00
parent 483cc35de3
commit 60a570892b
Signed by: m
GPG Key ID: 606EEEF3C479A91F
9 changed files with 135 additions and 103 deletions

View File

@ -15,7 +15,7 @@ export interface IpfsConfig {
export default function useIpfsApi(config: IpfsConfig) { export default function useIpfsApi(config: IpfsConfig) {
const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs)) const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs))
const [ipfsError, setIpfsError] = useState(null) const [ipfsError, setIpfsError] = useState('')
useEffect(() => { useEffect(() => {
async function initIpfs() { async function initIpfs() {
@ -49,7 +49,7 @@ export default function useIpfsApi(config: IpfsConfig) {
ipfs = null ipfs = null
ipfsMessage = '' ipfsMessage = ''
ipfsVersion = '' ipfsVersion = ''
setIpfsError(null) setIpfsError('')
} }
} }
}, []) }, [])

View File

@ -1,32 +0,0 @@
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import Ipfs from './Ipfs'
const addFile = jest.fn()
describe('Ipfs', () => {
const ui = <Ipfs addFile={addFile} />
it('renders without crashing', async () => {
const { container, findByText } = render(ui)
expect(container.firstChild).toBeInTheDocument()
// wait for IPFS node
await findByText(/Connected to /)
})
it('files can be dropped', async () => {
const { container, findByText } = render(ui)
// wait for IPFS node
await findByText(/Connected to /)
const file = new File(['(⌐□_□)'], 'chucknorris.png', {
type: 'image/png'
})
// drop a file
const dropzoneInput = container.querySelector('.dropzone input')
dropzoneInput && fireEvent.change(dropzoneInput, { target: [file] })
})
})

View File

@ -1,4 +1,4 @@
@import '../../../styles/variables'; @import '../../../../styles/variables';
.ipfsForm { .ipfsForm {
margin-top: $spacer / 2; margin-top: $spacer / 2;
@ -23,30 +23,3 @@
} }
} }
} }
.message {
font-size: $font-size-small;
margin-top: $spacer / 2;
color: $brand-grey-light;
&:before {
content: '';
width: .5rem;
height: .5rem;
display: inline-block;
background: $green;
border-radius: 50%;
margin-right: $spacer / 4;
margin-bottom: .05rem;
}
}
.error {
composes: message;
color: $red;
&:before {
border-radius: 0;
background: $red;
}
}

View File

@ -0,0 +1,26 @@
import React from 'react'
import Label from '../../../../components/atoms/Form/Label'
import Status from './Status'
import styles from './Form.module.scss'
export default function Form({
children,
ipfsMessage,
ipfsError,
error
}: {
children: any
ipfsMessage: string
ipfsError?: string
error?: string
}) {
return (
<div className={styles.ipfsForm}>
<Label htmlFor="fileUpload" required>
Add File To IPFS
</Label>
{children}
<Status message={ipfsMessage} error={ipfsError || error} />
</div>
)
}

View File

@ -0,0 +1,28 @@
@import '../../../../styles/variables';
.message {
font-size: $font-size-small;
margin-top: $spacer / 2;
color: $brand-grey-light;
&:before {
content: '';
width: .5rem;
height: .5rem;
display: inline-block;
background: $green;
border-radius: 50%;
margin-right: $spacer / 4;
margin-bottom: .05rem;
}
}
.error {
composes: message;
color: $red;
&:before {
border-radius: 0;
background: $red;
}
}

View File

@ -0,0 +1,13 @@
import React from 'react'
import styles from './Status.module.scss'
export default function Status({
message,
error
}: {
message: string
error?: string
}) {
const classes = error ? styles.error : styles.message
return <div className={classes}>{message}</div>
}

View File

@ -0,0 +1,44 @@
import React from 'react'
import { render, fireEvent, waitForElement, act } from '@testing-library/react'
import Ipfs from '.'
const addFile = jest.fn()
describe('IPFS', () => {
const ui = <Ipfs addFile={addFile} />
const file = new File(['(⌐□_□)'], 'chucknorris.png', {
type: 'image/png'
})
it('HTTP API: files can be dropped', async () => {
const { container, findByText, getByText } = render(ui)
expect(container).toBeInTheDocument()
// wait for IPFS node
await findByText(/Connected to /)
// drop a file
const dropzoneInput = container.querySelector('.dropzone')
Object.defineProperty(dropzoneInput, 'files', { value: [file] })
act(() => {
dropzoneInput && fireEvent.drop(dropzoneInput)
})
const addingText = await waitForElement(() => getByText(/Adding /))
expect(addingText).toBeDefined()
})
// it('Local Node: files can be dropped', async () => {
// const { debug, container, findByText, getByText } = render(
// <Ipfs addFile={addFile} node />
// )
// expect(container).toBeInTheDocument()
// // wait for IPFS node
// await findByText(/IPFS started/)
// // drop a file
// const dropzoneInput = container.querySelector('.dropzone input')
// Object.defineProperty(dropzoneInput, 'files', { value: [file] })
// dropzoneInput && fireEvent.drop(dropzoneInput)
// await waitForElement(() => getByText(/File found/), { timeout: 100000 })
// expect(addFile).toHaveBeenCalledTimes(1)
// })
})

View File

@ -1,12 +1,11 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import useIpfsApi, { IpfsConfig } from '../../../hooks/use-ipfs-api' import useIpfsApi, { IpfsConfig } from '../../../../hooks/use-ipfs-api'
import Label from '../../../components/atoms/Form/Label' import Spinner from '../../../../components/atoms/Spinner'
import Spinner from '../../../components/atoms/Spinner' import Dropzone from '../../../../components/molecules/Dropzone'
import Dropzone from '../../../components/molecules/Dropzone' import { formatBytes, pingUrl, readFileAsync } from '../../../../utils/utils'
import { formatBytes, pingUrl, readFileAsync } from '../../../utils/utils' import { ipfsGatewayUri } from '../../../../config'
import { ipfsGatewayUri } from '../../../config' import Form from './Form'
import styles from './Ipfs.module.scss'
const config: IpfsConfig = { const config: IpfsConfig = {
host: 'ipfs.infura.io', host: 'ipfs.infura.io',
@ -15,34 +14,26 @@ const config: IpfsConfig = {
} }
export default function Ipfs({ addFile }: { addFile(url: string): void }) { export default function Ipfs({ addFile }: { addFile(url: string): void }) {
const { const { ipfs, isIpfsReady, ipfsError, ipfsMessage } = useIpfsApi(config)
ipfs,
ipfsVersion,
isIpfsReady,
ipfsError,
ipfsMessage
} = useIpfsApi(config)
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [message, setMessage] = useState('') const [message, setMessage] = useState('')
const [fileSize, setFileSize] = useState('') const [fileSize, setFileSize] = useState('')
const [fileSizeReceived, setFileSizeReceived] = useState('') const [fileSizeReceived, setFileSizeReceived] = useState('')
const [error, setError] = useState('')
useEffect(() => { useEffect(() => {
setMessage( setMessage(
`Adding to IPFS<br /> `Adding to IPFS<br />
<small>${fileSizeReceived || 0}/${fileSize}</small><br />` <small>${fileSizeReceived || 0}/${fileSize}</small><br />`
) )
}) }, [fileSize, fileSizeReceived])
async function addToIpfs(data: any) { async function addToIpfs(data: any) {
try { try {
const response = await ipfs.add(data, { const response = await ipfs.add(data, {
wrapWithDirectory: true, wrapWithDirectory: true,
progress: (length: number) => { progress: (length: number) =>
console.log(`Received: ${formatBytes(length, 0)}`)
setFileSizeReceived(formatBytes(length, 0)) setFileSizeReceived(formatBytes(length, 0))
}
}) })
// CID of wrapping directory is returned last // CID of wrapping directory is returned last
@ -50,25 +41,26 @@ export default function Ipfs({ addFile }: { addFile(url: string): void }) {
console.log(`File added: ${cid}`) console.log(`File added: ${cid}`)
return cid return cid
} catch (error) { } catch (error) {
console.error(`Adding to IPFS failed: ${error.message}`) setError(`Adding to IPFS failed: ${error.message}`)
setLoading(false) setLoading(false)
} }
} }
async function handleOnDrop(acceptedFiles: File[]) { async function handleOnDrop(acceptedFiles: any) {
if (!acceptedFiles[0]) return if (!acceptedFiles[0]) return
const { name, size } = acceptedFiles[0]
const totalSize = formatBytes(size, 0)
setLoading(true) setLoading(true)
setError('')
const { path, size } = acceptedFiles[0]
const totalSize = formatBytes(size, 0)
setFileSize(totalSize) setFileSize(totalSize)
// Add file to IPFS node // Add file to IPFS node
const content: any = await readFileAsync(acceptedFiles[0]) const content: any = await readFileAsync(acceptedFiles[0])
const data = Buffer.from(content) const data = Buffer.from(content)
const fileDetails = { const fileDetails = {
path: name, path,
content: data content: data
} }
@ -77,8 +69,8 @@ export default function Ipfs({ addFile }: { addFile(url: string): void }) {
// Ping gateway url to make it globally available, // Ping gateway url to make it globally available,
// but store native url in DDO. // but store native url in DDO.
const urlGateway = `${ipfsGatewayUri}/ipfs/${cid}/${name}` const urlGateway = `${ipfsGatewayUri}/ipfs/${cid}/${path}`
const url = `ipfs://${cid}/${name}` const url = `ipfs://${cid}/${path}`
setMessage('Checking IPFS gateway URL') setMessage('Checking IPFS gateway URL')
await pingUrl(urlGateway) await pingUrl(urlGateway)
@ -88,10 +80,7 @@ export default function Ipfs({ addFile }: { addFile(url: string): void }) {
} }
return ( return (
<div className={styles.ipfsForm}> <Form error={error} ipfsMessage={ipfsMessage} ipfsError={ipfsError}>
<Label htmlFor="fileUpload" required>
Add File To IPFS
</Label>
{loading ? ( {loading ? (
<Spinner message={message} /> <Spinner message={message} />
) : ( ) : (
@ -101,12 +90,6 @@ export default function Ipfs({ addFile }: { addFile(url: string): void }) {
disabled={!isIpfsReady} disabled={!isIpfsReady}
/> />
)} )}
{ipfsMessage !== '' && ( </Form>
<div className={styles.message} title={ipfsVersion}>
{ipfsMessage}
</div>
)}
{ipfsError && <div className={styles.error}>{ipfsError}</div>}
</div>
) )
} }

View File

@ -74,9 +74,6 @@ describe('Files', () => {
await waitForElement(() => getByText('- Cancel')) await waitForElement(() => getByText('- Cancel'))
expect(container.querySelector('.ipfsForm')).toBeInTheDocument() expect(container.querySelector('.ipfsForm')).toBeInTheDocument()
// wait for IPFS node
await findByText(/Connected to /)
// close // close
fireEvent.click(getByText('- Cancel')) fireEvent.click(getByText('- Cancel'))
await waitForElement(() => getByText('+ Add to IPFS')) await waitForElement(() => getByText('+ Add to IPFS'))