mirror of
https://github.com/oceanprotocol/commons.git
synced 2023-03-15 18:03:00 +01:00
196 lines
5.5 KiB
TypeScript
196 lines
5.5 KiB
TypeScript
import React, { FormEvent, PureComponent, ChangeEvent } from 'react'
|
|
import axios from 'axios'
|
|
import { Logger } from '@oceanprotocol/squid'
|
|
import Button from '../../../components/atoms/Button'
|
|
import Help from '../../../components/atoms/Form/Help'
|
|
import ItemForm from './ItemForm'
|
|
import Item from './Item'
|
|
import Ipfs from './Ipfs'
|
|
import styles from './index.module.scss'
|
|
|
|
import { serviceUri } from '../../../config'
|
|
import cleanupContentType from '../../../utils/cleanupContentType'
|
|
|
|
export interface File {
|
|
url: string
|
|
contentType: string
|
|
checksum?: string
|
|
checksumType?: string
|
|
contentLength?: number
|
|
resourceId?: string
|
|
encoding?: string
|
|
compression?: string
|
|
found: boolean // non-standard
|
|
}
|
|
|
|
interface FilesProps {
|
|
files: File[]
|
|
placeholder: string
|
|
help?: string
|
|
name: string
|
|
onChange(
|
|
event:
|
|
| ChangeEvent<HTMLInputElement>
|
|
| FormEvent<HTMLInputElement>
|
|
| ChangeEvent<HTMLSelectElement>
|
|
| ChangeEvent<HTMLTextAreaElement>
|
|
): void
|
|
}
|
|
|
|
interface FilesStates {
|
|
isFormShown: boolean
|
|
isIpfsFormShown: boolean
|
|
}
|
|
|
|
export default class Files extends PureComponent<FilesProps, FilesStates> {
|
|
public state: FilesStates = {
|
|
isFormShown: false,
|
|
isIpfsFormShown: false
|
|
}
|
|
|
|
// for canceling axios requests
|
|
public signal = axios.CancelToken.source()
|
|
|
|
public componentWillUnmount() {
|
|
this.signal.cancel()
|
|
}
|
|
|
|
private toggleForm = (e: Event) => {
|
|
e.preventDefault()
|
|
this.setState({
|
|
isFormShown: !this.state.isFormShown,
|
|
isIpfsFormShown: false
|
|
})
|
|
}
|
|
|
|
private toggleIpfsForm = (e: Event) => {
|
|
e.preventDefault()
|
|
this.setState({
|
|
isIpfsFormShown: !this.state.isIpfsFormShown,
|
|
isFormShown: false
|
|
})
|
|
}
|
|
|
|
private async getFile(url: string) {
|
|
const file: File = {
|
|
url,
|
|
contentType: '',
|
|
found: false // non-standard
|
|
}
|
|
|
|
try {
|
|
const response = await axios({
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
url: `${serviceUri}/api/v1/urlcheck`,
|
|
data: { url },
|
|
cancelToken: this.signal.token
|
|
})
|
|
|
|
const { contentLength, contentType, found } = response.data.result
|
|
|
|
file.contentLength = contentLength
|
|
file.contentType = contentType
|
|
file.compression = cleanupContentType(contentType)
|
|
file.found = found
|
|
|
|
return file
|
|
} catch (error) {
|
|
!axios.isCancel(error) && Logger.error(error.message)
|
|
}
|
|
}
|
|
|
|
private addFile = async (url: string) => {
|
|
// check for duplicate urls
|
|
const duplicateFiles = this.props.files.filter(props =>
|
|
url.includes(props.url)
|
|
)
|
|
|
|
if (duplicateFiles.length > 0) {
|
|
return this.setState({
|
|
isFormShown: false,
|
|
isIpfsFormShown: false
|
|
})
|
|
}
|
|
|
|
const file: File | undefined = await this.getFile(url)
|
|
file && this.props.files.push(file)
|
|
|
|
const event = {
|
|
currentTarget: {
|
|
name: 'files',
|
|
value: this.props.files
|
|
}
|
|
}
|
|
this.props.onChange(event as any)
|
|
|
|
this.setState({
|
|
isFormShown: false,
|
|
isIpfsFormShown: false
|
|
})
|
|
}
|
|
|
|
private removeFile = (index: number) => {
|
|
this.props.files.splice(index, 1)
|
|
const event = {
|
|
currentTarget: {
|
|
name: 'files',
|
|
value: this.props.files
|
|
}
|
|
}
|
|
this.props.onChange(event as any)
|
|
this.forceUpdate()
|
|
}
|
|
|
|
public render() {
|
|
const { files, help, placeholder, name, onChange } = this.props
|
|
const { isFormShown, isIpfsFormShown } = this.state
|
|
|
|
return (
|
|
<>
|
|
{help && <Help>{help}</Help>}
|
|
|
|
{/* Use hidden input to collect files */}
|
|
<input
|
|
type="hidden"
|
|
name={name}
|
|
value={JSON.stringify(files)}
|
|
onChange={onChange}
|
|
data-testid="files"
|
|
/>
|
|
|
|
<div className={styles.newItems}>
|
|
{files.length > 0 && (
|
|
<ul className={styles.itemsList}>
|
|
{files.map((item: any, index: number) => (
|
|
<Item
|
|
key={item.url}
|
|
item={item}
|
|
removeItem={() => this.removeFile(index)}
|
|
/>
|
|
))}
|
|
</ul>
|
|
)}
|
|
|
|
<Button link onClick={this.toggleForm}>
|
|
{isFormShown ? '- Cancel' : '+ From public URL'}
|
|
</Button>
|
|
|
|
<Button link onClick={this.toggleIpfsForm}>
|
|
{isIpfsFormShown ? '- Cancel' : '+ Add to IPFS'}
|
|
</Button>
|
|
|
|
{isFormShown && (
|
|
<ItemForm
|
|
placeholder={placeholder}
|
|
addFile={this.addFile}
|
|
/>
|
|
)}
|
|
|
|
{isIpfsFormShown && <Ipfs addFile={this.addFile} />}
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
}
|