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

migrate to Next.js (#935)

* migrate to Next.js

* migrate scripts

* generate markdown pages

* make all the markdown work

* fix profile, fix image loading

* git+ssh → git+https, again

* bump packages

* maybe windows build fix

* add public to gitignore

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* Next.js v12! Webpack 5! No build hacks anymore

* json import fixes

* fixes

Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro>
This commit is contained in:
Matthias Kretschmann 2021-10-27 11:27:14 +01:00
parent 032b3e1496
commit 3729c63581
Signed by: m
GPG Key ID: 606EEEF3C479A91F
154 changed files with 21781 additions and 52552 deletions

View File

@ -1,7 +1,7 @@
#GATSBY_INFURA_PROJECT_ID="xxx"
#GATSBY_MARKET_FEE_ADDRESS="0xxx"
#GATSBY_PORTIS_ID="xxx"
#NEXT_INFURA_PROJECT_ID="xxx"
#NEXT_MARKET_FEE_ADDRESS="0xxx"
#NEXT_PORTIS_ID="xxx"
#
@ -9,9 +9,9 @@
#
# Toggle pricing options presented during price creation
#GATSBY_ALLOW_FIXED_PRICING="true"
#GATSBY_ALLOW_DYNAMIC_PRICING="true"
#GATSBY_ALLOW_FREE_PRICING="true"
#NEXT_ALLOW_FIXED_PRICING="true"
#NEXT_ALLOW_DYNAMIC_PRICING="true"
#NEXT_ALLOW_FREE_PRICING="true"
# Privacy Preference Center
#GATSBY_PRIVACY_PREFERENCE_CENTER="true"
#NEXT_PRIVACY_PREFERENCE_CENTER="true"

View File

@ -27,6 +27,7 @@
"rules": {
"react/prop-types": "off",
"react/no-unused-prop-types": "off",
"react/jsx-no-bind": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": "error"

View File

@ -36,7 +36,7 @@ jobs:
restore-keys: ${{ runner.os }}-${{ matrix.node }}-build-${{ env.cache-name }}-
- run: npm ci
- run: npm run apollo:codegen
- run: npm run codegen:apollo
- run: npm run lint
# - run: npm test
- run: npm run build

View File

@ -16,8 +16,8 @@ jobs:
- run: npm run build
env:
GATSBY_INFURA_PROJECT_ID: ${{ secrets.GATSBY_INFURA_PROJECT_ID }}
GATSBY_PORTIS_ID: ${{ secrets.GATSBY_PORTIS_ID }}
NEXT_INFURA_PROJECT_ID: ${{ secrets.NEXT_INFURA_PROJECT_ID }}
NEXT_PORTIS_ID: ${{ secrets.NEXT_PORTIS_ID }}
- run: npm run deploy:s3
env:

8
.gitignore vendored
View File

@ -4,15 +4,13 @@ out
.idea
.env
coverage
dist
public
.cache
storybook-static
public/storybook
.next
.artifacts
.vercel
repo-metadata.json
content/networks-metadata.json
networks-metadata.json
src/@types/apollo
graphql.schema.json
src/@types/graph.types.ts
public

View File

@ -11,7 +11,7 @@
"typescriptreact"
],
"search.exclude": {
"**/.cache": true,
"**/public": true
"**/.next": true,
"**/out": true
}
}

View File

@ -36,7 +36,7 @@
## 🏄 Get Started
The app is a React app built with [Gatsby.js](https://www.gatsbyjs.org) + TypeScript + CSS modules and will connect to Ocean remote components by default.
The app is a React app built with [Next.js](https://nextjs.org) + TypeScript + CSS modules and will connect to Ocean remote components by default.
To start local development:
@ -54,9 +54,6 @@ npm start
This will start the development server under
`http://localhost:8000`.
To explore the generated GraphQL data structure fire up the accompanying GraphiQL IDE under
`http://localhost:8000/__graphql`.
### Local components with Barge
If you prefer to connect to locally running components instead of remote connections, you can spin up [`barge`](https://github.com/oceanprotocol/barge) and use a local Ganache network in another terminal before running `npm start`:
@ -260,7 +257,7 @@ function Component() {
### Network Metadata
All displayed chain & network metadata is retrieved from `https://chainid.network` on build time and integrated into Gatsby's GraphQL layer. This data source is a community-maintained GitHub repository under [ethereum-lists/chains](https://github.com/ethereum-lists/chains).
All displayed chain & network metadata is retrieved from `https://chainid.network` on build time and integrated into NEXT's GraphQL layer. This data source is a community-maintained GitHub repository under [ethereum-lists/chains](https://github.com/ethereum-lists/chains).
Within components this metadata can be queried for under `allNetworksMetadataJson`. The `useWeb3()` hook does this in the background to expose the final `networkDisplayName` for use in components:
@ -343,15 +340,15 @@ Everything else is made open according to the apache2 license. We look forward t
### Dynamic Pricing
To allow publishers to set pricing as "Dynamic" you need to add the following environmental variable to your .env file: `GATSBY_ALLOW_DYNAMIC_PRICING="true"` (default).
To allow publishers to set pricing as "Dynamic" you need to add the following environmental variable to your .env file: `NEXT_ALLOW_DYNAMIC_PRICING="true"` (default).
### Fixed Pricing
To allow publishers to set pricing as "Fixed" you need to add the following environmental variable to your .env file: `GATSBY_ALLOW_FIXED_PRICING="true"` (default).
To allow publishers to set pricing as "Fixed" you need to add the following environmental variable to your .env file: `NEXT_ALLOW_FIXED_PRICING="true"` (default).
### Free Pricing
To allow publishers to set pricing as "Free" you need to add the following environmental variable to your .env file: `GATSBY_ALLOW_FREE_PRICING="true"` (default).
To allow publishers to set pricing as "Free" you need to add the following environmental variable to your .env file: `NEXT_ALLOW_FREE_PRICING="true"` (default).
This allocates the datatokens to the [dispenser contract](https://github.com/oceanprotocol/contracts/blob/main/contracts/dispenser/Dispenser.sol) which dispenses data tokens to users for free. Publishers in your market will now be able to offer their datasets to users for free (excluding gas costs).
@ -365,7 +362,7 @@ Feel free to adopt our provided privacy policies to your needs. Per default we c
### Privacy Preference Center
Additionally, Ocean Market provides a privacy preference center for you to use. This feature is disabled per default since we do not use cookies requiring consent on our deployment of the market. However, if you need to add some functionality depending on cookies, you can simply enable this feature by changing the value of the `GATSBY_PRIVACY_PREFERENCE_CENTER` environmental variable to `"true"` in your `.env` file. This will enable a customizable cookie banner stating the use of your individual cookies. The content of this banner can be adjusted within the `content/gdpr.json` file. If no `optionalCookies` are provided, the privacy preference center will be set to a simpler version displaying only the `title`, `text` and `close`-button. This can be used to inform the user about the use of essential cookies, where no consent is needed. The privacy preference center supports two different styling options: `'small'` and `'default'`. Setting the style propertie to `'small'` will display a smaller cookie banner to the user at first, only showing the default styled privacy preference center upon the user's customization request.
Additionally, Ocean Market provides a privacy preference center for you to use. This feature is disabled per default since we do not use cookies requiring consent on our deployment of the market. However, if you need to add some functionality depending on cookies, you can simply enable this feature by changing the value of the `NEXT_PRIVACY_PREFERENCE_CENTER` environmental variable to `"true"` in your `.env` file. This will enable a customizable cookie banner stating the use of your individual cookies. The content of this banner can be adjusted within the `content/gdpr.json` file. If no `optionalCookies` are provided, the privacy preference center will be set to a simpler version displaying only the `title`, `text` and `close`-button. This can be used to inform the user about the use of essential cookies, where no consent is needed. The privacy preference center supports two different styling options: `'small'` and `'default'`. Setting the style propertie to `'small'` will display a smaller cookie banner to the user at first, only showing the default styled privacy preference center upon the user's customization request.
Now your market users will be provided with additional options to toggle the use of your configured cookie consent categories. You can always retrieve the current consent status per category with the provided `useConsent()` hook. See below, how you can set your own custom cookies depending on the market user's consent. Feel free to adjust the provided utility functions for cookie usage provided in the `src/utils/cookies.ts` file to your needs.

View File

@ -1,2 +0,0 @@
/asset/* /asset/index.html 200
/profile/* /profile/index.html 200

View File

@ -15,11 +15,11 @@ module.exports = {
// List of all supported chainIds. Used to populate the Chains user preferences list.
chainIdsSupported: [1, 3, 4, 137, 80001, 1287, 56, 2021000, 1285, 246],
infuraProjectId: process.env.GATSBY_INFURA_PROJECT_ID || 'xxx',
infuraProjectId: process.env.NEXT_INFURA_PROJECT_ID || 'xxx',
// The ETH address the marketplace fee will be sent to.
marketFeeAddress:
process.env.GATSBY_MARKET_FEE_ADDRESS ||
process.env.NEXT_MARKET_FEE_ADDRESS ||
'0x9984b2453eC7D99a73A5B3a46Da81f197B753C8d',
// Used for conversion display, can be whatever coingecko API supports
@ -48,13 +48,13 @@ module.exports = {
},
// Wallets
portisId: process.env.GATSBY_PORTIS_ID || 'xxx',
portisId: process.env.NEXT_PORTIS_ID || 'xxx',
// Used to show or hide the fixed, dynamic or free price options
// tab to publishers during the price creation.
allowFixedPricing: process.env.GATSBY_ALLOW_FIXED_PRICING || 'true',
allowDynamicPricing: process.env.GATSBY_ALLOW_DYNAMIC_PRICING || 'true',
allowFreePricing: process.env.GATSBY_ALLOW_FREE_PRICING || 'true',
allowFixedPricing: process.env.NEXT_ALLOW_FIXED_PRICING || 'true',
allowDynamicPricing: process.env.NEXT_ALLOW_DYNAMIC_PRICING || 'true',
allowFreePricing: process.env.NEXT_ALLOW_FREE_PRICING || 'true',
// Set the default privacy policy to initially display
// this should be the slug of your default policy markdown file
@ -65,6 +65,5 @@ module.exports = {
// If set to true a gdpr.json file inside the content directory
// is used to create and show a privacy preference center / cookie banner
// To learn more about how to configure and use this, please refer to the readme
privacyPreferenceCenter:
process.env.GATSBY_PRIVACY_PREFERENCE_CENTER || 'false'
privacyPreferenceCenter: process.env.NEXT_PRIVACY_PREFERENCE_CENTER || 'false'
}

View File

@ -1,5 +1,4 @@
{
"site": {
"siteTitle": "Ocean Market",
"siteTagline": "A marketplace to find, publish and trade data sets in the Ocean Network.",
"siteUrl": "https://market.oceanprotocol.com",
@ -25,4 +24,3 @@
"polygon": "Polygon/Matic EVM support is in early stages. [Use the Polygon Bridge](https://docs.oceanprotocol.com/tutorials/polygon-bridge/) to get mOCEAN."
}
}
}

View File

@ -1,5 +0,0 @@
import wrapPageElementWithStyles from './src/components/App/wrapPageElement'
import ContextProviders from './src/components/App/ContextProviders'
export const wrapPageElement = wrapPageElementWithStyles
export const wrapRootElement = ContextProviders

View File

@ -1,83 +0,0 @@
require('dotenv').config()
const siteContent = require('./content/site.json')
const appConfig = require('./app.config')
module.exports = {
siteMetadata: {
...siteContent.site,
appConfig: {
...appConfig
}
},
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/`
}
},
{
resolve: 'gatsby-plugin-sharp',
options: {
defaultQuality: 80
}
},
'gatsby-transformer-sharp',
'gatsby-transformer-json',
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [`gatsby-remark-autolink-headers`]
}
},
{
resolve: 'gatsby-plugin-svgr',
options: {
icon: false,
svgoConfig: {
plugins: [{ removeViewBox: false }]
}
}
},
'gatsby-plugin-react-helmet',
'gatsby-plugin-remove-trailing-slashes',
{
// https://www.gatsbyjs.org/packages/gatsby-plugin-manifest/#using-with-gatsby-plugin-offline
resolve: 'gatsby-plugin-manifest',
options: {
name: siteContent.site.siteTitle,
short_name: siteContent.site.siteTitle,
start_url: '/',
background_color: '#ffffff',
theme_color: '#141414',
icon: siteContent.site.siteIcon,
display: 'standalone',
cache_busting_mode: 'none'
}
},
'gatsby-plugin-webpack-size',
{
resolve: 'gatsby-plugin-use-dark-mode',
options: {
...appConfig.darkModeConfig,
minify: true
}
}
]
}

View File

@ -1,73 +0,0 @@
const createMarkdownFields = require('./gatsby/createMarkdownFields')
const createMarkdownPages = require('./gatsby/createMarkdownPages')
const createTypes = require('./gatsby/createTypes')
const execSync = require('child_process').execSync
const path = require('path')
// Write out repo metadata
execSync(`node ./scripts/write-repo-metadata > repo-metadata.json`, {
stdio: 'inherit'
})
// Generate GraphQL typings for urql
// execSync(`npm run graphql:graphTypes`, { stdio: 'inherit' })
// Generate Apollo typings
execSync(`npm run apollo:codegen`, { stdio: 'inherit' })
// Fetch EVM networks metadata
execSync(
`node ./scripts/write-networks-metadata > content/networks-metadata.json`,
{
stdio: 'inherit'
}
)
exports.sourceNodes = ({ actions }) => {
createTypes(actions)
}
exports.onCreateNode = ({ node, actions, getNode }) => {
createMarkdownFields(node, actions, getNode)
}
exports.createPages = async ({ graphql, actions }) => {
await createMarkdownPages(graphql, actions)
}
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions
// page.matchPath is a special key that's used for matching pages
// only on the client.
const handleClientSideOnlyAsset = page.path.match(/^\/asset/)
const handleClientSideOnlyAccount = page.path.match(/^\/profile/)
if (handleClientSideOnlyAsset) {
page.matchPath = '/asset/*'
// Update the page.
createPage(page)
} else if (handleClientSideOnlyAccount) {
page.matchPath = '/profile/*'
createPage(page)
}
}
exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
resolve: {
alias: {
'@shared': path.resolve(__dirname, 'src/components/@shared'),
'@hooks': path.resolve(__dirname, 'src/@hooks'),
'@context': path.resolve(__dirname, 'src/@context'),
'@images': path.resolve(__dirname, 'src/@images'),
'@utils': path.resolve(__dirname, 'src/@utils')
}
},
node: {
// 'fs' fix for ocean.js
fs: 'empty'
},
// fix for 'got'/'swarm-js' dependency
externals: ['got']
})
}

View File

@ -1,5 +0,0 @@
import wrapPageElementWithStyles from './src/components/App/wrapPageElement'
import ContextProviders from './src/components/App/ContextProviders'
export const wrapPageElement = wrapPageElementWithStyles
export const wrapRootElement = ContextProviders

View File

@ -1,27 +0,0 @@
const { createFilePath } = require('gatsby-source-filesystem')
function createMarkdownFields(node, actions, getNode) {
const { createNodeField } = actions
// Automatically create slugs for specific node types,
// relative to ./content/pages/
const { type } = node.internal
if (type === 'MarkdownRemark') {
// Create a slug from the file path & name
const slug = createFilePath({
node,
getNode,
basePath: 'pages/',
trailingSlash: false
})
createNodeField({
name: 'slug',
node,
value: slug
})
}
}
module.exports = createMarkdownFields

View File

@ -1,42 +0,0 @@
const path = require('path')
async function createMarkdownPages(graphql, actions) {
const { createPage } = actions
const markdownPageTemplate = path.resolve(
'./src/components/@shared/Page/PageMarkdown.tsx'
)
// Grab all markdown files with a frontmatter title defined
const markdownResult = await graphql(`
{
allMarkdownRemark(filter: { frontmatter: { title: { ne: "" } } }) {
edges {
node {
fields {
slug
}
}
}
}
}
`)
if (markdownResult.errors) {
throw markdownResult.errors
}
// Create markdown pages.
const markdownPages = markdownResult.data.allMarkdownRemark.edges
markdownPages.forEach((page) => {
createPage({
path: page.node.fields.slug,
component: markdownPageTemplate,
context: {
slug: page.node.fields.slug
}
})
})
}
module.exports = createMarkdownPages

View File

@ -1,27 +0,0 @@
function createTypes(actions) {
const { createTypes } = actions
// Extend ContentJson to support optional field "optionalCookies" in gdpr.json
// Extend PublishJsonData to support optional fields for disclaimers
const typeDefs = `
type ContentJson implements Node {
accept: String
reject: String
close: String
configure: String
optionalCookies: [Cookie!]
}
type Cookie {
title: String!
desc: String!
cookieName: String!
}
type PublishJsonData implements Node {
disclaimer: String
disclaimerValues: [String!]
}
`
createTypes(typeDefs)
}
module.exports = createTypes

6
next-env.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

42
next.config.js Normal file
View File

@ -0,0 +1,42 @@
module.exports = (phase, { defaultConfig }) => {
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
webpack: (config, options) => {
config.module.rules.push(
{
test: /\.svg$/,
issuer: /\.(tsx|ts)$/,
use: [{ loader: '@svgr/webpack', options: { icon: true } }]
},
{
test: /\.gif$/,
// yay for webpack 5
// https://webpack.js.org/guides/asset-management/#loading-images
type: 'asset/resource'
}
)
// for old ocean.js, most likely can be removed later on
config.resolve.fallback = {
fs: false,
crypto: false,
os: false,
stream: false,
http: false,
https: false
}
return typeof defaultConfig.webpack === 'function'
? defaultConfig.webpack(config, options)
: config
}
// Prefer loading of ES Modules over CommonJS
// https://nextjs.org/blog/next-11-1#es-modules-support
// experimental: { esmExternals: true }
}
return nextConfig
}

71203
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,20 +5,19 @@
"license": "Apache-2.0",
"homepage": "https://market.oceanprotocol.com",
"scripts": {
"start": "gatsby develop --host 0.0.0.0",
"build": "gatsby build && cp _redirects public/_redirects",
"start": "npm run pregenerate && next dev -p 8000",
"build": "npm run pregenerate && next build",
"serve": "serve -s public/",
"test-graphql": "npm run graphql:graphTypes && npm run lint",
"test": "npm run apollo:codegen && npm run lint",
"lint": "npm run write:repoMetadata && eslint --ignore-path .gitignore --ext .js --ext .ts --ext .tsx . && npm run type-check",
"pregenerate": "bash scripts/pregenerate.sh",
"test": "npm run pregenerate && npm run lint && npm run type-check",
"test:graphql": "npm run codegen:graphql && npm run lint",
"lint": "eslint --ignore-path .gitignore --ext .js --ext .ts --ext .tsx .",
"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'",
"write:repoMetadata": "node ./scripts/write-repo-metadata > repo-metadata.json",
"deploy:s3": "./scripts/deploy-s3.sh",
"deploy:s3": "bash scripts/deploy-s3.sh",
"postinstall": "husky install",
"apollo:codegen": "apollo client:codegen --target typescript --tsFileExtension=d.ts --outputFlat src/@types/apollo/",
"graphql:graphTypes": "graphql-codegen --config codegen.yml"
"codegen:apollo": "apollo client:codegen --target typescript --tsFileExtension=d.ts --outputFlat src/@types/apollo/",
"codegen:graphql": "graphql-codegen --config codegen.yml"
},
"dependencies": {
"@coingecko/cryptoformat": "^0.4.4",
@ -26,12 +25,11 @@
"@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^0.19.2",
"@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.1.0",
"@sindresorhus/slugify": "^2.1.0",
"@portis/web3": "^4.0.6",
"@tippyjs/react": "^4.2.5",
"@urql/introspection": "^0.3.0",
"@walletconnect/web3-provider": "^1.6.6",
"axios": "^0.23.0",
"axios": "^0.24.0",
"chart.js": "^2.9.4",
"classnames": "^2.3.1",
"date-fns": "^2.25.0",
@ -42,28 +40,13 @@
"ethereum-blockies": "github:MyEtherWallet/blockies",
"filesize": "^8.0.3",
"formik": "^2.2.9",
"gatsby": "^2.32.13",
"gatsby-image": "^2.9.0",
"gatsby-plugin-manifest": "^2.10.0",
"gatsby-plugin-react-helmet": "^3.8.0",
"gatsby-plugin-remove-trailing-slashes": "^2.8.0",
"gatsby-plugin-sharp": "^2.14.4",
"gatsby-plugin-svgr": "^2.1.0",
"gatsby-plugin-use-dark-mode": "^1.3.0",
"gatsby-plugin-webpack-size": "^2.0.1",
"gatsby-remark-autolink-headers": "^4.8.0",
"gatsby-source-filesystem": "^2.9.0",
"gatsby-source-graphql": "^2.12.0",
"gatsby-transformer-json": "^2.9.0",
"gatsby-transformer-remark": "^2.16.1",
"gatsby-transformer-sharp": "^2.12.1",
"graphql": "14.7.0",
"graphql-schema-typescript": "^1.5.2",
"gray-matter": "^4.0.3",
"is-url-superb": "^6.0.0",
"js-cookie": "^3.0.1",
"jwt-decode": "^3.1.2",
"lodash.debounce": "^4.0.8",
"lodash.omit": "^4.5.0",
"next": "^12.0.1",
"query-string": "^7.0.1",
"react": "^17.0.2",
"react-chartjs-2": "^2.11.2",
@ -71,17 +54,17 @@
"react-data-table-component": "^6.11.7",
"react-dom": "^17.0.2",
"react-dotdotdot": "^1.3.1",
"react-helmet": "^6.1.0",
"react-markdown": "^6.0.2",
"react-modal": "^3.14.3",
"react-paginate": "^7.1.3",
"react-spring": "^9.3.0",
"react-tabs": "^3.2.2",
"react-toastify": "^7.0.4",
"react-toastify": "^8.0.3",
"remark": "^13.0.0",
"remark-gfm": "^1.0.0",
"remark-html": "^13.0.1",
"remove-markdown": "^0.3.0",
"shortid": "^2.2.16",
"slugify": "^1.6.1",
"swr": "^0.5.6",
"swr": "^1.0.1",
"urql": "^2.0.5",
"use-dark-mode": "^2.3.1",
"web3": "^1.6.0",
@ -89,26 +72,24 @@
"yup": "^0.32.11"
},
"devDependencies": {
"@graphql-codegen/cli": "1.21.6",
"@graphql-codegen/introspection": "1.18.2",
"@graphql-codegen/typescript": "1.22.4",
"@graphql-codegen/typescript-operations": "^1.18.3",
"@graphql-codegen/typescript-react-apollo": "2.3.0",
"@graphql-codegen/cli": "^2.2.1",
"@graphql-codegen/introspection": "^2.1.0",
"@graphql-codegen/typescript": "^2.2.4",
"@graphql-codegen/typescript-operations": "^2.1.8",
"@graphql-codegen/typescript-react-apollo": "^3.1.6",
"@svgr/webpack": "^5.5.0",
"@types/chart.js": "^2.9.32",
"@types/jest": "^26.0.23",
"@types/js-cookie": "^2.2.7",
"@types/js-cookie": "^3.0.0",
"@types/loadable__component": "^5.13.1",
"@types/lodash.debounce": "^4.0.3",
"@types/lodash.omit": "^4.5.6",
"@types/node": "^15.6.1",
"@types/react": "^17.0.8",
"@types/react-helmet": "^6.1.1",
"@types/react-modal": "^3.12.0",
"@types/react-paginate": "^7.1.0",
"@types/react-tabs": "^2.3.2",
"@types/remove-markdown": "^0.3.0",
"@types/shortid": "0.0.29",
"@types/node": "^16.11.5",
"@types/react": "^17.0.32",
"@types/react-dom": "^17.0.10",
"@types/react-modal": "^3.13.1",
"@types/react-paginate": "^7.1.1",
"@types/react-tabs": "^2.3.3",
"@types/remove-markdown": "^0.3.1",
"@types/yup": "^0.29.11",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
@ -116,14 +97,14 @@
"eslint": "^7.27.0",
"eslint-config-oceanprotocol": "^1.5.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"file-loader": "^6.2.0",
"husky": "^7.0.2",
"prettier": "^2.4.1",
"pretty-quick": "^3.1.1",
"serve": "^12.0.1",
"source-map-explorer": "^2.5.2",
"typescript": "^4.4.4"
},
"repository": {

13
scripts/pregenerate.sh Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Write out repo metadata
node ./scripts/write-repo-metadata > content/repo-metadata.json
# Generate GraphQL typings for urql
# npm run codegen:graphql
# Generate Apollo typings
npm run codegen:apollo
# Fetch EVM networks metadata
node ./scripts/write-networks-metadata > content/networks-metadata.json

View File

@ -180,5 +180,5 @@ function AssetProvider({
// Helper hook to access the provider values
const useAsset = (): AssetProviderValue => useContext(AssetContext)
export { AssetProvider, useAsset, AssetProviderValue, AssetContext }
export { AssetProvider, useAsset, AssetContext }
export default AssetProvider

View File

@ -134,5 +134,5 @@ function ConsentProvider({ children }: { children: ReactNode }): ReactElement {
const useConsent = (): ConsentProviderValue => useContext(ConsentContext)
export { ConsentProvider, useConsent, ConsentProviderValue, ConsentContext }
export { ConsentProvider, useConsent, ConsentContext }
export default ConsentProvider

View File

@ -109,5 +109,5 @@ function OceanProvider({ children }: { children: ReactNode }): ReactElement {
// Helper hook to access the provider values
const useOcean = (): OceanProviderValue => useContext(OceanContext)
export { OceanProvider, useOcean, OceanProviderValue, OceanContext }
export { OceanProvider, useOcean, OceanContext }
export default OceanProvider

View File

@ -59,4 +59,4 @@ export default function PricesProvider({
// Helper hook to access the provider values
const usePrices = (): PricesValue => useContext(PricesContext)
export { PricesProvider, usePrices, PricesValue }
export { PricesProvider, usePrices }

View File

@ -320,5 +320,5 @@ function ProfileProvider({
// Helper hook to access the provider values
const useProfile = (): ProfileProviderValue => useContext(ProfileContext)
export { ProfileProvider, useProfile, ProfileProviderValue, ProfileContext }
export { ProfileProvider, useProfile, ProfileContext }
export default ProfileProvider

View File

@ -166,4 +166,4 @@ function UserPreferencesProvider({
const useUserPreferences = (): UserPreferencesValue =>
useContext(UserPreferencesContext)
export { UserPreferencesProvider, useUserPreferences, UserPreferencesValue }
export { UserPreferencesProvider, useUserPreferences }

View File

@ -47,7 +47,7 @@ const web3ModalTheme = {
hover: 'var(--background-highlight)'
}
// HEADS UP! We inline-require some packages so the Gatsby SSR build does not break.
// HEADS UP! We inline-require some packages so the SSR build does not break.
// We only need them client-side.
const providerOptions = isBrowser
? {
@ -363,5 +363,5 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
// Helper hook to access the provider values
const useWeb3 = (): Web3ProviderValue => useContext(Web3Context)
export { Web3Provider, useWeb3, Web3ProviderValue, Web3Context }
export { Web3Provider, useWeb3, Web3Context }
export default Web3Provider

View File

@ -44,5 +44,5 @@ function useAccountPurgatory(accountId: string): UseAccountPurgatory {
}
}
export { useAccountPurgatory, UseAccountPurgatory }
export { useAccountPurgatory }
export default useAccountPurgatory

View File

@ -100,5 +100,5 @@ function useConsume(): UseConsume {
return { consume, consumeStep, consumeStepText, consumeError, isLoading }
}
export { useConsume, UseConsume }
export { useConsume }
export default useConsume

View File

@ -1,4 +1,4 @@
import { useStaticQuery, graphql } from 'gatsby'
import gdprContent from '../../content/gdpr.json'
export interface UseGdprMetadata {
title: string
@ -7,7 +7,7 @@ export interface UseGdprMetadata {
reject: string
close: string
configure: string
placeholder: string
placeholder?: string
optionalCookies?: {
title: string
desc: string
@ -15,32 +15,6 @@ export interface UseGdprMetadata {
}[]
}
const query = graphql`
query GdprQuery {
gdpr: allFile(filter: { relativePath: { eq: "gdpr.json" } }) {
edges {
node {
childContentJson {
title
text
accept
reject
close
configure
optionalCookies {
title
desc
cookieName
}
}
}
}
}
}
`
export function useGdprMetadata(): UseGdprMetadata {
const data = useStaticQuery(query)
return { ...data.gdpr.edges[0].node.childContentJson }
return { ...gdprContent }
}

View File

@ -16,5 +16,5 @@ export const networkDataGaiaX: EthereumListsChain = {
'https://faucet.gx.gaiaxtestnet.oceanprotocol.com/'
],
infoURL: 'https://www.gaia-x.eu',
explorers: [{ url: '' }]
explorers: [{ name: '', url: '', standard: '' }]
}

View File

@ -1,35 +1,8 @@
import { useStaticQuery, graphql } from 'gatsby'
import { UseNetworkMetadata } from './types'
const networksQuery = graphql`
query {
allNetworksMetadataJson {
edges {
node {
chain
network
networkId
chainId
rpc
explorers {
url
}
nativeCurrency {
name
symbol
decimals
}
}
}
}
}
`
import networkdata from '../../../content/networks-metadata.json'
export default function useNetworkMetadata(): UseNetworkMetadata {
const data = useStaticQuery(networksQuery)
const networksList: { node: EthereumListsChain }[] =
data.allNetworksMetadataJson.edges
const networksList: EthereumListsChain[] = networkdata
return { networksList }
}

View File

@ -1,3 +1,3 @@
export interface UseNetworkMetadata {
networksList: { node: EthereumListsChain }[]
networksList: EthereumListsChain[]
}

View File

@ -33,21 +33,21 @@ export function getNetworkDisplayName(
}
export function getNetworkDataById(
data: { node: EthereumListsChain }[],
data: EthereumListsChain[],
networkId: number
): EthereumListsChain {
if (!networkId) return
const networkData = data.filter(
({ node }: { node: EthereumListsChain }) => node.chainId === networkId
(chain: EthereumListsChain) => chain.chainId === networkId
)
return networkId === 2021000 ? networkDataGaiaX : networkData[0]?.node
return networkId === 2021000 ? networkDataGaiaX : networkData[0]
}
export function filterNetworksByType(
type: 'mainnet' | 'testnet',
chainIds: number[],
networksList: { node: EthereumListsChain }[]
networksList: EthereumListsChain[]
): number[] {
const finalNetworks = chainIds.filter((chainId: number) => {
const networkData = getNetworkDataById(networksList, chainId)

View File

@ -257,7 +257,7 @@ function usePricing(): UsePricing {
`${dtAmount}`,
weightOnDataToken,
`${oceanAmount}`,
swapFee
`${swapFee}`
)
.next((step: number) => setStep(step, 'pool', ddo))
: type === 'fixed'
@ -292,5 +292,5 @@ function usePricing(): UsePricing {
}
}
export { usePricing, UsePricing }
export { usePricing }
export default usePricing

View File

@ -1,4 +1,4 @@
import { useStaticQuery, graphql } from 'gatsby'
import privacyContent from '../../content/pages/privacy/policies.json'
export interface UsePrivacyMetadata {
policies: {
@ -14,26 +14,6 @@ export interface UsePrivacyMetadata {
}[]
}
const query = graphql`
{
privacyJson {
policies {
policy
date
language
params {
updated
dateFormat
tocHeader
languageLabel
}
}
}
}
`
export function usePrivacyMetadata(): UsePrivacyMetadata {
const data = useStaticQuery(query)
return { ...data.privacyJson }
return { ...privacyContent }
}

View File

@ -11,7 +11,7 @@ import { useOcean } from '@context/Ocean'
import { useWeb3 } from '@context/Web3'
import { getOceanConfig } from '@utils/ocean'
interface DataTokenOptions {
export interface DataTokenOptions {
cap?: string
name?: string
symbol?: string
@ -161,5 +161,5 @@ function usePublish(): UsePublish {
}
}
export { usePublish, UsePublish, DataTokenOptions }
export { usePublish }
export default usePublish

View File

@ -1,75 +1,11 @@
import { useStaticQuery, graphql } from 'gatsby'
import { UseSiteMetadata } from './types'
const query = graphql`
query {
site {
siteMetadata {
siteTitle
siteTagline
siteUrl
siteIcon
copyright
menu {
name
link
}
warning {
main
polygonPublish
}
announcement {
main
polygon
}
appConfig {
metadataCacheUri
infuraProjectId
chainIds
chainIdsSupported
marketFeeAddress
currencies
portisId
allowFixedPricing
allowDynamicPricing
allowFreePricing
defaultPrivacyPolicySlug
privacyPreferenceCenter
darkModeConfig {
classNameDark
classNameLight
storageKey
}
}
}
}
siteImage: allFile(filter: { relativePath: { eq: "site.json" } }) {
edges {
node {
childContentJson {
site {
siteImage {
childImageSharp {
original {
src
}
}
}
}
}
}
}
}
}
`
import siteContent from '../../../content/site.json'
import siteConfig from '../../../app.config'
export function useSiteMetadata(): UseSiteMetadata {
const data = useStaticQuery(query)
const siteMeta: UseSiteMetadata = {
...data.siteImage.edges[0].node.childContentJson.site,
...data.site.siteMetadata
...siteContent,
appConfig: siteConfig
}
return siteMeta

View File

@ -3,7 +3,7 @@ export interface UseSiteMetadata {
siteTagline: string
siteUrl: string
siteIcon: string
siteImage: { childImageSharp: { original: { src: string } } }
siteImage: string
copyright: string
menu: {
name: string

View File

@ -9,7 +9,7 @@ interface EthereumListsChain {
rpc: string[]
infoURL: string
faucets: string[]
explorers: [{ url: string }]
explorers?: { name: string; url: string; standard: string }[]
}
interface NetworkObject {

View File

@ -1,15 +0,0 @@
declare module '*.module.css' {
const classes: { [key: string]: string }
export default classes
}
declare module '*.svg' {
import * as React from 'react'
export const ReactComponent: React.FunctionComponent<
React.SVGProps<SVGSVGElement>
>
const src: string
export default src
}
declare module '*.gif'

View File

@ -3,7 +3,7 @@ import {
DID,
Logger,
publisherTrustedAlgorithm as PublisherTrustedAlgorithm
} from '@oceanprotocol/lib/'
} from '@oceanprotocol/lib'
import { AssetSelectionAsset } from '@shared/Form/FormFields/AssetSelection'
import { PriceList, getAssetsPriceList } from './subgraph'
import axios, { CancelToken, AxiosResponse } from 'axios'

12
src/@utils/markdown.ts Normal file
View File

@ -0,0 +1,12 @@
import remark from 'remark'
import remarkHtml from 'remark-html'
import remarkGfm from 'remark-gfm'
export function markdownToHtml(markdown: string): string {
const result = remark()
.use(remarkGfm)
.use(remarkHtml) // serializes through remark-rehype and rehype-stringify
.processSync(markdown).contents
return result.toString()
}

View File

@ -0,0 +1,35 @@
import fs from 'fs'
import { join } from 'path'
import matter from 'gray-matter'
//
// Next.js specifics to be used in getStaticProps / getStaticPaths
// to automatically generate pages from Markdown files in `src/pages/[slug].tsx`.
//
const pagesDirectory = join(process.cwd(), 'content', 'pages')
export interface PageData {
slug: string
frontmatter: { [key: string]: any }
content: string
}
export function getPageBySlug(slug: string, subDir?: string): PageData {
const realSlug = slug.replace(/\.md$/, '')
const fullPath = subDir
? join(pagesDirectory, subDir, `${realSlug}.md`)
: join(pagesDirectory, `${realSlug}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const { data, content } = matter(fileContents)
return { slug: realSlug, frontmatter: { ...data }, content }
}
export function getAllPages(subDir?: string): PageData[] {
const slugs = fs
.readdirSync(join(pagesDirectory, subDir || ''))
.filter((slug) => slug.includes('.md'))
const pages = slugs.map((slug) => getPageBySlug(slug, subDir))
return pages
}

View File

@ -1,7 +1,7 @@
import axios from 'axios'
import { toast } from 'react-toastify'
import isUrl from 'is-url-superb'
import slugify from '@sindresorhus/slugify'
import slugify from 'slugify'
import { DDO, MetadataAlgorithm, Logger } from '@oceanprotocol/lib'
import { FormPublishData } from '../components/Publish/_types'
@ -97,72 +97,72 @@ function getAlgorithmFileExtension(fileUrl: string): string {
return splitedFileUrl[splitedFileUrl.length - 1]
}
export function transformPublishFormToMetadata(
{
name,
author,
description,
tags,
links,
termsAndConditions,
files
}: Partial<FormPublishData>,
ddo?: DDO
): MetadataMarket {
const currentTime = dateToStringNoMS(new Date())
// export function transformPublishFormToMetadata(
// {
// name,
// author,
// description,
// tags,
// links,
// termsAndConditions,
// files
// }: Partial<FormPublishData>,
// ddo?: DDO
// ): MetadataMarket {
// const currentTime = dateToStringNoMS(new Date())
const metadata: MetadataMarket = {
main: {
name,
author,
dateCreated: ddo ? ddo.created : currentTime,
datePublished: '',
files: typeof files !== 'string' && files,
license: 'https://market.oceanprotocol.com/terms'
},
additionalInformation: {
description,
tags: transformTags(tags),
links: typeof links !== 'string' ? links : [],
termsAndConditions
}
}
// const metadata: MetadataMarket = {
// main: {
// name,
// author,
// dateCreated: ddo ? ddo.created : currentTime,
// datePublished: '',
// files: typeof files !== 'string' && files,
// license: 'https://market.oceanprotocol.com/terms'
// },
// additionalInformation: {
// description,
// tags: transformTags(tags),
// links: typeof links !== 'string' ? links : [],
// termsAndConditions
// }
// }
return metadata
}
// return metadata
// }
async function isDockerHubImageValid(
image: string,
tag: string
): Promise<boolean> {
try {
const response = await axios.post(
`https://dockerhub-proxy.oceanprotocol.com`,
{
image,
tag
}
)
if (
!response ||
response.status !== 200 ||
response.data.status !== 'success'
) {
toast.error(
'Could not fetch docker hub image info. Please check image name and tag and try again'
)
return false
}
// async function isDockerHubImageValid(
// image: string,
// tag: string
// ): Promise<boolean> {
// try {
// const response = await axios.post(
// `https://dockerhub-proxy.oceanprotocol.com`,
// {
// image,
// tag
// }
// )
// if (
// !response ||
// response.status !== 200 ||
// response.data.status !== 'success'
// ) {
// toast.error(
// 'Could not fetch docker hub image info. Please check image name and tag and try again'
// )
// return false
// }
return true
} catch (error) {
Logger.error(error.message)
toast.error(
'Could not fetch docker hub image info. Please check image name and tag and try again'
)
return false
}
}
// return true
// } catch (error) {
// Logger.error(error.message)
// toast.error(
// 'Could not fetch docker hub image info. Please check image name and tag and try again'
// )
// return false
// }
// }
async function is3rdPartyImageValid(imageURL: string): Promise<boolean> {
try {
@ -183,55 +183,55 @@ async function is3rdPartyImageValid(imageURL: string): Promise<boolean> {
}
}
export async function validateDockerImage(
dockerImage: string,
tag: string
): Promise<boolean> {
const isValid = isUrl(dockerImage)
? await is3rdPartyImageValid(dockerImage)
: await isDockerHubImageValid(dockerImage, tag)
return isValid
}
// export async function validateDockerImage(
// dockerImage: string,
// tag: string
// ): Promise<boolean> {
// const isValid = isUrl(dockerImage)
// ? await is3rdPartyImageValid(dockerImage)
// : await isDockerHubImageValid(dockerImage, tag)
// return isValid
// }
export function transformPublishAlgorithmFormToMetadata(
{
name,
author,
description,
tags,
image,
containerTag,
entrypoint,
termsAndConditions,
files
}: Partial<FormPublishData>,
ddo?: DDO
): MetadataMarket {
const currentTime = dateToStringNoMS(new Date())
const fileUrl = typeof files !== 'string' && files[0].url
const algorithmLanguage = getAlgorithmFileExtension(fileUrl)
const algorithm = getAlgorithmComponent(
image,
containerTag,
entrypoint,
algorithmLanguage
)
const metadata: MetadataMarket = {
main: {
name,
type: 'algorithm',
author,
dateCreated: ddo ? ddo.created : currentTime,
files: typeof files !== 'string' && files,
license: 'https://market.oceanprotocol.com/terms',
algorithm
},
additionalInformation: {
description,
tags: transformTags(tags),
termsAndConditions
}
}
// export function transformPublishAlgorithmFormToMetadata(
// {
// name,
// author,
// description,
// tags,
// image,
// containerTag,
// entrypoint,
// termsAndConditions,
// files
// }: Partial<FormPublishData>,
// ddo?: DDO
// ): MetadataMarket {
// const currentTime = dateToStringNoMS(new Date())
// const fileUrl = typeof files !== 'string' && files[0].url
// const algorithmLanguage = getAlgorithmFileExtension(fileUrl)
// const algorithm = getAlgorithmComponent(
// image,
// containerTag,
// entrypoint,
// algorithmLanguage
// )
// const metadata: MetadataMarket = {
// main: {
// name,
// type: 'algorithm',
// author,
// dateCreated: ddo ? ddo.created : currentTime,
// files: typeof files !== 'string' && files,
// license: 'https://market.oceanprotocol.com/terms',
// algorithm
// },
// additionalInformation: {
// description,
// tags: transformTags(tags),
// termsAndConditions
// }
// }
return metadata
}
// return metadata
// }

View File

@ -14,7 +14,7 @@ export function getOceanConfig(network: string | number): ConfigHelperConfig {
network === 'gaiaxtestnet' ||
network === 2021000
? undefined
: process.env.GATSBY_INFURA_PROJECT_ID
: process.env.NEXT_INFURA_PROJECT_ID
) as ConfigHelperConfig
return config as ConfigHelperConfig
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react'
import classNames from 'classnames/bind'
import Markdown from '@shared/atoms/Markdown'
import Markdown from '@shared/Markdown'
import Button from '@shared/atoms/Button'
import styles from './index.module.css'

View File

@ -1,6 +1,6 @@
import React from 'react'
import Dotdotdot from 'react-dotdotdot'
import { Link } from 'gatsby'
import Link from 'next/link'
import PriceUnit from '@shared/Price/PriceUnit'
import Loader from '@shared/atoms/Loader'
import styles from './AssetComputeList.module.css'
@ -24,11 +24,8 @@ export default function AssetComputeSelection({
<Empty />
) : (
assets.map((asset: AssetSelectionAsset) => (
<Link
to={`/asset/${asset.did}`}
className={styles.row}
key={asset.did}
>
<Link href={`/asset/${asset.did}`} key={asset.did}>
<a className={styles.row}>
<div className={styles.info}>
<h3 className={styles.title}>
<Dotdotdot clamp={1} tagName="span">
@ -40,6 +37,7 @@ export default function AssetComputeSelection({
</Dotdotdot>
</div>
<PriceUnit price={asset.price} small className={styles.price} />
</a>
</Link>
))
)}

View File

@ -1,5 +1,5 @@
import { DDO } from '@oceanprotocol/lib'
import { Link } from 'gatsby'
import Link from 'next/link'
import React, { ReactElement, useEffect, useState } from 'react'
import { getAssetsNames } from '@utils/aquarius'
import styles from './AssetListTitle.module.css'
@ -42,7 +42,9 @@ export default function AssetListTitle({
return (
<h3 className={styles.title}>
<Link to={`/asset/${did || ddo?.id}`}>{assetTitle}</Link>
<Link href={`/asset/${did || ddo?.id}`}>
<a>{assetTitle}</a>
</Link>
</h3>
)
}

View File

@ -4,7 +4,7 @@
}
.link {
composes: box from '../atoms/Box.module.css';
composes: box from '@shared/atoms/Box.module.css';
font-size: var(--font-size-small);
height: 100%;
color: var(--color-secondary);

View File

@ -1,5 +1,5 @@
import React from 'react'
import { Link } from 'gatsby'
import Link from 'next/link'
import Dotdotdot from 'react-dotdotdot'
import Price from '@shared/Price'
import { DDO } from '@oceanprotocol/lib'
@ -29,7 +29,8 @@ const AssetTeaser: React.FC<AssetTeaserProps> = ({
return (
<article className={`${styles.teaser} ${styles[type]}`}>
<Link to={`/asset/${ddo.id}`} className={styles.link}>
<Link href={`/asset/${ddo.id}`}>
<a className={styles.link}>
<header className={styles.header}>
<div className={styles.symbol}>{dataTokenInfo?.symbol}</div>
<Dotdotdot clamp={3}>
@ -61,6 +62,7 @@ const AssetTeaser: React.FC<AssetTeaserProps> = ({
<Price price={price} small />
<NetworkName networkId={ddo.chainId} className={styles.network} />
</footer>
</a>
</Link>
</article>
)

View File

@ -1,9 +1,9 @@
import React, { ReactElement } from 'react'
import styles from './index.module.css'
import classNames from 'classnames/bind'
import { ReactComponent as Compute } from '@images/compute.svg'
import { ReactComponent as Download } from '@images/download.svg'
import { ReactComponent as Lock } from '@images/lock.svg'
import Compute from '@images/compute.svg'
import Download from '@images/download.svg'
import Lock from '@images/lock.svg'
const cx = classNames.bind(styles)

View File

@ -1,5 +1,5 @@
import React, { ReactElement, ReactNode, useEffect, useState } from 'react'
import { ReactComponent as External } from '@images/external.svg'
import External from '@images/external.svg'
import classNames from 'classnames/bind'
import { ConfigHelperConfig } from '@oceanprotocol/lib'
import { useOcean } from '@context/Ocean'

View File

@ -3,7 +3,7 @@ import Dotdotdot from 'react-dotdotdot'
import slugify from 'slugify'
import classNames from 'classnames/bind'
import PriceUnit from '@shared/Price/PriceUnit'
import { ReactComponent as External } from '@images/external.svg'
import External from '@images/external.svg'
import InputElement from '@shared/Form/Input/InputElement'
import Loader from '@shared/atoms/Loader'
import styles from './AssetSelection.module.css'

View File

@ -35,7 +35,7 @@
pointer-events: none;
}
input[type='radio']:checked + label {
.boxSelectionsWrapper input[type='radio']:checked + label {
color: var(--font-color-text);
border-color: var(--color-secondary);
}

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react'
import styles from './RefreshName.module.css'
import Button from '@shared/atoms/Button'
import { ReactComponent as Refresh } from '@images/refresh.svg'
import Refresh from '@images/refresh.svg'
export default function RefreshName({
generateName

View File

@ -2,18 +2,8 @@ import React, { ReactElement } from 'react'
import { InputProps } from '@shared/Form/Input'
import InputElement from '@shared/Form/Input/InputElement'
import styles from './Terms.module.css'
import { graphql, useStaticQuery } from 'gatsby'
const query = graphql`
query TermsQuery {
terms: markdownRemark(fields: { slug: { eq: "/terms" } }) {
html
}
}
`
export default function Terms(props: InputProps): ReactElement {
const data = useStaticQuery(query)
const termsProps: InputProps = {
...props,
defaultChecked: props.value.toString() === 'true'
@ -21,10 +11,6 @@ export default function Terms(props: InputProps): ReactElement {
return (
<>
<div
className={styles.terms}
dangerouslySetInnerHTML={{ __html: data.terms.html }}
/>
<InputElement {...termsProps} type="checkbox" />
</>
)

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react'
import styles from './Help.module.css'
import Markdown from '@shared/atoms/Markdown'
import Markdown from '@shared/Markdown'
import classNames from 'classnames/bind'
const cx = classNames.bind(styles)

View File

@ -218,17 +218,17 @@
border-color: var(--brand-grey);
}
input[type='range'] {
.input[type='range'] {
background: transparent;
appearance: none;
}
input[type='range']:focus {
.input[type='range']:focus {
outline: none;
}
/* Selectors need to be split up to work in both engines */
input[type='range']::-webkit-slider-thumb {
.input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
margin-top: -0.5rem;
background: var(--brand-gradient);
@ -240,7 +240,7 @@ input[type='range']::-webkit-slider-thumb {
box-shadow: 0 2px 9px 0 rgba(0, 0, 0, 0.2);
}
input[type='range']::-moz-range-thumb {
.input[type='range']::-moz-range-thumb {
background: var(--brand-gradient);
border: 2px solid var(--border-color);
width: var(--font-size-large);
@ -250,7 +250,7 @@ input[type='range']::-moz-range-thumb {
box-shadow: 0 2px 9px 0 rgba(0, 0, 0, 0.2);
}
input[type='range']::-webkit-slider-runnable-track {
.input[type='range']::-webkit-slider-runnable-track {
margin-top: -1rem;
background: var(--border-color);
border-radius: var(--border-radius);
@ -258,7 +258,7 @@ input[type='range']::-webkit-slider-runnable-track {
border: none;
}
input[type='range']::-moz-range-track {
.input[type='range']::-moz-range-track {
background: var(--border-color);
border-radius: var(--border-radius);
height: 0.3rem;

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react'
import slugify from '@sindresorhus/slugify'
import slugify from 'slugify'
import styles from './InputElement.module.css'
import { InputProps } from '.'
import FilesInput from '../FormFields/FilesInput'

View File

@ -0,0 +1,24 @@
import { markdownToHtml } from '@utils/markdown'
import React, { ReactElement } from 'react'
import styles from './index.module.css'
const Markdown = ({
text,
className
}: {
text: string
className?: string
}): ReactElement => {
const content = markdownToHtml(text)
return (
<div
className={`${styles.markdown} ${className}`}
// Note: We serialize and kill all embedded HTML over in markdownToHtml()
// so the danger here is gone.
dangerouslySetInnerHTML={{ __html: content }}
/>
)
}
export default Markdown

View File

@ -1,9 +1,9 @@
import React, { ReactElement } from 'react'
import { ReactComponent as EthIcon } from '@images/eth.svg'
import { ReactComponent as PolygonIcon } from '@images/polygon.svg'
import { ReactComponent as MoonbeamIcon } from '@images/moonbeam.svg'
import { ReactComponent as BscIcon } from '@images/bsc.svg'
import { ReactComponent as EnergywebIcon } from '@images/energyweb.svg'
import EthIcon from '@images/eth.svg'
import PolygonIcon from '@images/polygon.svg'
import MoonbeamIcon from '@images/moonbeam.svg'
import BscIcon from '@images/bsc.svg'
import EnergywebIcon from '@images/energyweb.svg'
import styles from './index.module.css'
export function NetworkIcon({ name }: { name: string }): ReactElement {

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react'
import classNames from 'classnames/bind'
import styles from './PageHeader.module.css'
import Markdown from '@shared/atoms/Markdown'
import Markdown from '@shared/Markdown'
const cx = classNames.bind(styles)

View File

@ -1,48 +0,0 @@
import React, { ReactElement } from 'react'
import { graphql, PageProps } from 'gatsby'
import Page from '.'
import styles from './PageMarkdown.module.css'
import Container from '@shared/atoms/Container'
import PrivacyPolicyHeader from '../../Privacy/PrivacyHeader'
export default function PageTemplateMarkdown(props: PageProps): ReactElement {
const { html, frontmatter, tableOfContents, fields } = (props.data as any)
.markdownRemark
const { title, description } = frontmatter
const { slug } = fields
const isPrivacy = slug.includes('/privacy/')
return (
<Page title={title} description={description} uri={props.uri} headerCenter>
<Container narrow>
{isPrivacy && (
<PrivacyPolicyHeader
tableOfContents={tableOfContents}
policy={slug.replace('/privacy/', '')}
/>
)}
<div
className={styles.content}
dangerouslySetInnerHTML={{ __html: html }}
/>
</Container>
</Page>
)
}
export const pageQuery = graphql`
query PageMarkdownBySlug($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
tableOfContents(absolute: false)
frontmatter {
title
description
}
fields {
slug
}
}
}
`

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react'
import { Helmet } from 'react-helmet'
import Head from 'next/head'
import { useSiteMetadata } from '@hooks/useSiteMetadata'
import { isBrowser } from '@utils/index'
@ -18,13 +18,11 @@ export default function Seo({
const canonical = `${siteUrl}${uri}`.replace(/\/$/, '')
return (
<Helmet
defaultTitle={`${siteTitle}${siteTagline}`}
titleTemplate={`%s — ${siteTitle}`}
title={title}
>
<Head>
<html lang="en" />
<title>{`${siteTitle}${siteTagline}`}</title>
{isBrowser &&
window.location &&
window.location.hostname !== 'oceanprotocol.com' && (
@ -38,18 +36,12 @@ export default function Seo({
<meta property="og:description" content={description} />
<meta property="og:url" content={uri} />
<meta
name="image"
content={`${siteUrl}${siteImage.childImageSharp.original.src}`}
/>
<meta
property="og:image"
content={`${siteUrl}${siteImage.childImageSharp.original.src}`}
/>
<meta name="image" content={`${siteUrl}${siteImage}`} />
<meta property="og:image" content={`${siteUrl}${siteImage}`} />
<meta property="og:site_name" content={siteTitle} />
<meta name="twitter:creator" content="@oceanprotocol" />
<meta name="twitter:card" content="summary_large_image" />
</Helmet>
</Head>
)
}

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect, ReactElement } from 'react'
import ReactPaginate from 'react-paginate'
import styles from './index.module.css'
import { MAXIMUM_NUMBER_OF_PAGES_WITH_RESULTS } from '@utils/aquarius'
import { ReactComponent as Arrow } from '@images/arrow.svg'
import Arrow from '@images/arrow.svg'
import { PaginationProps } from './_types'
export default function Pagination({

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react'
import { ReactComponent as External } from '@images/external.svg'
import External from '@images/external.svg'
import styles from './Add.module.css'
export default function Add(): ReactElement {

View File

@ -1,7 +1,7 @@
import React, { ReactElement, useEffect, useState } from 'react'
import styles from './index.module.css'
import classNames from 'classnames/bind'
import { Link } from 'gatsby'
import Link from 'next/link'
import get3BoxProfile from '@utils/profile'
import { accountTruncate } from '@utils/web3'
import axios from 'axios'
@ -67,11 +67,8 @@ export default function Publisher({
name
) : (
<>
<Link
to={`/profile/${accountEns || account}`}
title="Show profile page."
>
{name}
<Link href={`/profile/${accountEns || account}`}>
<a title="Show profile page.">{name}</a>
</Link>
{showAdd && <Add />}
</>

View File

@ -1,29 +1,9 @@
import React from 'react'
import React, { ReactElement } from 'react'
import Button from '@shared/atoms/Button'
import Loader from '@shared/atoms/Loader'
import { useUserPreferences } from '@context/UserPreferences'
import Tooltip from '@shared/atoms/Tooltip'
import { useStaticQuery, graphql } from 'gatsby'
import { ReactElement } from 'react-markdown'
export const query = graphql`
query {
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
edges {
node {
childContentJson {
pool {
tooltips {
approveSpecific
approveInfinite
}
}
}
}
}
}
}
`
import content from '../../../../content/price.json'
export function ButtonApprove({
amount,
@ -36,10 +16,6 @@ export function ButtonApprove({
approveTokens: (amount: string) => void
isLoading: boolean
}): ReactElement {
// Get content
const data = useStaticQuery(query)
const content = data.content.edges[0].node.childContentJson.pool.tooltips
const { infiniteApproval } = useUserPreferences()
return isLoading ? (
@ -52,12 +28,16 @@ export function ButtonApprove({
onClick={() => approveTokens(`${2 ** 53 - 1}`)}
>
Approve {coin}{' '}
<Tooltip content={content.approveInfinite.replace('COIN', coin)} />
<Tooltip
content={content.pool.tooltips.approveInfinite.replace('COIN', coin)}
/>
</Button>
) : (
<Button style="primary" size="small" onClick={() => approveTokens(amount)}>
Approve {amount} {coin}
<Tooltip content={content.approveSpecific.replace('COIN', coin)} />
<Tooltip
content={content.pool.tooltips.approveSpecific.replace('COIN', coin)}
/>
</Button>
)
}

View File

@ -25,8 +25,8 @@ export default function WalletNetworkSwitcher(): ReactElement {
async function switchWalletNetwork() {
const networkNode = await networksList.find(
(data) => data.node.chainId === ddo.chainId
).node
(data) => data.chainId === ddo.chainId
)
addCustomNetwork(web3Provider, networkNode)
}

View File

@ -2,7 +2,7 @@ import React, { ReactElement, FormEvent } from 'react'
import classNames from 'classnames/bind'
import styles from './Alert.module.css'
import Button from './Button'
import Markdown from './Markdown'
import Markdown from '../Markdown'
import Badge from './Badge'
const cx = classNames.bind(styles)

View File

@ -1,5 +1,5 @@
import React, { ReactNode, FormEvent, ReactElement } from 'react'
import { Link } from 'gatsby'
import Link from 'next/link'
import classNames from 'classnames/bind'
import styles from './Button.module.css'
@ -41,8 +41,10 @@ export default function Button({
})
return to ? (
<Link to={to} className={styleClasses} {...props}>
<Link href={to}>
<a className={styleClasses} {...props}>
{children}
</a>
</Link>
) : href ? (
<a href={href} className={styleClasses} {...props}>

View File

@ -1,7 +1,7 @@
import React, { ReactElement, useEffect, useState } from 'react'
import loadable from '@loadable/component'
import styles from './Copy.module.css'
import { ReactComponent as IconCopy } from '@images/copy.svg'
import IconCopy from '@images/copy.svg'
// lazy load when needed only, as library is a bit big
const Clipboard = loadable(() => import('react-clipboard.js'))

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react'
import { ReactComponent as LogoAssetFull } from '@oceanprotocol/art/logo/logo.svg'
import { ReactComponent as LogoAsset } from '@images/logo.svg'
import LogoAssetFull from '@oceanprotocol/art/logo/logo.svg'
import LogoAsset from '@images/logo.svg'
import styles from './Logo.module.css'
export default function Logo({

View File

@ -1,22 +0,0 @@
import React, { ReactElement } from 'react'
import ReactMarkdown from 'react-markdown'
import styles from './Markdown.module.css'
const Markdown = ({
text,
className
}: {
text: string
className?: string
}): ReactElement => {
// fix react-markdown \n transformation
// https://github.com/rexxars/react-markdown/issues/105#issuecomment-351585313
const textCleaned = text?.replace(/\\n/g, '\n ')
return (
<ReactMarkdown className={`${styles.markdown} ${className}`}>
{textCleaned}
</ReactMarkdown>
)
}
export default Markdown

View File

@ -1,8 +1,3 @@
/* prevent background scrolling */
:global(.ReactModal__Body--open) {
overflow: hidden;
}
.modalOverlay {
position: fixed;
top: 0;

View File

@ -2,7 +2,7 @@ import React, { ReactElement, ReactNode } from 'react'
import ReactModal from 'react-modal'
import styles from './Modal.module.css'
if (process.env.NODE_ENV !== 'test') ReactModal.setAppElement('#___gatsby')
if (process.env.NODE_ENV !== 'test') ReactModal.setAppElement('#__next')
export interface ModalProps extends ReactModal.Props {
title: string

View File

@ -61,7 +61,7 @@
display: none;
}
div [class*='Table-module'] {
.table [class*='Table-module'] {
scrollbar-width: thin;
}

View File

@ -1,6 +1,5 @@
import React from 'react'
import { Link } from 'gatsby'
import shortid from 'shortid'
import Link from 'next/link'
import styles from './Tags.module.css'
declare type TagsProps = {
@ -16,12 +15,10 @@ const Tag = ({ tag, noLinks }: { tag: string; noLinks?: boolean }) => {
return noLinks ? (
<span className={styles.tag}>{tag}</span>
) : (
<Link
to={`/search?tags=${urlEncodedTag}&sort=created&sortOrder=desc`}
className={styles.tag}
title={tag}
>
<Link href={`/search?tags=${urlEncodedTag}&sort=created&sortOrder=desc`}>
<a className={styles.tag} title={tag}>
{tag}
</a>
</Link>
)
}
@ -43,7 +40,7 @@ const Tags: React.FC<TagsProps> = ({
return (
<div className={classes}>
{tags?.map((tag) => (
<Tag tag={tag} noLinks={noLinks} key={shortid.generate()} />
<Tag tag={tag} noLinks={noLinks} key={tag} />
))}
{shouldShowMore && (
<span className={styles.more}>{`+ ${items.length - max} more`}</span>

View File

@ -3,7 +3,7 @@ import classNames from 'classnames/bind'
import loadable from '@loadable/component'
import { useSpring, animated } from 'react-spring'
import styles from './Tooltip.module.css'
import { ReactComponent as Info } from '@images/info.svg'
import Info from '@images/info.svg'
import { Placement } from 'tippy.js'
const cx = classNames.bind(styles)

View File

@ -1,6 +1,7 @@
.app {
height: 100%;
background: url('@oceanprotocol/art/waves/waves.svg') no-repeat center 13.5rem;
background: url('../../../node_modules/@oceanprotocol/art/waves/waves.svg')
no-repeat center 13.5rem;
/* sticky footer technique */
display: flex;

View File

@ -1,59 +1,39 @@
import React, { ReactElement } from 'react'
import { graphql, PageProps, useStaticQuery } from 'gatsby'
import Alert from '@shared/atoms/Alert'
import Footer from '../Footer/Footer'
import Header from '../Header'
import StylesGlobal from '../../stylesGlobal/StylesGlobal'
import { useWeb3 } from '@context/Web3'
import { useSiteMetadata } from '@hooks/useSiteMetadata'
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'
import AnnouncementBanner from '@shared/AnnouncementBanner'
import PrivacyPreferenceCenter from '../Privacy/PrivacyPreferenceCenter'
import styles from './index.module.css'
const contentQuery = graphql`
query AppQuery {
purgatory: allFile(filter: { relativePath: { eq: "purgatory.json" } }) {
edges {
node {
childContentJson {
account {
title
description
}
}
}
}
}
}
`
import { ToastContainer } from 'react-toastify'
import { useRouter } from 'next/router'
// import waves from '@oceanprotocol/art/waves/waves.png'
import content from '../../../content/purgatory.json'
export default function App({
children,
...props
children
}: {
children: ReactElement
}): ReactElement {
const data = useStaticQuery(contentQuery)
const purgatory = data.purgatory.edges[0].node.childContentJson.account
const router = useRouter()
const { warning, appConfig } = useSiteMetadata()
const { accountId } = useWeb3()
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
return (
<StylesGlobal>
<div className={styles.app}>
{(props as PageProps).uri === '/' && (
<AnnouncementBanner text={warning.main} />
)}
{router.pathname === '/' && <AnnouncementBanner text={warning.main} />}
<Header />
{isInPurgatory && (
<Alert
title={purgatory.title}
title={content.account.title}
badge={`Reason: ${purgatoryData?.reason}`}
text={purgatory.description}
text={content.account.description}
state="error"
/>
)}
@ -63,7 +43,8 @@ export default function App({
{appConfig.privacyPreferenceCenter === 'true' && (
<PrivacyPreferenceCenter style="small" />
)}
<ToastContainer position="bottom-right" newestOnTop />
</div>
</StylesGlobal>
)
}

View File

@ -1,14 +0,0 @@
import { PageProps } from 'gatsby'
import React, { ReactElement } from 'react'
import App from '.'
// Gatsby-specific, referenced in gatsby-browser.js & gatsby-ssr.js
const wrapPageElement = ({
element,
props
}: {
element: ReactElement
props: PageProps
}): ReactElement => <App {...props}>{element}</App>
export default wrapPageElement

View File

@ -1,8 +1,7 @@
import React, { ReactElement, useState } from 'react'
import React, { ReactElement, ReactNode, useState } from 'react'
import Button from '@shared/atoms/Button'
import styles from './AssetActionHistoryTable.module.css'
import { ReactComponent as Caret } from '@images/caret.svg'
import { ReactNode } from 'react-markdown'
import Caret from '@images/caret.svg'
export default function AssetActionHistoryTable({
title,

View File

@ -2,7 +2,6 @@ import React, { ReactElement, useEffect, useState } from 'react'
import styles from './FormComputeDataset.module.css'
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
import Input from '@shared/Form/Input'
import { useStaticQuery, graphql } from 'gatsby'
import { DDO } from '@oceanprotocol/lib'
import { AssetSelectionAsset } from '@shared/Form/FormFields/AssetSelection'
import { compareAsBN } from '@utils/numbers'
@ -11,36 +10,7 @@ import PriceOutput from './PriceOutput'
import { useAsset } from '@context/Asset'
import { useOcean } from '@context/Ocean'
import { useWeb3 } from '@context/Web3'
const contentQuery = graphql`
query StartComputeDatasetQuery {
content: allFile(
filter: { relativePath: { eq: "pages/startComputeDataset.json" } }
) {
edges {
node {
childPagesJson {
description
form {
success
successAction
error
data {
name
label
help
type
required
sortOptions
options
}
}
}
}
}
}
}
`
import content from '../../../../../content/pages/startComputeDataset.json'
export default function FormStartCompute({
algorithms,
@ -91,9 +61,6 @@ export default function FormStartCompute({
isConsumable: boolean
consumableFeedback: string
}): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childPagesJson
const { isValid, values }: FormikContextType<{ algorithm: string }> =
useFormikContext()
const { price, ddo, isAssetNetwork } = useAsset()

View File

@ -1,31 +1,31 @@
import { DDO } from '@oceanprotocol/lib'
import React, { ReactElement } from 'react'
import { transformPublishFormToMetadata } from '@utils/metadata'
import DebugOutput from '@shared/DebugOutput'
import { FormPublishData } from '../../../Publish/_types'
// import React, { ReactElement } from 'react'
// import { transformPublishFormToMetadata } from '@utils/metadata'
// import DebugOutput from '@shared/DebugOutput'
// import { FormPublishData } from '../../../Publish/_types'
export default function Debug({
values,
ddo
}: {
values: Partial<FormPublishData>
ddo: DDO
}): ReactElement {
const newDdo = {
'@context': 'https://w3id.org/did/v1',
service: [
{
index: 0,
type: 'metadata',
attributes: { ...transformPublishFormToMetadata(values, ddo) }
}
]
}
// export default function Debug({
// values,
// ddo
// }: {
// values: Partial<FormPublishData>
// ddo: DDO
// }): ReactElement {
// const newDdo = {
// '@context': 'https://w3id.org/did/v1',
// service: [
// {
// index: 0,
// type: 'metadata',
// attributes: { ...transformPublishFormToMetadata(values, ddo) }
// }
// ]
// }
return (
<>
<DebugOutput title="Collected Form Values" output={values} />
<DebugOutput title="Transformed DDO Values" output={newDdo} />
</>
)
}
// return (
// <>
// <DebugOutput title="Collected Form Values" output={values} />
// <DebugOutput title="Transformed DDO Values" output={newDdo} />
// </>
// )
// }

View File

@ -5,7 +5,6 @@ import React, { ReactElement, useState } from 'react'
import { useAsset } from '@context/Asset'
import FormEditComputeDataset from './FormEditComputeDataset'
import { Logger, ServiceComputePrivacy } from '@oceanprotocol/lib'
import { graphql, useStaticQuery } from 'gatsby'
import { useUserPreferences } from '@context/UserPreferences'
import DebugEditCompute from './DebugEditCompute'
import styles from './index.module.css'
@ -14,49 +13,13 @@ import { setMinterToDispenser, setMinterToPublisher } from '@utils/freePrice'
import Web3Feedback from '@shared/Web3Feedback'
import MetadataFeedback from '../../../Publish/MetadataFeedback'
import { getInitialValues, validationSchema } from './_constants'
const contentQuery = graphql`
query EditComputeDataQuery {
content: allFile(
filter: { relativePath: { eq: "pages/editComputeDataset.json" } }
) {
edges {
node {
childPagesJson {
description
form {
title
success
successAction
error
data {
name
placeholder
label
help
type
required
sortOptions
options
multiple
rows
}
}
}
}
}
}
}
`
import content from '../../../../../content/pages/editComputeDataset.json'
export default function EditComputeDataset({
setShowEdit
}: {
setShowEdit: (show: boolean) => void
}): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childPagesJson
const { debug } = useUserPreferences()
const { ocean } = useOcean()
const { accountId } = useWeb3()
@ -127,15 +90,18 @@ export default function EditComputeDataset({
return (
<Formik
initialValues={getInitialValues(
ddo.findServiceByType('compute').attributes.main.privacy
)}
initialValues={
{}
// getInitialValues(
// ddo.findServiceByType('compute').attributes.main.privacy
// )
}
validationSchema={validationSchema}
onSubmit={async (values, { resetForm }) => {
// move user's focus to top of screen
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
// kick off editing
await handleSubmit(values, resetForm)
// await handleSubmit(values, resetForm)
}}
>
{({ values, isSubmitting }) =>
@ -166,7 +132,7 @@ export default function EditComputeDataset({
<Web3Feedback isAssetNetwork={isAssetNetwork} />
{debug === true && (
<div className={styles.grid}>
<DebugEditCompute values={values} ddo={ddo} />
{/* <DebugEditCompute values={values} ddo={ddo} /> */}
</div>
)}
</>

View File

@ -7,39 +7,39 @@ import FormActions from './FormActions'
import styles from './FormEditMetadata.module.css'
import { FormPublishData } from '../../../Publish/_types'
function handleTimeoutCustomOption(
data: FormFieldProps[],
values: Partial<FormPublishData>
) {
const timeoutFieldContent = data.filter(
(field) => field.name === 'timeout'
)[0]
const timeoutInputIndex = data.findIndex(
(element) => element.name === 'timeout'
)
if (
data[timeoutInputIndex].options.length < 6 &&
!checkIfTimeoutInPredefinedValues(
values.timeout,
timeoutFieldContent.options
)
) {
data[timeoutInputIndex].options.push(values.timeout)
} else if (
data[timeoutInputIndex].options.length === 6 &&
checkIfTimeoutInPredefinedValues(
values.timeout,
timeoutFieldContent.options
)
) {
data[timeoutInputIndex].options.pop()
} else if (
data[timeoutInputIndex].options.length === 6 &&
data[timeoutInputIndex].options[5] !== values.timeout
) {
data[timeoutInputIndex].options[5] = values.timeout
}
}
// function handleTimeoutCustomOption(
// data: FormFieldProps[],
// values: Partial<FormPublishData>
// ) {
// const timeoutFieldContent = data.filter(
// (field) => field.name === 'timeout'
// )[0]
// const timeoutInputIndex = data.findIndex(
// (element) => element.name === 'timeout'
// )
// if (
// data[timeoutInputIndex].options.length < 6 &&
// !checkIfTimeoutInPredefinedValues(
// values.timeout,
// timeoutFieldContent.options
// )
// ) {
// data[timeoutInputIndex].options.push(values.timeout)
// } else if (
// data[timeoutInputIndex].options.length === 6 &&
// checkIfTimeoutInPredefinedValues(
// values.timeout,
// timeoutFieldContent.options
// )
// ) {
// data[timeoutInputIndex].options.pop()
// } else if (
// data[timeoutInputIndex].options.length === 6 &&
// data[timeoutInputIndex].options[5] !== values.timeout
// ) {
// data[timeoutInputIndex].options[5] = values.timeout
// }
// }
export default function FormEditMetadata({
data,
setShowEdit,
@ -73,18 +73,18 @@ export default function FormEditMetadata({
// This component is handled by Formik so it's not rendered like a "normal" react component,
// so handleTimeoutCustomOption is called only once.
// https://github.com/oceanprotocol/market/pull/324#discussion_r561132310
if (data && values) handleTimeoutCustomOption(data, values)
// if (data && values) handleTimeoutCustomOption(data, values)
const timeoutOptionsArray = data.filter(
(field) => field.name === 'timeout'
)[0].options
if (isComputeDataset && timeoutOptionsArray.includes('Forever')) {
const foreverOptionIndex = timeoutOptionsArray.indexOf('Forever')
timeoutOptionsArray.splice(foreverOptionIndex, 1)
} else if (!isComputeDataset && !timeoutOptionsArray.includes('Forever')) {
timeoutOptionsArray.push('Forever')
}
// if (isComputeDataset && timeoutOptionsArray.includes('Forever')) {
// const foreverOptionIndex = timeoutOptionsArray.indexOf('Forever')
// timeoutOptionsArray.splice(foreverOptionIndex, 1)
// } else if (!isComputeDataset && !timeoutOptionsArray.includes('Forever')) {
// timeoutOptionsArray.push('Forever')
// }
return (
<Form className={styles.form}>
@ -108,10 +108,10 @@ export default function FormEditMetadata({
)
)}
<FormActions
{/* <FormActions
setShowEdit={setShowEdit}
handleClick={() => setTimeoutStringValue(values.timeout)}
/>
/> */}
</Form>
)
}

View File

@ -22,7 +22,6 @@ export function getInitialValues(
name: metadata.main.name,
description: metadata.additionalInformation.description,
price,
links: metadata.additionalInformation.links,
timeout: secondsToString(timeout),
author: metadata.main.author
}

View File

@ -3,49 +3,18 @@ import React, { ReactElement, useState } from 'react'
import { validationSchema, getInitialValues } from './_constants'
import { useAsset } from '@context/Asset'
import { useUserPreferences } from '@context/UserPreferences'
import Debug from './DebugEditMetadata'
// import Debug from './DebugEditMetadata'
import Web3Feedback from '@shared/Web3Feedback'
import FormEditMetadata from './FormEditMetadata'
import { mapTimeoutStringToSeconds } from '@utils/metadata'
import styles from './index.module.css'
import { Logger } from '@oceanprotocol/lib'
import { graphql, useStaticQuery } from 'gatsby'
import { useWeb3 } from '@context/Web3'
import { useOcean } from '@context/Ocean'
import { setMinterToDispenser, setMinterToPublisher } from '@utils/freePrice'
import { MetadataPreview } from '../../../Publish/MetadataPreview'
import MetadataFeedback from '../../../Publish/MetadataFeedback'
const contentQuery = graphql`
query EditMetadataQuery {
content: allFile(filter: { relativePath: { eq: "pages/edit.json" } }) {
edges {
node {
childPagesJson {
description
form {
success
successAction
error
data {
name
placeholder
label
help
type
min
required
sortOptions
options
rows
}
}
}
}
}
}
}
`
import content from '../../../../../content/pages/edit.json'
export default function Edit({
setShowEdit,
@ -54,9 +23,6 @@ export default function Edit({
setShowEdit: (show: boolean) => void
isComputeType?: boolean
}): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childPagesJson
const { debug } = useUserPreferences()
const { accountId } = useWeb3()
const { ocean } = useOcean()
@ -190,21 +156,21 @@ export default function Edit({
<>
<p className={styles.description}>{content.description}</p>
<article className={styles.grid}>
<FormEditMetadata
{/* <FormEditMetadata
data={content.form.data}
setShowEdit={setShowEdit}
setTimeoutStringValue={setTimeoutStringValue}
values={initialValues}
// values={initialValues}
showPrice={price.type === 'exchange'}
isComputeDataset={isComputeType}
/>
/> */}
<aside>
<MetadataPreview values={values} />
{/* <MetadataPreview values={values} /> */}
<Web3Feedback />
</aside>
{debug === true && <Debug values={values} ddo={ddo} />}
{/* {debug === true && <Debug values={values} ddo={ddo} />} */}
</article>
</>
)

View File

@ -1,33 +1,11 @@
import { FormikContextType, useFormikContext } from 'formik'
import { graphql, useStaticQuery } from 'gatsby'
import React, { ReactElement, useEffect, useState } from 'react'
import { FormAddLiquidity } from '.'
import FormHelp from '@shared/Form/Input/Help'
import Token from '../Token'
import styles from './Output.module.css'
import Decimal from 'decimal.js'
const contentQuery = graphql`
query PoolAddOutputQuery {
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
edges {
node {
childContentJson {
pool {
add {
output {
help
titleIn
titleOut
}
}
}
}
}
}
}
}
`
import content from '../../../../../../content/price.json'
export default function Output({
newPoolTokens,
@ -46,9 +24,7 @@ export default function Output({
totalBalance: PoolBalance
coin: string
}): ReactElement {
const data = useStaticQuery(contentQuery)
const { help, titleIn, titleOut } =
data.content.edges[0].node.childContentJson.pool.add.output
const { help, titleIn, titleOut } = content.pool.add.output
// Connect with form
const { values }: FormikContextType<FormAddLiquidity> = useFormikContext()

View File

@ -2,7 +2,6 @@ import React, { ReactElement, useState, useEffect } from 'react'
import Header from '../Header'
import { toast } from 'react-toastify'
import Actions from '../Actions'
import { graphql, useStaticQuery } from 'gatsby'
import * as Yup from 'yup'
import { Formik } from 'formik'
import FormAdd from './FormAdd'
@ -14,26 +13,7 @@ import DebugOutput from '@shared/DebugOutput'
import { useOcean } from '@context/Ocean'
import { useWeb3 } from '@context/Web3'
import { useAsset } from '@context/Asset'
const contentQuery = graphql`
query PoolAddQuery {
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
edges {
node {
childContentJson {
pool {
add {
title
action
warning
}
}
}
}
}
}
}
`
import content from '../../../../../../content/price.json'
export interface FormAddLiquidity {
amount: number
@ -62,9 +42,6 @@ export default function Add({
dtSymbol: string
dtAddress: string
}): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childContentJson.pool.add
const { accountId, balance } = useWeb3()
const { ocean } = useOcean()
const { isAssetNetwork } = useAsset()
@ -147,7 +124,10 @@ export default function Add({
return (
<>
<Header title={content.title} backAction={() => setShowAdd(false)} />
<Header
title={content.pool.add.title}
backAction={() => setShowAdd(false)}
/>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
@ -174,10 +154,10 @@ export default function Add({
setNewPoolShare={setNewPoolShare}
/>
) : (
content.warning && (
content.pool.add.warning && (
<Alert
className={styles.warning}
text={content.warning.toString()}
text={content.pool.add.warning.toString()}
state="info"
action={{
name: 'I understand',
@ -209,7 +189,7 @@ export default function Add({
isLoading={isSubmitting}
loaderMessage="Adding Liquidity..."
successMessage="Successfully added liquidity."
actionName={content.action}
actionName={content.pool.add.action}
action={submitForm}
amount={amount}
coin={coin}

View File

@ -15,7 +15,6 @@ import Token from './Token'
import FormHelp from '@shared/Form/Input/Help'
import Button from '@shared/atoms/Button'
import { getMaxPercentRemove } from './utils'
import { graphql, useStaticQuery } from 'gatsby'
import debounce from 'lodash.debounce'
import UserLiquidity from '../UserLiquidity'
import InputElement from '@shared/Form/Input/InputElement'
@ -23,31 +22,7 @@ import { useOcean } from '@context/Ocean'
import { useWeb3 } from '@context/Web3'
import Decimal from 'decimal.js'
import { useAsset } from '@context/Asset'
const contentQuery = graphql`
query PoolRemoveQuery {
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
edges {
node {
childContentJson {
pool {
remove {
title
simple
advanced
output {
titleIn
titleOut
}
action
}
}
}
}
}
}
}
`
import content from '../../../../../content/price.json'
export default function Remove({
setShowRemove,
@ -64,9 +39,6 @@ export default function Remove({
totalPoolTokens: string
dtSymbol: string
}): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childContentJson.pool.remove
const slippagePresets = ['5', '10', '15', '25', '50']
const { accountId } = useWeb3()
const { ocean } = useOcean()
@ -222,7 +194,10 @@ export default function Remove({
return (
<div className={styles.remove}>
<Header title={content.title} backAction={() => setShowRemove(false)} />
<Header
title={content.pool.remove.title}
backAction={() => setShowRemove(false)}
/>
<form className={styles.removeInput}>
<UserLiquidity amount={poolTokens} symbol="pool shares" />
@ -249,7 +224,9 @@ export default function Remove({
</div>
<FormHelp>
{isAdvanced === true ? content.advanced : content.simple}
{isAdvanced === true
? content.pool.remove.advanced
: content.pool.remove.simple}
</FormHelp>
<Button
style="text"
@ -264,11 +241,11 @@ export default function Remove({
</form>
<div className={styles.output}>
<div>
<p>{content.output.titleIn}</p>
<p>{content.pool.remove.output.titleIn}</p>
<Token symbol="pool shares" balance={amountPoolShares} noIcon />
</div>
<div>
<p>{content.output.titleOut} minimum</p>
<p>{content.pool.remove.output.titleOut} minimum</p>
{isAdvanced === true ? (
<>
<Token symbol="OCEAN" balance={minOceanAmount} />
@ -296,7 +273,7 @@ export default function Remove({
<Actions
isLoading={isLoading}
loaderMessage="Removing Liquidity..."
actionName={content.action}
actionName={content.pool.remove.action}
action={handleRemoveLiquidity}
successMessage="Successfully removed liquidity."
isDisabled={!isAssetNetwork}

View File

@ -10,7 +10,6 @@ import Tooltip from '@shared/atoms/Tooltip'
import ExplorerLink from '@shared/ExplorerLink'
import Token from './Token'
import TokenList from './TokenList'
import { graphql, useStaticQuery } from 'gatsby'
import AssetActionHistoryTable from '../AssetActionHistoryTable'
import Graph from './Graph'
import { useAsset } from '@context/Asset'
@ -21,29 +20,12 @@ import PoolTransactions from '@shared/PoolTransactions'
import { fetchData, getQueryContext } from '@utils/subgraph'
import { isValidNumber } from '@utils/numbers'
import Decimal from 'decimal.js'
import content from '../../../../../content/price.json'
const REFETCH_INTERVAL = 5000
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
const contentQuery = graphql`
query PoolQuery {
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
edges {
node {
childContentJson {
pool {
tooltips {
price
liquidity
}
}
}
}
}
}
}
`
const poolLiquidityQuery = gql`
query PoolLiquidity($id: ID!, $shareId: ID) {
pool(id: $id) {
@ -79,9 +61,6 @@ const userPoolShareQuery = gql`
`
export default function Pool(): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childContentJson.pool
const { accountId } = useWeb3()
const [dtSymbol, setDtSymbol] = useState<string>()
const [oceanSymbol, setOceanSymbol] = useState<string>()
@ -397,7 +376,7 @@ export default function Pool(): ReactElement {
<div className={styles.dataToken}>
<PriceUnit price="1" symbol={dtSymbol} /> ={' '}
<PriceUnit price={`${price?.value}`} symbol={oceanSymbol} />
<Tooltip content={content.tooltips.price} />
<Tooltip content={content.pool.tooltips.price} />
<div className={styles.dataTokenLinks}>
<ExplorerLink
networkId={ddo.chainId}
@ -423,7 +402,7 @@ export default function Pool(): ReactElement {
<>
Your Liquidity
<Tooltip
content={content.tooltips.liquidity.replace(
content={content.pool.tooltips.liquidity.replace(
'SWAPFEE',
swapFee
)}

View File

@ -3,7 +3,6 @@ import { DDO, Logger } from '@oceanprotocol/lib'
import * as Yup from 'yup'
import { Formik } from 'formik'
import Actions from '../Pool/Actions'
import { graphql, useStaticQuery } from 'gatsby'
import { useUserPreferences } from '@context/UserPreferences'
import { toast } from 'react-toastify'
import Swap from './Swap'
@ -15,23 +14,7 @@ import { useWeb3 } from '@context/Web3'
import { useAsset } from '@context/Asset'
import { FormTradeData } from './_types'
import { initialValues } from './_constants'
const contentQuery = graphql`
query TradeQuery {
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
edges {
node {
childContentJson {
trade {
action
warning
}
}
}
}
}
}
`
import content from '../../../../../content/price.json'
export default function FormTrade({
ddo,
@ -46,8 +29,6 @@ export default function FormTrade({
maxOcean: string
price: BestPrice
}): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childContentJson.trade
const { accountId } = useWeb3()
const { ocean } = useOcean()
const { isAssetNetwork } = useAsset()
@ -141,7 +122,7 @@ export default function FormTrade({
) : (
<div className={styles.alertWrap}>
<Alert
text={content.warning}
text={content.trade.warning}
state="info"
action={{
name: 'I understand',
@ -162,7 +143,7 @@ export default function FormTrade({
isLoading={isSubmitting}
loaderMessage="Swapping tokens..."
successMessage="Successfully swapped tokens."
actionName={content.action}
actionName={content.trade.action}
amount={
values.type === 'sell'
? values.datatoken

View File

@ -3,7 +3,7 @@ import { DDO } from '@oceanprotocol/lib'
import styles from './Swap.module.css'
import TradeInput from './TradeInput'
import Button from '@shared/atoms/Button'
import { ReactComponent as Arrow } from '@images/arrow.svg'
import Arrow from '@images/arrow.svg'
import { FormikContextType, useFormikContext } from 'formik'
import { useOcean } from '@context/Ocean'
import Output from './Output'

Some files were not shown because too many files have changed in this diff Show More