2019-01-23 14:43:41 +01:00
|
|
|
import React, { ChangeEvent, Component, FormEvent } from 'react'
|
2019-02-11 16:53:55 +01:00
|
|
|
import { Logger } from '@oceanprotocol/squid'
|
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'
|
2019-04-15 11:40:25 +02:00
|
|
|
import { User } from '../../context'
|
2019-04-13 13:43:04 +02:00
|
|
|
import Web3message from '../../components/organisms/Web3message'
|
2019-02-19 16:32:58 +01:00
|
|
|
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-01-24 17:52:11 +01:00
|
|
|
|
2019-02-28 18:24:04 +01:00
|
|
|
import { steps } from '../../data/form-publish.json'
|
2019-05-15 16:45:32 +02:00
|
|
|
import Content from '../../components/atoms/Content'
|
2019-02-07 18:11:12 +01:00
|
|
|
|
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
|
2019-03-29 15:47:18 +01:00
|
|
|
dateCreated?: string
|
2019-02-05 16:00:22 +01:00
|
|
|
description?: string
|
2019-02-19 16:32:58 +01:00
|
|
|
files?: string[]
|
2019-05-23 18:33:38 +02:00
|
|
|
price?: string
|
2019-02-05 16:00:22 +01:00
|
|
|
author?: string
|
|
|
|
type?: AssetType
|
|
|
|
license?: string
|
|
|
|
copyrightHolder?: string
|
2019-03-26 17:42:24 +01:00
|
|
|
categories?: string
|
2019-02-12 10:48:35 +01:00
|
|
|
tags?: string[]
|
|
|
|
isPublishing?: boolean
|
|
|
|
isPublished?: boolean
|
|
|
|
publishedDid?: string
|
2019-02-11 16:53:55 +01:00
|
|
|
publishingError?: string
|
2019-05-31 17:13:31 +02:00
|
|
|
publishingStep?: number
|
2019-02-19 16:32:58 +01:00
|
|
|
currentStep?: number
|
2019-02-20 16:50:27 +01:00
|
|
|
validationStatus?: any
|
2019-01-23 12:15:16 +01:00
|
|
|
}
|
|
|
|
|
2019-05-31 17:13:31 +02:00
|
|
|
export default class Publish extends Component<{}, PublishState> {
|
|
|
|
public static contextType = User
|
|
|
|
|
2019-01-24 17:52:11 +01:00
|
|
|
public state = {
|
2019-02-19 16:32:58 +01:00
|
|
|
currentStep: 1,
|
2019-01-24 17:52:11 +01:00
|
|
|
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: '',
|
2019-03-26 17:42:24 +01:00
|
|
|
categories: '',
|
2019-02-11 16:53:55 +01:00
|
|
|
isPublishing: false,
|
2019-02-12 10:48:35 +01:00
|
|
|
isPublished: false,
|
|
|
|
publishedDid: '',
|
2019-02-20 16:50:27 +01:00
|
|
|
publishingError: '',
|
2019-05-31 17:13:31 +02:00
|
|
|
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 },
|
2019-03-29 15:47:18 +01:00
|
|
|
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
|
|
|
|
2019-02-07 18:11:12 +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)
|
|
|
|
|
2019-02-07 18:11:12 +01:00
|
|
|
this.setState({
|
2019-02-13 12:30:05 +01:00
|
|
|
[event.currentTarget.name]: event.currentTarget.value
|
2019-02-07 18:11:12 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
private inputToArrayChange = (
|
|
|
|
event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLSelectElement>
|
|
|
|
) => {
|
2019-02-21 15:05:12 +01:00
|
|
|
this.validateInputs(event.currentTarget.name, event.currentTarget.value)
|
|
|
|
|
2019-02-07 18:11:12 +01:00
|
|
|
this.setState({
|
2019-02-13 12:30:05 +01:00
|
|
|
[event.currentTarget.name]: [event.currentTarget.value]
|
2019-02-07 18:11:12 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-19 16:32:58 +01:00
|
|
|
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 })
|
2019-02-19 16:32:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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-19 16:32:58 +01:00
|
|
|
}
|
|
|
|
|
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: '',
|
2019-03-26 17:42:24 +01:00
|
|
|
categories: '',
|
2019-02-12 10:48:35 +01:00
|
|
|
isPublishing: false,
|
2019-02-20 14:07:29 +01:00
|
|
|
isPublished: false,
|
2019-05-31 17:13:31 +02:00
|
|
|
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-02-21 14:35:25 +01:00
|
|
|
let hasContent = value.length > 0
|
|
|
|
|
|
|
|
// Setting state for all fields
|
|
|
|
if (hasContent) {
|
2019-03-01 16:57:09 +01:00
|
|
|
this.setState(
|
|
|
|
prevState => ({
|
|
|
|
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(
|
|
|
|
prevState => ({
|
|
|
|
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-03-01 12:18:48 +01:00
|
|
|
}
|
2019-02-21 14:35:25 +01:00
|
|
|
|
2019-03-01 12:18:48 +01:00
|
|
|
private runValidation = () => {
|
|
|
|
let { 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
|
|
|
//
|
2019-03-04 16:58:33 +01:00
|
|
|
if (validationStatus[1].name && validationStatus[1].files) {
|
2019-02-21 14:35:25 +01:00
|
|
|
this.setState(prevState => ({
|
|
|
|
validationStatus: {
|
|
|
|
...prevState.validationStatus,
|
|
|
|
1: {
|
|
|
|
...prevState.validationStatus[1],
|
|
|
|
allFieldsValid: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}))
|
2019-03-05 10:10:22 +01:00
|
|
|
} else {
|
|
|
|
this.setState(prevState => ({
|
|
|
|
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) {
|
2019-02-21 14:35:25 +01:00
|
|
|
this.setState(prevState => ({
|
|
|
|
validationStatus: {
|
|
|
|
...prevState.validationStatus,
|
|
|
|
2: {
|
|
|
|
...prevState.validationStatus[2],
|
|
|
|
allFieldsValid: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}))
|
2019-03-05 10:10:22 +01:00
|
|
|
} else {
|
|
|
|
this.setState(prevState => ({
|
|
|
|
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
|
|
|
|
) {
|
|
|
|
this.setState(prevState => ({
|
|
|
|
validationStatus: {
|
|
|
|
...prevState.validationStatus,
|
|
|
|
3: {
|
|
|
|
...prevState.validationStatus[3],
|
|
|
|
allFieldsValid: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}))
|
2019-03-05 10:10:22 +01:00
|
|
|
} else {
|
|
|
|
this.setState(prevState => ({
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-02-07 18:11:12 +01:00
|
|
|
private registerAsset = async (event: FormEvent<HTMLFormElement>) => {
|
|
|
|
event.preventDefault()
|
2019-05-31 17:13:31 +02:00
|
|
|
|
|
|
|
ReactGA.event({ category: 'Publish', action: 'registerAsset-start' })
|
|
|
|
|
2019-02-11 16:53:55 +01:00
|
|
|
this.setState({
|
|
|
|
publishingError: '',
|
2019-05-31 17:13:31 +02:00
|
|
|
isPublishing: true,
|
|
|
|
publishingStep: 0
|
2019-02-11 16:53:55 +01:00
|
|
|
})
|
2019-05-31 17:13:31 +02:00
|
|
|
|
2019-02-20 14:58:55 +01:00
|
|
|
const { ocean } = this.context
|
2019-03-25 15:22:45 +01:00
|
|
|
const account = await ocean.accounts.list()
|
2019-02-07 18:11:12 +01:00
|
|
|
const newAsset = {
|
|
|
|
// OEP-08 Attributes
|
|
|
|
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
|
|
|
base: Object.assign(AssetModel.base, {
|
|
|
|
name: this.state.name,
|
|
|
|
description: this.state.description,
|
2019-03-29 15:55:50 +01:00
|
|
|
dateCreated: new Date(this.state.dateCreated).toISOString(),
|
2019-02-07 18:11:12 +01:00
|
|
|
author: this.state.author,
|
|
|
|
license: this.state.license,
|
|
|
|
copyrightHolder: this.state.copyrightHolder,
|
2019-02-14 21:27:18 +01:00
|
|
|
files: this.state.files,
|
2019-02-07 18:11:12 +01:00
|
|
|
price: this.state.price,
|
|
|
|
type: this.state.type,
|
2019-03-26 17:42:24 +01:00
|
|
|
categories: [this.state.categories],
|
2019-02-07 18:11:12 +01:00
|
|
|
workExample: undefined,
|
|
|
|
inLanguage: undefined,
|
|
|
|
tags: ''
|
|
|
|
}),
|
|
|
|
curation: Object.assign(AssetModel.curation),
|
|
|
|
additionalInformation: Object.assign(
|
|
|
|
AssetModel.additionalInformation
|
|
|
|
)
|
|
|
|
}
|
2019-02-12 14:07:22 +01:00
|
|
|
|
2019-02-11 16:53:55 +01:00
|
|
|
try {
|
2019-05-31 17:13:31 +02:00
|
|
|
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-05-31 17:13:31 +02:00
|
|
|
|
2019-04-08 11:35:10 +02:00
|
|
|
ReactGA.event({
|
|
|
|
category: 'Publish',
|
2019-05-31 17:13:31 +02:00
|
|
|
action: `registerAsset-end ${asset.id}`
|
2019-04-08 11:35:10 +02:00
|
|
|
})
|
2019-05-31 17:13:31 +02:00
|
|
|
} catch (error) {
|
2019-02-11 16:53:55 +01:00
|
|
|
// make readable errors
|
2019-05-31 17:13:31 +02:00
|
|
|
Logger.error('error:', error.message)
|
|
|
|
this.setState({ publishingError: error.message })
|
|
|
|
|
2019-04-08 11:35:10 +02:00
|
|
|
ReactGA.event({
|
|
|
|
category: 'Publish',
|
2019-05-31 17:13:31 +02:00
|
|
|
action: `registerAsset-error ${error.message}`
|
2019-04-08 11:35:10 +02:00
|
|
|
})
|
2019-02-11 16:53:55 +01:00
|
|
|
}
|
2019-05-31 17:13:31 +02:00
|
|
|
|
|
|
|
this.setState({ isPublishing: false })
|
2019-02-07 18:11:12 +01:00
|
|
|
}
|
|
|
|
|
2019-01-23 14:43:41 +01:00
|
|
|
public render() {
|
|
|
|
return (
|
2019-02-20 12:33:04 +01:00
|
|
|
<Route
|
|
|
|
title="Publish"
|
|
|
|
description="Publish a new data set into the Ocean Protocol Network."
|
|
|
|
>
|
2019-05-15 16:45:32 +02:00
|
|
|
<Content>
|
|
|
|
{(!this.context.isLogged ||
|
|
|
|
!this.context.isOceanNetwork) && <Web3message />}
|
2019-04-13 13:43:04 +02:00
|
|
|
|
2019-05-15 16:45:32 +02:00
|
|
|
<Progress
|
|
|
|
steps={steps}
|
|
|
|
currentStep={this.state.currentStep}
|
|
|
|
/>
|
2019-02-20 13:46:54 +01:00
|
|
|
|
2019-05-15 16:45:32 +02:00
|
|
|
<Form onSubmit={this.registerAsset}>
|
|
|
|
{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}
|
|
|
|
inputToArrayChange={this.inputToArrayChange}
|
|
|
|
state={this.state}
|
|
|
|
next={this.next}
|
|
|
|
prev={this.prev}
|
|
|
|
totalSteps={steps.length}
|
|
|
|
tryAgain={this.tryAgain}
|
|
|
|
toStart={this.toStart}
|
|
|
|
content={step.content}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</Form>
|
|
|
|
</Content>
|
2019-02-08 14:22:40 +01:00
|
|
|
</Route>
|
2019-01-23 14:43:41 +01:00
|
|
|
)
|
|
|
|
}
|
2019-01-23 12:15:16 +01:00
|
|
|
}
|