mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
refactor Next.js pages into Gatsby pages
This commit is contained in:
parent
9cc38304c8
commit
6f9bf0176f
@ -27,6 +27,7 @@
|
|||||||
"plugins": ["@typescript-eslint", "prettier"],
|
"plugins": ["@typescript-eslint", "prettier"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"react/prop-types": "off",
|
"react/prop-types": "off",
|
||||||
|
"react/no-unused-prop-types": "off",
|
||||||
"@typescript-eslint/explicit-function-return-type": "off"
|
"@typescript-eslint/explicit-function-return-type": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,7 +1,6 @@
|
|||||||
node_modules
|
node_modules
|
||||||
out
|
out
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.next
|
|
||||||
.idea
|
.idea
|
||||||
.env
|
.env
|
||||||
coverage
|
coverage
|
||||||
|
4
content/pages/history.json
Normal file
4
content/pages/history.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "History",
|
||||||
|
"description": "Find the data sets and jobs that you previously accessed."
|
||||||
|
}
|
4
content/pages/publish.json
Normal file
4
content/pages/publish.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "Publish Data",
|
||||||
|
"description": "Highlight the important features of your data set to make it more discoverable and catch the interest of data consumers."
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
|
|
||||||
const siteConfig = require('./site.config.js')
|
const siteConfig = require('./content/site.json')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
siteMetadata: {
|
siteMetadata: {
|
||||||
...siteConfig
|
...siteConfig.site
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
{
|
{
|
||||||
|
54
package-lock.json
generated
54
package-lock.json
generated
@ -6009,6 +6009,36 @@
|
|||||||
"@types/yargs": "^13.0.0"
|
"@types/yargs": "^13.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@loadable/component": {
|
||||||
|
"version": "5.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.13.0.tgz",
|
||||||
|
"integrity": "sha512-+qS6xoA4DN5Pjm5sR6vWuuYEhMWZ9Y7ALgI8JuDOMCiqOG+PTau0phOyqFgrFqDXijVpeInoIoZQdW1FKjGBYA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.7.7",
|
||||||
|
"hoist-non-react-statics": "^3.3.1",
|
||||||
|
"react-is": "^16.12.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": {
|
||||||
|
"version": "7.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.3.tgz",
|
||||||
|
"integrity": "sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw==",
|
||||||
|
"requires": {
|
||||||
|
"regenerator-runtime": "^0.13.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-is": {
|
||||||
|
"version": "16.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
|
||||||
|
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@mdx-js/mdx": {
|
"@mdx-js/mdx": {
|
||||||
"version": "1.6.6",
|
"version": "1.6.6",
|
||||||
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.6.tgz",
|
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.6.tgz",
|
||||||
@ -32909,8 +32939,7 @@
|
|||||||
"react-fast-compare": {
|
"react-fast-compare": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==",
|
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"react-focus-lock": {
|
"react-focus-lock": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
@ -32926,6 +32955,17 @@
|
|||||||
"use-sidecar": "^1.0.1"
|
"use-sidecar": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-helmet": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||||
|
"requires": {
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-fast-compare": "^3.1.1",
|
||||||
|
"react-side-effect": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-helmet-async": {
|
"react-helmet-async": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.0.6.tgz",
|
||||||
@ -33126,6 +33166,11 @@
|
|||||||
"no-scroll": "^2.1.1"
|
"no-scroll": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-side-effect": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg=="
|
||||||
|
},
|
||||||
"react-sizeme": {
|
"react-sizeme": {
|
||||||
"version": "2.6.12",
|
"version": "2.6.12",
|
||||||
"resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-2.6.12.tgz",
|
"resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-2.6.12.tgz",
|
||||||
@ -37855,11 +37900,6 @@
|
|||||||
"integrity": "sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ==",
|
"integrity": "sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"use-debounce": {
|
|
||||||
"version": "3.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-3.4.2.tgz",
|
|
||||||
"integrity": "sha512-rW44wZaFPh3XiwUzGBA0JRuklpbfKO/szU/5CYD2Q/erLmCem63lJ650p3a+NJE6S+g0rulKtBOfa/3rw/GN+Q=="
|
|
||||||
},
|
|
||||||
"use-sidecar": {
|
"use-sidecar": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.2.tgz",
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
"storybook:build": "build-storybook -c .storybook -o public/storybook"
|
"storybook:build": "build-storybook -c .storybook -o public/storybook"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@loadable/component": "^5.13.0",
|
||||||
"@oceanprotocol/art": "^2.2.0",
|
"@oceanprotocol/art": "^2.2.0",
|
||||||
"@oceanprotocol/react": "0.0.11",
|
"@oceanprotocol/react": "0.0.11",
|
||||||
"@oceanprotocol/squid": "^2.2.0",
|
"@oceanprotocol/squid": "^2.2.0",
|
||||||
@ -48,6 +49,7 @@
|
|||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"react-dotdotdot": "^1.3.1",
|
"react-dotdotdot": "^1.3.1",
|
||||||
"react-dropzone": "^11.0.1",
|
"react-dropzone": "^11.0.1",
|
||||||
|
"react-helmet": "^6.1.0",
|
||||||
"react-jsonschema-form": "^1.8.1",
|
"react-jsonschema-form": "^1.8.1",
|
||||||
"react-markdown": "^4.3.1",
|
"react-markdown": "^4.3.1",
|
||||||
"react-paginate": "^6.3.2",
|
"react-paginate": "^6.3.2",
|
||||||
@ -56,7 +58,6 @@
|
|||||||
"react-toastify": "^6.0.6",
|
"react-toastify": "^6.0.6",
|
||||||
"shortid": "^2.2.15",
|
"shortid": "^2.2.15",
|
||||||
"slugify": "^1.4.4",
|
"slugify": "^1.4.4",
|
||||||
"use-debounce": "^3.4.2",
|
|
||||||
"web3connect": "^1.0.0-beta.33"
|
"web3connect": "^1.0.0-beta.33"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { WidgetProps } from 'react-jsonschema-form'
|
import { WidgetProps } from 'react-jsonschema-form'
|
||||||
import dynamic from 'next/dynamic'
|
import loadable from '@loadable/component'
|
||||||
import styles from './DateRangeWidget.module.css'
|
import styles from './DateRangeWidget.module.css'
|
||||||
import { toStringNoMS } from '../../../utils'
|
import { toStringNoMS } from '../../../utils'
|
||||||
|
|
||||||
// lazy load this module, it's huge
|
// lazy load this module, it's huge
|
||||||
const LazyDatePicker = dynamic(() => import('react-datepicker'))
|
const LazyDatePicker = loadable(() => import('react-datepicker'))
|
||||||
|
|
||||||
export function getWidgetValue(
|
export function getWidgetValue(
|
||||||
date1: Date,
|
date1: Date,
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { WidgetProps } from 'react-jsonschema-form'
|
import { WidgetProps } from 'react-jsonschema-form'
|
||||||
import styles from './TermsWidget.module.css'
|
import styles from './TermsWidget.module.css'
|
||||||
import Markdown from '../Markdown'
|
|
||||||
import terms from '../../../../content/terms.md'
|
|
||||||
|
|
||||||
export default function TermsWidget(props: WidgetProps) {
|
export default function TermsWidget(props: WidgetProps) {
|
||||||
const {
|
const {
|
||||||
@ -21,7 +19,7 @@ export default function TermsWidget(props: WidgetProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Markdown text={terms} className={styles.terms} />
|
{/* <Markdown text={terms} className={styles.terms} /> */}
|
||||||
<label
|
<label
|
||||||
htmlFor={id}
|
htmlFor={id}
|
||||||
className={required ? `${styles.label} ${styles.req}` : styles.label}
|
className={required ? `${styles.label} ${styles.req}` : styles.label}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.help {
|
.help {
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
color: var(--brand-grey-light);
|
color: var(--brand-grey-light);
|
||||||
margin-top: var(--spacer) / 4;
|
margin-top: calc(var(--spacer) / 6);
|
||||||
}
|
}
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
import cx from 'classnames'
|
|
||||||
import React, { PureComponent, FormEvent, ChangeEvent } from 'react'
|
|
||||||
import slugify from '@sindresorhus/slugify'
|
|
||||||
import DatePicker from 'react-datepicker'
|
|
||||||
import Help from './Help'
|
|
||||||
import Label from './Label'
|
|
||||||
import Row from './Row'
|
|
||||||
import InputGroup from './InputGroup'
|
|
||||||
import styles from './Input.module.css'
|
|
||||||
|
|
||||||
interface InputProps {
|
|
||||||
name: string
|
|
||||||
label: string
|
|
||||||
placeholder?: string
|
|
||||||
required?: boolean
|
|
||||||
help?: string
|
|
||||||
tag?: string
|
|
||||||
type?: string
|
|
||||||
options?: string[]
|
|
||||||
additionalComponent?: any
|
|
||||||
value?: string
|
|
||||||
onChange?(
|
|
||||||
event:
|
|
||||||
| FormEvent<HTMLInputElement>
|
|
||||||
| ChangeEvent<HTMLInputElement>
|
|
||||||
| ChangeEvent<HTMLSelectElement>
|
|
||||||
| ChangeEvent<HTMLTextAreaElement>
|
|
||||||
): void
|
|
||||||
rows?: number
|
|
||||||
group?: any
|
|
||||||
multiple?: boolean
|
|
||||||
pattern?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface InputState {
|
|
||||||
isFocused: boolean
|
|
||||||
dateCreated?: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Input extends PureComponent<InputProps, InputState> {
|
|
||||||
public state: InputState = {
|
|
||||||
isFocused: false,
|
|
||||||
dateCreated: new Date()
|
|
||||||
}
|
|
||||||
|
|
||||||
public inputWrapClasses() {
|
|
||||||
if (this.props.type === 'search') {
|
|
||||||
return styles.inputWrapSearch
|
|
||||||
} else if (this.props.type === 'search' && this.state.isFocused) {
|
|
||||||
return cx(styles.inputWrapSearch, styles.isFocused)
|
|
||||||
} else if (this.state.isFocused && this.props.type !== 'search') {
|
|
||||||
return cx(styles.inputWrap, styles.isFocused)
|
|
||||||
} else {
|
|
||||||
return styles.inputWrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public handleFocus = () => {
|
|
||||||
this.setState({ isFocused: !this.state.isFocused })
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleDateChange = (date: Date) => {
|
|
||||||
this.setState({ dateCreated: date })
|
|
||||||
|
|
||||||
const event = {
|
|
||||||
currentTarget: {
|
|
||||||
name: 'dateCreated',
|
|
||||||
value: date
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.props.onChange!(event as any) // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputComponent = () => {
|
|
||||||
const { type, options, group, name, required, onChange, value } = this.props
|
|
||||||
|
|
||||||
const wrapClass = this.inputWrapClasses()
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'select':
|
|
||||||
return (
|
|
||||||
<div className={wrapClass}>
|
|
||||||
<select
|
|
||||||
id={name}
|
|
||||||
className={styles.select}
|
|
||||||
name={name}
|
|
||||||
required={required}
|
|
||||||
onFocus={this.handleFocus}
|
|
||||||
onBlur={this.handleFocus}
|
|
||||||
onChange={onChange}
|
|
||||||
value={value}
|
|
||||||
>
|
|
||||||
<option value="">---</option>
|
|
||||||
{options &&
|
|
||||||
options
|
|
||||||
.sort((a, b) => a.localeCompare(b))
|
|
||||||
.map((option: string, index: number) => (
|
|
||||||
<option key={index} value={option}>
|
|
||||||
{option}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
case 'textarea':
|
|
||||||
return (
|
|
||||||
<div className={wrapClass}>
|
|
||||||
<textarea
|
|
||||||
id={name}
|
|
||||||
className={styles.input}
|
|
||||||
onFocus={this.handleFocus}
|
|
||||||
onBlur={this.handleFocus}
|
|
||||||
{...this.props}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
case 'radio':
|
|
||||||
case 'checkbox':
|
|
||||||
return (
|
|
||||||
<div className={styles.radioGroup}>
|
|
||||||
{options &&
|
|
||||||
options.map((option: string, index: number) => (
|
|
||||||
<div className={styles.radioWrap} key={index}>
|
|
||||||
<input
|
|
||||||
className={styles.radio}
|
|
||||||
id={slugify(option)}
|
|
||||||
type={type}
|
|
||||||
name={name}
|
|
||||||
value={slugify(option)}
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
className={styles.radioLabel}
|
|
||||||
htmlFor={slugify(option)}
|
|
||||||
>
|
|
||||||
{option}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
case 'date':
|
|
||||||
return (
|
|
||||||
<div className={wrapClass}>
|
|
||||||
<DatePicker
|
|
||||||
selected={this.state.dateCreated}
|
|
||||||
onChange={this.handleDateChange}
|
|
||||||
className={styles.input}
|
|
||||||
onFocus={this.handleFocus}
|
|
||||||
onBlur={this.handleFocus}
|
|
||||||
id={name}
|
|
||||||
name={name}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<div className={wrapClass}>
|
|
||||||
{group ? (
|
|
||||||
<InputGroup>
|
|
||||||
<input
|
|
||||||
id={name}
|
|
||||||
type={type || 'text'}
|
|
||||||
className={styles.input}
|
|
||||||
onFocus={this.handleFocus}
|
|
||||||
onBlur={this.handleFocus}
|
|
||||||
{...this.props}
|
|
||||||
/>
|
|
||||||
{group}
|
|
||||||
</InputGroup>
|
|
||||||
) : (
|
|
||||||
<input
|
|
||||||
id={name}
|
|
||||||
type={type || 'text'}
|
|
||||||
className={styles.input}
|
|
||||||
onFocus={this.handleFocus}
|
|
||||||
onBlur={this.handleFocus}
|
|
||||||
{...this.props}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* {type === 'search' && <SearchIcon />} */}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
label,
|
|
||||||
required,
|
|
||||||
help,
|
|
||||||
additionalComponent,
|
|
||||||
multiple
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Row>
|
|
||||||
<Label htmlFor={name} required={required}>
|
|
||||||
{label}
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<this.InputComponent />
|
|
||||||
|
|
||||||
{help && <Help>{help}</Help>}
|
|
||||||
|
|
||||||
{multiple && 'hello'}
|
|
||||||
|
|
||||||
{additionalComponent && additionalComponent}
|
|
||||||
</Row>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +1,27 @@
|
|||||||
.inputWrap,
|
|
||||||
.inputWrapSearch {
|
|
||||||
background: var(--brand-gradient);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: 2px;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.inputWrap .isFocused,
|
|
||||||
.inputWrapSearch .isFocused {
|
|
||||||
background: var(--brand-black);
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputWrap > div,
|
|
||||||
.inputWrap > div > div,
|
|
||||||
.inputWrapSearch > div,
|
|
||||||
.inputWrapSearch > div > div {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputWrapSearch,
|
|
||||||
.input {
|
.input {
|
||||||
padding-left: var(--spacer) * 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputWrapSearch svg {
|
|
||||||
position: absolute;
|
|
||||||
left: var(--spacer) / 2;
|
|
||||||
width: 1.25rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -0.6rem;
|
|
||||||
fill: rgba(var(--brand-grey-light), 0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input,
|
|
||||||
.select {
|
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
font-family: var(--font-family-base);
|
font-family: var(--font-family-base);
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
color: var(--brand-black);
|
color: var(--brand-black);
|
||||||
border: none;
|
border: 1px solid var(--brand-grey-lighter);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: var(--brand-white);
|
background: var(--brand-white);
|
||||||
padding: var(--spacer) / 3;
|
padding: calc(var(--spacer) / 3);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
transition: 0.2s ease-out;
|
transition: 0.2s ease-out;
|
||||||
min-height: 43px;
|
min-height: 43px;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
.input:focus,
|
|
||||||
.select:focus {
|
.input:focus {
|
||||||
border: none;
|
border-color: var(--brand-grey);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select::placeholder,
|
|
||||||
.input::placeholder {
|
.input::placeholder {
|
||||||
font-family: var(--font-family-base);
|
font-family: var(--font-family-base);
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
@ -67,9 +31,7 @@
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select[readonly],
|
|
||||||
.input[readonly],
|
.input[readonly],
|
||||||
.select[disabled],
|
|
||||||
.input[disabled] {
|
.input[disabled] {
|
||||||
background-color: var(--brand-grey-lighter);
|
background-color: var(--brand-grey-lighter);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
@ -80,35 +42,38 @@
|
|||||||
composes: input;
|
composes: input;
|
||||||
height: 43px;
|
height: 43px;
|
||||||
padding-right: 3rem;
|
padding-right: 3rem;
|
||||||
border: 0;
|
|
||||||
|
|
||||||
|
/* custom arrow */
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
45deg,
|
45deg,
|
||||||
transparent 50%,
|
transparent 50%,
|
||||||
var(--brand-purple 50%)
|
var(--brand-purple) 50%
|
||||||
),
|
),
|
||||||
linear-gradient(135deg, var(--brand-purple) 50%, transparent 50%),
|
linear-gradient(135deg, var(--brand-grey) 50%, transparent 50%),
|
||||||
linear-gradient(
|
linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
var(--brand-pink) 1px,
|
var(--brand-grey-lighter) 1px,
|
||||||
lighten(var(--brand-grey-lighter), 5%) 2px,
|
transparent 1px,
|
||||||
lighten(var(--brand-grey-lighter), 5%)
|
transparent
|
||||||
);
|
);
|
||||||
background-position: calc(100% - 18px) calc(1rem + 5px),
|
background-position: calc(100% - 18px) calc(1rem + 5px),
|
||||||
calc(100% - 13px) calc(1rem + 5px), 100% 0;
|
calc(100% - 13px) calc(1rem + 5px), 100% 0;
|
||||||
background-size: 5px 5px, 5px 5px, 2.5rem 3rem;
|
background-size: 5px 5px, 5px 5px, 2.5rem 3rem;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select:focus {
|
.select:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
font-family: var(--font-family-base);
|
font-family: var(--font-family-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
.radioGroup {
|
.radioGroup {
|
||||||
margin-top: var(--spacer) / 2;
|
margin-top: calc(var(--spacer) / 2);
|
||||||
margin-bottom: -2%;
|
margin-bottom: -2%;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: var(--break-point--small)) {
|
@media screen and (min-width: 40rem) {
|
||||||
|
.radioGroup {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -117,13 +82,15 @@
|
|||||||
|
|
||||||
.radioWrap {
|
.radioWrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: var(--spacer) / 2;
|
padding: calc(var(--spacer) / 2);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 2%;
|
margin-bottom: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: var(--break-point--small)) {
|
@media screen and (min-width: 40rem) {
|
||||||
|
.radioWrap {
|
||||||
flex: 0 0 49%;
|
flex: 0 0 49%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,7 +105,7 @@
|
|||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
border: 2px solid var(--brand-grey-lighter);
|
border: 1px solid var(--brand-grey-lighter);
|
||||||
border-radius: 0.2rem;
|
border-radius: 0.2rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -152,13 +119,16 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputSmall {
|
/* Size modifiers */
|
||||||
|
|
||||||
|
.small {
|
||||||
composes: input;
|
composes: input;
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
padding: var(--spacer) / 4;
|
padding: calc(var(--spacer) / 4);
|
||||||
}
|
}
|
||||||
.inputSmall::placeholder {
|
|
||||||
|
.small::placeholder {
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +136,8 @@
|
|||||||
composes: select;
|
composes: select;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
padding-right: 2rem;
|
padding-right: 2rem;
|
||||||
|
|
||||||
|
/* custom arrow */
|
||||||
background-position: calc(100% - 14px) 1rem, calc(100% - 9px) 1rem, 100% 0;
|
background-position: calc(100% - 14px) 1rem, calc(100% - 9px) 1rem, 100% 0;
|
||||||
background-size: 5px 5px, 5px 5px, 2rem 3rem;
|
background-size: 5px 5px, 5px 5px, 2rem 3rem;
|
||||||
}
|
}
|
66
src/components/atoms/Input/InputElement.tsx
Normal file
66
src/components/atoms/Input/InputElement.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import slugify from '@sindresorhus/slugify'
|
||||||
|
import styles from './InputElement.module.css'
|
||||||
|
import { InputProps } from '.'
|
||||||
|
|
||||||
|
export default function InputElement(props: InputProps) {
|
||||||
|
const { type, options, rows, name } = props
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'select':
|
||||||
|
return (
|
||||||
|
<select id={name} className={styles.select} name={name} {...props}>
|
||||||
|
<option value="">---</option>
|
||||||
|
{options &&
|
||||||
|
options
|
||||||
|
.sort((a: string, b: string) => a.localeCompare(b))
|
||||||
|
.map((option: string, index: number) => (
|
||||||
|
<option key={index} value={option}>
|
||||||
|
{option}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
)
|
||||||
|
case 'textarea':
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
id={name}
|
||||||
|
className={styles.input}
|
||||||
|
rows={rows}
|
||||||
|
name={name}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
case 'radio':
|
||||||
|
case 'checkbox':
|
||||||
|
return (
|
||||||
|
<div className={styles.radioGroup}>
|
||||||
|
{options &&
|
||||||
|
options.map((option: string, index: number) => (
|
||||||
|
<div className={styles.radioWrap} key={index}>
|
||||||
|
<input
|
||||||
|
className={styles.radio}
|
||||||
|
id={slugify(option)}
|
||||||
|
type={type}
|
||||||
|
name={name}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<label className={styles.radioLabel} htmlFor={slugify(option)}>
|
||||||
|
{option}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
id={name}
|
||||||
|
type={type || 'text'}
|
||||||
|
className={styles.input}
|
||||||
|
name={name}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
.label .required {
|
.label {
|
||||||
color: var(--brand-grey);
|
color: var(--brand-grey);
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
font-family: var(--font-family-title);
|
font-family: var(--font-family-title);
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: var(--spacer) / 6;
|
margin-bottom: calc(var(--spacer) / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.required:after {
|
.required:after {
|
||||||
|
@ -11,7 +11,7 @@ const Label = ({
|
|||||||
htmlFor: string
|
htmlFor: string
|
||||||
}) => (
|
}) => (
|
||||||
<label
|
<label
|
||||||
className={required ? styles.required : styles.label}
|
className={`${styles.label} ${required && styles.required}`}
|
||||||
title={required ? 'Required' : ''}
|
title={required ? 'Required' : ''}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
3
src/components/atoms/Input/index.module.css
Normal file
3
src/components/atoms/Input/index.module.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.field {
|
||||||
|
margin-bottom: var(--spacer);
|
||||||
|
}
|
59
src/components/atoms/Input/index.tsx
Normal file
59
src/components/atoms/Input/index.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import React, { FormEvent, ChangeEvent, ReactElement } from 'react'
|
||||||
|
import InputElement from './InputElement'
|
||||||
|
import Help from './Help'
|
||||||
|
import Label from './Label'
|
||||||
|
import styles from './index.module.css'
|
||||||
|
|
||||||
|
export interface InputProps {
|
||||||
|
name: string
|
||||||
|
label?: string
|
||||||
|
placeholder?: string
|
||||||
|
required?: boolean
|
||||||
|
help?: string
|
||||||
|
tag?: string
|
||||||
|
type?: string
|
||||||
|
options?: string[]
|
||||||
|
additionalComponent?: ReactElement
|
||||||
|
value?: string
|
||||||
|
onChange?(
|
||||||
|
e:
|
||||||
|
| FormEvent<HTMLInputElement>
|
||||||
|
| ChangeEvent<HTMLInputElement>
|
||||||
|
| ChangeEvent<HTMLSelectElement>
|
||||||
|
| ChangeEvent<HTMLTextAreaElement>
|
||||||
|
): void
|
||||||
|
rows?: number
|
||||||
|
multiple?: boolean
|
||||||
|
pattern?: string
|
||||||
|
min?: string
|
||||||
|
disabled?: boolean
|
||||||
|
field?: {
|
||||||
|
name: string
|
||||||
|
value: string
|
||||||
|
onChange: () => void
|
||||||
|
onBlur: () => void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Input(props: InputProps) {
|
||||||
|
const {
|
||||||
|
required,
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
help,
|
||||||
|
additionalComponent,
|
||||||
|
field
|
||||||
|
} = props as Partial<InputProps>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.field}>
|
||||||
|
<Label htmlFor={name} required={required}>
|
||||||
|
{label}
|
||||||
|
</Label>
|
||||||
|
<InputElement {...field} {...props} />
|
||||||
|
|
||||||
|
{help && <Help>{help}</Help>}
|
||||||
|
{additionalComponent && additionalComponent}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
#nprogress {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nprogress .bar {
|
|
||||||
background: var(--color-primary);
|
|
||||||
position: fixed;
|
|
||||||
z-index: 99;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nprogress .peg {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
right: 0px;
|
|
||||||
width: 100px;
|
|
||||||
height: 100%;
|
|
||||||
box-shadow: 0 0 10px var(--color-primary), 0 0 5px var(--color-primary);
|
|
||||||
opacity: 1;
|
|
||||||
transform: rotate(3deg) translate(0px, -4px);
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
import React, { useEffect } from 'react'
|
|
||||||
import NProgress, { NProgressOptions } from 'nprogress'
|
|
||||||
import Router from 'next/router'
|
|
||||||
|
|
||||||
//
|
|
||||||
// Component loosely taken from, but highly refactored
|
|
||||||
// https://github.com/sergiodxa/next-nprogress/blob/master/src/component.js
|
|
||||||
//
|
|
||||||
|
|
||||||
declare type NProgressContainerProps = {
|
|
||||||
showAfterMs?: number
|
|
||||||
options?: NProgressOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function NProgressContainer({
|
|
||||||
showAfterMs = 300,
|
|
||||||
options
|
|
||||||
}: NProgressContainerProps) {
|
|
||||||
let timer: NodeJS.Timeout
|
|
||||||
|
|
||||||
function routeChangeStart() {
|
|
||||||
clearTimeout(timer)
|
|
||||||
timer = setTimeout(NProgress.start, showAfterMs)
|
|
||||||
}
|
|
||||||
|
|
||||||
function routeChangeEnd() {
|
|
||||||
clearTimeout(timer)
|
|
||||||
NProgress.done()
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (options) {
|
|
||||||
NProgress.configure(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
Router.events.on('routeChangeStart', routeChangeStart)
|
|
||||||
Router.events.on('routeChangeComplete', routeChangeEnd)
|
|
||||||
Router.events.on('routeChangeError', routeChangeEnd)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearTimeout(timer)
|
|
||||||
Router.events.off('routeChangeStart', routeChangeStart)
|
|
||||||
Router.events.off('routeChangeComplete', routeChangeEnd)
|
|
||||||
Router.events.off('routeChangeError', routeChangeEnd)
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return <div />
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import {
|
|||||||
AdditionalInformationMarket,
|
AdditionalInformationMarket,
|
||||||
MetaDataMarket
|
MetaDataMarket
|
||||||
} from '../../@types/MetaData'
|
} from '../../@types/MetaData'
|
||||||
import { findServiceByType } from '../../utils'
|
|
||||||
import Tags from '../atoms/Tags'
|
import Tags from '../atoms/Tags'
|
||||||
import Price from '../atoms/Price'
|
import Price from '../atoms/Price'
|
||||||
import styles from './AssetTeaser.module.css'
|
import styles from './AssetTeaser.module.css'
|
||||||
@ -17,7 +16,7 @@ declare type AssetTeaserProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
|
const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
|
||||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
const { name, price } = attributes.main
|
const { name, price } = attributes.main
|
||||||
|
|
||||||
let description
|
let description
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { DDO, Ocean } from '@oceanprotocol/squid'
|
import { useNavigate } from '@reach/router'
|
||||||
import { useRouter } from 'next/router'
|
import { DDO } from '@oceanprotocol/squid'
|
||||||
import { findServiceByType, redeploy } from '../../utils'
|
import { redeploy } from '../../utils'
|
||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
import BaseDialog from '../atoms/BaseDialog'
|
import BaseDialog from '../atoms/BaseDialog'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '@oceanprotocol/react'
|
||||||
@ -15,19 +15,17 @@ const content = [
|
|||||||
|
|
||||||
export default function DeleteAction({ ddo }: { ddo: DDO }) {
|
export default function DeleteAction({ ddo }: { ddo: DDO }) {
|
||||||
const { ocean, accountId } = useOcean()
|
const { ocean, accountId } = useOcean()
|
||||||
|
const navigate = useNavigate()
|
||||||
const isOwner = ddo.publicKey[0].owner === accountId
|
const isOwner = ddo.publicKey[0].owner === accountId
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const [isModal, setIsModal] = useState(false)
|
const [isModal, setIsModal] = useState(false)
|
||||||
const [status, setStatus] = useState(0) // 0-confirmation, 1-deleting, 2-success, 3-error
|
const [status, setStatus] = useState(0) // 0-confirmation, 1-deleting, 2-success, 3-error
|
||||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let tId: number
|
let tId: number
|
||||||
if (status === 2) {
|
if (status === 2) {
|
||||||
tId = window.setTimeout(() => {
|
tId = window.setTimeout(() => {
|
||||||
router.push(`/explore`)
|
navigate(`/`)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -105,7 +105,7 @@ export default function Form({
|
|||||||
transformErrors={transformErrors}
|
transformErrors={transformErrors}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<Button disabled={buttonDisabled} primary>
|
<Button disabled={buttonDisabled} style="primary">
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ComputeItem } from '@oceanprotocol/react'
|
import { ComputeItem } from '@oceanprotocol/react'
|
||||||
import BaseDialog from '../atoms/BaseDialog'
|
import BaseDialog from '../atoms/BaseDialog'
|
||||||
import { findServiceByType } from '../../utils'
|
|
||||||
import styles from './JobDetailsDialog.module.css'
|
import styles from './JobDetailsDialog.module.css'
|
||||||
import MetaItem from '../templates/AssetDetails/MetaItem'
|
import MetaItem from '../templates/AssetDetails/MetaItem'
|
||||||
import Time from '../atoms/Time'
|
import Time from '../atoms/Time'
|
||||||
@ -19,7 +18,7 @@ export default function JobDetailsDialog({
|
|||||||
}) {
|
}) {
|
||||||
if (!computeItem) return null
|
if (!computeItem) return null
|
||||||
|
|
||||||
const { attributes } = findServiceByType(computeItem.ddo, 'metadata')
|
const { attributes } = computeItem.ddo.findServiceByType('metadata')
|
||||||
const { name } = attributes.main
|
const { name } = attributes.main
|
||||||
const {
|
const {
|
||||||
dateCreated,
|
dateCreated,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useNavigate } from '@reach/router'
|
||||||
import Form from '../../molecules/Form/index'
|
import Form from '../../molecules/Form/index'
|
||||||
import {
|
import {
|
||||||
PublishFormSchema,
|
PublishFormSchema,
|
||||||
@ -11,7 +12,6 @@ import { MetaDataMarket } from '../../../@types/MetaData'
|
|||||||
import { File, MetaData } from '@oceanprotocol/squid'
|
import { File, MetaData } from '@oceanprotocol/squid'
|
||||||
import { isBrowser, toStringNoMS } from '../../../utils'
|
import { isBrowser, toStringNoMS } from '../../../utils'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import styles from './PublishForm.module.css'
|
import styles from './PublishForm.module.css'
|
||||||
import utils from 'web3-utils'
|
import utils from 'web3-utils'
|
||||||
import AssetModel from '../../../models/Asset'
|
import AssetModel from '../../../models/Asset'
|
||||||
@ -21,8 +21,6 @@ import {
|
|||||||
ServiceCompute
|
ServiceCompute
|
||||||
} from '@oceanprotocol/squid/dist/node/ddo/Service'
|
} from '@oceanprotocol/squid/dist/node/ddo/Service'
|
||||||
|
|
||||||
declare type PublishFormProps = {}
|
|
||||||
|
|
||||||
const FILES_DATA_LOCAL_STORAGE_KEY = 'filesData'
|
const FILES_DATA_LOCAL_STORAGE_KEY = 'filesData'
|
||||||
const PUBLISH_FORM_LOCAL_STORAGE_KEY = 'publishForm'
|
const PUBLISH_FORM_LOCAL_STORAGE_KEY = 'publishForm'
|
||||||
|
|
||||||
@ -101,11 +99,11 @@ export function transformPublishFormToMetadata(
|
|||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
const PublishForm: React.FC<PublishFormProps> = () => {
|
const PublishForm: React.FC<any> = () => {
|
||||||
const [buttonDisabled, setButtonDisabled] = useState(false)
|
const [buttonDisabled, setButtonDisabled] = useState(false)
|
||||||
const { web3Connect } = useWeb3()
|
const { web3Connect } = useWeb3()
|
||||||
const { ocean, account } = useOcean()
|
const { ocean, account } = useOcean()
|
||||||
const router = useRouter()
|
const navigate = useNavigate()
|
||||||
const [data, updateData] = useStoredValue(
|
const [data, updateData] = useStoredValue(
|
||||||
PUBLISH_FORM_LOCAL_STORAGE_KEY,
|
PUBLISH_FORM_LOCAL_STORAGE_KEY,
|
||||||
publishFormData
|
publishFormData
|
||||||
@ -172,7 +170,7 @@ const PublishForm: React.FC<PublishFormProps> = () => {
|
|||||||
className: styles.success
|
className: styles.success
|
||||||
})
|
})
|
||||||
toast.dismiss(submittingToast)
|
toast.dismiss(submittingToast)
|
||||||
router.push(`/asset/${asset.id}`)
|
navigate(`/asset/${asset.id}`)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, ChangeEvent, FormEvent } from 'react'
|
import React, { useState, ChangeEvent, FormEvent } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useNavigate } from '@reach/router'
|
||||||
import styles from './SearchBar.module.css'
|
import styles from './SearchBar.module.css'
|
||||||
import Loader from '../atoms/Loader'
|
import Loader from '../atoms/Loader'
|
||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
@ -15,7 +15,7 @@ export default function SearchBar({
|
|||||||
filters?: boolean
|
filters?: boolean
|
||||||
large?: true
|
large?: true
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter()
|
const navigate = useNavigate()
|
||||||
const [value, setValue] = useState(initialValue || '')
|
const [value, setValue] = useState(initialValue || '')
|
||||||
const [searchStarted, setSearchStarted] = useState(false)
|
const [searchStarted, setSearchStarted] = useState(false)
|
||||||
|
|
||||||
@ -29,20 +29,9 @@ export default function SearchBar({
|
|||||||
if (value === '') return
|
if (value === '') return
|
||||||
|
|
||||||
setSearchStarted(true)
|
setSearchStarted(true)
|
||||||
router.push(`/search?text=${value}`)
|
navigate(`/search?text=${value}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// fix for storybook
|
|
||||||
if (!router) return
|
|
||||||
|
|
||||||
router.events.on('routeChangeComplete', () => setSearchStarted(false))
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
router.events.off('routeChangeComplete', () => setSearchStarted(false))
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className={styles.form}>
|
<form className={styles.form}>
|
||||||
<div className={styles.inputGroup}>
|
<div className={styles.inputGroup}>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { DDO, Ocean, Logger } from '@oceanprotocol/squid'
|
import { DDO, Ocean } from '@oceanprotocol/squid'
|
||||||
import { ServiceMetadata } from '@oceanprotocol/squid/dist/node/ddo/Service'
|
import { ServiceMetadata } from '@oceanprotocol/squid/dist/node/ddo/Service'
|
||||||
import { fromWei } from 'web3-utils'
|
import { fromWei } from 'web3-utils'
|
||||||
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
||||||
@ -7,7 +7,6 @@ import Loader from '../atoms/Loader'
|
|||||||
import Web3Feedback from '../molecules/Web3Feedback'
|
import Web3Feedback from '../molecules/Web3Feedback'
|
||||||
import Dropzone from '../atoms/Dropzone'
|
import Dropzone from '../atoms/Dropzone'
|
||||||
import Price from '../atoms/Price'
|
import Price from '../atoms/Price'
|
||||||
import { findServiceByType } from '../../utils'
|
|
||||||
import {
|
import {
|
||||||
computeOptions,
|
computeOptions,
|
||||||
useCompute,
|
useCompute,
|
||||||
@ -42,7 +41,7 @@ export default function Compute({
|
|||||||
const [isPublished, setIsPublished] = useState(false)
|
const [isPublished, setIsPublished] = useState(false)
|
||||||
const [file, setFile] = useState(null)
|
const [file, setFile] = useState(null)
|
||||||
|
|
||||||
const metadata = findServiceByType(ddo, 'metadata') as ServiceMetadata
|
const metadata = ddo.findServiceByType('metadata') as ServiceMetadata
|
||||||
const { price } = metadata.attributes.main
|
const { price } = metadata.attributes.main
|
||||||
|
|
||||||
const isFree = price === '0'
|
const isFree = price === '0'
|
||||||
@ -118,7 +117,7 @@ export default function Compute({
|
|||||||
|
|
||||||
<div className={styles.jobButtonWrapper}>
|
<div className={styles.jobButtonWrapper}>
|
||||||
<Button
|
<Button
|
||||||
primary
|
style="primary"
|
||||||
onClick={() => startJob()}
|
onClick={() => startJob()}
|
||||||
disabled={isComputeButtonDisabled}
|
disabled={isComputeButtonDisabled}
|
||||||
>
|
>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { DDO } from '@oceanprotocol/squid'
|
import { DDO } from '@oceanprotocol/squid'
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
import { findServiceByType } from '../../utils'
|
|
||||||
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
import File from '../atoms/File'
|
import File from '../atoms/File'
|
||||||
@ -18,9 +17,9 @@ export default function Consume({ ddo }: { ddo: DDO | undefined }) {
|
|||||||
const { web3 } = useWeb3()
|
const { web3 } = useWeb3()
|
||||||
const { ocean, balanceInOcean } = useOcean()
|
const { ocean, balanceInOcean } = useOcean()
|
||||||
const { consume, consumeStepText, isLoading } = useConsume()
|
const { consume, consumeStepText, isLoading } = useConsume()
|
||||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
const { price } = attributes.main
|
const { price } = attributes.main
|
||||||
const file = (attributes as MetaDataMarket).main.files[0]
|
const file = (attributes as any).main.files[0]
|
||||||
const isFree = price === '0'
|
const isFree = price === '0'
|
||||||
const isBalanceSufficient =
|
const isBalanceSufficient =
|
||||||
isFree ||
|
isFree ||
|
||||||
|
@ -11,7 +11,6 @@ import { fromWei } from 'web3-utils'
|
|||||||
import DateCell from '../atoms/Table/DateCell'
|
import DateCell from '../atoms/Table/DateCell'
|
||||||
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
|
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
|
||||||
import { MetaDataMain } from '@oceanprotocol/squid'
|
import { MetaDataMain } from '@oceanprotocol/squid'
|
||||||
import { findServiceByType } from '../../utils'
|
|
||||||
|
|
||||||
const consumedColumns = [
|
const consumedColumns = [
|
||||||
{
|
{
|
||||||
@ -57,7 +56,7 @@ export default function ConsumedList() {
|
|||||||
if (!consumedItems) return
|
if (!consumedItems) return
|
||||||
|
|
||||||
const data = consumedItems.map((ddo) => {
|
const data = consumedItems.map((ddo) => {
|
||||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
const { name, price, datePublished } = attributes.main as MetaDataMain
|
const { name, price, datePublished } = attributes.main as MetaDataMain
|
||||||
return {
|
return {
|
||||||
published: datePublished,
|
published: datePublished,
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styles from './Footer.module.css'
|
import styles from './Footer.module.css'
|
||||||
import { copyright } from '../../../site.config'
|
|
||||||
import Markdown from '../atoms/Markdown'
|
import Markdown from '../atoms/Markdown'
|
||||||
|
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
|
const { copyright } = useSiteMetadata()
|
||||||
const year = new Date().getFullYear()
|
const year = new Date().getFullYear()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
|
|
||||||
import Price from '../atoms/Price'
|
import Price from '../atoms/Price'
|
||||||
import { fromWei } from 'web3-utils'
|
import { fromWei } from 'web3-utils'
|
||||||
import { findServiceByType } from '../../utils'
|
|
||||||
import Table from '../atoms/Table'
|
import Table from '../atoms/Table'
|
||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
import { MetaDataMain, Logger } from '@oceanprotocol/squid'
|
import { MetaDataMain, Logger } from '@oceanprotocol/squid'
|
||||||
@ -97,7 +96,7 @@ export default function JobsList() {
|
|||||||
const computeItems = await getComputeItems()
|
const computeItems = await getComputeItems()
|
||||||
if (!computeItems) return
|
if (!computeItems) return
|
||||||
const data = computeItems.map((item) => {
|
const data = computeItems.map((item) => {
|
||||||
const { attributes } = findServiceByType(item.ddo, 'metadata')
|
const { attributes } = item.ddo.findServiceByType('metadata')
|
||||||
const { name, price } = attributes.main as MetaDataMain
|
const { name, price } = attributes.main as MetaDataMain
|
||||||
return {
|
return {
|
||||||
dateCreated: item.job.dateCreated,
|
dateCreated: item.job.dateCreated,
|
||||||
@ -136,7 +135,7 @@ export default function JobsList() {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<Button primary onClick={getJobs}>
|
<Button style="primary" onClick={getJobs}>
|
||||||
Sign to retrieve jobs
|
Sign to retrieve jobs
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
import Table from '../atoms/Table'
|
import Table from '../atoms/Table'
|
||||||
import Price from '../atoms/Price'
|
import Price from '../atoms/Price'
|
||||||
import { fromWei } from 'web3-utils'
|
import { fromWei } from 'web3-utils'
|
||||||
import { findServiceByType } from '../../utils'
|
|
||||||
import DateCell from '../atoms/Table/DateCell'
|
import DateCell from '../atoms/Table/DateCell'
|
||||||
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
|
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ export default function PublishedList() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const data = publishedItems.results.map((ddo) => {
|
const data = publishedItems.results.map((ddo) => {
|
||||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
const { name, price, datePublished } = attributes.main as MetaDataMain
|
const { name, price, datePublished } = attributes.main as MetaDataMain
|
||||||
return {
|
return {
|
||||||
published: datePublished,
|
published: datePublished,
|
||||||
|
51
src/components/pages/History.tsx
Normal file
51
src/components/pages/History.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import styles from './History.module.css'
|
||||||
|
import Web3Feedback from '../molecules/Web3Feedback'
|
||||||
|
import ConsumedList from '../organisms/ConsumedList'
|
||||||
|
import PublishedList from '../organisms/PublishedList'
|
||||||
|
import JobsList from '../organisms/JobsList'
|
||||||
|
|
||||||
|
const sections = [
|
||||||
|
{
|
||||||
|
title: 'Published',
|
||||||
|
component: <PublishedList />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Downloaded',
|
||||||
|
component: <ConsumedList />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Compute Jobs',
|
||||||
|
component: <JobsList />
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const Section = ({ title, component }: { title: string; component: any }) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.section}>
|
||||||
|
<h2 className={styles.sectionTitle}>{title}</h2>
|
||||||
|
{component}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const HistoryPage: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<article className={styles.grid}>
|
||||||
|
<div>
|
||||||
|
{sections.map((section) => {
|
||||||
|
const { title, component } = section
|
||||||
|
return <Section key={title} title={title} component={component} />
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<aside>
|
||||||
|
<div className={styles.sticky}>
|
||||||
|
<Web3Feedback />
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
</article>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HistoryPage
|
@ -1,21 +1,3 @@
|
|||||||
.header {
|
|
||||||
max-width: 37rem;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-bottom: calc(var(--spacer) * 3);
|
|
||||||
margin-top: 3vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header h1 {
|
|
||||||
margin-bottom: calc(var(--spacer) / 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header h2 {
|
|
||||||
font-size: var(--font-size-large);
|
|
||||||
color: var(--color-secondary);
|
|
||||||
margin-bottom: calc(var(--spacer) * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import React from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { Link } from 'gatsby'
|
import { Link } from 'gatsby'
|
||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import Layout from '../../components/Layout'
|
|
||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
import SearchBar from '../molecules/SearchBar'
|
import SearchBar from '../molecules/SearchBar'
|
||||||
import Explore from '../../images/explore.svg'
|
import Explore from '../../images/explore.svg'
|
||||||
import Publish from '../../images/publish.svg'
|
import Publish from '../../images/publish.svg'
|
||||||
import DataPool from '../../images/datapool.svg'
|
import DataPool from '../../images/datapool.svg'
|
||||||
import styles from './Home.module.css'
|
import styles from './Home.module.css'
|
||||||
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
|
||||||
|
|
||||||
const actions = [
|
const actions = [
|
||||||
{
|
{
|
||||||
@ -36,16 +34,10 @@ const actions = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage(): ReactElement {
|
||||||
const { siteTitle, siteDescription } = useSiteMetadata()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout noPageHeader>
|
<>
|
||||||
<header className={styles.header}>
|
|
||||||
<h1>{siteTitle}</h1>
|
|
||||||
<h2>{siteDescription}</h2>
|
|
||||||
<SearchBar large />
|
<SearchBar large />
|
||||||
</header>
|
|
||||||
|
|
||||||
<div className={styles.actions}>
|
<div className={styles.actions}>
|
||||||
{actions.map((action) => (
|
{actions.map((action) => (
|
||||||
@ -63,6 +55,6 @@ export default function HomePage() {
|
|||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Layout from '../../components/Layout'
|
|
||||||
import PublishForm from '../molecules/PublishForm/PublishForm'
|
import PublishForm from '../molecules/PublishForm/PublishForm'
|
||||||
import styles from './Publish.module.css'
|
import styles from './Publish.module.css'
|
||||||
import Web3Feedback from '../molecules/Web3Feedback'
|
import Web3Feedback from '../molecules/Web3Feedback'
|
||||||
|
|
||||||
const title = 'Publish Data'
|
|
||||||
const description = `Highlight the important features of your data set to make \
|
|
||||||
it more discoverable and catch the interest of data consumers.`
|
|
||||||
|
|
||||||
const PublishPage: React.FC = () => {
|
const PublishPage: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Layout title={title} description={description}>
|
|
||||||
<article className={styles.grid}>
|
<article className={styles.grid}>
|
||||||
<PublishForm />
|
<PublishForm />
|
||||||
<aside>
|
<aside>
|
||||||
@ -19,7 +13,6 @@ const PublishPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</article>
|
</article>
|
||||||
</Layout>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default PublishPage
|
export default PublishPage
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import Layout from '../../components/Layout'
|
|
||||||
import styles from './Transactions.module.css'
|
|
||||||
import Web3Feedback from '../molecules/Web3Feedback'
|
|
||||||
import ConsumedList from '../organisms/ConsumedList'
|
|
||||||
import PublishedList from '../organisms/PublishedList'
|
|
||||||
import JobsList from '../organisms/JobsList'
|
|
||||||
|
|
||||||
const title = 'Transactions'
|
|
||||||
const description = 'Find the data sets and jobs that you previously accessed'
|
|
||||||
|
|
||||||
const sections = [
|
|
||||||
{
|
|
||||||
title: 'Published',
|
|
||||||
component: <PublishedList />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Downloaded',
|
|
||||||
component: <ConsumedList />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Compute Jobs',
|
|
||||||
component: <JobsList />
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const Section = ({ title, component }: { title: string; component: any }) => {
|
|
||||||
return (
|
|
||||||
<div className={styles.section}>
|
|
||||||
<h2 className={styles.sectionTitle}>{title}</h2>
|
|
||||||
{component}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const TransactionsPage: React.FC = () => {
|
|
||||||
return (
|
|
||||||
<Layout title={title} description={description}>
|
|
||||||
<article className={styles.grid}>
|
|
||||||
<div>
|
|
||||||
{sections.map((section) => {
|
|
||||||
const { title, component } = section
|
|
||||||
return <Section key={title} title={title} component={component} />
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<aside>
|
|
||||||
<div className={styles.sticky}>
|
|
||||||
<Web3Feedback />
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
</article>
|
|
||||||
</Layout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TransactionsPage
|
|
@ -1,8 +1,14 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
|
import { Web3Provider, OceanProvider, Config } from '@oceanprotocol/react'
|
||||||
|
import { config } from '../config/ocean'
|
||||||
import Styles from '../global/Styles'
|
import Styles from '../global/Styles'
|
||||||
|
|
||||||
const wrapPageElement = ({ element }: { element: ReactElement }) => (
|
const wrapPageElement = ({ element }: { element: ReactElement }) => (
|
||||||
|
<Web3Provider>
|
||||||
|
<OceanProvider config={config as Config}>
|
||||||
<Styles>{element}</Styles>
|
<Styles>{element}</Styles>
|
||||||
|
</OceanProvider>
|
||||||
|
</Web3Provider>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default wrapPageElement
|
export default wrapPageElement
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { setProperty, JSONparse } from '../utils'
|
import { setProperty, JSONparse } from '../utils'
|
||||||
|
|
||||||
const CATEGORIES_QUERY_PARAM = 'categories'
|
const CATEGORIES_QUERY_PARAM = 'categories'
|
||||||
@ -9,8 +8,6 @@ const useGetCategoriesFromQueryParam = (
|
|||||||
allCategories: string[],
|
allCategories: string[],
|
||||||
setSelectedCategories: (categories: string[]) => void
|
setSelectedCategories: (categories: string[]) => void
|
||||||
) => {
|
) => {
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (router.query && router.query.categories) {
|
if (router.query && router.query.categories) {
|
||||||
const parsedCategories = JSONparse<string[]>(
|
const parsedCategories = JSONparse<string[]>(
|
||||||
@ -27,7 +24,6 @@ const useGetCategoriesFromQueryParam = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function useCategoriesQueryParam(allCategories: string[]) {
|
export default function useCategoriesQueryParam(allCategories: string[]) {
|
||||||
const router = useRouter()
|
|
||||||
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
|
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
|
||||||
useGetCategoriesFromQueryParam(allCategories, setSelectedCategories)
|
useGetCategoriesFromQueryParam(allCategories, setSelectedCategories)
|
||||||
|
|
||||||
|
@ -1,27 +1,15 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { NextRouter, useRouter } from 'next/router'
|
import { useLocation } from '@reach/router'
|
||||||
import { useDebouncedCallback } from 'use-debounce'
|
|
||||||
import { setProperty } from '../utils'
|
|
||||||
|
|
||||||
function updateQuery(router: NextRouter) {
|
|
||||||
return (min?: string, max?: string) => {
|
|
||||||
const query = Object.assign({}, router.query)
|
|
||||||
|
|
||||||
setProperty(query, 'minPrice', min)
|
|
||||||
setProperty(query, 'maxPrice', max)
|
|
||||||
|
|
||||||
router.push({
|
|
||||||
pathname: router.pathname,
|
|
||||||
query: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function usePriceQueryParams() {
|
export default function usePriceQueryParams() {
|
||||||
const router = useRouter()
|
const location = useLocation()
|
||||||
const [min, setMin] = useState((router.query?.minPrice as string) || '0')
|
|
||||||
const [max, setMax] = useState((router.query?.maxPrice as string) || '0')
|
const [min, setMin] = useState(
|
||||||
const [debouncedUpdateQuery] = useDebouncedCallback(updateQuery(router), 1000)
|
(JSON.parse(location.search).minPrice as string) || '0'
|
||||||
|
)
|
||||||
|
const [max, setMax] = useState(
|
||||||
|
(JSON.parse(location.search).maxPrice as string) || '0'
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (parseFloat(max) < parseFloat(min)) {
|
if (parseFloat(max) < parseFloat(min)) {
|
||||||
@ -35,9 +23,5 @@ export default function usePriceQueryParams() {
|
|||||||
}
|
}
|
||||||
}, [max])
|
}, [max])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
debouncedUpdateQuery(min, max)
|
|
||||||
}, [min, max])
|
|
||||||
|
|
||||||
return { min, setMin, max, setMax }
|
return { min, setMin, max, setMax }
|
||||||
}
|
}
|
||||||
|
@ -9,30 +9,11 @@ const query = graphql`
|
|||||||
site {
|
site {
|
||||||
siteTitle
|
siteTitle
|
||||||
siteTagline
|
siteTagline
|
||||||
siteDescription
|
|
||||||
siteUrl
|
siteUrl
|
||||||
siteIcon
|
copyright
|
||||||
siteImage {
|
menu {
|
||||||
childImageSharp {
|
|
||||||
original {
|
|
||||||
src
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
analyticsId
|
|
||||||
company {
|
|
||||||
name
|
name
|
||||||
address {
|
link
|
||||||
location
|
|
||||||
street
|
|
||||||
city
|
|
||||||
zip
|
|
||||||
country
|
|
||||||
}
|
|
||||||
}
|
|
||||||
social {
|
|
||||||
name
|
|
||||||
url
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { AppProps } from 'next/app'
|
|
||||||
import Head from 'next/head'
|
|
||||||
import { DefaultSeo } from 'next-seo'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import NProgress from '../components/atoms/NProgress'
|
|
||||||
import { title, description, url } from '../../site.config'
|
|
||||||
import { toast } from 'react-toastify'
|
|
||||||
|
|
||||||
// this is the place to import global css
|
|
||||||
import 'tippy.js/dist/tippy.css'
|
|
||||||
import 'react-responsive-modal/styles.css'
|
|
||||||
import '@oceanprotocol/typographies/css/ocean-typo.css'
|
|
||||||
import 'react-toastify/dist/ReactToastify.css'
|
|
||||||
import '../styles/global.css'
|
|
||||||
import '../components/atoms/NProgress.css'
|
|
||||||
import { Web3Provider, OceanProvider, Config } from '@oceanprotocol/react'
|
|
||||||
import { config } from '../config/ocean'
|
|
||||||
|
|
||||||
export default function marketApp({ Component, pageProps }: AppProps) {
|
|
||||||
const { asPath } = useRouter()
|
|
||||||
|
|
||||||
toast.configure()
|
|
||||||
// Hacky workaround for mode: pure css modules disallowing any
|
|
||||||
// css modules with :global scope. We load this as global css ideally
|
|
||||||
// only when date picker is present which rpesently is only on the
|
|
||||||
// /publish route.
|
|
||||||
if (asPath.includes('/publish')) {
|
|
||||||
require('../styles/datepicker.css')
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Head>
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Montserrat:400,400i,600&display=swap"
|
|
||||||
rel="stylesheet"
|
|
||||||
key="google-fonts-montserrat"
|
|
||||||
/>
|
|
||||||
</Head>
|
|
||||||
<DefaultSeo
|
|
||||||
title={title}
|
|
||||||
description={description}
|
|
||||||
canonical={`${url}${asPath}`}
|
|
||||||
openGraph={{
|
|
||||||
type: 'website',
|
|
||||||
locale: 'en_US',
|
|
||||||
images: [{ url: `${url}/share.png` }],
|
|
||||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
||||||
site_name: title
|
|
||||||
}}
|
|
||||||
twitter={{
|
|
||||||
handle: '@oceanprotocol',
|
|
||||||
site: '@oceanprotocol',
|
|
||||||
cardType: 'summary_large_image'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<NProgress />
|
|
||||||
<Web3Provider>
|
|
||||||
<OceanProvider config={config as Config}>
|
|
||||||
<Component {...pageProps} />
|
|
||||||
</OceanProvider>
|
|
||||||
</Web3Provider>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,117 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { NextPage, GetStaticProps, GetStaticPaths } from 'next'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { Aquarius, Logger } from '@oceanprotocol/squid'
|
|
||||||
import AssetDetailsPage, {
|
|
||||||
AssetDetailsPageProps
|
|
||||||
} from '../../components/templates/AssetDetails'
|
|
||||||
import { config } from '../../config/ocean'
|
|
||||||
import { findServiceByType, isDid } from '../../utils'
|
|
||||||
import Loader from '../../components/atoms/Loader'
|
|
||||||
import Layout from '../../Layout'
|
|
||||||
import styles from '../../components/templates/AssetDetails/index.module.css'
|
|
||||||
|
|
||||||
const AssetDetails: NextPage<AssetDetailsPageProps> = (
|
|
||||||
props: AssetDetailsPageProps
|
|
||||||
) => {
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
// If the page is not yet generated, this will be displayed
|
|
||||||
// initially until getStaticProps() finishes running
|
|
||||||
if (router.isFallback) {
|
|
||||||
return (
|
|
||||||
<Layout title={props.title}>
|
|
||||||
<div className={styles.loaderWrap}>
|
|
||||||
<Loader />
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse back the DDO object, workaround for Next.js
|
|
||||||
let ddo
|
|
||||||
if (props.ddo) {
|
|
||||||
ddo = JSON.parse(props.ddo as any)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AssetDetailsPage
|
|
||||||
title={props.title}
|
|
||||||
ddo={ddo}
|
|
||||||
attributes={props.attributes}
|
|
||||||
error={props.error}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export function normalizeDid(did: string): string {
|
|
||||||
if (did.length === 73) {
|
|
||||||
if (did.charAt(9) === '0' && did.charAt(10) === '0') {
|
|
||||||
return did.substr(0, 9) + did.substr(11)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return did
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getMetadata(did?: string) {
|
|
||||||
if (did) {
|
|
||||||
did = normalizeDid(did)
|
|
||||||
if (!isDid(did)) {
|
|
||||||
return {
|
|
||||||
title: 'Not a DID',
|
|
||||||
error:
|
|
||||||
'The provided DID in the URL is not a valid DID. Please check your URL.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
title: 'No DID provided',
|
|
||||||
error: 'No DID provided. Please check your URL.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let ddo
|
|
||||||
|
|
||||||
try {
|
|
||||||
const aquarius = new Aquarius(config.aquariusUri as string, Logger)
|
|
||||||
ddo = await aquarius.retrieveDDO(did as string)
|
|
||||||
|
|
||||||
if (!ddo) {
|
|
||||||
return {
|
|
||||||
title: 'Could not retrieve asset',
|
|
||||||
error: 'The DDO was not found in Aquarius.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return { title: 'Error retrieving asset', error: error.message }
|
|
||||||
}
|
|
||||||
|
|
||||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
|
||||||
const title = attributes.main.name
|
|
||||||
|
|
||||||
// stringify the DDO object, workaround for Next.js
|
|
||||||
return { ddo: JSON.stringify(ddo), attributes, title }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async ({
|
|
||||||
params
|
|
||||||
}: {
|
|
||||||
params?: { did?: string }
|
|
||||||
}) => {
|
|
||||||
if (!params) return { props: { title: 'Not found' } }
|
|
||||||
const props = await getMetadata(params.did)
|
|
||||||
return { props }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getStaticPaths: GetStaticPaths = async () => {
|
|
||||||
const response = await axios(`${config.aquariusUri}/api/v1/aquarius/assets`)
|
|
||||||
const assets = response.data.ids
|
|
||||||
|
|
||||||
const paths = assets.map((did: string) => ({
|
|
||||||
params: { did }
|
|
||||||
}))
|
|
||||||
|
|
||||||
return { paths, fallback: true }
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AssetDetails
|
|
@ -1,29 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { NextPage, GetServerSideProps } from 'next'
|
|
||||||
import { Aquarius, Logger } from '@oceanprotocol/squid'
|
|
||||||
import { SearchQuery } from '@oceanprotocol/squid/dist/node/aquarius/Aquarius'
|
|
||||||
import ExplorePage from '../components/pages/Explore'
|
|
||||||
import { config } from '../config/ocean'
|
|
||||||
|
|
||||||
const Explore: NextPage<{ queryResult: string }> = ({ queryResult }) => (
|
|
||||||
<ExplorePage queryResult={JSON.parse(queryResult)} />
|
|
||||||
)
|
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
|
||||||
const searchQuery = {
|
|
||||||
offset: 15,
|
|
||||||
page: Number(context.query.page) || 1,
|
|
||||||
query: {},
|
|
||||||
sort: {
|
|
||||||
created: -1
|
|
||||||
}
|
|
||||||
} as SearchQuery
|
|
||||||
const aquarius = new Aquarius(config.aquariusUri as string, Logger)
|
|
||||||
const queryResult = await aquarius.queryMetadata(searchQuery)
|
|
||||||
// Note: stringifying the results cause Next.js otherwise complains about
|
|
||||||
// not being able to serialize the results array for whatever reason.
|
|
||||||
// So manually serialize them here, and parse them back in the above page.
|
|
||||||
return { props: { queryResult: JSON.stringify(queryResult) } }
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Explore
|
|
30
src/pages/history.tsx
Normal file
30
src/pages/history.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import React, { ReactElement } from 'react'
|
||||||
|
import PageHistory from '../components/pages/History'
|
||||||
|
import Layout from '../components/Layout'
|
||||||
|
import { graphql, PageProps } from 'gatsby'
|
||||||
|
|
||||||
|
export default function PageGatsbyHistory(props: PageProps): ReactElement {
|
||||||
|
const content = (props.data as any).content.edges[0].node.childPagesJson
|
||||||
|
const { title, description } = content
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout title={title} description={description} location={props.location}>
|
||||||
|
<PageHistory />
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const contentQuery = graphql`
|
||||||
|
query HistoryPageQuery {
|
||||||
|
content: allFile(filter: { relativePath: { eq: "pages/history.json" } }) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
childPagesJson {
|
||||||
|
title
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
@ -1,7 +1,19 @@
|
|||||||
import React from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { NextPage } from 'next'
|
import { PageProps } from 'gatsby'
|
||||||
import HomePage from '../components/pages/Home'
|
import PageHome from '../components/pages/Home'
|
||||||
|
import { useSiteMetadata } from '../hooks/useSiteMetadata'
|
||||||
|
import Layout from '../components/Layout'
|
||||||
|
|
||||||
const Home: NextPage<{}> = () => <HomePage />
|
export default function PageGatsbyHome(props: PageProps): ReactElement {
|
||||||
|
const { siteTitle, siteTagline } = useSiteMetadata()
|
||||||
|
|
||||||
export default Home
|
return (
|
||||||
|
<Layout
|
||||||
|
title={siteTitle}
|
||||||
|
description={siteTagline}
|
||||||
|
location={props.location}
|
||||||
|
>
|
||||||
|
<PageHome />
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -1,9 +1,30 @@
|
|||||||
import { NextPage } from 'next'
|
import React, { ReactElement } from 'react'
|
||||||
import React from 'react'
|
import PagePublish from '../components/pages/Publish'
|
||||||
import PublishPage from '../components/pages/Publish'
|
import Layout from '../components/Layout'
|
||||||
|
import { graphql, PageProps } from 'gatsby'
|
||||||
|
|
||||||
const Publish: NextPage = () => {
|
export default function PageGatsbyPublish(props: PageProps): ReactElement {
|
||||||
return <PublishPage />
|
const content = (props.data as any).content.edges[0].node.childPagesJson
|
||||||
|
const { title, description } = content
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout title={title} description={description} location={props.location}>
|
||||||
|
<PagePublish />
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Publish
|
export const contentQuery = graphql`
|
||||||
|
query PublishPageQuery {
|
||||||
|
content: allFile(filter: { relativePath: { eq: "pages/publish.json" } }) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
childPagesJson {
|
||||||
|
title
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
@ -1,71 +1,77 @@
|
|||||||
import React from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { NextPage } from 'next'
|
|
||||||
import { Aquarius, Logger } from '@oceanprotocol/squid'
|
import { Aquarius, Logger } from '@oceanprotocol/squid'
|
||||||
import { SearchQuery } from '@oceanprotocol/squid/dist/node/aquarius/Aquarius'
|
import { SearchQuery } from '@oceanprotocol/squid/dist/node/aquarius/Aquarius'
|
||||||
import SearchPage, { SearchPageProps } from '../components/templates/Search'
|
import PageSearch, { SearchPageProps } from '../components/templates/Search'
|
||||||
import { config } from '../config/ocean'
|
import { config } from '../config/ocean'
|
||||||
import { JSONparse, priceQueryParamToWei } from '../utils'
|
import { JSONparse, priceQueryParamToWei } from '../utils'
|
||||||
|
import { PageProps } from 'gatsby'
|
||||||
|
import Layout from '../components/Layout'
|
||||||
|
|
||||||
const Search: NextPage<SearchPageProps> = ({ text, tag, queryResult }) => {
|
export default function PageGatsbySearch(props: PageProps): ReactElement {
|
||||||
return <SearchPage text={text} tag={tag} queryResult={queryResult} />
|
const content = (props.data as any).content.edges[0].node.childPagesJson
|
||||||
}
|
const { title, description } = content
|
||||||
|
|
||||||
export function getSearchQuery(
|
return (
|
||||||
page?: string | string[],
|
<Layout title={title} description={description} location={props.location}>
|
||||||
offset?: string | string[],
|
<PageSearch text={text} tag={tag} queryResult={queryResult} />
|
||||||
text?: string | string[],
|
</Layout>
|
||||||
tag?: string | string[],
|
|
||||||
priceQuery?: [string | undefined, string | undefined]
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
page: Number(page) || 1,
|
|
||||||
offset: Number(offset) || 20,
|
|
||||||
query: {
|
|
||||||
text,
|
|
||||||
tags: tag ? [tag] : undefined,
|
|
||||||
price: priceQuery
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
created: -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Something in squid-js is weird when using 'categories: [type]'
|
|
||||||
// which is the only way the query actually returns desired results.
|
|
||||||
// But it doesn't follow 'SearchQuery' interface so we have to assign
|
|
||||||
// it here.
|
|
||||||
} as SearchQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
Search.getInitialProps = async (context) => {
|
|
||||||
const { text, tag, page, offset, minPrice, maxPrice } = context.query
|
|
||||||
|
|
||||||
const minPriceParsed = priceQueryParamToWei(
|
|
||||||
minPrice as string,
|
|
||||||
'Error parsing context.query.minPrice'
|
|
||||||
)
|
)
|
||||||
const maxPriceParsed = priceQueryParamToWei(
|
|
||||||
maxPrice as string,
|
|
||||||
'Error parsing context.query.maxPrice'
|
|
||||||
)
|
|
||||||
const priceQuery =
|
|
||||||
minPriceParsed || maxPriceParsed
|
|
||||||
? // sometimes TS gets a bit silly
|
|
||||||
([minPriceParsed, maxPriceParsed] as [
|
|
||||||
string | undefined,
|
|
||||||
string | undefined
|
|
||||||
])
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
const aquarius = new Aquarius(config.aquariusUri as string, Logger)
|
|
||||||
const queryResult = await aquarius.queryMetadata(
|
|
||||||
getSearchQuery(page, offset, text, tag, priceQuery)
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
|
||||||
text: text,
|
|
||||||
tag: tag,
|
|
||||||
queryResult
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Search
|
// export function getSearchQuery(
|
||||||
|
// page?: string | string[],
|
||||||
|
// offset?: string | string[],
|
||||||
|
// text?: string | string[],
|
||||||
|
// tag?: string | string[],
|
||||||
|
// priceQuery?: [string | undefined, string | undefined]
|
||||||
|
// ) {
|
||||||
|
// return {
|
||||||
|
// page: Number(page) || 1,
|
||||||
|
// offset: Number(offset) || 20,
|
||||||
|
// query: {
|
||||||
|
// text,
|
||||||
|
// tags: tag ? [tag] : undefined,
|
||||||
|
// price: priceQuery
|
||||||
|
// },
|
||||||
|
// sort: {
|
||||||
|
// created: -1
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Something in squid-js is weird when using 'categories: [type]'
|
||||||
|
// // which is the only way the query actually returns desired results.
|
||||||
|
// // But it doesn't follow 'SearchQuery' interface so we have to assign
|
||||||
|
// // it here.
|
||||||
|
// } as SearchQuery
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Search.getInitialProps = async (context) => {
|
||||||
|
// const { text, tag, page, offset, minPrice, maxPrice } = context.query
|
||||||
|
|
||||||
|
// const minPriceParsed = priceQueryParamToWei(
|
||||||
|
// minPrice as string,
|
||||||
|
// 'Error parsing context.query.minPrice'
|
||||||
|
// )
|
||||||
|
// const maxPriceParsed = priceQueryParamToWei(
|
||||||
|
// maxPrice as string,
|
||||||
|
// 'Error parsing context.query.maxPrice'
|
||||||
|
// )
|
||||||
|
// const priceQuery =
|
||||||
|
// minPriceParsed || maxPriceParsed
|
||||||
|
// ? // sometimes TS gets a bit silly
|
||||||
|
// ([minPriceParsed, maxPriceParsed] as [
|
||||||
|
// string | undefined,
|
||||||
|
// string | undefined
|
||||||
|
// ])
|
||||||
|
// : undefined
|
||||||
|
|
||||||
|
// const aquarius = new Aquarius(config.aquariusUri as string, Logger)
|
||||||
|
// const queryResult = await aquarius.queryMetadata(
|
||||||
|
// getSearchQuery(page, offset, text, tag, priceQuery)
|
||||||
|
// )
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// text: text,
|
||||||
|
// tag: tag,
|
||||||
|
// queryResult
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import { NextPage } from 'next'
|
|
||||||
import React from 'react'
|
|
||||||
import TransactionsPage from '../components/pages/Transactions'
|
|
||||||
|
|
||||||
const Transactions: NextPage = () => {
|
|
||||||
return <TransactionsPage />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Transactions
|
|
@ -1,25 +1,9 @@
|
|||||||
import axios, { AxiosResponse } from 'axios'
|
import axios, { AxiosResponse } from 'axios'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { File, DDO } from '@oceanprotocol/squid'
|
import { File } from '@oceanprotocol/squid'
|
||||||
import numeral from 'numeral'
|
import numeral from 'numeral'
|
||||||
import {
|
|
||||||
ServiceAccess,
|
|
||||||
ServiceCommon,
|
|
||||||
ServiceType,
|
|
||||||
ServiceMetadata,
|
|
||||||
ServiceAuthorization
|
|
||||||
} from '@oceanprotocol/squid/dist/node/ddo/Service'
|
|
||||||
import web3Utils from 'web3-utils'
|
import web3Utils from 'web3-utils'
|
||||||
|
|
||||||
// Helper to work around Next.js serialization of props
|
|
||||||
// for replacing usage of ddo.findServiceByType()
|
|
||||||
export function findServiceByType(
|
|
||||||
ddo: string | Partial<DDO>,
|
|
||||||
type: ServiceType
|
|
||||||
): ServiceCommon | ServiceAccess | ServiceMetadata | ServiceAuthorization {
|
|
||||||
return new DDO(ddo as Partial<DDO>).findServiceByType(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateQueryStringParameter(
|
export function updateQueryStringParameter(
|
||||||
uri: string,
|
uri: string,
|
||||||
key: string,
|
key: string,
|
||||||
|
@ -24,10 +24,8 @@ const oceanMock = {
|
|||||||
return {
|
return {
|
||||||
results: [ddo] as any[],
|
results: [ddo] as any[],
|
||||||
page: 1,
|
page: 1,
|
||||||
/* eslint-disable @typescript-eslint/camelcase */
|
|
||||||
total_pages: 1611,
|
total_pages: 1611,
|
||||||
total_results: 1611
|
total_results: 1611
|
||||||
/* eslint-enable @typescript-eslint/camelcase */
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: () => null as any,
|
resolve: () => null as any,
|
||||||
|
@ -3,13 +3,11 @@ module.exports = {
|
|||||||
transform: {
|
transform: {
|
||||||
'^.+\\.[jt]sx?$': ['babel-jest', { configFile: './jest/babel.config.js' }]
|
'^.+\\.[jt]sx?$': ['babel-jest', { configFile: './jest/babel.config.js' }]
|
||||||
},
|
},
|
||||||
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node', 'md'],
|
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'.+\\.(css|styl|less|sass|scss)$': 'identity-obj-proxy',
|
'.+\\.(css|styl|less|sass|scss)$': 'identity-obj-proxy',
|
||||||
'.+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|md)$':
|
'.+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||||
'<rootDir>/tests/unit/__mocks__/fileMock.js',
|
'<rootDir>/tests/unit/__mocks__/file-mock.js',
|
||||||
'\\.svg': '<rootDir>/tests/unit/__mocks__/svgrMock.js',
|
'\\.svg': '<rootDir>/tests/unit/__mocks__/svgr-mock.js'
|
||||||
'next/router': '<rootDir>/tests/unit/__mocks__/nextRouter.js'
|
|
||||||
},
|
},
|
||||||
testPathIgnorePatterns: ['node_modules', '.cache', 'public', 'coverage'],
|
testPathIgnorePatterns: ['node_modules', '.cache', 'public', 'coverage'],
|
||||||
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)'],
|
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)'],
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { render } from '@testing-library/react'
|
|
||||||
import AssetDetails, { getMetadata } from '../../../src/pages/asset/[did]'
|
|
||||||
import ddo from '../__fixtures__/ddo'
|
|
||||||
import { findServiceByType } from '../../../src/utils'
|
|
||||||
import { MetaDataMarket } from '../../../src/@types/MetaData'
|
|
||||||
import oceanMock from '../__mocks__/ocean-mock'
|
|
||||||
import web3ProviderMock from '../__mocks__/web3'
|
|
||||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
|
||||||
// import { useOcean } from '@oceanprotocol/react'
|
|
||||||
|
|
||||||
jest.mock('web3')
|
|
||||||
jest.mock('@oceanprotocol/react')
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
jest.mock('@oceanprotocol/react', () => ({
|
|
||||||
useOcean: () => {
|
|
||||||
return {
|
|
||||||
ocean: oceanMock
|
|
||||||
}
|
|
||||||
},
|
|
||||||
useWeb3: () => {
|
|
||||||
return {
|
|
||||||
web3: web3ProviderMock,
|
|
||||||
account: '0x0000000011111111aaaaaaaabbbbbbbb22222222',
|
|
||||||
ethProviderStatus: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
useConsume: () => {
|
|
||||||
return {
|
|
||||||
consume: () => null as any,
|
|
||||||
consumeStepText: '',
|
|
||||||
isLoading: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
useMetadata: () => {
|
|
||||||
return {
|
|
||||||
getCuration: () => {
|
|
||||||
return Promise.resolve({ rating: 0, numVotes: 0 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
describe('AssetDetails', () => {
|
|
||||||
it('renders without crashing', () => {
|
|
||||||
const { container } = render(
|
|
||||||
<AssetDetails
|
|
||||||
ddo={JSON.stringify(ddo) as any}
|
|
||||||
attributes={attributes as MetaDataMarket}
|
|
||||||
title="Hello"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
expect(container.firstChild).toBeInTheDocument()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('getMetadata()', () => {
|
|
||||||
it('not a valid DID', async () => {
|
|
||||||
const response = await getMetadata('hello')
|
|
||||||
expect(response.title).toBe('Not a DID')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Not Found', async () => {
|
|
||||||
const response = await getMetadata(
|
|
||||||
'did:op:c678e7e5963d4fdc99afea49ac221d4d4177790f30204417823319d4d35f851f'
|
|
||||||
)
|
|
||||||
expect(response.title).toBe('Could not retrieve asset')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Found', async () => {
|
|
||||||
const response = await getMetadata(
|
|
||||||
'did:op:8898adb69e334755a568738ce3f6c03760f9eb5a4f344c688e483a04cb0855d6'
|
|
||||||
)
|
|
||||||
expect(response.title).toBe('compute1')
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,28 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { render } from '@testing-library/react'
|
|
||||||
import Explore, { getServerSideProps } from '../../../src/pages/explore'
|
|
||||||
import ddo from '../__fixtures__/ddo'
|
|
||||||
import { DDO } from '@oceanprotocol/squid'
|
|
||||||
|
|
||||||
const asset = new DDO(ddo)
|
|
||||||
const queryResult = {
|
|
||||||
results: [asset, asset, asset, asset, asset, asset].map(
|
|
||||||
(asset) => new DDO(asset)
|
|
||||||
),
|
|
||||||
page: 1,
|
|
||||||
totalPages: 100,
|
|
||||||
totalResults: 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Explore', () => {
|
|
||||||
it('renders without crashing', () => {
|
|
||||||
const { container } = render(
|
|
||||||
<Explore queryResult={JSON.stringify(queryResult)} />
|
|
||||||
)
|
|
||||||
expect(container.firstChild).toBeInTheDocument()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('getServerSideProps', () => {
|
|
||||||
getServerSideProps({ query: { page: '1' } } as any)
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render } from '@testing-library/react'
|
import { render } from '@testing-library/react'
|
||||||
import Publish from '../../../src/pages/publish'
|
import Publish from '../../../src/pages/publish'
|
||||||
import web3ProviderMock, { context } from '../__mocks__/web3provider'
|
import web3ProviderMock from '../__mocks__/web3provider'
|
||||||
import oceanMock from '../__mocks__/ocean-mock'
|
import oceanMock from '../__mocks__/ocean-mock'
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
|
Loading…
Reference in New Issue
Block a user