commons/client/src/routes/Publish/index.tsx

380 lines
12 KiB
TypeScript
Raw Normal View History

2019-01-23 14:43:41 +01:00
import React, { ChangeEvent, Component, FormEvent } from 'react'
import { Logger, File } from '@oceanprotocol/squid'
2019-07-23 16:02:58 +02:00
import Web3 from 'web3'
2019-02-12 14:07:22 +01:00
import Route from '../../components/templates/Route'
import Form from '../../components/atoms/Form/Form'
import AssetModel from '../../models/AssetModel'
import { User, Market } from '../../context'
import Step from './Step'
2019-02-19 17:39:53 +01:00
import Progress from './Progress'
2019-04-08 11:35:10 +02:00
import ReactGA from 'react-ga'
2019-07-23 16:02:58 +02:00
import { allowPricing } from '../../config'
2019-02-28 18:24:04 +01:00
import { steps } from '../../data/form-publish.json'
import Content from '../../components/atoms/Content'
import withTracker from '../../hoc/withTracker'
2019-01-24 17:52:11 +01:00
type AssetType = 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
2019-01-23 12:15:16 +01:00
2019-02-05 17:05:28 +01:00
interface PublishState {
2019-02-05 16:00:22 +01:00
name?: string
dateCreated?: string
2019-05-23 18:33:38 +02:00
price?: string
2019-02-05 16:00:22 +01:00
author?: string
license?: string
2019-06-03 12:07:06 +02:00
description?: string
files?: File[]
type?: AssetType
2019-02-05 16:00:22 +01:00
copyrightHolder?: string
categories?: string
2019-06-03 12:07:06 +02:00
currentStep?: number
publishingStep?: number
2019-02-12 10:48:35 +01:00
isPublishing?: boolean
isPublished?: boolean
publishedDid?: string
publishingError?: string
2019-02-20 16:50:27 +01:00
validationStatus?: any
2019-01-23 12:15:16 +01:00
}
2019-07-24 15:49:47 +02:00
if (allowPricing) {
2019-09-02 13:25:46 +02:00
;(steps as any)[0].fields.price = {
2019-07-24 15:49:47 +02:00
label: 'Price',
placeholder: 'Price in Ocean tokens',
type: 'string',
2019-07-23 16:02:58 +02:00
required: true,
2019-07-24 15:49:47 +02:00
help: 'Enter the price of assets in Ocean tokens.'
2019-07-23 16:02:58 +02:00
}
}
class Publish extends Component<{}, PublishState> {
public static contextType = User
2019-01-24 17:52:11 +01:00
public state = {
name: '',
2019-04-01 15:07:53 +02:00
dateCreated: new Date().toISOString(),
2019-01-24 17:52:11 +01:00
description: '',
2019-02-13 12:19:45 +01:00
files: [],
2019-05-23 18:33:38 +02:00
price: '0',
2019-01-24 17:52:11 +01:00
author: '',
type: 'dataset' as AssetType,
license: '',
copyrightHolder: '',
categories: '',
2019-06-03 12:07:06 +02:00
currentStep: 1,
isPublishing: false,
2019-02-12 10:48:35 +01:00
isPublished: false,
publishedDid: '',
2019-02-20 16:50:27 +01:00
publishingError: '',
publishingStep: 0,
2019-02-20 16:50:27 +01:00
validationStatus: {
2019-02-21 14:35:25 +01:00
1: { name: false, files: false, allFieldsValid: false },
2: {
description: false,
categories: false,
allFieldsValid: false
},
2019-02-21 14:35:25 +01:00
3: {
author: false,
copyrightHolder: false,
license: false,
allFieldsValid: false
}
2019-02-20 16:50:27 +01:00
}
2019-01-24 17:52:11 +01:00
}
2019-01-23 14:43:41 +01:00
private inputChange = (
event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLSelectElement>
) => {
2019-02-20 16:50:27 +01:00
this.validateInputs(event.currentTarget.name, event.currentTarget.value)
this.setState({
[event.currentTarget.name]: event.currentTarget.value
})
}
private next = () => {
let { currentStep } = this.state
2019-02-28 18:24:04 +01:00
const totalSteps = steps.length
2019-02-19 17:26:15 +01:00
currentStep =
currentStep >= totalSteps - 1 ? totalSteps : currentStep + 1
2019-04-08 11:35:10 +02:00
ReactGA.event({
category: 'Publish',
action: 'nextStep ' + currentStep
})
2019-02-19 17:26:15 +01:00
this.setState({ currentStep })
}
private prev = () => {
let { currentStep } = this.state
currentStep = currentStep <= 1 ? 1 : currentStep - 1
2019-02-19 17:26:15 +01:00
this.setState({ currentStep })
}
2019-02-20 13:46:54 +01:00
private tryAgain = () => {
this.setState({ publishingError: '' })
}
2019-02-12 10:48:35 +01:00
private toStart = () => {
this.setState({
name: '',
2019-04-01 15:07:53 +02:00
dateCreated: new Date().toISOString(),
2019-02-12 10:48:35 +01:00
description: '',
2019-02-13 20:41:59 +01:00
files: [],
2019-05-23 18:33:38 +02:00
price: '0',
2019-02-12 10:48:35 +01:00
author: '',
type: 'dataset' as AssetType,
license: '',
copyrightHolder: '',
categories: '',
2019-02-12 10:48:35 +01:00
isPublishing: false,
2019-02-20 14:07:29 +01:00
isPublished: false,
publishingStep: 0,
2019-02-20 14:07:29 +01:00
currentStep: 1
2019-02-12 10:48:35 +01:00
})
}
2019-04-01 13:49:25 +02:00
private validateInputs = (name: string, value: string) => {
2019-09-02 13:25:46 +02:00
const hasContent = value.length > 0
2019-02-21 14:35:25 +01:00
// Setting state for all fields
if (hasContent) {
2019-03-01 16:57:09 +01:00
this.setState(
2020-05-19 10:36:18 +02:00
(prevState) => ({
2019-03-01 16:57:09 +01:00
validationStatus: {
...prevState.validationStatus,
[this.state.currentStep]: {
...prevState.validationStatus[
this.state.currentStep
],
[name]: true
}
2019-02-21 14:35:25 +01:00
}
2019-03-01 16:57:09 +01:00
}),
this.runValidation
)
2019-02-21 14:35:25 +01:00
} else {
2019-03-01 16:57:09 +01:00
this.setState(
2020-05-19 10:36:18 +02:00
(prevState) => ({
2019-03-01 16:57:09 +01:00
validationStatus: {
...prevState.validationStatus,
[this.state.currentStep]: {
...prevState.validationStatus[
this.state.currentStep
],
[name]: false
}
2019-02-21 14:35:25 +01:00
}
2019-03-01 16:57:09 +01:00
}),
this.runValidation
)
2019-02-21 14:35:25 +01:00
}
}
2019-02-21 14:35:25 +01:00
private runValidation = () => {
2019-09-02 13:25:46 +02:00
const { validationStatus } = this.state
2019-02-21 14:35:25 +01:00
//
2019-02-20 16:50:27 +01:00
// Step 1
2019-02-21 14:35:25 +01:00
//
if (validationStatus[1].name && validationStatus[1].files) {
2020-05-19 10:36:18 +02:00
this.setState((prevState) => ({
2019-02-21 14:35:25 +01:00
validationStatus: {
...prevState.validationStatus,
1: {
...prevState.validationStatus[1],
allFieldsValid: true
}
}
}))
2019-03-05 10:10:22 +01:00
} else {
2020-05-19 10:36:18 +02:00
this.setState((prevState) => ({
2019-03-05 10:10:22 +01:00
validationStatus: {
...prevState.validationStatus,
1: {
...prevState.validationStatus[1],
allFieldsValid: false
}
}
}))
2019-02-20 16:50:27 +01:00
}
2019-02-21 14:35:25 +01:00
//
2019-02-20 16:50:27 +01:00
// Step 2
2019-02-21 14:35:25 +01:00
//
2019-04-01 13:49:25 +02:00
if (validationStatus[2].description && validationStatus[2].categories) {
2020-05-19 10:36:18 +02:00
this.setState((prevState) => ({
2019-02-21 14:35:25 +01:00
validationStatus: {
...prevState.validationStatus,
2: {
...prevState.validationStatus[2],
allFieldsValid: true
}
}
}))
2019-03-05 10:10:22 +01:00
} else {
2020-05-19 10:36:18 +02:00
this.setState((prevState) => ({
2019-03-05 10:10:22 +01:00
validationStatus: {
...prevState.validationStatus,
2: {
...prevState.validationStatus[2],
allFieldsValid: false
}
}
}))
2019-02-20 16:50:27 +01:00
}
2019-02-21 15:05:12 +01:00
//
2019-02-20 16:50:27 +01:00
// Step 3
2019-02-21 15:05:12 +01:00
//
if (
validationStatus[3].author &&
validationStatus[3].copyrightHolder &&
validationStatus[3].license
) {
2020-05-19 10:36:18 +02:00
this.setState((prevState) => ({
2019-02-21 15:05:12 +01:00
validationStatus: {
...prevState.validationStatus,
3: {
...prevState.validationStatus[3],
allFieldsValid: true
}
}
}))
2019-03-05 10:10:22 +01:00
} else {
2020-05-19 10:36:18 +02:00
this.setState((prevState) => ({
2019-03-05 10:10:22 +01:00
validationStatus: {
...prevState.validationStatus,
3: {
...prevState.validationStatus[3],
allFieldsValid: false
}
}
}))
2019-02-21 15:05:12 +01:00
}
2019-02-20 16:50:27 +01:00
}
private handleRegisterAsset = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault()
ReactGA.event({ category: 'Publish', action: 'registerAsset-start' })
this.setState({
publishingError: '',
isPublishing: true,
publishingStep: 0
})
const { ocean } = this.context
2019-03-25 15:22:45 +01:00
const account = await ocean.accounts.list()
2019-06-03 12:07:06 +02:00
// remove `found` attribute from all File objects
// in a new array
const files = this.state.files.map(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
({ found, ...keepAttrs }: { found: boolean }) => keepAttrs
)
2019-06-03 12:07:06 +02:00
const newAsset = {
// OEP-08 Attributes
// https://github.com/oceanprotocol/OEPs/tree/master/8
2019-11-07 17:38:17 +01:00
main: Object.assign(AssetModel.main, {
type: this.state.type,
name: this.state.name,
2019-06-03 16:05:53 +02:00
dateCreated:
new Date(this.state.dateCreated)
.toISOString()
.split('.')[0] + 'Z', // remove milliseconds
author: this.state.author,
license: this.state.license,
2019-07-24 15:49:47 +02:00
price: allowPricing
? Web3.utils.toWei(this.state.price, 'ether')
: this.state.price,
2019-11-07 17:38:17 +01:00
files
}),
additionalInformation: Object.assign(
AssetModel.additionalInformation,
{
description: this.state.description,
copyrightHolder: this.state.copyrightHolder,
categories: [this.state.categories]
}
)
}
2019-02-12 14:07:22 +01:00
try {
const asset = await this.context.ocean.assets
.create(newAsset, account[0])
.next((publishingStep: number) =>
this.setState({ publishingStep })
)
2019-02-12 10:48:35 +01:00
this.setState({
publishedDid: asset.id,
isPublished: true
})
2019-04-08 11:35:10 +02:00
ReactGA.event({
category: 'Publish',
action: `registerAsset-end ${asset.id}`
2019-04-08 11:35:10 +02:00
})
} catch (error) {
// make readable errors
Logger.error('error:', error.message)
this.setState({ publishingError: error.message })
2019-04-08 11:35:10 +02:00
ReactGA.event({
category: 'Publish',
action: `registerAsset-error ${error.message}`
2019-04-08 11:35:10 +02:00
})
}
this.setState({ isPublishing: false })
}
2019-01-23 14:43:41 +01:00
public render() {
return (
<Market.Consumer>
2020-05-19 10:36:18 +02:00
{(market) => (
<Route
title="Publish"
description={`Publish a new data set into the Ocean Protocol ${market.network} Network.`}
>
<Content>
<Progress
steps={steps}
currentStep={this.state.currentStep}
/>
<Form onSubmit={this.handleRegisterAsset}>
{steps.map((step: any, index: number) => (
<Step
key={index}
index={index}
title={step.title}
description={step.description}
currentStep={this.state.currentStep}
fields={step.fields}
inputChange={this.inputChange}
state={this.state}
next={this.next}
prev={this.prev}
totalSteps={steps.length}
tryAgain={this.tryAgain}
toStart={this.toStart}
content={step.content}
/>
))}
</Form>
</Content>
</Route>
)}
</Market.Consumer>
2019-01-23 14:43:41 +01:00
)
}
2019-01-23 12:15:16 +01:00
}
export default withTracker(Publish)