1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

refactor for Gatsby, update all the things

This commit is contained in:
Matthias Kretschmann 2020-06-30 11:28:49 +02:00
parent 41fcb2f4c3
commit 38ccfc635e
Signed by: m
GPG Key ID: 606EEEF3C479A91F
56 changed files with 19744 additions and 7532 deletions

View File

@ -1,6 +1,7 @@
{
"parser": "babel-eslint",
"extends": ["eslint:recommended", "prettier"],
"env": { "es6": true, "browser": true, "node": true },
"env": { "es6": true, "browser": true, "node": true, "jest": true },
"settings": {
"react": {
"version": "detect"

2
.github/CODEOWNERS vendored
View File

@ -1 +1 @@
* @maxieprotocol @kremalicious @pfmescher @unjapones
* @mihaisc @kremalicious

4
.gitignore vendored
View File

@ -4,8 +4,10 @@ out
.next
.idea
.env
.env.build
coverage
dist
public
.cache
storybook-static
public/storybook
.artifacts

View File

@ -1,7 +1,3 @@
module.exports = {
stories: [
'../src/components/**/*.stories.tsx',
'../src/styles/**/*.stories.tsx'
],
addons: []
stories: ['../src/**/*.stories.tsx', '../tests/**/*.stories.tsx']
}

View File

@ -1,20 +1,11 @@
import React from 'react'
import { addDecorator } from '@storybook/react'
import WebFont from 'webfontloader'
WebFont.load({
google: {
families: ['Montserrat:400,400i,600']
}
})
// Import global css with custom properties once for all stories.
// Needed because in Next.js we impoprt that file only once too,
// in src/_app.tsx which does not get loaded by Storybook
import '../src/styles/global.css'
import '../src/global/styles.css'
// Wrapper for all stories previews
addDecorator(storyFn => (
addDecorator((storyFn) => (
<div
style={{
minHeight: '100vh',
@ -25,3 +16,19 @@ addDecorator(storyFn => (
{storyFn()}
</div>
))
// Gatsby's Link overrides:
// Gatsby defines a global called ___loader to prevent its method calls from creating console errors you override it here
global.___loader = {
enqueue: () => {},
hovering: () => {}
}
// Gatsby internal mocking to prevent unnecessary errors in storybook testing environment
global.__PATH_PREFIX__ = ''
global.__BASE_PATH__ = ''
// This is to utilized to override the window.___navigate method Gatsby defines and uses to report what path a Link would be taking us to if it wasn't inside a storybook
window.___navigate = (pathname) => {
action('NavigateTo:')(pathname)
}

View File

@ -1,6 +1,8 @@
// https://www.gatsbyjs.org/docs/visual-testing-with-storybook/
// Make CSS modules work
// https://github.com/storybookjs/storybook/issues/4306#issuecomment-517951264
const setCssModulesRule = rule => {
const setCssModulesRule = (rule) => {
const nextRule = rule
const cssLoader = rule.use[1]
@ -15,8 +17,8 @@ const setCssModulesRule = rule => {
return nextRule
}
module.exports = async ({ config, mode }) => {
const cssRules = config.module.rules.map(rule => {
module.exports = ({ config }) => {
const cssRules = config.module.rules.map((rule) => {
const isCssRule = rule.test.toString().indexOf('css') !== -1
let nextRule = rule
@ -28,28 +30,46 @@ module.exports = async ({ config, mode }) => {
config.module.rules = cssRules
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
// use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
config.module.rules[0].use[0].loader = require.resolve('babel-loader')
// use @babel/preset-react for JSX and env (instead of staged presets)
config.module.rules[0].use[0].options.presets = [
require.resolve('@babel/preset-react'),
require.resolve('@babel/preset-env')
]
config.module.rules[0].use[0].options.plugins = [
// use @babel/plugin-proposal-class-properties for class arrow functions
require.resolve('@babel/plugin-proposal-class-properties'),
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
require.resolve('babel-plugin-remove-graphql-queries')
]
// Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
config.resolve.mainFields = ['browser', 'module', 'main']
// Handle TypeScript
config.module.rules.push({
test: /\.(ts|tsx)$/,
loader: require.resolve('babel-loader'),
options: {
presets: [['react-app', { flow: false, typescript: true }]]
presets: [['react-app', { flow: false, typescript: true }]],
plugins: [
require.resolve('@babel/plugin-proposal-class-properties'),
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
require.resolve('babel-plugin-remove-graphql-queries')
]
}
})
config.resolve.extensions.push('.ts', '.tsx')
config.node = {
fs: 'empty'
}
// Handle SVGs
// Don't use Storybook's default SVG Configuration
config.module.rules = config.module.rules.map(rule => {
config.module.rules = config.module.rules.map((rule) => {
if (rule.test.toString().includes('svg')) {
const test = rule.test
.toString()
.replace('svg|', '')
.replace(/\//g, '')
const test = rule.test.toString().replace('svg|', '').replace(/\//g, '')
return { ...rule, test: new RegExp(test) }
} else {
return rule
@ -59,7 +79,19 @@ module.exports = async ({ config, mode }) => {
// Use SVG Configuration for SVGR yourself
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack']
use: [
{
loader: '@svgr/webpack',
options: {
svgoConfig: {
plugins: {
removeViewBox: false
}
}
}
},
'url-loader'
]
})
return config

View File

@ -4,8 +4,6 @@ node_js: node
cache:
npm: true
directories:
- .next/cache
before_script:
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter

View File

@ -2,8 +2,6 @@
<h1 align="center">Ocean Marketplace</h1>
>
[![Build Status](https://travis-ci.com/oceanprotocol/market.svg?branch=master)](https://travis-ci.com/oceanprotocol/market)
[![Now deployment](https://flat.badgen.net/badge/now/auto-deployment/21c4dd?icon=now)](https://zeit.co/oceanprotocol/market)
[![Maintainability](https://api.codeclimate.com/v1/badges/d114f94f75e6efd2ee71/maintainability)](https://codeclimate.com/repos/5e3933869a31771fd800011c/maintainability)
@ -15,6 +13,7 @@
- [🤓 Resources](#-resources)
- [🏄 Get Started](#-get-started)
- [Local Spree components with Barge](#local-spree-components-with-barge)
- [API](#api)
- [🦑 Environment variables](#-environment-variables)
- [🎨 Storybook](#-storybook)
- [✨ Code Style](#-code-style)
@ -27,30 +26,25 @@
## 🤓 Resources
- [UI Design: Figma Mock Up](https://www.figma.com/file/K38ZsQjzndyp2YFJCLxIN7/dexFreight-Marketplace)
- [Planning: ZenHub Board](https://app.zenhub.com/workspaces/dexfreight-marketplace-5e2f201751116794cf4f2e75/board?repos=236508929)
## 🏄 Get Started
The app is a React app built with [Next.js](https://nextjs.org) + TypeScript + CSS modules and will connect to Ocean components in Pacific by default.
The app is a React app built with [Gatsby.js](https://www.gatsbyjs.org) + TypeScript + CSS modules and will connect to Ocean components in Pacific by default.
To start local development:
```bash
git clone git@github.com:oceanprotocol/dexfreight.git
cd dexfreight
git clone git@github.com:oceanprotocol/market.git
cd market
npm install
npm start
```
This will launch the app under [localhost:3000](http://localhost:3000).
This will start the development server under
`http://localhost:8000`.
Depending on your configuration, you might have to increase the amount of `inotify` watchers:
```
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
```
To explore the generated GraphQL data structure fire up the accompanying GraphiQL IDE under
`http://localhost:8000/__graphql`.
### Local Spree components with Barge
@ -72,33 +66,30 @@ This will take some time on first start, and at the end you need to copy the gen
The script will wait for all contracts to be generated in the `keeper-contracts` Docker container, then will copy the artifacts in place into `node_modules/@oceanprotocol/keeper-contracts/artifacts/`.
Finally, set environment variables to use those local connections in `.env` & `.env.build` in the app:
Finally, set environment variables to use those local connections in `.env` in the app:
```bash
# modify env variables, Spree is enabled by default when using those files
cp .env.example .env && cp .env.example .env.build
cp .env.example .env
```
### API
Files under `/api` are isolated and not part of Gatsby.
- [API Documentation](api/)
## 🦑 Environment variables
The `./src/config/ocean.ts` file is setup to prioritize environment variables for setting each Ocean component endpoint. By setting environment variables, you can easily switch between Ocean networks the app connects to, without directly modifying `./src/config/ocean.ts`.
For local development, you can use a `.env` & `.env.build` file:
For local development, you can use a `.env` file:
```bash
# modify env variables, Spree is enabled by default when using those files
cp .env.example .env && cp .env.example .env.build
cp .env.example .env
```
For a Now deployment, all environment variables defining the Ocean component endpoints need to be added with `now secrets` to `oceanprotocol` org based on the `@` variable names defined in `now.json`, e.g.:
```bash
now switch
now secrets add aquarius_uri https://aquarius.pacific.dexfreight.dev-ocean.com
```
Adding the env vars like that will provide them during both, build & run time.
## 🎨 Storybook
[Storybook](https://storybook.js.org) is set up for this project and is used for UI development of components. Stories are created inside `src/components/` alongside each component in the form of `ComponentName.stories.tsx`.
@ -130,9 +121,7 @@ npm run format
Test suite for unit tests is setup with [Jest](https://jestjs.io) as a test runner and:
- [react-testing-library](https://github.com/kentcdodds/react-testing-library) for all React components
- [node-mocks-http](https://github.com/howardabrams/node-mocks-http) for all `src/pages/api/` routes
> Note: fully testing Next.js API routes should be part of integration tests. There are [various problems](https://spectrum.chat/next-js/general/api-routes-unit-testing~aa868f97-3a7d-45fe-97e5-3f0408f0022d) with fully testing them so a proper unit test suite for them should be setup.
- [node-mocks-http](https://github.com/howardabrams/node-mocks-http) for all `api/` routes
To run all linting and unit tests:
@ -164,7 +153,7 @@ npm run serve
## ⬆️ Deployment
Every branch or Pull Request is automatically deployed by [Now](https://zeit.co/now) with their GitHub integration. A link to a deployment will appear under each Pull Request.
Every branch or Pull Request is automatically deployed by [Vercel](https://vercel.com) with their GitHub integration. A link to a deployment will appear under each Pull Request.
The latest deployment of the `master` branch is automatically aliased to `xxx`.
@ -174,47 +163,47 @@ If needed, app can be deployed manually. Make sure to switch to Ocean Protocol o
```bash
# first run
now login
now switch
vercel login
vercel switch
# deploy
now
vercel
# switch alias to new deployment
now alias
vercel alias
```
## 🏗 Ocean Protocol Infrastructure
The following Aquarius & Brizo instances specifically for dexFreight marketplace are deployed in Ocean Protocol's AWS K8:
The following Aquarius & Brizo instances specifically for marketplace are deployed in Ocean Protocol's AWS K8:
**Nile (Staging)**
- K8 namespace: `dexfreight-nile`
- `aquarius.nile.dexfreight.dev-ocean.com`
- `brizo.nile.dexfreight.dev-ocean.com`
- K8 namespace: `market-nile`
- `aquarius.nile.market.dev-ocean.com`
- `brizo.nile.market.dev-ocean.com`
Edit command with `kubectl`, e.g.:
```bash
kubectl edit deployment -n dexfreight-nile aquarius
kubectl edit deployment -n market-nile aquarius
```
**Pacific (Production)**
- K8 namespace: `dexfreight-pacific`
- `aquarius.pacific.dexfreight.dev-ocean.com`
- `brizo.pacific.dexfreight.dev-ocean.com`
- K8 namespace: `market-pacific`
- `aquarius.pacific.market.dev-ocean.com`
- `brizo.pacific.market.dev-ocean.com`
Edit command with `kubectl`, e.g.:
```bash
kubectl edit deployment -n dexfreight-pacific aquarius
kubectl edit deployment -n market-pacific aquarius
```
## 🏛 License
```text
Copyright 2019 Ocean Protocol Foundation Ltd.
Copyright 2020 Ocean Protocol Foundation Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

46
gatsby-config.js Normal file
View File

@ -0,0 +1,46 @@
require('dotenv').config()
const siteConfig = require('./site.config.js')
module.exports = {
siteMetadata: {
...siteConfig
},
plugins: [
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'content',
path: `${__dirname}/content`
}
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'images',
path: `${__dirname}/src/images`
}
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'art',
path: `${__dirname}/node_modules/@oceanprotocol/art/`
}
},
'gatsby-transformer-json',
'gatsby-transformer-remark',
{
resolve: 'gatsby-plugin-svgr',
options: {
icon: false,
svgoConfig: {
plugins: [{ removeViewBox: false }]
}
}
},
'gatsby-plugin-react-helmet',
'gatsby-plugin-remove-trailing-slashes',
'gatsby-plugin-webpack-size'
]
}

View File

@ -1,12 +0,0 @@
{
"compilerOptions": {
"jsx": "react",
"allowJs": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"noImplicitAny": true,
"sourceMap": true,
"target": "es5"
}
}

2
next-env.d.ts vendored
View File

@ -1,2 +0,0 @@
/// <reference types="next" />
/// <reference types="next/types/global" />

View File

@ -1,109 +0,0 @@
const webpack = require('webpack')
require('dotenv').config()
// Returns environment variables as an object
const env = Object.keys(process.env).reduce((acc, curr) => {
acc[`process.env.${curr}`] = JSON.stringify(process.env[curr])
return acc
}, {})
const withSvgr = (nextConfig = {}) => ({
webpack(config, options) {
config.module.rules.push({
test: /\.svg$/,
use: [
{
loader: '@svgr/webpack',
options: {
icon: true
}
}
]
})
if (typeof nextConfig.webpack === 'function') {
return nextConfig.webpack(config, options)
}
return config
}
})
// eslint-disable-next-line no-unused-vars
const withFsFix = (nextConfig = {}) => ({
webpack(config, options) {
// Fixes npm packages that depend on `fs` module
// https://github.com/zeit/next.js/issues/7755#issuecomment-508633125
// or https://github.com/zeit/next.js/issues/7755
if (!options.isServer) {
config.node = {
fs: 'empty'
}
}
if (typeof nextConfig.webpack === 'function') {
return nextConfig.webpack(config, options)
}
return config
}
})
const withGlobalConstants = (nextConfig = {}) => ({
webpack(config, options) {
// Allows to create global constants which can be configured at compile
// time (in this case they are the environment variables)
config.plugins.push(new webpack.DefinePlugin(env))
if (typeof nextConfig.webpack === 'function') {
return nextConfig.webpack(config, options)
}
return config
}
})
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true'
})
const withMarkdown = (nextConfig = {}) => ({
webpack(config, options) {
config.module.rules.push({
test: /\.md$/,
loader: 'raw-loader'
})
if (typeof nextConfig.webpack === 'function') {
return nextConfig.webpack(config, options)
}
return config
}
})
module.exports = withBundleAnalyzer(
withSvgr(
withFsFix(
withMarkdown(
withGlobalConstants({
exportPathMap: (defaultPathMap, { dev }) => {
// In dev environment return defaultPathMas as it is
if (dev) {
return defaultPathMap
}
// pages we know about beforehand
const paths = {
'/': { page: '/' },
'/publish': { page: '/publish' },
'/explore': { page: '/explore' }
}
return paths
}
})
)
)
)
)

26559
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,20 @@
{
"name": "market",
"name": "@oceanprotocol/market",
"description": "Data marketplace for ocean.",
"version": "0.0.1",
"license": "Apache-2.0",
"homepage": "https://oceanprotocol.com",
"scripts": {
"start": "next dev",
"export": "next export",
"build": "npm run storybook:build && next build",
"serve": "next start",
"start": "gatsby develop --host 0.0.0.0",
"build": "gatsby build",
"serve": "serve -s public/",
"jest": "NODE_ENV=test jest -c tests/unit/jest.config.js",
"test": "npm run lint && npm run jest",
"test:watch": "npm run lint && npm run jest -- --watch",
"lint": "eslint --ignore-path .gitignore --ext .js --ext .ts --ext .tsx .",
"format": "prettier --ignore-path .gitignore **/**/*.{css,yml,js,jsx,ts,tsx,json} --write",
"analyze": "ANALYZE=true next build",
"format": "prettier --ignore-path .gitignore './**/*.{css,yml,js,ts,tsx,json}' --write",
"type-check": "tsc --noEmit",
"analyze": "npm run build && source-map-explorer 'public/*.js'",
"storybook": "start-storybook -p 4000 -c .storybook",
"storybook:build": "build-storybook -c .storybook -o public/storybook"
},
@ -23,70 +24,70 @@
"@oceanprotocol/squid": "^2.2.0",
"@oceanprotocol/typographies": "^0.1.0",
"@sindresorhus/slugify": "^1.0.0",
"@tippyjs/react": "^4.0.2",
"@tippyjs/react": "^4.0.5",
"@types/classnames": "^2.2.10",
"axios": "^0.19.2",
"classnames": "^2.2.6",
"date-fns": "^2.11.0",
"date-fns": "^2.14.0",
"dotenv": "^8.2.0",
"filesize": "^6.1.0",
"is-url-superb": "^3.0.0",
"next": "^9.3.2",
"next-seo": "^4.4.0",
"next-svgr": "^0.0.2",
"nprogress": "^0.2.0",
"gatsby": "^2.23.12",
"gatsby-plugin-react-helmet": "^3.3.6",
"gatsby-plugin-remove-trailing-slashes": "^2.3.7",
"gatsby-plugin-svgr": "^2.0.2",
"gatsby-plugin-webpack-size": "^1.0.0",
"gatsby-source-filesystem": "^2.3.14",
"gatsby-source-graphql": "^2.5.7",
"gatsby-transformer-json": "^2.4.7",
"gatsby-transformer-remark": "^2.8.20",
"is-url-superb": "^4.0.0",
"numeral": "^2.0.6",
"react": "^16.13.1",
"react-data-table-component": "^6.9.2",
"react-datepicker": "^2.14.0",
"react-data-table-component": "^6.9.3",
"react-datepicker": "^3.0.0",
"react-dom": "^16.13.1",
"react-dotdotdot": "^1.3.1",
"react-dropzone": "^11.0.1",
"react-jsonschema-form": "^1.8.1",
"react-markdown": "^4.3.1",
"react-paginate": "^6.3.2",
"react-rating": "^2.0.4",
"react-rating": "^2.0.5",
"react-responsive-modal": "^5.0.2",
"react-toastify": "^5.5.0",
"react-toastify": "^6.0.6",
"shortid": "^2.2.15",
"slugify": "^1.4.0",
"use-debounce": "^3.4.0",
"slugify": "^1.4.4",
"use-debounce": "^3.4.2",
"web3connect": "^1.0.0-beta.33"
},
"devDependencies": {
"@babel/core": "^7.8.7",
"@next/bundle-analyzer": "^9.3.0",
"@storybook/addon-storyshots": "^5.3.17",
"@storybook/react": "^5.3.17",
"@testing-library/jest-dom": "^5.1.1",
"@testing-library/react": "^10.0.1",
"@testing-library/react-hooks": "^3.2.1",
"@types/jest": "^25.1.4",
"@types/node": "^13.9.1",
"@types/nprogress": "^0.2.0",
"@types/numeral": "0.0.26",
"@types/react": "^16.9.23",
"@types/react-datepicker": "^2.11.0",
"@types/react-jsonschema-form": "^1.7.0",
"@babel/core": "^7.10.3",
"@storybook/addon-storyshots": "^5.3.19",
"@storybook/react": "^5.3.19",
"@testing-library/jest-dom": "^5.11.0",
"@testing-library/react": "^10.4.3",
"@testing-library/react-hooks": "^3.3.0",
"@types/jest": "^26.0.3",
"@types/node": "^14.0.14",
"@types/numeral": "^0.0.28",
"@types/react": "^16.9.41",
"@types/react-datepicker": "^3.0.2",
"@types/react-jsonschema-form": "^1.7.3",
"@types/react-paginate": "^6.2.1",
"@types/shortid": "0.0.29",
"@typescript-eslint/eslint-plugin": "^2.23.0",
"@typescript-eslint/parser": "^2.23.0",
"babel-loader": "^8.0.6",
"babel-preset-react-app": "^9.1.1",
"eslint": "^6.8.0",
"@typescript-eslint/eslint-plugin": "^3.5.0",
"@typescript-eslint/parser": "^3.5.0",
"babel-loader": "^8.1.0",
"babel-preset-react-app": "^9.1.2",
"eslint": "^7.3.1",
"eslint-config-oceanprotocol": "^1.5.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.19.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.2",
"identity-obj-proxy": "^3.0.0",
"jest": "^25.1.0",
"jest": "^26.1.0",
"node-mocks-http": "^1.8.1",
"prettier": "^1.19.1",
"react-test-renderer": "^16.12.0",
"ts-jest": "^25.2.1",
"typescript": "^3.8.3",
"webfontloader": "^1.6.28"
"prettier": "^2.0.5",
"typescript": "^3.9.5"
},
"repository": {
"type": "git",

View File

@ -1,23 +1,9 @@
module.exports = {
title: 'Ocean Market',
description: `A marketplace to find and publish open data sets in the Ocean Network.`,
url: 'https://market.oceanprotocol.now.sh/',
siteTitle: 'Ocean Market',
siteTagline: `A marketplace to find and publish open data sets in the Ocean Network.`,
siteUrl: 'https://market.oceanprotocol.now.sh/',
copyright:
'All Rights Reserved. Powered by [Ocean Protocol](https://oceanprotocol.com)',
refundPolicy: [
'Data can be challenged within 2 days after purchase.',
'The marketplace decides if you are eligible for refund.'
],
assetTerms: [
{
name: 'Personal Identifiable Information',
value: 'This offer contains no personal data'
},
{
name: 'Regions where data can be used',
value: 'Worldwide'
}
],
menu: [
{
name: 'Explore',

View File

@ -14,7 +14,7 @@ export default function Dropzone({
multiple?: boolean
error?: string
}) {
const onDrop = useCallback(acceptedFiles => handleOnDrop(acceptedFiles), [
const onDrop = useCallback((acceptedFiles) => handleOnDrop(acceptedFiles), [
handleOnDrop
])

View File

@ -75,7 +75,7 @@ export default function DateRangeWidget(props: WidgetProps) {
<input
id="range"
type="checkbox"
onChange={ev => setRange(ev.target.checked)}
onChange={(ev) => setRange(ev.target.checked)}
checked={range}
/>
<label className={styles.label} htmlFor="range">

View File

@ -32,9 +32,9 @@ export default function TermsWidget(props: WidgetProps) {
checked={typeof value === 'undefined' ? false : value}
disabled={disabled || readonly}
autoFocus={autofocus}
onChange={event => onChange(event.target.checked)}
onBlur={onBlur && (event => onBlur(id, event.target.checked))}
onFocus={onFocus && (event => onFocus(id, event.target.checked))}
onChange={(event) => onChange(event.target.checked)}
onBlur={onBlur && ((event) => onBlur(id, event.target.checked))}
onFocus={onFocus && ((event) => onFocus(id, event.target.checked))}
/>
<span>{label}</span>
</label>

View File

@ -44,7 +44,7 @@ const Tags: React.FC<TagsProps> = ({
return (
<div className={classes}>
{tags &&
tags.map(tag => (
tags.map((tag) => (
<Tag tag={tag} noLinks={noLinks} key={shortid.generate()} />
))}
{shouldShowMore && (

View File

@ -13,7 +13,7 @@ export const FieldTemplate = ({
rawErrors,
children
}: FieldTemplateProps) => {
const noLabel = id !== noLabelFields.filter(f => id === f)[0]
const noLabel = id !== noLabelFields.filter((f) => id === f)[0]
return (
<section
key={id}

View File

@ -39,8 +39,8 @@ export default function Pagination({
// adapt based on media query match
marginPagesDisplayed={smallViewport ? 0 : 1}
pageRangeDisplayed={smallViewport ? 3 : 6}
onPageChange={data => onPageChange(data.selected)}
hrefBuilder={pageIndex => hrefBuilder(pageIndex)}
onPageChange={(data) => onPageChange(data.selected)}
hrefBuilder={(pageIndex) => hrefBuilder(pageIndex)}
disableInitialCallback
previousLabel="←"
nextLabel="→"

View File

@ -51,7 +51,7 @@ export default function SearchBar({
className={large ? `${styles.input} ${styles.large}` : styles.input}
placeholder={placeholder || 'What are you looking for?'}
value={value}
onChange={e => handleChange(e)}
onChange={(e) => handleChange(e)}
required
/>
<Button onClick={(e: FormEvent<HTMLButtonElement>) => startSearch(e)}>

View File

@ -42,13 +42,13 @@ export const SearchPriceFilter = () => {
<PriceInput
label="minPrice"
value={min}
onChange={ev => setMin(ev.target.value)}
onChange={(ev) => setMin(ev.target.value)}
text="Min price"
/>
<PriceInput
label="maxPrice"
value={max}
onChange={ev => setMax(ev.target.value)}
onChange={(ev) => setMax(ev.target.value)}
text="Max price"
/>
</div>

View File

@ -5,7 +5,7 @@ import asset from '../../../tests/unit/__fixtures__/ddo'
const queryResult = {
results: [asset, asset, asset, asset, asset, asset].map(
asset => new DDO(asset)
(asset) => new DDO(asset)
),
page: 1,
totalPages: 100,

View File

@ -40,7 +40,7 @@ const AssetList: React.FC<AssetListProps> = ({ queryResult }) => {
<>
<div className={styles.assetList}>
{queryResult.results &&
queryResult.results.map(ddo => (
queryResult.results.map((ddo) => (
<AssetTeaser ddo={ddo} key={shortid.generate()} />
))}
</div>

View File

@ -74,7 +74,7 @@ export default function Compute({
const comType = event.target.value
setComputeType(comType)
const selectedComputeOption = computeOptions.find(x => x.name === comType)
const selectedComputeOption = computeOptions.find((x) => x.name === comType)
if (selectedComputeOption !== undefined)
setComputeContainer(selectedComputeOption.value)
}
@ -109,7 +109,7 @@ export default function Compute({
label="Select image to run the algorithm"
placeholder=""
value={computeType}
options={computeOptions.map(x => x.name)}
options={computeOptions.map((x) => x.name)}
onChange={handleSelectChange}
/>
</div>

View File

@ -57,7 +57,7 @@ export default function ConsumedList() {
if (!consumedItems) return
const data = consumedItems.map(ddo => {
const data = consumedItems.map((ddo) => {
const { attributes } = findServiceByType(ddo, 'metadata')
const { name, price, datePublished } = attributes.main as MetaDataMain
return {

View File

@ -96,7 +96,7 @@ export default function JobsList() {
try {
const computeItems = await getComputeItems()
if (!computeItems) return
const data = computeItems.map(item => {
const data = computeItems.map((item) => {
const { attributes } = findServiceByType(item.ddo, 'metadata')
const { name, price } = attributes.main as MetaDataMain
return {

View File

@ -73,7 +73,7 @@ export default function PublishedList() {
count: publishedItems.totalPages
})
const data = publishedItems.results.map(ddo => {
const data = publishedItems.results.map((ddo) => {
const { attributes } = findServiceByType(ddo, 'metadata')
const { name, price, datePublished } = attributes.main as MetaDataMain
return {

View File

@ -46,7 +46,7 @@ const HomePage = () => {
</header>
<div className={styles.actions}>
{actions.map(action => (
{actions.map((action) => (
<Link key={shortid.generate()} href={action.link}>
<a
className={action.comingSoon ? styles.comingSoon : styles.action}

View File

@ -38,7 +38,7 @@ const TransactionsPage: React.FC = () => {
<Layout title={title} description={description}>
<article className={styles.grid}>
<div>
{sections.map(section => {
{sections.map((section) => {
const { title, component } = section
return <Section key={title} title={title} component={component} />
})}

View File

@ -25,7 +25,7 @@ export default function MetaSecondary({
title="Sample Data"
content={
<ul>
{links?.map(link => (
{links?.map((link) => (
<ListItem key={shortid.generate()}>
<a href={link.url}>{link.name}</a>
</ListItem>
@ -51,7 +51,7 @@ export default function MetaSecondary({
title="Refund Policy"
content={
<ul>
{refundPolicy.map(item => (
{refundPolicy.map((item) => (
<ListItem key={shortid.generate()}>{item}</ListItem>
))}
</ul>
@ -59,7 +59,7 @@ export default function MetaSecondary({
/>
)}
{assetTerms.map(item => (
{assetTerms.map((item) => (
<MetaItem
key={shortid.generate()}
title={item.name}

View File

@ -34,7 +34,7 @@ export default function useCategoriesQueryParam(allCategories: string[]) {
// Update url and the state with the selected categories
const toggleCategory = (category: string) => {
const newSelectedCategories = selectedCategories.includes(category)
? selectedCategories.filter(c => c !== category)
? selectedCategories.filter((c) => c !== category)
: [...selectedCategories, category]
setSelectedCategories(newSelectedCategories)

View File

@ -9,7 +9,7 @@ const Explore: NextPage<{ queryResult: string }> = ({ queryResult }) => (
<ExplorePage queryResult={JSON.parse(queryResult)} />
)
export const getServerSideProps: GetServerSideProps = async context => {
export const getServerSideProps: GetServerSideProps = async (context) => {
const searchQuery = {
offset: 15,
page: Number(context.query.page) || 1,

View File

@ -36,7 +36,7 @@ export function getSearchQuery(
} as SearchQuery
}
Search.getInitialProps = async context => {
Search.getInitialProps = async (context) => {
const { text, tag, page, offset, minPrice, maxPrice } = context.query
const minPriceParsed = priceQueryParamToWei(

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,29 @@
/* eslint-disable no-unused-vars */
const React = require('react')
const gatsby = jest.requireActual('gatsby')
module.exports = {
...gatsby,
graphql: jest.fn(),
Link: jest.fn().mockImplementation(
// these props are invalid for an `a` tag
({
activeClassName,
activeStyle,
getProps,
innerRef,
partiallyActive,
ref,
replace,
to,
...rest
}) =>
React.createElement('a', {
...rest,
href: to
})
),
StaticQuery: jest.fn(),
useStaticQuery: jest.fn()
}

View File

@ -1,6 +1,6 @@
export default Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,

View File

@ -1,24 +0,0 @@
const Router = require('next/router')
Router.router = {
push: () => null,
prefetch: () => null,
asPath: '/hello',
events: {
on: () => null,
off: () => null
},
useRouter: () => {
return {
push: () => null,
prefetch: () => null,
asPath: '/hello',
events: {
on: () => null,
off: () => null
}
}
}
}
module.exports = Router.router

View File

@ -1 +1,6 @@
module.exports = 'svg'
import React from 'react'
export default 'SvgrURL'
const SvgrMock = React.forwardRef((props, ref) => <span ref={ref} {...props} />)
export const ReactComponent = SvgrMock

View File

@ -0,0 +1,4 @@
// this file only exists for Jest
module.exports = {
presets: ['babel-preset-gatsby', '@babel/preset-typescript']
}

View File

@ -1,11 +1,7 @@
module.exports = {
rootDir: '../../',
preset: 'ts-jest/presets/js-with-ts',
setupFilesAfterEnv: ['<rootDir>/tests/unit/setupTests.ts'],
globals: {
'ts-jest': {
tsConfig: 'jest.tsconfig.json'
}
transform: {
'^.+\\.[jt]sx?$': ['babel-jest', { configFile: './jest/babel.config.js' }]
},
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node', 'md'],
moduleNameMapper: {
@ -15,12 +11,13 @@ module.exports = {
'\\.svg': '<rootDir>/tests/unit/__mocks__/svgrMock.js',
'next/router': '<rootDir>/tests/unit/__mocks__/nextRouter.js'
},
testPathIgnorePatterns: [
'<rootDir>/.next',
'<rootDir>/node_modules',
'<rootDir>/build',
'<rootDir>/coverage'
],
testPathIgnorePatterns: ['node_modules', '.cache', 'public', 'coverage'],
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)'],
globals: {
__PATH_PREFIX__: ''
},
setupFiles: ['<rootDir>/tests/unit/loadershim.js'],
setupFilesAfterEnv: ['<rootDir>/tests/unit/setupTests.ts'],
collectCoverageFrom: [
'<rootDir>/src/**/*.{ts,tsx}',
'!<rootDir>/src/@types/**/*',

3
tests/unit/loadershim.js Normal file
View File

@ -0,0 +1,3 @@
global.___loader = {
enqueue: jest.fn()
}

View File

@ -7,7 +7,7 @@ import { DDO } from '@oceanprotocol/squid'
const asset = new DDO(ddo)
const queryResult = {
results: [asset, asset, asset, asset, asset, asset].map(
asset => new DDO(asset)
(asset) => new DDO(asset)
),
page: 1,
totalPages: 100,

View File

@ -1,5 +1,9 @@
import '@testing-library/jest-dom/extend-expect'
if (typeof window.IntersectionObserver === 'undefined') {
import('intersection-observer')
}
beforeAll(() => {
require('./__mocks__/matchMedia')
jest.mock('web3')

View File

@ -1,19 +1,18 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"target": "esnext",
"module": "commonjs",
"lib": ["dom", "es2017"],
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
"jsx": "react",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noEmit": true,
"sourceMap": true,
"noImplicitAny": true,
"skipLibCheck": true
},
"exclude": ["node_modules", ".next"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
"exclude": ["node_modules", "public", ".cache", "*.js"],
"include": ["./src/**/*", "./api/**/*", "./tests/**/*"]
}

View File

@ -1,23 +1,4 @@
{
"name": "market",
"build": {
"env": {
"NODE_URI": "@node_uri",
"AQUARIUS_URI": "@aquarius_uri",
"BRIZO_URI": "@brizo_uri",
"BRIZO_ADDRESS": "@brizo_address",
"SECRET_STORE_URI": "@secret_store_uri",
"FAUCET_URI": "@faucet_uri",
"RATING_URI": "@rating_uri"
}
},
"env": {
"NODE_URI": "@node_uri",
"AQUARIUS_URI": "@aquarius_uri",
"BRIZO_URI": "@brizo_uri",
"BRIZO_ADDRESS": "@brizo_address",
"SECRET_STORE_URI": "@secret_store_uri",
"FAUCET_URI": "@faucet_uri",
"RATING_URI": "@rating_uri"
}
"cleanUrls": true,
"trailingSlash": false
}