mirror of
https://github.com/oceanprotocol/commons.git
synced 2023-03-15 18:03:00 +01:00
Merge branch 'master' into feature/account-popup
This commit is contained in:
commit
b95e7dfc9f
@ -37,10 +37,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
color: rgba($brand-white, .7);
|
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: .8;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ interface ButtonProps {
|
|||||||
link?: boolean
|
link?: boolean
|
||||||
href?: string
|
href?: string
|
||||||
onClick?: any
|
onClick?: any
|
||||||
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Button extends PureComponent<ButtonProps, any> {
|
export default class Button extends PureComponent<ButtonProps, any> {
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
.form {
|
.form {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
background: $brand-white;
|
||||||
|
padding: $spacer;
|
||||||
|
border: 1px solid $brand-grey-lighter;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -9,6 +13,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.formMinimal {
|
||||||
|
composes: form;
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.formHeader {
|
.formHeader {
|
||||||
margin-bottom: $spacer;
|
margin-bottom: $spacer;
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,20 @@ const Form = ({
|
|||||||
description,
|
description,
|
||||||
children,
|
children,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
minimal,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
title?: string
|
title?: string
|
||||||
description?: string
|
description?: string
|
||||||
children: any
|
children: any
|
||||||
onSubmit?: any
|
onSubmit?: any
|
||||||
|
minimal?: boolean
|
||||||
}) => (
|
}) => (
|
||||||
<form className={styles.form} onSubmit={onSubmit} {...props}>
|
<form
|
||||||
|
className={minimal ? styles.formMinimal : styles.form}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
{title && (
|
{title && (
|
||||||
<header className={styles.formHeader}>
|
<header className={styles.formHeader}>
|
||||||
<h1 className={styles.formTitle}>{title}</h1>
|
<h1 className={styles.formTitle}>{title}</h1>
|
||||||
|
@ -49,7 +49,15 @@ export default class Input extends PureComponent<InputProps, InputState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public InputComponent = () => {
|
public InputComponent = () => {
|
||||||
const { type, options, group, name, required, onChange } = this.props
|
const {
|
||||||
|
type,
|
||||||
|
options,
|
||||||
|
group,
|
||||||
|
name,
|
||||||
|
required,
|
||||||
|
onChange,
|
||||||
|
value
|
||||||
|
} = this.props
|
||||||
|
|
||||||
const wrapClass = this.inputWrapClasses()
|
const wrapClass = this.inputWrapClasses()
|
||||||
|
|
||||||
@ -64,19 +72,22 @@ export default class Input extends PureComponent<InputProps, InputState> {
|
|||||||
onFocus={this.toggleFocus}
|
onFocus={this.toggleFocus}
|
||||||
onBlur={this.toggleFocus}
|
onBlur={this.toggleFocus}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
value={value}
|
||||||
>
|
>
|
||||||
<option value="">---</option>
|
<option value="">---</option>
|
||||||
{options &&
|
{options &&
|
||||||
options.map((option: string, index: number) => (
|
options
|
||||||
<option
|
.sort((a, b) => a.localeCompare(b))
|
||||||
key={index}
|
.map((option: string, index: number) => (
|
||||||
value={slugify(option, {
|
<option
|
||||||
lower: true
|
key={index}
|
||||||
})}
|
value={slugify(option, {
|
||||||
>
|
lower: true
|
||||||
{option}
|
})}
|
||||||
</option>
|
>
|
||||||
))}
|
{option}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
.spinnerMessage {
|
.spinnerMessage {
|
||||||
color: $brand-grey-light;
|
color: $brand-grey-light;
|
||||||
margin-top: $spacer / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spinner {
|
@keyframes spinner {
|
||||||
|
@ -1,90 +1,114 @@
|
|||||||
{
|
{
|
||||||
"title": "Publish a new data asset",
|
"steps": [
|
||||||
"description": "A cool form description",
|
{
|
||||||
"fields": {
|
"title": "Essentials",
|
||||||
"name": {
|
"description": "Start by adding a title and URLs for your data set.",
|
||||||
"label": "Title",
|
"fields": {
|
||||||
"placeholder": "i.e. My cool data set",
|
"name": {
|
||||||
"type": "text",
|
"label": "Title",
|
||||||
"required": true,
|
"placeholder": "i.e. Almond sales data",
|
||||||
"help": "Help me Obiwan"
|
"type": "text",
|
||||||
|
"required": true,
|
||||||
|
"help": "Enter a concise title. You will be able to enter a more thorough description in the next step."
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"label": "Files",
|
||||||
|
"placeholder": "i.e. https://file.com/file.json",
|
||||||
|
"type": "text",
|
||||||
|
"required": true,
|
||||||
|
"help": "Provide one or multiple urls to your data set files."
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"files": {
|
{
|
||||||
"label": "Files",
|
"title": "Information",
|
||||||
"placeholder": "i.e. https://file.com/file.json",
|
"description": "Further describe and categorize your data set to help people discover it.",
|
||||||
"type": "text",
|
"fields": {
|
||||||
"required": true,
|
"description": {
|
||||||
"help": "Provide one or multiple links to your data files."
|
"label": "Description",
|
||||||
|
"description": "Add a thorough description with as much detail as possible.",
|
||||||
|
"placeholder": "i.e. Almond sales data ",
|
||||||
|
"type": "textarea",
|
||||||
|
"required": true,
|
||||||
|
"rows": 5
|
||||||
|
},
|
||||||
|
"categories": {
|
||||||
|
"label": "Categories",
|
||||||
|
"description": "Pick a category which best fits your data set.",
|
||||||
|
"type": "select",
|
||||||
|
"required": true,
|
||||||
|
"options": [
|
||||||
|
"Image Recognition",
|
||||||
|
"Dataset Of Datasets",
|
||||||
|
"Language",
|
||||||
|
"Performing Arts",
|
||||||
|
"Visual Arts & Design",
|
||||||
|
"Philosophy",
|
||||||
|
"History",
|
||||||
|
"Theology",
|
||||||
|
"Anthropology & Archeology",
|
||||||
|
"Sociology",
|
||||||
|
"Psychology",
|
||||||
|
"Politics",
|
||||||
|
"Interdisciplinary",
|
||||||
|
"Economics & Finance",
|
||||||
|
"Demography",
|
||||||
|
"Biology",
|
||||||
|
"Chemistry",
|
||||||
|
"Physics & Energy",
|
||||||
|
"Earth & Climate",
|
||||||
|
"Space & Astronomy",
|
||||||
|
"Mathematics",
|
||||||
|
"Computer Technology",
|
||||||
|
"Engineering",
|
||||||
|
"Agriculture & Bio Engineering",
|
||||||
|
"Transportation",
|
||||||
|
"Urban Planning",
|
||||||
|
"Medicine",
|
||||||
|
"Business & Management",
|
||||||
|
"Sports & Recreation",
|
||||||
|
"Communication & Journalism",
|
||||||
|
"Other"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"description": {
|
{
|
||||||
"label": "Description",
|
"title": "Authorship",
|
||||||
"placeholder": "i.e. My cool data set",
|
"description": "Give proper attribution for your data set.",
|
||||||
"type": "textarea",
|
"fields": {
|
||||||
"required": true,
|
"author": {
|
||||||
"rows": 5
|
"label": "Author",
|
||||||
|
"placeholder": "i.e. Jelly McJellyfish",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"copyrightHolder": {
|
||||||
|
"label": "Copyright Holder",
|
||||||
|
"placeholder": "i.e. Marine Institute of Jellyfish",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"license": {
|
||||||
|
"label": "License",
|
||||||
|
"type": "select",
|
||||||
|
"required": true,
|
||||||
|
"options": [
|
||||||
|
"Public Domain",
|
||||||
|
"CC BY: Attribution",
|
||||||
|
"CC BY-SA: Attribution ShareAlike",
|
||||||
|
"CC BY-ND: Attribution-NoDerivs",
|
||||||
|
"CC BY-NC: Attribution-NonCommercial",
|
||||||
|
"CC BY-NC-SA: Attribution-NonCommercial-ShareAlike",
|
||||||
|
"CC BY-NC-ND: Attribution-NonCommercial-NoDerivs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"categories": {
|
{
|
||||||
"label": "Categories",
|
"title": "Register",
|
||||||
"type": "select",
|
"description": "Splendid, we got all the data. Now let's register your data set.",
|
||||||
"options": [
|
"content": "After clicking the button below you will be asked by your wallet to sign this request."
|
||||||
"Image Recognition",
|
|
||||||
"Dataset Of Datasets",
|
|
||||||
"Language",
|
|
||||||
"Performing Arts",
|
|
||||||
"Visual Arts & Design",
|
|
||||||
"Philosophy",
|
|
||||||
"History",
|
|
||||||
"Theology",
|
|
||||||
"Anthropology & Archeology",
|
|
||||||
"Sociology",
|
|
||||||
"Psychology",
|
|
||||||
"Politics",
|
|
||||||
"Interdisciplinary",
|
|
||||||
"Economics & Finance",
|
|
||||||
"Demography",
|
|
||||||
"Biology",
|
|
||||||
"Chemistry",
|
|
||||||
"Physics & Energy",
|
|
||||||
"Earth & Climate",
|
|
||||||
"Space & Astronomy",
|
|
||||||
"Mathematics",
|
|
||||||
"Computer Technology",
|
|
||||||
"Engineering",
|
|
||||||
"Agriculture & Bio Engineering",
|
|
||||||
"Transportation",
|
|
||||||
"Urban Planning",
|
|
||||||
"Medicine",
|
|
||||||
"Business & Management",
|
|
||||||
"Sports & Recreation",
|
|
||||||
"Communication & Journalism",
|
|
||||||
"Other"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"copyrightHolder": {
|
|
||||||
"label": "Copyright Holder",
|
|
||||||
"placeholder": "i.e. fwhfiw",
|
|
||||||
"type": "text",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"author": {
|
|
||||||
"label": "Author",
|
|
||||||
"placeholder": "i.e. Jelly McJellyfish",
|
|
||||||
"type": "text",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"label": "License",
|
|
||||||
"type": "select",
|
|
||||||
"required": true,
|
|
||||||
"options": [
|
|
||||||
"Public Domain",
|
|
||||||
"CC BY: Attribution",
|
|
||||||
"CC BY-SA: Attribution ShareAlike",
|
|
||||||
"CC BY-ND: Attribution-NoDerivs",
|
|
||||||
"CC BY-NC: Attribution-NonCommercial",
|
|
||||||
"CC BY-NC-SA: Attribution-NonCommercial-ShareAlike",
|
|
||||||
"CC BY-NC-ND: Attribution-NonCommercial-NoDerivs"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
|
@ -2,22 +2,9 @@
|
|||||||
|
|
||||||
.home {
|
.home {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
|
||||||
|
|
||||||
.published {
|
form {
|
||||||
margin-top: $spacer * 3;
|
margin-top: $spacer * 2;
|
||||||
margin-bottom: $spacer;
|
margin-bottom: $spacer * 4;
|
||||||
|
|
||||||
> div {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: $spacer;
|
|
||||||
margin-bottom: $spacer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.subTitle {
|
|
||||||
font-size: $font-size-h4;
|
|
||||||
color: $brand-grey-light;
|
|
||||||
border-bottom: 1px solid $brand-grey-lighter;
|
|
||||||
padding-bottom: $spacer / 2;
|
|
||||||
}
|
|
||||||
|
@ -26,26 +26,21 @@ class Home extends Component<HomeProps, HomeState> {
|
|||||||
description={meta.description}
|
description={meta.description}
|
||||||
className={styles.home}
|
className={styles.home}
|
||||||
>
|
>
|
||||||
<Form onSubmit={this.searchAssets}>
|
<Form onSubmit={this.searchAssets} minimal>
|
||||||
<Input
|
<Input
|
||||||
type="search"
|
type="search"
|
||||||
name="search"
|
name="search"
|
||||||
label="Search"
|
label="Search for data sets"
|
||||||
placeholder="i.e. almond sales data"
|
placeholder="i.e. almond sales data"
|
||||||
value={this.state.search}
|
value={this.state.search}
|
||||||
onChange={this.inputChange}
|
onChange={this.inputChange}
|
||||||
group={<Button>Search</Button>}
|
group={
|
||||||
|
<Button primary disabled={!this.state.search}>
|
||||||
|
Search
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
<div className={styles.published}>
|
|
||||||
<h2 className={styles.subTitle}>Your Data Sets</h2>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<p>None yet.</p>
|
|
||||||
<Link to="/publish">+ Publish A Data Set</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Route>
|
</Route>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ interface FilesProps {
|
|||||||
help?: string
|
help?: string
|
||||||
name: string
|
name: string
|
||||||
onChange: any
|
onChange: any
|
||||||
// resetForm: any
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FilesStates {
|
interface FilesStates {
|
||||||
@ -32,12 +31,26 @@ export default class Files extends PureComponent<FilesProps, FilesStates> {
|
|||||||
|
|
||||||
public addItem = (value: string) => {
|
public addItem = (value: string) => {
|
||||||
this.props.files.push({ url: value })
|
this.props.files.push({ url: value })
|
||||||
// this.props.resetForm()
|
const event = {
|
||||||
|
currentTarget: {
|
||||||
|
name: 'files',
|
||||||
|
value: this.props.files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.props.onChange(event as any)
|
||||||
this.setState({ isFormShown: !this.state.isFormShown })
|
this.setState({ isFormShown: !this.state.isFormShown })
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeItem = (index: number) => {
|
public removeItem = (index: number) => {
|
||||||
this.props.files.splice(index, 1)
|
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() {
|
public render() {
|
||||||
@ -52,7 +65,7 @@ export default class Files extends PureComponent<FilesProps, FilesStates> {
|
|||||||
<input
|
<input
|
||||||
type="hidden"
|
type="hidden"
|
||||||
name={name}
|
name={name}
|
||||||
value={files}
|
value={JSON.stringify(files)}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
76
src/routes/Publish/Progress.module.scss
Normal file
76
src/routes/Publish/Progress.module.scss
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
@import '../../styles/variables';
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
margin-top: $spacer * 1.5;
|
||||||
|
margin-bottom: $spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: inline-block;
|
||||||
|
width: 25%;
|
||||||
|
text-align: center;
|
||||||
|
color: $brand-grey-light;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 60%;
|
||||||
|
height: .1rem;
|
||||||
|
background: $brand-grey-lighter;
|
||||||
|
position: absolute;
|
||||||
|
top: 20%;
|
||||||
|
left: -30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
&:before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
composes: item;
|
||||||
|
font-family: $font-family-button;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $brand-black;
|
||||||
|
|
||||||
|
.number {
|
||||||
|
background: $brand-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
background: $green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.completed {
|
||||||
|
composes: active;
|
||||||
|
|
||||||
|
.number {
|
||||||
|
background: $green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
margin-top: $spacer / 8;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number {
|
||||||
|
width: 1.6rem;
|
||||||
|
height: 1.6rem;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: $brand-grey-light;
|
||||||
|
color: $brand-white;
|
||||||
|
font-family: $font-family-button;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
}
|
32
src/routes/Publish/Progress.tsx
Normal file
32
src/routes/Publish/Progress.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import styles from './Progress.module.scss'
|
||||||
|
|
||||||
|
const Progress = ({
|
||||||
|
currentStep,
|
||||||
|
steps
|
||||||
|
}: {
|
||||||
|
currentStep: number
|
||||||
|
steps: any[]
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<ul className={styles.progress}>
|
||||||
|
{steps.map(({ title }, index) => (
|
||||||
|
<li
|
||||||
|
key={index}
|
||||||
|
className={
|
||||||
|
currentStep === index + 1
|
||||||
|
? styles.active
|
||||||
|
: currentStep > index + 1
|
||||||
|
? styles.completed
|
||||||
|
: styles.item
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span className={styles.number}>{index + 1}</span>
|
||||||
|
<span className={styles.label}>{title}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Progress
|
26
src/routes/Publish/Step.module.scss
Normal file
26
src/routes/Publish/Step.module.scss
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@import '../../styles/variables';
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: $spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: $font-size-h2;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin-top: $spacer / 4;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-top: $spacer / 2;
|
||||||
|
|
||||||
|
button:last-child {
|
||||||
|
min-width: 12rem;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
164
src/routes/Publish/Step.tsx
Normal file
164
src/routes/Publish/Step.tsx
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import React, { PureComponent } from 'react'
|
||||||
|
import Input from '../../components/atoms/Form/Input'
|
||||||
|
import Label from '../../components/atoms/Form/Label'
|
||||||
|
import Row from '../../components/atoms/Form/Row'
|
||||||
|
import Button from '../../components/atoms/Button'
|
||||||
|
import { User } from '../../context/User'
|
||||||
|
import Files from './Files/'
|
||||||
|
import StepRegisterContent from './StepRegisterContent'
|
||||||
|
import styles from './Step.module.scss'
|
||||||
|
|
||||||
|
interface StepProps {
|
||||||
|
currentStep: number
|
||||||
|
index: number
|
||||||
|
inputChange: any
|
||||||
|
inputToArrayChange: any
|
||||||
|
fields?: any[]
|
||||||
|
state: any
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
next: any
|
||||||
|
prev: any
|
||||||
|
totalSteps: number
|
||||||
|
tryAgain: any
|
||||||
|
toStart: any
|
||||||
|
publishedDid?: string
|
||||||
|
content?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Step extends PureComponent<StepProps, {}> {
|
||||||
|
public previousButton() {
|
||||||
|
const { currentStep, prev } = this.props
|
||||||
|
|
||||||
|
if (currentStep !== 1) {
|
||||||
|
return (
|
||||||
|
<Button link onClick={prev}>
|
||||||
|
← Previous
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
public nextButton() {
|
||||||
|
const { currentStep, next, totalSteps, state } = this.props
|
||||||
|
|
||||||
|
if (currentStep < totalSteps) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
disabled={
|
||||||
|
!state.validationStatus[currentStep].allFieldsValid
|
||||||
|
}
|
||||||
|
onClick={next}
|
||||||
|
>
|
||||||
|
Next →
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const {
|
||||||
|
currentStep,
|
||||||
|
index,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
fields,
|
||||||
|
inputChange,
|
||||||
|
inputToArrayChange,
|
||||||
|
state,
|
||||||
|
totalSteps,
|
||||||
|
tryAgain,
|
||||||
|
toStart,
|
||||||
|
content
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (currentStep !== index + 1) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastStep = currentStep === totalSteps
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header className={styles.header}>
|
||||||
|
<h2 className={styles.title}>{title}</h2>
|
||||||
|
<p className={styles.description}>{description}</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{fields &&
|
||||||
|
Object.entries(fields).map(([key, value]) => {
|
||||||
|
let onChange = inputChange
|
||||||
|
|
||||||
|
if (key === 'categories') {
|
||||||
|
onChange = inputToArrayChange
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === 'files') {
|
||||||
|
return (
|
||||||
|
<Row key={key}>
|
||||||
|
<Label htmlFor={key} required>
|
||||||
|
{value.label}
|
||||||
|
</Label>
|
||||||
|
<Files
|
||||||
|
placeholder={value.placeholder}
|
||||||
|
name={key}
|
||||||
|
help={value.help}
|
||||||
|
files={state.files}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
key={key}
|
||||||
|
name={key}
|
||||||
|
label={value.label}
|
||||||
|
placeholder={value.placeholder}
|
||||||
|
required={value.required}
|
||||||
|
type={value.type}
|
||||||
|
help={value.help}
|
||||||
|
options={value.options}
|
||||||
|
onChange={onChange}
|
||||||
|
rows={value.rows}
|
||||||
|
value={(state as any)[key]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
|
{lastStep && (
|
||||||
|
<StepRegisterContent
|
||||||
|
tryAgain={tryAgain}
|
||||||
|
toStart={toStart}
|
||||||
|
state={state}
|
||||||
|
content={content}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={styles.actions}>
|
||||||
|
{this.previousButton()}
|
||||||
|
{this.nextButton()}
|
||||||
|
|
||||||
|
{lastStep && (
|
||||||
|
<User.Consumer>
|
||||||
|
{states =>
|
||||||
|
states.isLogged ? (
|
||||||
|
<Button primary>Register asset</Button>
|
||||||
|
) : (
|
||||||
|
<Button onClick={states.startLogin}>
|
||||||
|
Register asset (login first)
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</User.Consumer>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Step.contextType = User
|
5
src/routes/Publish/StepRegisterContent.module.scss
Normal file
5
src/routes/Publish/StepRegisterContent.module.scss
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@import '../../styles/variables';
|
||||||
|
|
||||||
|
.message {
|
||||||
|
margin-bottom: $spacer;
|
||||||
|
}
|
54
src/routes/Publish/StepRegisterContent.tsx
Normal file
54
src/routes/Publish/StepRegisterContent.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React, { PureComponent } from 'react'
|
||||||
|
import Web3message from '../../components/Web3message'
|
||||||
|
import Spinner from '../../components/atoms/Spinner'
|
||||||
|
import styles from './StepRegisterContent.module.scss'
|
||||||
|
|
||||||
|
interface StepRegisterContentProps {
|
||||||
|
tryAgain: any
|
||||||
|
toStart: any
|
||||||
|
state: any
|
||||||
|
content?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class StepRegisterContent extends PureComponent<
|
||||||
|
StepRegisterContentProps,
|
||||||
|
{}
|
||||||
|
> {
|
||||||
|
public publishingState = () => (
|
||||||
|
<Spinner message={'Please sign with your crypto wallet'} />
|
||||||
|
)
|
||||||
|
|
||||||
|
public errorState = () => (
|
||||||
|
<div className={styles.message}>
|
||||||
|
Something went wrong,{' '}
|
||||||
|
<a onClick={() => this.props.tryAgain()}>try again</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
public publishedState = () => (
|
||||||
|
<div className={styles.message}>
|
||||||
|
Your asset is published! See it{' '}
|
||||||
|
<a href={'/asset/' + this.props.state.publishedDid}>here</a>, submit
|
||||||
|
another asset by clicking{' '}
|
||||||
|
<a onClick={() => this.props.toStart()}>here</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Web3message />
|
||||||
|
|
||||||
|
{this.props.state.isPublishing ? (
|
||||||
|
this.publishingState()
|
||||||
|
) : this.props.state.publishingError ? (
|
||||||
|
this.errorState()
|
||||||
|
) : this.props.state.isPublished ? (
|
||||||
|
this.publishedState()
|
||||||
|
) : (
|
||||||
|
<p>{this.props.content}</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,13 @@
|
|||||||
import React, { ChangeEvent, Component, FormEvent } from 'react'
|
import React, { ChangeEvent, Component, FormEvent } from 'react'
|
||||||
import { Logger } from '@oceanprotocol/squid'
|
import { Logger } from '@oceanprotocol/squid'
|
||||||
import Route from '../../components/templates/Route'
|
import Route from '../../components/templates/Route'
|
||||||
import Button from '../../components/atoms/Button'
|
|
||||||
import Form from '../../components/atoms/Form/Form'
|
import Form from '../../components/atoms/Form/Form'
|
||||||
import Input from '../../components/atoms/Form/Input'
|
|
||||||
import Label from '../../components/atoms/Form/Label'
|
|
||||||
import Row from '../../components/atoms/Form/Row'
|
|
||||||
import { User } from '../../context/User'
|
|
||||||
import AssetModel from '../../models/AssetModel'
|
import AssetModel from '../../models/AssetModel'
|
||||||
import Web3message from '../../components/molecules/Web3message'
|
import { User } from '../../context/User'
|
||||||
import Files from './Files/'
|
import Step from './Step'
|
||||||
|
import Progress from './Progress'
|
||||||
|
|
||||||
import form from '../../data/form-publish.json'
|
import { steps } from '../../data/form-publish.json'
|
||||||
|
|
||||||
type AssetType = 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
|
type AssetType = 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
|
||||||
|
|
||||||
@ -19,22 +15,25 @@ interface PublishState {
|
|||||||
name?: string
|
name?: string
|
||||||
dateCreated?: Date
|
dateCreated?: Date
|
||||||
description?: string
|
description?: string
|
||||||
files?: any[]
|
files?: string[]
|
||||||
price?: number
|
price?: number
|
||||||
author?: string
|
author?: string
|
||||||
type?: AssetType
|
type?: AssetType
|
||||||
license?: string
|
license?: string
|
||||||
copyrightHolder?: string
|
copyrightHolder?: string
|
||||||
categories?: string[]
|
categories?: string
|
||||||
tags?: string[]
|
tags?: string[]
|
||||||
isPublishing?: boolean
|
isPublishing?: boolean
|
||||||
isPublished?: boolean
|
isPublished?: boolean
|
||||||
publishedDid?: string
|
publishedDid?: string
|
||||||
publishingError?: string
|
publishingError?: string
|
||||||
|
currentStep?: number
|
||||||
|
validationStatus?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
class Publish extends Component<{}, PublishState> {
|
class Publish extends Component<{}, PublishState> {
|
||||||
public state = {
|
public state = {
|
||||||
|
currentStep: 1,
|
||||||
name: '',
|
name: '',
|
||||||
dateCreated: new Date(),
|
dateCreated: new Date(),
|
||||||
description: '',
|
description: '',
|
||||||
@ -44,58 +43,28 @@ class Publish extends Component<{}, PublishState> {
|
|||||||
type: 'dataset' as AssetType,
|
type: 'dataset' as AssetType,
|
||||||
license: '',
|
license: '',
|
||||||
copyrightHolder: '',
|
copyrightHolder: '',
|
||||||
categories: [],
|
categories: '',
|
||||||
isPublishing: false,
|
isPublishing: false,
|
||||||
isPublished: false,
|
isPublished: false,
|
||||||
publishedDid: '',
|
publishedDid: '',
|
||||||
publishingError: ''
|
publishingError: '',
|
||||||
|
validationStatus: {
|
||||||
|
1: { name: false, files: false, allFieldsValid: false },
|
||||||
|
2: { description: false, categories: false, allFieldsValid: false },
|
||||||
|
3: {
|
||||||
|
author: false,
|
||||||
|
copyrightHolder: false,
|
||||||
|
license: false,
|
||||||
|
allFieldsValid: false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public formFields = (entries: any[]) =>
|
|
||||||
entries.map(([key, value]) => {
|
|
||||||
let onChange = this.inputChange
|
|
||||||
|
|
||||||
if (key === 'files' || key === 'categories') {
|
|
||||||
onChange = this.inputToArrayChange
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === 'files') {
|
|
||||||
return (
|
|
||||||
<Row key={key}>
|
|
||||||
<Label htmlFor={key} required>
|
|
||||||
{value.label}
|
|
||||||
</Label>
|
|
||||||
<Files
|
|
||||||
placeholder={value.placeholder}
|
|
||||||
name={value.name}
|
|
||||||
help={value.help}
|
|
||||||
files={this.state.files}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
</Row>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Input
|
|
||||||
key={key}
|
|
||||||
name={key}
|
|
||||||
label={value.label}
|
|
||||||
placeholder={value.placeholder}
|
|
||||||
required={value.required}
|
|
||||||
type={value.type}
|
|
||||||
help={value.help}
|
|
||||||
options={value.options}
|
|
||||||
onChange={onChange}
|
|
||||||
rows={value.rows}
|
|
||||||
value={(this.state as any)[key]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
private inputChange = (
|
private inputChange = (
|
||||||
event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLSelectElement>
|
event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLSelectElement>
|
||||||
) => {
|
) => {
|
||||||
|
this.validateInputs(event.currentTarget.name, event.currentTarget.value)
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
[event.currentTarget.name]: event.currentTarget.value
|
[event.currentTarget.name]: event.currentTarget.value
|
||||||
})
|
})
|
||||||
@ -104,11 +73,28 @@ class Publish extends Component<{}, PublishState> {
|
|||||||
private inputToArrayChange = (
|
private inputToArrayChange = (
|
||||||
event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLSelectElement>
|
event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLSelectElement>
|
||||||
) => {
|
) => {
|
||||||
|
this.validateInputs(event.currentTarget.name, event.currentTarget.value)
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
[event.currentTarget.name]: [event.currentTarget.value]
|
[event.currentTarget.name]: [event.currentTarget.value]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private next = () => {
|
||||||
|
let { currentStep } = this.state
|
||||||
|
const totalSteps = steps.length
|
||||||
|
|
||||||
|
currentStep =
|
||||||
|
currentStep >= totalSteps - 1 ? totalSteps : currentStep + 1
|
||||||
|
this.setState({ currentStep })
|
||||||
|
}
|
||||||
|
|
||||||
|
private prev = () => {
|
||||||
|
let { currentStep } = this.state
|
||||||
|
currentStep = currentStep <= 1 ? 1 : currentStep - 1
|
||||||
|
this.setState({ currentStep })
|
||||||
|
}
|
||||||
|
|
||||||
private tryAgain = () => {
|
private tryAgain = () => {
|
||||||
this.setState({ publishingError: '' })
|
this.setState({ publishingError: '' })
|
||||||
}
|
}
|
||||||
@ -124,19 +110,140 @@ class Publish extends Component<{}, PublishState> {
|
|||||||
type: 'dataset' as AssetType,
|
type: 'dataset' as AssetType,
|
||||||
license: '',
|
license: '',
|
||||||
copyrightHolder: '',
|
copyrightHolder: '',
|
||||||
categories: [],
|
categories: '',
|
||||||
isPublishing: false,
|
isPublishing: false,
|
||||||
isPublished: false
|
isPublished: false,
|
||||||
|
currentStep: 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private validateInputs = (name: string, value: any) => {
|
||||||
|
let hasContent = value.length > 0
|
||||||
|
|
||||||
|
// Setting state for all fields
|
||||||
|
if (hasContent) {
|
||||||
|
this.setState(
|
||||||
|
prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
[this.state.currentStep]: {
|
||||||
|
...prevState.validationStatus[
|
||||||
|
this.state.currentStep
|
||||||
|
],
|
||||||
|
[name]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
this.runValidation
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.setState(
|
||||||
|
prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
[this.state.currentStep]: {
|
||||||
|
...prevState.validationStatus[
|
||||||
|
this.state.currentStep
|
||||||
|
],
|
||||||
|
[name]: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
this.runValidation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private runValidation = () => {
|
||||||
|
let { validationStatus } = this.state
|
||||||
|
//
|
||||||
|
// Step 1
|
||||||
|
//
|
||||||
|
if (validationStatus[1].name && validationStatus[1].files) {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
1: {
|
||||||
|
...prevState.validationStatus[1],
|
||||||
|
allFieldsValid: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
1: {
|
||||||
|
...prevState.validationStatus[1],
|
||||||
|
allFieldsValid: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Step 2
|
||||||
|
//
|
||||||
|
if (validationStatus[2].description && validationStatus[2].categories) {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
2: {
|
||||||
|
...prevState.validationStatus[2],
|
||||||
|
allFieldsValid: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
2: {
|
||||||
|
...prevState.validationStatus[2],
|
||||||
|
allFieldsValid: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Step 3
|
||||||
|
//
|
||||||
|
if (
|
||||||
|
validationStatus[3].author &&
|
||||||
|
validationStatus[3].copyrightHolder &&
|
||||||
|
validationStatus[3].license
|
||||||
|
) {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
3: {
|
||||||
|
...prevState.validationStatus[3],
|
||||||
|
allFieldsValid: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
validationStatus: {
|
||||||
|
...prevState.validationStatus,
|
||||||
|
3: {
|
||||||
|
...prevState.validationStatus[3],
|
||||||
|
allFieldsValid: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private registerAsset = async (event: FormEvent<HTMLFormElement>) => {
|
private registerAsset = async (event: FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
this.setState({
|
this.setState({
|
||||||
publishingError: '',
|
publishingError: '',
|
||||||
isPublishing: true
|
isPublishing: true
|
||||||
})
|
})
|
||||||
const account = await this.context.ocean.getAccounts()
|
const { ocean } = this.context
|
||||||
|
const account = await ocean.getAccounts()
|
||||||
const newAsset = {
|
const newAsset = {
|
||||||
// OEP-08 Attributes
|
// OEP-08 Attributes
|
||||||
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
||||||
@ -166,10 +273,7 @@ class Publish extends Component<{}, PublishState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const asset = await this.context.ocean.registerAsset(
|
const asset = await ocean.registerAsset(newAsset, account[0])
|
||||||
newAsset,
|
|
||||||
account[0]
|
|
||||||
)
|
|
||||||
this.setState({
|
this.setState({
|
||||||
publishedDid: asset.id,
|
publishedDid: asset.id,
|
||||||
isPublished: true
|
isPublished: true
|
||||||
@ -187,66 +291,37 @@ class Publish extends Component<{}, PublishState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const entries = Object.entries(form.fields)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Route title="Publish">
|
<Route
|
||||||
<Web3message />
|
title="Publish"
|
||||||
|
description="Publish a new data set into the Ocean Protocol Network."
|
||||||
|
>
|
||||||
|
<Progress steps={steps} currentStep={this.state.currentStep} />
|
||||||
|
|
||||||
{this.state.isPublishing ? (
|
<Form onSubmit={this.registerAsset}>
|
||||||
this.publishingState()
|
{steps.map((step: any, index: number) => (
|
||||||
) : this.state.publishingError ? (
|
<Step
|
||||||
this.errorState()
|
key={index}
|
||||||
) : this.state.isPublished ? (
|
index={index}
|
||||||
this.publishedState()
|
title={step.title}
|
||||||
) : (
|
description={step.description}
|
||||||
<Form
|
currentStep={this.state.currentStep}
|
||||||
title={form.title}
|
fields={step.fields}
|
||||||
description={form.description}
|
inputChange={this.inputChange}
|
||||||
onSubmit={this.registerAsset}
|
inputToArrayChange={this.inputToArrayChange}
|
||||||
>
|
state={this.state}
|
||||||
{this.formFields(entries)}
|
next={this.next}
|
||||||
|
prev={this.prev}
|
||||||
<User.Consumer>
|
totalSteps={steps.length}
|
||||||
{states =>
|
tryAgain={this.tryAgain}
|
||||||
states.isLogged ? (
|
toStart={this.toStart}
|
||||||
<Button primary>Register asset</Button>
|
content={step.content}
|
||||||
) : (
|
/>
|
||||||
<Button onClick={states.startLogin}>
|
))}
|
||||||
Register asset (login first)
|
</Form>
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</User.Consumer>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Route>
|
</Route>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public publishingState = () => {
|
|
||||||
return <div>Please sign with your crypto wallet</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
public errorState = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
Something went wrong,{' '}
|
|
||||||
<a onClick={() => this.tryAgain()}>try again</a>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
public publishedState = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
Your asset is published! See it{' '}
|
|
||||||
<a href={'/asset/' + this.state.publishedDid}>here</a>, submit
|
|
||||||
another asset by clicking{' '}
|
|
||||||
<a onClick={() => this.toStart()}>here</a>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Publish.contextType = User
|
Publish.contextType = User
|
||||||
|
Loading…
Reference in New Issue
Block a user