mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Merge pull request #37 from oceanprotocol/feature/price
Custom price input
This commit is contained in:
commit
12d3b2f0a0
@ -35,11 +35,9 @@
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "cost",
|
||||
"name": "price",
|
||||
"label": "Price",
|
||||
"help": "Set your price for accessing this data set in Ocean Tokens.",
|
||||
"type": "price",
|
||||
"min": 1,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
|
8
src/@types/MetaData.d.ts
vendored
8
src/@types/MetaData.d.ts
vendored
@ -5,12 +5,9 @@ import {
|
||||
ServiceMetadata
|
||||
} from '@oceanprotocol/lib'
|
||||
|
||||
export declare type AccessType = 'Download' | 'Compute'
|
||||
|
||||
export interface AdditionalInformationMarket extends AdditionalInformation {
|
||||
links?: File[]
|
||||
termsAndConditions: boolean
|
||||
access: AccessType | string
|
||||
}
|
||||
|
||||
export interface MetadataMarket extends Metadata {
|
||||
@ -24,7 +21,10 @@ export interface MetadataPublishForm {
|
||||
files: string | File[]
|
||||
author: string
|
||||
license: string
|
||||
cost: string
|
||||
price: {
|
||||
cost: number
|
||||
tokensToMint: number
|
||||
}
|
||||
access: 'Download' | 'Compute' | string
|
||||
termsAndConditions: boolean
|
||||
// ---- optional fields ----
|
||||
|
@ -1,9 +1,23 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import styles from './Help.module.css'
|
||||
import Markdown from '../Markdown'
|
||||
import classNames from 'classnames/bind'
|
||||
|
||||
const FormHelp = ({ children }: { children: string }): ReactElement => (
|
||||
<Markdown className={styles.help} text={children} />
|
||||
)
|
||||
const cx = classNames.bind(styles)
|
||||
|
||||
const FormHelp = ({
|
||||
children,
|
||||
className
|
||||
}: {
|
||||
children: string
|
||||
className?: string
|
||||
}): ReactElement => {
|
||||
const styleClasses = cx({
|
||||
help: true,
|
||||
[className]: className
|
||||
})
|
||||
|
||||
return <Markdown className={styleClasses} text={children} />
|
||||
}
|
||||
|
||||
export default FormHelp
|
||||
|
@ -12,6 +12,7 @@
|
||||
border-radius: var(--border-radius);
|
||||
transition: 0.2s ease-out;
|
||||
min-height: 43px;
|
||||
min-width: 0;
|
||||
appearance: none;
|
||||
display: block;
|
||||
}
|
||||
@ -33,7 +34,8 @@
|
||||
|
||||
.input[readonly],
|
||||
.input[disabled] {
|
||||
background-color: var(--brand-grey-lighter);
|
||||
background-color: var(--brand-grey-dimmed);
|
||||
color: var(--brand-grey-light);
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
@ -84,6 +86,52 @@
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.prefixGroup,
|
||||
.postfixGroup {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.prefixGroup input {
|
||||
border-left: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.postfixGroup input {
|
||||
border-right: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.prefix,
|
||||
.postfix {
|
||||
border: 1px solid var(--brand-grey-lighter);
|
||||
min-height: 43px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: calc(var(--spacer) / 4);
|
||||
padding-right: calc(var(--spacer) / 4);
|
||||
color: var(--color-secondary);
|
||||
font-size: var(--font-size-small);
|
||||
transition: border 0.2s ease-out;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.prefix {
|
||||
border-top-left-radius: var(--border-radius);
|
||||
border-bottom-left-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.postfix {
|
||||
border-top-right-radius: var(--border-radius);
|
||||
border-bottom-right-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.input:focus + .postfix {
|
||||
border-color: var(--brand-grey);
|
||||
}
|
||||
|
||||
/* Size modifiers */
|
||||
|
||||
.small {
|
||||
|
@ -4,9 +4,23 @@ import styles from './InputElement.module.css'
|
||||
import { InputProps } from '.'
|
||||
import FilesInput from '../../molecules/FormFields/FilesInput'
|
||||
import Terms from '../../molecules/FormFields/Terms'
|
||||
import Price from '../../molecules/FormFields/Price'
|
||||
|
||||
const DefaultInput = (
|
||||
{ name, type }: { name: string; type?: string },
|
||||
props: InputProps
|
||||
) => (
|
||||
<input
|
||||
id={name}
|
||||
className={styles.input}
|
||||
name={name}
|
||||
{...props}
|
||||
type={type || 'text'}
|
||||
/>
|
||||
)
|
||||
|
||||
export default function InputElement(props: InputProps): ReactElement {
|
||||
const { type, options, rows, name, value } = props
|
||||
const { type, options, rows, name, prefix, postfix } = props
|
||||
|
||||
switch (type) {
|
||||
case 'select':
|
||||
@ -56,18 +70,19 @@ export default function InputElement(props: InputProps): ReactElement {
|
||||
)
|
||||
case 'files':
|
||||
return <FilesInput name={name} {...props} />
|
||||
case 'price':
|
||||
return <Price name={name} {...props} />
|
||||
case 'terms':
|
||||
return <Terms name={name} {...props} />
|
||||
default:
|
||||
return (
|
||||
<input
|
||||
id={name}
|
||||
className={styles.input}
|
||||
name={name}
|
||||
{...props}
|
||||
value={value || ''}
|
||||
type={type || 'text'}
|
||||
/>
|
||||
return prefix || postfix ? (
|
||||
<div className={`${prefix ? styles.prefixGroup : styles.postfixGroup}`}>
|
||||
{prefix && <div className={styles.prefix}>{prefix}</div>}
|
||||
<DefaultInput name={name} type={type || 'text'} />
|
||||
{postfix && <div className={styles.postfix}>{postfix}</div>}
|
||||
</div>
|
||||
) : (
|
||||
<DefaultInput name={name} type={type || 'text'} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { FormEvent, ChangeEvent, ReactElement } from 'react'
|
||||
import React, { FormEvent, ChangeEvent, ReactElement, ReactNode } from 'react'
|
||||
import InputElement from './InputElement'
|
||||
import Help from './Help'
|
||||
import Label from './Label'
|
||||
@ -31,8 +31,12 @@ export interface InputProps {
|
||||
pattern?: string
|
||||
min?: string
|
||||
disabled?: boolean
|
||||
readOnly?: boolean
|
||||
field?: any
|
||||
form?: any
|
||||
prefix?: string
|
||||
postfix?: string
|
||||
step?: string
|
||||
}
|
||||
|
||||
export default function Input(props: Partial<InputProps>): ReactElement {
|
||||
|
@ -1,6 +1,6 @@
|
||||
.conversion {
|
||||
display: inline-block;
|
||||
font-size: var(--font-size-mini);
|
||||
font-size: var(--font-size-small);
|
||||
margin-left: calc(var(--spacer) / 6);
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
@ -2,19 +2,29 @@ import React, { useEffect, useState, ReactElement } from 'react'
|
||||
import useSWR from 'swr'
|
||||
import { fetchData, isBrowser } from '../../../utils'
|
||||
import styles from './Conversion.module.css'
|
||||
import classNames from 'classnames/bind'
|
||||
|
||||
const cx = classNames.bind(styles)
|
||||
|
||||
const currencies = 'EUR' // comma-separated list
|
||||
const url = `https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=${currencies}&include_24hr_change=true`
|
||||
|
||||
export default function Conversion({
|
||||
price,
|
||||
update = true
|
||||
update = true,
|
||||
className
|
||||
}: {
|
||||
price: string // expects price in OCEAN, not wei
|
||||
update?: boolean
|
||||
className?: string
|
||||
}): ReactElement {
|
||||
const [priceEur, setPriceEur] = useState('0.00')
|
||||
|
||||
const styleClasses = cx({
|
||||
conversion: true,
|
||||
[className]: className
|
||||
})
|
||||
|
||||
const onSuccess = async (data: { 'ocean-protocol': { eur: number } }) => {
|
||||
if (!data) return
|
||||
if (!price || price === '' || price === '0') {
|
||||
@ -45,5 +55,12 @@ export default function Conversion({
|
||||
})
|
||||
}
|
||||
|
||||
return <span className={styles.conversion}>≈ EUR {priceEur}</span>
|
||||
return (
|
||||
<span
|
||||
className={styleClasses}
|
||||
title="Approximation based on current spot price on Coingecko"
|
||||
>
|
||||
≈ EUR {priceEur}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { ReactElement } from 'react'
|
||||
import DataTable from 'react-data-table-component'
|
||||
|
||||
export declare type AssetTablePagination = {
|
||||
|
26
src/components/atoms/Tabs.module.css
Normal file
26
src/components/atoms/Tabs.module.css
Normal file
@ -0,0 +1,26 @@
|
||||
.tabList {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid var(--brand-grey-lighter);
|
||||
padding-top: calc(var(--spacer) / 2);
|
||||
padding-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: inline-block;
|
||||
padding: calc(var(--spacer) / 12) var(--spacer);
|
||||
border-radius: var(--border-radius);
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-size: var(--font-size-small);
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
color: var(--brand-grey-light);
|
||||
}
|
||||
|
||||
.tab[aria-selected='true'] {
|
||||
background: var(--brand-black);
|
||||
color: var(--brand-white);
|
||||
}
|
||||
|
||||
.tabContent {
|
||||
padding: var(--spacer);
|
||||
}
|
33
src/components/atoms/Tabs.tsx
Normal file
33
src/components/atoms/Tabs.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React, { ReactElement, ReactNode } from 'react'
|
||||
import { Tab, Tabs as ReactTabs, TabList, TabPanel } from 'react-tabs'
|
||||
import styles from './Tabs.module.css'
|
||||
|
||||
interface TabsItem {
|
||||
title: string
|
||||
content: ReactNode
|
||||
}
|
||||
|
||||
export default function Tabs({
|
||||
items,
|
||||
className
|
||||
}: {
|
||||
items: TabsItem[]
|
||||
className?: string
|
||||
}): ReactElement {
|
||||
return (
|
||||
<ReactTabs className={`${className && className}`}>
|
||||
<TabList className={styles.tabList}>
|
||||
{items.map((item) => (
|
||||
<Tab className={styles.tab} key={item.title}>
|
||||
{item.title}
|
||||
</Tab>
|
||||
))}
|
||||
</TabList>
|
||||
<div className={styles.tabContent}>
|
||||
{items.map((item) => (
|
||||
<TabPanel key={item.title}>{item.content}</TabPanel>
|
||||
))}
|
||||
</div>
|
||||
</ReactTabs>
|
||||
)
|
||||
}
|
@ -36,7 +36,7 @@ export default function FilesInput(props: InputProps): ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
{typeof field.value === 'object' ? (
|
||||
{field && typeof field.value === 'object' ? (
|
||||
<FileInfo file={field.value[0]} removeItem={removeItem} />
|
||||
) : (
|
||||
<FileInput
|
||||
|
@ -0,0 +1,56 @@
|
||||
.advanced {
|
||||
}
|
||||
|
||||
.wallet {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.balance {
|
||||
text-align: center;
|
||||
font-size: var(--font-size-small);
|
||||
border: 1px solid var(--brand-grey-lighter);
|
||||
border-right: 0;
|
||||
margin-right: -3px;
|
||||
padding: calc(var(--spacer) / 4.5) calc(var(--spacer) / 2);
|
||||
border-top-left-radius: var(--border-radius);
|
||||
border-bottom-left-radius: var(--border-radius);
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.balance strong {
|
||||
color: var(--brand-grey);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: var(--font-size-base);
|
||||
margin-top: var(--spacer);
|
||||
margin-bottom: 0;
|
||||
color: var(--color-secondary);
|
||||
text-align: center;
|
||||
padding-bottom: calc(var(--spacer) / 3);
|
||||
}
|
||||
|
||||
.tokens {
|
||||
display: grid;
|
||||
margin-bottom: -2rem;
|
||||
margin-left: -3rem;
|
||||
margin-right: -3rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 40rem) {
|
||||
.tokens {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.alertArea {
|
||||
margin-left: -3rem;
|
||||
margin-right: -3rem;
|
||||
padding: var(--spacer) calc(var(--spacer) / 2);
|
||||
padding-bottom: 0;
|
||||
margin-top: var(--spacer);
|
||||
border-top: 1px solid var(--brand-grey-lighter);
|
||||
}
|
89
src/components/molecules/FormFields/Price/Advanced.tsx
Normal file
89
src/components/molecules/FormFields/Price/Advanced.tsx
Normal file
@ -0,0 +1,89 @@
|
||||
import React, { ReactElement, useState, ChangeEvent, useEffect } from 'react'
|
||||
import stylesIndex from './index.module.css'
|
||||
import styles from './Advanced.module.css'
|
||||
import FormHelp from '../../../atoms/Input/Help'
|
||||
import Wallet from '../../Wallet'
|
||||
import { useOcean } from '@oceanprotocol/react'
|
||||
import Alert from '../../../atoms/Alert'
|
||||
import Coin from './Coin'
|
||||
import { isCorrectNetwork } from '../../../../utils/wallet'
|
||||
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
|
||||
|
||||
export default function Advanced({
|
||||
ocean,
|
||||
tokensToMint,
|
||||
weightOnDataToken,
|
||||
onChange
|
||||
}: {
|
||||
ocean: string
|
||||
tokensToMint: number
|
||||
weightOnDataToken: string
|
||||
onChange: (event: ChangeEvent<HTMLInputElement>) => void
|
||||
}): ReactElement {
|
||||
const { appConfig } = useSiteMetadata()
|
||||
const { account, balance, chainId } = useOcean()
|
||||
|
||||
const [error, setError] = useState<string>()
|
||||
const correctNetwork = isCorrectNetwork(chainId)
|
||||
const desiredNetworkName = appConfig.network.replace(/^\w/, (c: string) =>
|
||||
c.toUpperCase()
|
||||
)
|
||||
|
||||
// Check: account, network & insuffciant balance
|
||||
useEffect(() => {
|
||||
if (!account) {
|
||||
setError(`No account connected. Please connect your Web3 wallet.`)
|
||||
} else if (!correctNetwork) {
|
||||
setError(`Wrong Network. Please connect to ${desiredNetworkName}.`)
|
||||
} else if (balance.ocean < ocean) {
|
||||
setError(`Insufficiant balance. You need at least ${ocean} OCEAN`)
|
||||
} else {
|
||||
setError(undefined)
|
||||
}
|
||||
}, [ocean])
|
||||
|
||||
return (
|
||||
<div className={stylesIndex.content}>
|
||||
<div className={styles.advanced}>
|
||||
<FormHelp className={stylesIndex.help}>
|
||||
{`Let's create a decentralized, automated market for your data set. A Data Token contract for this data set worth the entered amount of OCEAN will be created. Additionally, you will provide liquidity into a Data Token/OCEAN
|
||||
liquidity pool with Balancer.`}
|
||||
</FormHelp>
|
||||
|
||||
<aside className={styles.wallet}>
|
||||
{balance && balance.ocean && (
|
||||
<div className={styles.balance}>
|
||||
OCEAN <strong>{balance.ocean}</strong>
|
||||
</div>
|
||||
)}
|
||||
<Wallet />
|
||||
</aside>
|
||||
|
||||
<h4 className={styles.title}>Data Token Liquidity Pool</h4>
|
||||
|
||||
<div className={styles.tokens}>
|
||||
<Coin
|
||||
name="ocean"
|
||||
symbol="OCEAN"
|
||||
value={ocean}
|
||||
weight={`${100 - Number(weightOnDataToken)}%`}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<Coin
|
||||
name="tokensToMint"
|
||||
symbol="OCEAN-CAV"
|
||||
value={tokensToMint.toString()}
|
||||
weight={`${weightOnDataToken}%`}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className={styles.alertArea}>
|
||||
<Alert text={error} state="error" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
59
src/components/molecules/FormFields/Price/Coin.module.css
Normal file
59
src/components/molecules/FormFields/Price/Coin.module.css
Normal file
@ -0,0 +1,59 @@
|
||||
.coin {
|
||||
padding: var(--spacer) calc(var(--spacer) / 2);
|
||||
border-top: 1px solid var(--brand-grey-lighter);
|
||||
}
|
||||
|
||||
.coin:last-child {
|
||||
border-left: 1px solid var(--brand-grey-lighter);
|
||||
}
|
||||
|
||||
.icon {
|
||||
composes: box from '../../../atoms/Box.module.css';
|
||||
padding: calc(var(--spacer) / 1.5);
|
||||
width: 6rem;
|
||||
height: 6rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid var(--brand-grey-lighter);
|
||||
border-radius: 50%;
|
||||
background-color: var(--brand-white);
|
||||
margin-bottom: var(--spacer);
|
||||
}
|
||||
|
||||
.coin:last-child .icon path {
|
||||
fill: var(--brand-grey-dimmed);
|
||||
stroke: var(--brand-black);
|
||||
stroke-width: 5px;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.data {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
max-width: 12rem;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.max {
|
||||
position: absolute;
|
||||
right: var(--spacer);
|
||||
top: calc(var(--spacer) / 2.5);
|
||||
}
|
||||
|
||||
.weight {
|
||||
width: 100%;
|
||||
margin-top: var(--spacer);
|
||||
text-transform: uppercase;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.weight strong {
|
||||
color: var(--brand-grey);
|
||||
font-size: var(--font-size-base);
|
||||
}
|
46
src/components/molecules/FormFields/Price/Coin.tsx
Normal file
46
src/components/molecules/FormFields/Price/Coin.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React, { ReactElement, ChangeEvent } from 'react'
|
||||
import stylesIndex from './index.module.css'
|
||||
import styles from './Coin.module.css'
|
||||
import InputElement from '../../../atoms/Input/InputElement'
|
||||
import { ReactComponent as Logo } from '../../../../images/logo.svg'
|
||||
import Conversion from '../../../atoms/Price/Conversion'
|
||||
|
||||
export default function Coin({
|
||||
symbol,
|
||||
name,
|
||||
value,
|
||||
weight,
|
||||
onChange,
|
||||
readOnly
|
||||
}: {
|
||||
symbol: string
|
||||
name: string
|
||||
value: string
|
||||
weight: string
|
||||
onChange?: (event: ChangeEvent<HTMLInputElement>) => void
|
||||
readOnly?: boolean
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={styles.coin}>
|
||||
<figure className={styles.icon}>
|
||||
<Logo />
|
||||
</figure>
|
||||
|
||||
<div className={styles.data}>
|
||||
<InputElement
|
||||
value={value}
|
||||
name={name}
|
||||
type="number"
|
||||
onChange={onChange}
|
||||
readOnly={readOnly}
|
||||
prefix={symbol}
|
||||
/>
|
||||
<Conversion price={value} className={stylesIndex.conversion} />
|
||||
|
||||
<div className={styles.weight}>
|
||||
Weight <strong>{weight}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
.form {
|
||||
max-width: 12rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.simple label {
|
||||
display: none;
|
||||
}
|
40
src/components/molecules/FormFields/Price/Simple.tsx
Normal file
40
src/components/molecules/FormFields/Price/Simple.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import React, { ReactElement, ChangeEvent } from 'react'
|
||||
import stylesIndex from './index.module.css'
|
||||
import styles from './Simple.module.css'
|
||||
import FormHelp from '../../../atoms/Input/Help'
|
||||
import Label from '../../../atoms/Input/Label'
|
||||
import InputElement from '../../../atoms/Input/InputElement'
|
||||
import Conversion from '../../../atoms/Price/Conversion'
|
||||
|
||||
export default function Simple({
|
||||
ocean,
|
||||
onChange
|
||||
}: {
|
||||
ocean: string
|
||||
onChange: (event: ChangeEvent<HTMLInputElement>) => void
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={stylesIndex.content}>
|
||||
<div className={styles.simple}>
|
||||
<FormHelp className={stylesIndex.help}>
|
||||
Set your price for accessing this data set. A Data Token contract for
|
||||
this data set, worth the entered amount of OCEAN will be created.
|
||||
</FormHelp>
|
||||
|
||||
<form className={styles.form}>
|
||||
<Label htmlFor="ocean">Ocean Tokens</Label>
|
||||
|
||||
<InputElement
|
||||
value={ocean}
|
||||
name="ocean"
|
||||
type="number"
|
||||
prefix="OCEAN"
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
||||
<Conversion price={ocean} className={stylesIndex.conversion} />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
33
src/components/molecules/FormFields/Price/index.module.css
Normal file
33
src/components/molecules/FormFields/Price/index.module.css
Normal file
@ -0,0 +1,33 @@
|
||||
.price {
|
||||
border: 1px solid var(--brand-grey-lighter);
|
||||
background: var(--brand-grey-dimmed);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.content label {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.content input {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.content p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.conversion {
|
||||
width: 100%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: calc(var(--spacer) / 6);
|
||||
}
|
||||
|
||||
.help {
|
||||
text-align: center;
|
||||
margin-bottom: calc(var(--spacer) / 1.5);
|
||||
}
|
54
src/components/molecules/FormFields/Price/index.tsx
Normal file
54
src/components/molecules/FormFields/Price/index.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import React, { ReactElement, useState, ChangeEvent, useEffect } from 'react'
|
||||
import { InputProps } from '../../../atoms/Input'
|
||||
import styles from './index.module.css'
|
||||
import Tabs from '../../../atoms/Tabs'
|
||||
import Simple from './Simple'
|
||||
import Advanced from './Advanced'
|
||||
import { useField } from 'formik'
|
||||
|
||||
export default function Price(props: InputProps): ReactElement {
|
||||
const [field, meta, helpers] = useField(props)
|
||||
|
||||
const cost = 1
|
||||
const weightOnDataToken = '90' // in %
|
||||
const [ocean, setOcean] = useState('1')
|
||||
const [tokensToMint, setTokensToMint] = useState<number>()
|
||||
|
||||
function handleOceanChange(event: ChangeEvent<HTMLInputElement>) {
|
||||
setOcean(event.target.value)
|
||||
}
|
||||
|
||||
// Always update everything when ocean changes
|
||||
useEffect(() => {
|
||||
const tokensToMint = Number(ocean) * (Number(weightOnDataToken) / 10)
|
||||
setTokensToMint(tokensToMint)
|
||||
helpers.setValue({ cost, tokensToMint })
|
||||
}, [ocean])
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: 'Simple: Fixed',
|
||||
content: <Simple ocean={ocean} onChange={handleOceanChange} />
|
||||
},
|
||||
{
|
||||
title: 'Advanced: Dynamic',
|
||||
content: (
|
||||
<Advanced
|
||||
ocean={ocean}
|
||||
tokensToMint={tokensToMint}
|
||||
weightOnDataToken={weightOnDataToken}
|
||||
onChange={handleOceanChange}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className={styles.price}>
|
||||
<Tabs items={tabs} />
|
||||
<pre>
|
||||
<code>{JSON.stringify(field.value)}</code>
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -66,7 +66,7 @@
|
||||
padding: calc(var(--spacer) / 2);
|
||||
margin-left: var(--spacer);
|
||||
text-transform: uppercase;
|
||||
color: var(--brand-grey);
|
||||
color: var(--brand-grey-light);
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-size: var(--font-size-base);
|
||||
position: relative;
|
||||
@ -82,13 +82,13 @@
|
||||
.link:hover,
|
||||
.link:focus,
|
||||
.link:active {
|
||||
color: var(--brand-pink);
|
||||
color: var(--brand-grey);
|
||||
}
|
||||
|
||||
.link[aria-current],
|
||||
.link[aria-current]:hover,
|
||||
.link[aria-current]:focus {
|
||||
color: var(--brand-pink);
|
||||
color: var(--brand-black);
|
||||
}
|
||||
|
||||
.link:last-child {
|
||||
|
@ -8,12 +8,16 @@
|
||||
padding: calc(var(--spacer) / 4);
|
||||
white-space: nowrap;
|
||||
background: none;
|
||||
color: var(--brand-grey);
|
||||
margin: 0;
|
||||
transition: border 0.2s ease-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.button,
|
||||
.address {
|
||||
color: var(--brand-grey);
|
||||
}
|
||||
|
||||
.button:hover,
|
||||
.button:focus {
|
||||
transform: none;
|
||||
@ -21,6 +25,10 @@
|
||||
border-color: var(--brand-grey-light);
|
||||
}
|
||||
|
||||
.button.initial {
|
||||
color: var(--brand-pink);
|
||||
}
|
||||
|
||||
.blockies {
|
||||
width: var(--font-size-large);
|
||||
height: var(--font-size-large);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { FormEvent } from 'react'
|
||||
import styles from './Account.module.css'
|
||||
import { useOcean } from '@oceanprotocol/react'
|
||||
import { toDataUrl } from 'ethereum-blockies'
|
||||
@ -26,8 +26,20 @@ const Account = React.forwardRef((props, ref: any) => {
|
||||
const { accountId, status, connect, chainId } = useOcean()
|
||||
const hasSuccess = status === 1 && isCorrectNetwork(chainId)
|
||||
|
||||
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
||||
// prevent accidentially submitting a form the button might be in
|
||||
e.preventDefault()
|
||||
await connect()
|
||||
}
|
||||
|
||||
return accountId ? (
|
||||
<button className={styles.button} aria-label="Account" ref={ref}>
|
||||
<button
|
||||
className={styles.button}
|
||||
aria-label="Account"
|
||||
ref={ref}
|
||||
// prevent accidentially submitting a form the button might be in
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>
|
||||
<Blockies account={accountId} />
|
||||
<span className={styles.address} title={accountId}>
|
||||
{accountTruncate(accountId)}
|
||||
@ -39,13 +51,13 @@ const Account = React.forwardRef((props, ref: any) => {
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className={styles.button}
|
||||
onClick={async () => await connect()}
|
||||
className={`${styles.button} ${styles.initial}`}
|
||||
onClick={(e) => handleActivation(e)}
|
||||
// Need the `ref` here although we do not want
|
||||
// the Tippy to show in this state.
|
||||
ref={ref}
|
||||
>
|
||||
Activate Wallet
|
||||
Connect Wallet
|
||||
</button>
|
||||
)
|
||||
})
|
||||
|
@ -21,7 +21,7 @@ export default function Web3Feedback({
|
||||
const isOceanConnectionError = status === -1
|
||||
const correctNetwork = isCorrectNetwork(chainId)
|
||||
const showFeedback = !account || isOceanConnectionError || !correctNetwork
|
||||
const networkName = appConfig.network.replace(/^\w/, (c: string) =>
|
||||
const desiredNetworkName = appConfig.network.replace(/^\w/, (c: string) =>
|
||||
c.toUpperCase()
|
||||
)
|
||||
|
||||
@ -50,7 +50,7 @@ export default function Web3Feedback({
|
||||
: isOceanConnectionError
|
||||
? 'Please try again.'
|
||||
: !correctNetwork
|
||||
? `Please connect to ${networkName}.`
|
||||
? `Please connect to ${desiredNetworkName}.`
|
||||
: isBalanceInsufficient === true
|
||||
? 'You do not have enough OCEAN in your wallet to purchase this asset.'
|
||||
: 'Something went wrong.'
|
||||
|
@ -4,29 +4,3 @@
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tabList {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid var(--brand-grey-lighter);
|
||||
padding-top: calc(var(--spacer) / 2);
|
||||
padding-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: inline-block;
|
||||
padding: calc(var(--spacer) / 12) var(--spacer);
|
||||
border-radius: var(--border-radius);
|
||||
font-weight: var(--font-weight-bold);
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
color: var(--brand-grey-light);
|
||||
}
|
||||
|
||||
.tab[aria-selected='true'] {
|
||||
background: var(--brand-black);
|
||||
color: var(--brand-white);
|
||||
}
|
||||
|
||||
.tabContent {
|
||||
padding: var(--spacer);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'
|
||||
import styles from './index.module.css'
|
||||
import Compute from './Compute'
|
||||
import Consume from './Consume'
|
||||
import { MetadataMarket } from '../../../@types/Metadata'
|
||||
import { DDO } from '@oceanprotocol/lib'
|
||||
import Tabs from '../../atoms/Tabs'
|
||||
|
||||
export default function AssetActions({
|
||||
metadata,
|
||||
@ -15,23 +15,22 @@ export default function AssetActions({
|
||||
}): ReactElement {
|
||||
const { access } = metadata.additionalInformation
|
||||
const isCompute = access && access === 'Compute'
|
||||
|
||||
return (
|
||||
<Tabs className={styles.actions}>
|
||||
<TabList className={styles.tabList}>
|
||||
<Tab className={styles.tab}>Use</Tab>
|
||||
<Tab className={styles.tab}>Trade</Tab>
|
||||
</TabList>
|
||||
<div className={styles.tabContent}>
|
||||
<TabPanel>
|
||||
{isCompute ? (
|
||||
<Compute ddo={ddo} />
|
||||
) : (
|
||||
<Consume ddo={ddo} file={metadata.main.files[0]} />
|
||||
)}
|
||||
</TabPanel>
|
||||
<TabPanel>Trade Me</TabPanel>
|
||||
</div>
|
||||
</Tabs>
|
||||
const UseContent = isCompute ? (
|
||||
<Compute ddo={ddo} />
|
||||
) : (
|
||||
<Consume ddo={ddo} file={metadata.main.files[0]} />
|
||||
)
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: 'Use',
|
||||
content: UseContent
|
||||
},
|
||||
{
|
||||
title: 'Trade',
|
||||
content: 'Trade Me'
|
||||
}
|
||||
]
|
||||
|
||||
return <Tabs items={tabs} className={styles.actions} />
|
||||
}
|
||||
|
@ -51,6 +51,10 @@ export default function AssetContent({
|
||||
/> */}
|
||||
{/* <DeleteAction ddo={ddo} /> */}
|
||||
</div>
|
||||
|
||||
<pre>
|
||||
<code>{JSON.stringify(ddo, null, 2)}</code>
|
||||
</pre>
|
||||
</div>
|
||||
<div>
|
||||
<div className={styles.sticky}>
|
||||
|
@ -38,6 +38,7 @@ export default function Preview({
|
||||
key.includes('tags') ||
|
||||
key.includes('files') ||
|
||||
key.includes('termsAndConditions') ||
|
||||
key.includes('price') ||
|
||||
value === undefined ||
|
||||
value === ''
|
||||
)
|
||||
|
@ -19,7 +19,6 @@ export default function PublishForm({
|
||||
status,
|
||||
setStatus,
|
||||
isValid,
|
||||
touched,
|
||||
setErrors,
|
||||
setTouched,
|
||||
resetForm,
|
||||
@ -42,7 +41,6 @@ export default function PublishForm({
|
||||
{content.data.map((field: FormFieldProps) => (
|
||||
<Field key={field.name} {...field} component={Input} />
|
||||
))}
|
||||
|
||||
{isLoading ? (
|
||||
<Loader message={publishStepText} />
|
||||
) : (
|
||||
|
@ -7,7 +7,7 @@ import styles from './index.module.css'
|
||||
import PublishForm from './PublishForm'
|
||||
import Web3Feedback from '../../molecules/Wallet/Feedback'
|
||||
import { FormContent } from '../../../@types/Form'
|
||||
import { initialValues, validationSchema } from './validation'
|
||||
import { initialValues, validationSchema } from '../../../models/FormPublish'
|
||||
import { MetadataPublishForm } from '../../../@types/Metadata'
|
||||
import { transformPublishFormToMetadata } from './utils'
|
||||
import Preview from './Preview'
|
||||
@ -28,20 +28,20 @@ export default function PublishPage({
|
||||
`)
|
||||
|
||||
const metadata = transformPublishFormToMetadata(values)
|
||||
const tokensToMint = '4' // how to know this?
|
||||
const { cost, tokensToMint } = values.price
|
||||
const serviceType = values.access === 'Download' ? 'access' : 'compute'
|
||||
|
||||
console.log(`
|
||||
Transformed metadata values:
|
||||
----------------------
|
||||
${JSON.stringify(metadata, null, 2)}
|
||||
Cost: 1
|
||||
Cost: ${cost}
|
||||
Tokens to mint: ${tokensToMint}
|
||||
`)
|
||||
|
||||
try {
|
||||
const ddo = await publish(metadata as any, tokensToMint, [
|
||||
{ serviceType, cost: '1' }
|
||||
const ddo = await publish(metadata as any, tokensToMint.toString(), [
|
||||
{ serviceType, cost: cost.toString() }
|
||||
])
|
||||
|
||||
if (publishError) {
|
||||
@ -82,6 +82,26 @@ export default function PublishPage({
|
||||
<Web3Feedback />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<div>
|
||||
<h5>Collected Form Values</h5>
|
||||
<pre>
|
||||
<code>{JSON.stringify(values, null, 2)}</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h5>Transformed Values</h5>
|
||||
<pre>
|
||||
<code>
|
||||
{JSON.stringify(
|
||||
transformPublishFormToMetadata(values),
|
||||
null,
|
||||
2
|
||||
)}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Formik>
|
||||
|
@ -16,8 +16,7 @@ export function transformPublishFormToMetadata(
|
||||
tags,
|
||||
links,
|
||||
termsAndConditions,
|
||||
files,
|
||||
access
|
||||
files
|
||||
} = data
|
||||
|
||||
const metadata: MetadataMarket = {
|
||||
@ -38,8 +37,7 @@ export function transformPublishFormToMetadata(
|
||||
// links: {
|
||||
// url: links
|
||||
// },
|
||||
termsAndConditions,
|
||||
access: access || 'Download'
|
||||
termsAndConditions
|
||||
},
|
||||
curation: AssetModel.curation
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
code {
|
||||
font-family: var(--font-family-monospace);
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--brand-grey-light);
|
||||
color: var(--brand-grey);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
@ -14,13 +14,22 @@ code {
|
||||
pre {
|
||||
display: block;
|
||||
margin: calc(var(--spacer) / 2) 0;
|
||||
padding: 0;
|
||||
border: 1px solid var(--brand-grey-dark);
|
||||
padding: calc(var(--spacer) / 2);
|
||||
background-color: var(--brand-grey-dimmed) !important;
|
||||
border-radius: var(--border-radius);
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
max-height: 800px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
pre code {
|
||||
padding: calc(var(--spacer) / 2);
|
||||
padding: 0;
|
||||
white-space: pre;
|
||||
display: block;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: normal;
|
||||
word-wrap: normal;
|
||||
word-break: normal;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -132,6 +132,28 @@ fieldset {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
display: block;
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
table th,
|
||||
table td {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: calc(var(--spacer) / 2);
|
||||
border-bottom: 1px solid var(--brand-grey-lighter);
|
||||
text-align: left;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
table th {
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
@import '_code.css';
|
||||
@import '_toast.css';
|
||||
@import '_web3modal.css';
|
||||
|
26
src/images/logo.svg
Normal file
26
src/images/logo.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<svg width="394" height="399" viewBox="0 0 394 399" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M196.742 57.2631C212.525 57.2631 225.33 44.4482 225.33 28.6321C225.33 12.82 212.525 0 196.742 0C180.944 0 168.139 12.82 168.139 28.6321C168.139 44.4482 180.944 57.2631 196.742 57.2631Z" fill="#141414"/>
|
||||
<path d="M29.167 213.019C40.8609 213.019 50.3274 203.527 50.3274 191.826C50.3274 180.125 40.8609 170.644 29.167 170.644C17.4833 170.644 8.00663 180.125 8.00663 191.826C8.00663 203.527 17.4833 213.019 29.167 213.019Z" fill="#141414"/>
|
||||
<path d="M365.451 213.019C377.129 213.019 386.606 203.527 386.606 191.826C386.606 180.125 377.129 170.644 365.451 170.644C353.762 170.644 344.285 180.125 344.285 191.826C344.285 203.527 353.762 213.019 365.451 213.019Z" fill="#141414"/>
|
||||
<path d="M218.467 275.433C218.467 287.132 208.991 296.623 197.309 296.623C185.622 296.623 176.146 287.132 176.146 275.433C176.146 263.733 185.622 254.248 197.309 254.248C208.991 254.248 218.467 263.733 218.467 275.433Z" fill="#141414"/>
|
||||
<path d="M112.662 255.393C124.355 255.393 133.825 245.902 133.825 234.206C133.825 222.5 124.355 213.019 112.662 213.019C100.975 213.019 91.5044 222.5 91.5044 234.206C91.5044 245.902 100.975 255.393 112.662 255.393Z" fill="#141414"/>
|
||||
<path d="M301.965 234.206C301.965 245.902 292.489 255.393 280.807 255.393C269.114 255.393 259.644 245.902 259.644 234.206C259.644 222.5 269.114 213.019 280.807 213.019C292.489 213.019 301.965 222.5 301.965 234.206Z" fill="#141414"/>
|
||||
<path d="M29.1748 270.282C37.0689 270.282 43.4646 263.864 43.4646 255.971C43.4646 248.058 37.0689 241.65 29.1748 241.65C21.2703 241.65 14.8695 248.058 14.8695 255.971C14.8695 263.864 21.2703 270.282 29.1748 270.282Z" fill="#141414"/>
|
||||
<path d="M379.743 255.971C379.743 263.864 373.338 270.282 365.446 270.282C357.548 270.282 351.148 263.864 351.148 255.971C351.148 248.058 357.548 241.65 365.446 241.65C373.338 241.65 379.743 248.058 379.743 255.971Z" fill="#141414"/>
|
||||
<path d="M197.312 355.031C205.196 355.031 211.604 348.613 211.604 340.705C211.604 332.802 205.196 326.4 197.312 326.4C189.422 326.4 183.009 332.802 183.009 340.705C183.009 348.613 189.422 355.031 197.312 355.031Z" fill="#141414"/>
|
||||
<path d="M126.962 298.346C126.962 306.251 120.563 312.656 112.67 312.656C104.772 312.656 98.3672 306.251 98.3672 298.346C98.3672 290.435 104.772 284.025 112.67 284.025C120.563 284.025 126.962 290.435 126.962 298.346Z" fill="#141414"/>
|
||||
<path d="M280.812 312.656C288.693 312.656 295.102 306.251 295.102 298.346C295.102 290.435 288.693 284.025 280.812 284.025C272.91 284.025 266.507 290.435 266.507 298.346C266.507 306.251 272.91 312.656 280.812 312.656Z" fill="#141414"/>
|
||||
<path d="M36.6018 306.35C36.6018 310.469 33.2752 313.802 29.1697 313.802C25.0588 313.802 21.7323 310.469 21.7323 306.35C21.7323 302.241 25.0588 298.913 29.1697 298.913C33.2752 298.913 36.6018 302.241 36.6018 306.35Z" fill="#141414"/>
|
||||
<path d="M365.448 313.802C369.546 313.802 372.88 310.469 372.88 306.35C372.88 302.241 369.546 298.913 365.448 298.913C361.335 298.913 358.011 302.241 358.011 306.35C358.011 310.469 361.335 313.802 365.448 313.802Z" fill="#141414"/>
|
||||
<path d="M204.741 391.102C204.741 395.214 201.407 398.551 197.309 398.551C193.201 398.551 189.872 395.214 189.872 391.102C189.872 386.989 193.201 383.663 197.309 383.663C201.407 383.663 204.741 386.989 204.741 391.102Z" fill="#141414"/>
|
||||
<path d="M112.662 356.176C116.768 356.176 120.1 352.839 120.1 348.732C120.1 344.615 116.768 341.288 112.662 341.288C108.562 341.288 105.23 344.615 105.23 348.732C105.23 352.839 108.562 356.176 112.662 356.176Z" fill="#141414"/>
|
||||
<path d="M288.239 348.732C288.239 352.839 284.905 356.176 280.807 356.176C276.688 356.176 273.369 352.839 273.369 348.732C273.369 344.615 276.688 341.288 280.807 341.288C284.905 341.288 288.239 344.615 288.239 348.732Z" fill="#141414"/>
|
||||
<path d="M225.33 113.381C225.33 129.195 212.525 142.012 196.742 142.012C180.944 142.012 168.139 129.195 168.139 113.381C168.139 97.572 180.944 84.7494 196.742 84.7494C212.525 84.7494 225.33 97.572 225.33 113.381Z" fill="#141414"/>
|
||||
<path d="M196.742 225.617C212.525 225.617 225.33 212.797 225.33 196.99C225.33 181.173 212.525 168.353 196.742 168.353C180.944 168.353 168.139 181.173 168.139 196.99C168.139 212.797 180.944 225.617 196.742 225.617Z" fill="#141414"/>
|
||||
<path d="M393.469 113.381C393.469 129.195 380.667 142.012 364.876 142.012C349.081 142.012 336.279 129.195 336.279 113.381C336.279 97.572 349.081 84.7494 364.876 84.7494C380.667 84.7494 393.469 97.572 393.469 113.381Z" fill="#141414"/>
|
||||
<path d="M28.5977 142.012C44.3907 142.012 57.1903 129.195 57.1903 113.381C57.1903 97.572 44.3907 84.7494 28.5977 84.7494C12.8046 84.7494 0 97.572 0 113.381C0 129.195 12.8046 142.012 28.5977 142.012Z" fill="#141414"/>
|
||||
<path d="M141.832 71.0062C141.832 86.818 129.031 99.6378 113.237 99.6378C97.4422 99.6378 84.6416 86.818 84.6416 71.0062C84.6416 55.1842 97.4422 42.3747 113.237 42.3747C129.031 42.3747 141.832 55.1842 141.832 71.0062Z" fill="#141414"/>
|
||||
<path d="M113.237 183.242C129.031 183.242 141.832 170.421 141.832 154.608C141.832 138.8 129.031 125.979 113.237 125.979C97.4422 125.979 84.6416 138.8 84.6416 154.608C84.6416 170.421 97.4422 183.242 113.237 183.242Z" fill="#141414"/>
|
||||
<path d="M309.971 71.0062C309.971 86.818 297.167 99.6378 281.373 99.6378C265.58 99.6378 252.781 86.818 252.781 71.0062C252.781 55.1842 265.58 42.3747 281.373 42.3747C297.167 42.3747 309.971 55.1842 309.971 71.0062Z" fill="#141414"/>
|
||||
<path d="M281.373 183.242C297.167 183.242 309.971 170.421 309.971 154.608C309.971 138.8 297.167 125.979 281.373 125.979C265.58 125.979 252.781 138.8 252.781 154.608C252.781 170.421 265.58 183.242 281.373 183.242Z" fill="#141414"/>
|
||||
</svg>
|
After Width: | Height: | Size: 5.5 KiB |
@ -5,21 +5,20 @@ const AssetModel: MetadataMarket = {
|
||||
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
||||
main: {
|
||||
type: 'dataset',
|
||||
name: '',
|
||||
dateCreated: '',
|
||||
author: '',
|
||||
license: '',
|
||||
name: undefined,
|
||||
dateCreated: undefined,
|
||||
author: undefined,
|
||||
license: undefined,
|
||||
files: []
|
||||
},
|
||||
additionalInformation: {
|
||||
description: '',
|
||||
copyrightHolder: '',
|
||||
tags: [],
|
||||
links: [],
|
||||
description: undefined,
|
||||
copyrightHolder: undefined,
|
||||
tags: undefined,
|
||||
links: undefined,
|
||||
|
||||
// custom items
|
||||
termsAndConditions: false,
|
||||
access: 'Download'
|
||||
termsAndConditions: false
|
||||
},
|
||||
curation: {
|
||||
rating: 0,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MetadataPublishForm } from '../../../@types/Metadata'
|
||||
import { MetadataPublishForm } from '../@types/Metadata'
|
||||
import { File as FileMetadata } from '@oceanprotocol/lib'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
@ -6,7 +6,10 @@ export const validationSchema = Yup.object().shape<MetadataPublishForm>({
|
||||
// ---- required fields ----
|
||||
name: Yup.string().required('Required'),
|
||||
author: Yup.string().required('Required'),
|
||||
cost: Yup.string().required('Required'),
|
||||
price: Yup.object().shape({
|
||||
cost: Yup.number().required('Required'),
|
||||
tokensToMint: Yup.number().required('Required')
|
||||
}),
|
||||
files: Yup.array<FileMetadata>().required('Required').nullable(),
|
||||
description: Yup.string().required('Required'),
|
||||
license: Yup.string().required('Required'),
|
||||
@ -22,15 +25,18 @@ export const validationSchema = Yup.object().shape<MetadataPublishForm>({
|
||||
})
|
||||
|
||||
export const initialValues: MetadataPublishForm = {
|
||||
name: '',
|
||||
author: '',
|
||||
cost: '',
|
||||
files: '',
|
||||
description: '',
|
||||
license: '',
|
||||
access: '',
|
||||
name: undefined,
|
||||
author: undefined,
|
||||
price: {
|
||||
cost: 1,
|
||||
tokensToMint: 1
|
||||
},
|
||||
files: undefined,
|
||||
description: undefined,
|
||||
license: undefined,
|
||||
access: undefined,
|
||||
termsAndConditions: false,
|
||||
copyrightHolder: '',
|
||||
tags: '',
|
||||
links: ''
|
||||
copyrightHolder: undefined,
|
||||
tags: undefined,
|
||||
links: undefined
|
||||
}
|
@ -32,7 +32,6 @@ export const contentQuery = graphql`
|
||||
type
|
||||
required
|
||||
options
|
||||
min
|
||||
}
|
||||
success
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user