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"],
|
||||
"rules": {
|
||||
"react/prop-types": "off",
|
||||
"react/no-unused-prop-types": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off"
|
||||
}
|
||||
}
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,7 +1,6 @@
|
||||
node_modules
|
||||
out
|
||||
.DS_Store
|
||||
.next
|
||||
.idea
|
||||
.env
|
||||
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()
|
||||
|
||||
const siteConfig = require('./site.config.js')
|
||||
const siteConfig = require('./content/site.json')
|
||||
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
...siteConfig
|
||||
...siteConfig.site
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
|
54
package-lock.json
generated
54
package-lock.json
generated
@ -6009,6 +6009,36 @@
|
||||
"@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": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.6.tgz",
|
||||
@ -32909,8 +32939,7 @@
|
||||
"react-fast-compare": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
},
|
||||
"react-focus-lock": {
|
||||
"version": "2.4.0",
|
||||
@ -32926,6 +32955,17 @@
|
||||
"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": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.0.6.tgz",
|
||||
@ -33126,6 +33166,11 @@
|
||||
"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": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-2.6.12.tgz",
|
||||
@ -37855,11 +37900,6 @@
|
||||
"integrity": "sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ==",
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"@loadable/component": "^5.13.0",
|
||||
"@oceanprotocol/art": "^2.2.0",
|
||||
"@oceanprotocol/react": "0.0.11",
|
||||
"@oceanprotocol/squid": "^2.2.0",
|
||||
@ -48,6 +49,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-dotdotdot": "^1.3.1",
|
||||
"react-dropzone": "^11.0.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-jsonschema-form": "^1.8.1",
|
||||
"react-markdown": "^4.3.1",
|
||||
"react-paginate": "^6.3.2",
|
||||
@ -56,7 +58,6 @@
|
||||
"react-toastify": "^6.0.6",
|
||||
"shortid": "^2.2.15",
|
||||
"slugify": "^1.4.4",
|
||||
"use-debounce": "^3.4.2",
|
||||
"web3connect": "^1.0.0-beta.33"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { WidgetProps } from 'react-jsonschema-form'
|
||||
import dynamic from 'next/dynamic'
|
||||
import loadable from '@loadable/component'
|
||||
import styles from './DateRangeWidget.module.css'
|
||||
import { toStringNoMS } from '../../../utils'
|
||||
|
||||
// lazy load this module, it's huge
|
||||
const LazyDatePicker = dynamic(() => import('react-datepicker'))
|
||||
const LazyDatePicker = loadable(() => import('react-datepicker'))
|
||||
|
||||
export function getWidgetValue(
|
||||
date1: Date,
|
||||
|
@ -1,8 +1,6 @@
|
||||
import React from 'react'
|
||||
import { WidgetProps } from 'react-jsonschema-form'
|
||||
import styles from './TermsWidget.module.css'
|
||||
import Markdown from '../Markdown'
|
||||
import terms from '../../../../content/terms.md'
|
||||
|
||||
export default function TermsWidget(props: WidgetProps) {
|
||||
const {
|
||||
@ -21,7 +19,7 @@ export default function TermsWidget(props: WidgetProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Markdown text={terms} className={styles.terms} />
|
||||
{/* <Markdown text={terms} className={styles.terms} /> */}
|
||||
<label
|
||||
htmlFor={id}
|
||||
className={required ? `${styles.label} ${styles.req}` : styles.label}
|
||||
|
@ -1,5 +1,5 @@
|
||||
.help {
|
||||
font-size: var(--font-size-small);
|
||||
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 {
|
||||
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-family: var(--font-family-base);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--brand-black);
|
||||
border: none;
|
||||
border: 1px solid var(--brand-grey-lighter);
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
background: var(--brand-white);
|
||||
padding: var(--spacer) / 3;
|
||||
padding: calc(var(--spacer) / 3);
|
||||
margin: 0;
|
||||
border-radius: var(--border-radius);
|
||||
transition: 0.2s ease-out;
|
||||
min-height: 43px;
|
||||
appearance: none;
|
||||
display: block;
|
||||
}
|
||||
.input:focus,
|
||||
.select:focus {
|
||||
border: none;
|
||||
|
||||
.input:focus {
|
||||
border-color: var(--brand-grey);
|
||||
box-shadow: none;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.select::placeholder,
|
||||
.input::placeholder {
|
||||
font-family: var(--font-family-base);
|
||||
font-size: var(--font-size-base);
|
||||
@ -67,9 +31,7 @@
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.select[readonly],
|
||||
.input[readonly],
|
||||
.select[disabled],
|
||||
.input[disabled] {
|
||||
background-color: var(--brand-grey-lighter);
|
||||
cursor: not-allowed;
|
||||
@ -80,35 +42,38 @@
|
||||
composes: input;
|
||||
height: 43px;
|
||||
padding-right: 3rem;
|
||||
border: 0;
|
||||
|
||||
/* custom arrow */
|
||||
background-image: linear-gradient(
|
||||
45deg,
|
||||
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(
|
||||
to right,
|
||||
var(--brand-pink) 1px,
|
||||
lighten(var(--brand-grey-lighter), 5%) 2px,
|
||||
lighten(var(--brand-grey-lighter), 5%)
|
||||
var(--brand-grey-lighter) 1px,
|
||||
transparent 1px,
|
||||
transparent
|
||||
);
|
||||
background-position: calc(100% - 18px) calc(1rem + 5px),
|
||||
calc(100% - 13px) calc(1rem + 5px), 100% 0;
|
||||
background-size: 5px 5px, 5px 5px, 2.5rem 3rem;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.select:focus {
|
||||
outline: 0;
|
||||
font-family: var(--font-family-base);
|
||||
}
|
||||
|
||||
.radioGroup {
|
||||
margin-top: var(--spacer) / 2;
|
||||
margin-top: calc(var(--spacer) / 2);
|
||||
margin-bottom: -2%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: var(--break-point--small)) {
|
||||
@media screen and (min-width: 40rem) {
|
||||
.radioGroup {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
@ -117,13 +82,15 @@
|
||||
|
||||
.radioWrap {
|
||||
position: relative;
|
||||
padding: var(--spacer) / 2;
|
||||
padding: calc(var(--spacer) / 2);
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: var(--break-point--small)) {
|
||||
@media screen and (min-width: 40rem) {
|
||||
.radioWrap {
|
||||
flex: 0 0 49%;
|
||||
}
|
||||
}
|
||||
@ -138,7 +105,7 @@
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-size: var(--font-size-small);
|
||||
line-height: 1.2;
|
||||
border: 2px solid var(--brand-grey-lighter);
|
||||
border: 1px solid var(--brand-grey-lighter);
|
||||
border-radius: 0.2rem;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
@ -152,13 +119,16 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.inputSmall {
|
||||
/* Size modifiers */
|
||||
|
||||
.small {
|
||||
composes: input;
|
||||
font-size: var(--font-size-small);
|
||||
min-height: 32px;
|
||||
padding: var(--spacer) / 4;
|
||||
padding: calc(var(--spacer) / 4);
|
||||
}
|
||||
.inputSmall::placeholder {
|
||||
|
||||
.small::placeholder {
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
@ -166,6 +136,8 @@
|
||||
composes: select;
|
||||
height: 32px;
|
||||
padding-right: 2rem;
|
||||
|
||||
/* custom arrow */
|
||||
background-position: calc(100% - 14px) 1rem, calc(100% - 9px) 1rem, 100% 0;
|
||||
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);
|
||||
font-size: var(--font-size-base);
|
||||
font-family: var(--font-family-title);
|
||||
line-height: 1.2;
|
||||
display: block;
|
||||
margin-bottom: var(--spacer) / 6;
|
||||
margin-bottom: calc(var(--spacer) / 4);
|
||||
}
|
||||
|
||||
.required:after {
|
||||
|
@ -11,7 +11,7 @@ const Label = ({
|
||||
htmlFor: string
|
||||
}) => (
|
||||
<label
|
||||
className={required ? styles.required : styles.label}
|
||||
className={`${styles.label} ${required && styles.required}`}
|
||||
title={required ? 'Required' : ''}
|
||||
{...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,
|
||||
MetaDataMarket
|
||||
} from '../../@types/MetaData'
|
||||
import { findServiceByType } from '../../utils'
|
||||
import Tags from '../atoms/Tags'
|
||||
import Price from '../atoms/Price'
|
||||
import styles from './AssetTeaser.module.css'
|
||||
@ -17,7 +16,7 @@ declare type AssetTeaserProps = {
|
||||
}
|
||||
|
||||
const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
|
||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
const { name, price } = attributes.main
|
||||
|
||||
let description
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { DDO, Ocean } from '@oceanprotocol/squid'
|
||||
import { useRouter } from 'next/router'
|
||||
import { findServiceByType, redeploy } from '../../utils'
|
||||
import { useNavigate } from '@reach/router'
|
||||
import { DDO } from '@oceanprotocol/squid'
|
||||
import { redeploy } from '../../utils'
|
||||
import Button from '../atoms/Button'
|
||||
import BaseDialog from '../atoms/BaseDialog'
|
||||
import { useOcean } from '@oceanprotocol/react'
|
||||
@ -15,19 +15,17 @@ const content = [
|
||||
|
||||
export default function DeleteAction({ ddo }: { ddo: DDO }) {
|
||||
const { ocean, accountId } = useOcean()
|
||||
|
||||
const navigate = useNavigate()
|
||||
const isOwner = ddo.publicKey[0].owner === accountId
|
||||
|
||||
const router = useRouter()
|
||||
const [isModal, setIsModal] = useState(false)
|
||||
const [status, setStatus] = useState(0) // 0-confirmation, 1-deleting, 2-success, 3-error
|
||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
|
||||
useEffect(() => {
|
||||
let tId: number
|
||||
if (status === 2) {
|
||||
tId = window.setTimeout(() => {
|
||||
router.push(`/explore`)
|
||||
navigate(`/`)
|
||||
}, 1000)
|
||||
}
|
||||
return () => {
|
||||
|
@ -105,7 +105,7 @@ export default function Form({
|
||||
transformErrors={transformErrors}
|
||||
>
|
||||
<div>
|
||||
<Button disabled={buttonDisabled} primary>
|
||||
<Button disabled={buttonDisabled} style="primary">
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import { ComputeItem } from '@oceanprotocol/react'
|
||||
import BaseDialog from '../atoms/BaseDialog'
|
||||
import { findServiceByType } from '../../utils'
|
||||
import styles from './JobDetailsDialog.module.css'
|
||||
import MetaItem from '../templates/AssetDetails/MetaItem'
|
||||
import Time from '../atoms/Time'
|
||||
@ -19,7 +18,7 @@ export default function JobDetailsDialog({
|
||||
}) {
|
||||
if (!computeItem) return null
|
||||
|
||||
const { attributes } = findServiceByType(computeItem.ddo, 'metadata')
|
||||
const { attributes } = computeItem.ddo.findServiceByType('metadata')
|
||||
const { name } = attributes.main
|
||||
const {
|
||||
dateCreated,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useNavigate } from '@reach/router'
|
||||
import Form from '../../molecules/Form/index'
|
||||
import {
|
||||
PublishFormSchema,
|
||||
@ -11,7 +12,6 @@ import { MetaDataMarket } from '../../../@types/MetaData'
|
||||
import { File, MetaData } from '@oceanprotocol/squid'
|
||||
import { isBrowser, toStringNoMS } from '../../../utils'
|
||||
import { toast } from 'react-toastify'
|
||||
import { useRouter } from 'next/router'
|
||||
import styles from './PublishForm.module.css'
|
||||
import utils from 'web3-utils'
|
||||
import AssetModel from '../../../models/Asset'
|
||||
@ -21,8 +21,6 @@ import {
|
||||
ServiceCompute
|
||||
} from '@oceanprotocol/squid/dist/node/ddo/Service'
|
||||
|
||||
declare type PublishFormProps = {}
|
||||
|
||||
const FILES_DATA_LOCAL_STORAGE_KEY = 'filesData'
|
||||
const PUBLISH_FORM_LOCAL_STORAGE_KEY = 'publishForm'
|
||||
|
||||
@ -101,11 +99,11 @@ export function transformPublishFormToMetadata(
|
||||
return metadata
|
||||
}
|
||||
|
||||
const PublishForm: React.FC<PublishFormProps> = () => {
|
||||
const PublishForm: React.FC<any> = () => {
|
||||
const [buttonDisabled, setButtonDisabled] = useState(false)
|
||||
const { web3Connect } = useWeb3()
|
||||
const { ocean, account } = useOcean()
|
||||
const router = useRouter()
|
||||
const navigate = useNavigate()
|
||||
const [data, updateData] = useStoredValue(
|
||||
PUBLISH_FORM_LOCAL_STORAGE_KEY,
|
||||
publishFormData
|
||||
@ -172,7 +170,7 @@ const PublishForm: React.FC<PublishFormProps> = () => {
|
||||
className: styles.success
|
||||
})
|
||||
toast.dismiss(submittingToast)
|
||||
router.push(`/asset/${asset.id}`)
|
||||
navigate(`/asset/${asset.id}`)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
} finally {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, ChangeEvent, FormEvent } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import React, { useState, ChangeEvent, FormEvent } from 'react'
|
||||
import { useNavigate } from '@reach/router'
|
||||
import styles from './SearchBar.module.css'
|
||||
import Loader from '../atoms/Loader'
|
||||
import Button from '../atoms/Button'
|
||||
@ -15,7 +15,7 @@ export default function SearchBar({
|
||||
filters?: boolean
|
||||
large?: true
|
||||
}) {
|
||||
const router = useRouter()
|
||||
const navigate = useNavigate()
|
||||
const [value, setValue] = useState(initialValue || '')
|
||||
const [searchStarted, setSearchStarted] = useState(false)
|
||||
|
||||
@ -29,20 +29,9 @@ export default function SearchBar({
|
||||
if (value === '') return
|
||||
|
||||
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 (
|
||||
<form className={styles.form}>
|
||||
<div className={styles.inputGroup}>
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { fromWei } from 'web3-utils'
|
||||
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
||||
@ -7,7 +7,6 @@ import Loader from '../atoms/Loader'
|
||||
import Web3Feedback from '../molecules/Web3Feedback'
|
||||
import Dropzone from '../atoms/Dropzone'
|
||||
import Price from '../atoms/Price'
|
||||
import { findServiceByType } from '../../utils'
|
||||
import {
|
||||
computeOptions,
|
||||
useCompute,
|
||||
@ -42,7 +41,7 @@ export default function Compute({
|
||||
const [isPublished, setIsPublished] = useState(false)
|
||||
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 isFree = price === '0'
|
||||
@ -118,7 +117,7 @@ export default function Compute({
|
||||
|
||||
<div className={styles.jobButtonWrapper}>
|
||||
<Button
|
||||
primary
|
||||
style="primary"
|
||||
onClick={() => startJob()}
|
||||
disabled={isComputeButtonDisabled}
|
||||
>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import { DDO } from '@oceanprotocol/squid'
|
||||
import Web3 from 'web3'
|
||||
import { findServiceByType } from '../../utils'
|
||||
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
||||
import Button from '../atoms/Button'
|
||||
import File from '../atoms/File'
|
||||
@ -18,9 +17,9 @@ export default function Consume({ ddo }: { ddo: DDO | undefined }) {
|
||||
const { web3 } = useWeb3()
|
||||
const { ocean, balanceInOcean } = useOcean()
|
||||
const { consume, consumeStepText, isLoading } = useConsume()
|
||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
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 isBalanceSufficient =
|
||||
isFree ||
|
||||
|
@ -11,7 +11,6 @@ import { fromWei } from 'web3-utils'
|
||||
import DateCell from '../atoms/Table/DateCell'
|
||||
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
|
||||
import { MetaDataMain } from '@oceanprotocol/squid'
|
||||
import { findServiceByType } from '../../utils'
|
||||
|
||||
const consumedColumns = [
|
||||
{
|
||||
@ -57,7 +56,7 @@ export default function ConsumedList() {
|
||||
if (!consumedItems) return
|
||||
|
||||
const data = consumedItems.map((ddo) => {
|
||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
const { name, price, datePublished } = attributes.main as MetaDataMain
|
||||
return {
|
||||
published: datePublished,
|
||||
|
@ -1,9 +1,10 @@
|
||||
import React from 'react'
|
||||
import styles from './Footer.module.css'
|
||||
import { copyright } from '../../../site.config'
|
||||
import Markdown from '../atoms/Markdown'
|
||||
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
||||
|
||||
export default function Footer() {
|
||||
const { copyright } = useSiteMetadata()
|
||||
const year = new Date().getFullYear()
|
||||
|
||||
return (
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
|
||||
import Price from '../atoms/Price'
|
||||
import { fromWei } from 'web3-utils'
|
||||
import { findServiceByType } from '../../utils'
|
||||
import Table from '../atoms/Table'
|
||||
import Button from '../atoms/Button'
|
||||
import { MetaDataMain, Logger } from '@oceanprotocol/squid'
|
||||
@ -97,7 +96,7 @@ export default function JobsList() {
|
||||
const computeItems = await getComputeItems()
|
||||
if (!computeItems) return
|
||||
const data = computeItems.map((item) => {
|
||||
const { attributes } = findServiceByType(item.ddo, 'metadata')
|
||||
const { attributes } = item.ddo.findServiceByType('metadata')
|
||||
const { name, price } = attributes.main as MetaDataMain
|
||||
return {
|
||||
dateCreated: item.job.dateCreated,
|
||||
@ -136,7 +135,7 @@ export default function JobsList() {
|
||||
) : (
|
||||
<>
|
||||
<div>
|
||||
<Button primary onClick={getJobs}>
|
||||
<Button style="primary" onClick={getJobs}>
|
||||
Sign to retrieve jobs
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
import Table from '../atoms/Table'
|
||||
import Price from '../atoms/Price'
|
||||
import { fromWei } from 'web3-utils'
|
||||
import { findServiceByType } from '../../utils'
|
||||
import DateCell from '../atoms/Table/DateCell'
|
||||
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
|
||||
|
||||
@ -72,7 +71,7 @@ export default function PublishedList() {
|
||||
})
|
||||
|
||||
const data = publishedItems.results.map((ddo) => {
|
||||
const { attributes } = findServiceByType(ddo, 'metadata')
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
const { name, price, datePublished } = attributes.main as MetaDataMain
|
||||
return {
|
||||
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 {
|
||||
display: grid;
|
||||
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 shortid from 'shortid'
|
||||
import Layout from '../../components/Layout'
|
||||
import Button from '../atoms/Button'
|
||||
import SearchBar from '../molecules/SearchBar'
|
||||
import Explore from '../../images/explore.svg'
|
||||
import Publish from '../../images/publish.svg'
|
||||
import DataPool from '../../images/datapool.svg'
|
||||
import styles from './Home.module.css'
|
||||
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
||||
|
||||
const actions = [
|
||||
{
|
||||
@ -36,16 +34,10 @@ const actions = [
|
||||
}
|
||||
]
|
||||
|
||||
export default function HomePage() {
|
||||
const { siteTitle, siteDescription } = useSiteMetadata()
|
||||
|
||||
export default function HomePage(): ReactElement {
|
||||
return (
|
||||
<Layout noPageHeader>
|
||||
<header className={styles.header}>
|
||||
<h1>{siteTitle}</h1>
|
||||
<h2>{siteDescription}</h2>
|
||||
<SearchBar large />
|
||||
</header>
|
||||
<>
|
||||
<SearchBar large />
|
||||
|
||||
<div className={styles.actions}>
|
||||
{actions.map((action) => (
|
||||
@ -63,6 +55,6 @@ export default function HomePage() {
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1,25 +1,18 @@
|
||||
import React from 'react'
|
||||
import Layout from '../../components/Layout'
|
||||
import PublishForm from '../molecules/PublishForm/PublishForm'
|
||||
import styles from './Publish.module.css'
|
||||
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 = () => {
|
||||
return (
|
||||
<Layout title={title} description={description}>
|
||||
<article className={styles.grid}>
|
||||
<PublishForm />
|
||||
<aside>
|
||||
<div className={styles.sticky}>
|
||||
<Web3Feedback />
|
||||
</div>
|
||||
</aside>
|
||||
</article>
|
||||
</Layout>
|
||||
<article className={styles.grid}>
|
||||
<PublishForm />
|
||||
<aside>
|
||||
<div className={styles.sticky}>
|
||||
<Web3Feedback />
|
||||
</div>
|
||||
</aside>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
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 { Web3Provider, OceanProvider, Config } from '@oceanprotocol/react'
|
||||
import { config } from '../config/ocean'
|
||||
import Styles from '../global/Styles'
|
||||
|
||||
const wrapPageElement = ({ element }: { element: ReactElement }) => (
|
||||
<Styles>{element}</Styles>
|
||||
<Web3Provider>
|
||||
<OceanProvider config={config as Config}>
|
||||
<Styles>{element}</Styles>
|
||||
</OceanProvider>
|
||||
</Web3Provider>
|
||||
)
|
||||
|
||||
export default wrapPageElement
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { setProperty, JSONparse } from '../utils'
|
||||
|
||||
const CATEGORIES_QUERY_PARAM = 'categories'
|
||||
@ -9,8 +8,6 @@ const useGetCategoriesFromQueryParam = (
|
||||
allCategories: string[],
|
||||
setSelectedCategories: (categories: string[]) => void
|
||||
) => {
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
if (router.query && router.query.categories) {
|
||||
const parsedCategories = JSONparse<string[]>(
|
||||
@ -27,7 +24,6 @@ const useGetCategoriesFromQueryParam = (
|
||||
}
|
||||
|
||||
export default function useCategoriesQueryParam(allCategories: string[]) {
|
||||
const router = useRouter()
|
||||
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
|
||||
useGetCategoriesFromQueryParam(allCategories, setSelectedCategories)
|
||||
|
||||
|
@ -1,27 +1,15 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { NextRouter, useRouter } from 'next/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
|
||||
})
|
||||
}
|
||||
}
|
||||
import { useLocation } from '@reach/router'
|
||||
|
||||
export default function usePriceQueryParams() {
|
||||
const router = useRouter()
|
||||
const [min, setMin] = useState((router.query?.minPrice as string) || '0')
|
||||
const [max, setMax] = useState((router.query?.maxPrice as string) || '0')
|
||||
const [debouncedUpdateQuery] = useDebouncedCallback(updateQuery(router), 1000)
|
||||
const location = useLocation()
|
||||
|
||||
const [min, setMin] = useState(
|
||||
(JSON.parse(location.search).minPrice as string) || '0'
|
||||
)
|
||||
const [max, setMax] = useState(
|
||||
(JSON.parse(location.search).maxPrice as string) || '0'
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (parseFloat(max) < parseFloat(min)) {
|
||||
@ -35,9 +23,5 @@ export default function usePriceQueryParams() {
|
||||
}
|
||||
}, [max])
|
||||
|
||||
useEffect(() => {
|
||||
debouncedUpdateQuery(min, max)
|
||||
}, [min, max])
|
||||
|
||||
return { min, setMin, max, setMax }
|
||||
}
|
||||
|
@ -9,30 +9,11 @@ const query = graphql`
|
||||
site {
|
||||
siteTitle
|
||||
siteTagline
|
||||
siteDescription
|
||||
siteUrl
|
||||
siteIcon
|
||||
siteImage {
|
||||
childImageSharp {
|
||||
original {
|
||||
src
|
||||
}
|
||||
}
|
||||
}
|
||||
analyticsId
|
||||
company {
|
||||
copyright
|
||||
menu {
|
||||
name
|
||||
address {
|
||||
location
|
||||
street
|
||||
city
|
||||
zip
|
||||
country
|
||||
}
|
||||
}
|
||||
social {
|
||||
name
|
||||
url
|
||||
link
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 { NextPage } from 'next'
|
||||
import HomePage from '../components/pages/Home'
|
||||
import React, { ReactElement } from 'react'
|
||||
import { PageProps } from 'gatsby'
|
||||
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 from 'react'
|
||||
import PublishPage from '../components/pages/Publish'
|
||||
import React, { ReactElement } from 'react'
|
||||
import PagePublish from '../components/pages/Publish'
|
||||
import Layout from '../components/Layout'
|
||||
import { graphql, PageProps } from 'gatsby'
|
||||
|
||||
const Publish: NextPage = () => {
|
||||
return <PublishPage />
|
||||
export default function PageGatsbyPublish(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}>
|
||||
<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 { NextPage } from 'next'
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Aquarius, Logger } from '@oceanprotocol/squid'
|
||||
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 { JSONparse, priceQueryParamToWei } from '../utils'
|
||||
import { PageProps } from 'gatsby'
|
||||
import Layout from '../components/Layout'
|
||||
|
||||
const Search: NextPage<SearchPageProps> = ({ text, tag, queryResult }) => {
|
||||
return <SearchPage text={text} tag={tag} queryResult={queryResult} />
|
||||
export default function PageGatsbySearch(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}>
|
||||
<PageSearch text={text} tag={tag} queryResult={queryResult} />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
// 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
|
||||
}
|
||||
// // 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
|
||||
// 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 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)
|
||||
)
|
||||
// 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
|
||||
// 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 { toast } from 'react-toastify'
|
||||
import { File, DDO } from '@oceanprotocol/squid'
|
||||
import { File } from '@oceanprotocol/squid'
|
||||
import numeral from 'numeral'
|
||||
import {
|
||||
ServiceAccess,
|
||||
ServiceCommon,
|
||||
ServiceType,
|
||||
ServiceMetadata,
|
||||
ServiceAuthorization
|
||||
} from '@oceanprotocol/squid/dist/node/ddo/Service'
|
||||
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(
|
||||
uri: string,
|
||||
key: string,
|
||||
|
@ -24,10 +24,8 @@ const oceanMock = {
|
||||
return {
|
||||
results: [ddo] as any[],
|
||||
page: 1,
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
total_pages: 1611,
|
||||
total_results: 1611
|
||||
/* eslint-enable @typescript-eslint/camelcase */
|
||||
}
|
||||
},
|
||||
resolve: () => null as any,
|
||||
|
@ -3,13 +3,11 @@ module.exports = {
|
||||
transform: {
|
||||
'^.+\\.[jt]sx?$': ['babel-jest', { configFile: './jest/babel.config.js' }]
|
||||
},
|
||||
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node', 'md'],
|
||||
moduleNameMapper: {
|
||||
'.+\\.(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)$':
|
||||
'<rootDir>/tests/unit/__mocks__/fileMock.js',
|
||||
'\\.svg': '<rootDir>/tests/unit/__mocks__/svgrMock.js',
|
||||
'next/router': '<rootDir>/tests/unit/__mocks__/nextRouter.js'
|
||||
'.+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||
'<rootDir>/tests/unit/__mocks__/file-mock.js',
|
||||
'\\.svg': '<rootDir>/tests/unit/__mocks__/svgr-mock.js'
|
||||
},
|
||||
testPathIgnorePatterns: ['node_modules', '.cache', 'public', 'coverage'],
|
||||
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 { render } from '@testing-library/react'
|
||||
import Publish from '../../../src/pages/publish'
|
||||
import web3ProviderMock, { context } from '../__mocks__/web3provider'
|
||||
import web3ProviderMock from '../__mocks__/web3provider'
|
||||
import oceanMock from '../__mocks__/ocean-mock'
|
||||
|
||||
// eslint-disable-next-line
|
||||
|
Loading…
Reference in New Issue
Block a user