From 261348f883d8e76b5be7155fae65061f049c1e01 Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Wed, 4 Aug 2021 15:21:57 +0300 Subject: [PATCH 01/31] replace history page and route with account --- _redirects | 3 +- content/pages/account.json | 4 +++ content/pages/history.json | 2 -- content/site.json | 4 +-- gatsby-node.js | 12 ++++--- .../organisms/AssetActions/Compute/index.tsx | 2 +- .../History/ComputeJobs/Details.module.css | 2 +- .../History/ComputeJobs/Details.tsx | 18 +++++----- .../History/ComputeJobs/Results.module.css | 0 .../History/ComputeJobs/Results.tsx | 14 ++++---- .../History/ComputeJobs/index.module.css | 0 .../History/ComputeJobs/index.tsx | 26 +++++++------- .../pages/{ => Account}/History/Downloads.tsx | 20 +++++------ .../History/PoolShares.module.css | 0 .../{ => Account}/History/PoolShares.tsx | 20 +++++------ .../{ => Account}/History/PublishedList.tsx | 10 +++--- .../{ => Account}/History/index.module.css | 0 .../pages/{ => Account}/History/index.tsx | 8 ++--- src/components/pages/Account/index.tsx | 23 ++++++++++++ src/pages/account/index.tsx | 35 +++++++++++++++++++ src/pages/history.tsx | 30 ---------------- tests/unit/__fixtures__/siteMetadata.json | 4 +-- 22 files changed, 136 insertions(+), 101 deletions(-) create mode 100644 content/pages/account.json rename src/components/pages/{ => Account}/History/ComputeJobs/Details.module.css (95%) rename src/components/pages/{ => Account}/History/ComputeJobs/Details.tsx (82%) rename src/components/pages/{ => Account}/History/ComputeJobs/Results.module.css (100%) rename src/components/pages/{ => Account}/History/ComputeJobs/Results.tsx (86%) rename src/components/pages/{ => Account}/History/ComputeJobs/index.module.css (100%) rename src/components/pages/{ => Account}/History/ComputeJobs/index.tsx (91%) rename src/components/pages/{ => Account}/History/Downloads.tsx (83%) rename src/components/pages/{ => Account}/History/PoolShares.module.css (100%) rename src/components/pages/{ => Account}/History/PoolShares.tsx (91%) rename src/components/pages/{ => Account}/History/PublishedList.tsx (86%) rename src/components/pages/{ => Account}/History/index.module.css (100%) rename src/components/pages/{ => Account}/History/index.tsx (82%) create mode 100644 src/components/pages/Account/index.tsx create mode 100644 src/pages/account/index.tsx delete mode 100644 src/pages/history.tsx diff --git a/_redirects b/_redirects index 3b85ef2de..b810c2224 100644 --- a/_redirects +++ b/_redirects @@ -1 +1,2 @@ -/asset/* /asset/index.html 200 \ No newline at end of file +/asset/* /asset/index.html 200 +/account/* /account/index.html 200 \ No newline at end of file diff --git a/content/pages/account.json b/content/pages/account.json new file mode 100644 index 000000000..b1d2c8362 --- /dev/null +++ b/content/pages/account.json @@ -0,0 +1,4 @@ +{ + "title": "Account", + "description": "Find the data sets and jobs that you previously accessed." +} diff --git a/content/pages/history.json b/content/pages/history.json index 57df3eb16..8dfbf2a8a 100644 --- a/content/pages/history.json +++ b/content/pages/history.json @@ -1,6 +1,4 @@ { - "title": "History", - "description": "Find the data sets and jobs that you previously accessed.", "compute": { "storage": "Results are stored for 30 days." } diff --git a/content/site.json b/content/site.json index 6b6556de2..84e2ede5c 100644 --- a/content/site.json +++ b/content/site.json @@ -12,8 +12,8 @@ "link": "/publish" }, { - "name": "History", - "link": "/history" + "name": "My Account", + "link": "/account" } ], "warning": { diff --git a/gatsby-node.js b/gatsby-node.js index 86b1e751d..bb9ed6192 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -33,11 +33,15 @@ 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 handleClientSideOnly = page.path.match(/^\/asset/) - - if (handleClientSideOnly) { - page.matchPath = '/asset/*' + const handleClientSideOnlyAsset = page.path.match(/^\/asset/) + const handleClientSideOnlyAccount = page.path.match(/^\/account/) + if (handleClientSideOnlyAsset || handleClientSideOnlyAccount) { + page.matchPath = handleClientSideOnlyAsset + ? '/asset/*' + : handleClientSideOnlyAsset + ? '/account/*' + : '/' // Update the page. createPage(page) } diff --git a/src/components/organisms/AssetActions/Compute/index.tsx b/src/components/organisms/AssetActions/Compute/index.tsx index ec32d2acf..1359763b5 100644 --- a/src/components/organisms/AssetActions/Compute/index.tsx +++ b/src/components/organisms/AssetActions/Compute/index.tsx @@ -41,7 +41,7 @@ import { getPreviousOrders, getPrice } from '../../../../utils/subgraph' import { chainIds } from '../../../../../app.config' const SuccessAction = () => ( - ) diff --git a/src/components/pages/History/ComputeJobs/Details.module.css b/src/components/pages/Account/History/ComputeJobs/Details.module.css similarity index 95% rename from src/components/pages/History/ComputeJobs/Details.module.css rename to src/components/pages/Account/History/ComputeJobs/Details.module.css index 785537c38..53a32197e 100644 --- a/src/components/pages/History/ComputeJobs/Details.module.css +++ b/src/components/pages/Account/History/ComputeJobs/Details.module.css @@ -7,7 +7,7 @@ } .asset { - composes: box from '../../../atoms/Box.module.css'; + composes: box from '../../../../atoms/Box.module.css'; box-shadow: none; padding: calc(var(--spacer) / 2); margin-bottom: calc(var(--spacer) / 2); diff --git a/src/components/pages/History/ComputeJobs/Details.tsx b/src/components/pages/Account/History/ComputeJobs/Details.tsx similarity index 82% rename from src/components/pages/History/ComputeJobs/Details.tsx rename to src/components/pages/Account/History/ComputeJobs/Details.tsx index 1cc5fef97..ace32cf41 100644 --- a/src/components/pages/History/ComputeJobs/Details.tsx +++ b/src/components/pages/Account/History/ComputeJobs/Details.tsx @@ -1,16 +1,16 @@ import React, { ReactElement, useEffect, useState } from 'react' import axios from 'axios' -import { ComputeJobMetaData } from '../../../../@types/ComputeJobMetaData' -import Time from '../../../atoms/Time' -import Button from '../../../atoms/Button' -import Modal from '../../../atoms/Modal' -import MetaItem from '../../../organisms/AssetContent/MetaItem' -import { ReactComponent as External } from '../../../../images/external.svg' -import { retrieveDDO } from '../../../../utils/aquarius' -import { useOcean } from '../../../../providers/Ocean' +import { ComputeJobMetaData } from '../../../../../@types/ComputeJobMetaData' +import Time from '../../../../atoms/Time' +import Button from '../../../../atoms/Button' +import Modal from '../../../../atoms/Modal' +import MetaItem from '../../../../organisms/AssetContent/MetaItem' +import { ReactComponent as External } from '../../../../../images/external.svg' +import { retrieveDDO } from '../../../../../utils/aquarius' +import { useOcean } from '../../../../../providers/Ocean' import Results from './Results' import styles from './Details.module.css' -import { useSiteMetadata } from '../../../../hooks/useSiteMetadata' +import { useSiteMetadata } from '../../../../../hooks/useSiteMetadata' function Asset({ title, diff --git a/src/components/pages/History/ComputeJobs/Results.module.css b/src/components/pages/Account/History/ComputeJobs/Results.module.css similarity index 100% rename from src/components/pages/History/ComputeJobs/Results.module.css rename to src/components/pages/Account/History/ComputeJobs/Results.module.css diff --git a/src/components/pages/History/ComputeJobs/Results.tsx b/src/components/pages/Account/History/ComputeJobs/Results.tsx similarity index 86% rename from src/components/pages/History/ComputeJobs/Results.tsx rename to src/components/pages/Account/History/ComputeJobs/Results.tsx index 7d5f04941..14ae57d43 100644 --- a/src/components/pages/History/ComputeJobs/Results.tsx +++ b/src/components/pages/Account/History/ComputeJobs/Results.tsx @@ -1,17 +1,17 @@ import { Logger } from '@oceanprotocol/lib' import React, { ReactElement, useState } from 'react' -import Loader from '../../../atoms/Loader' -import { ComputeJobMetaData } from '../../../../@types/ComputeJobMetaData' -import { ListItem } from '../../../atoms/Lists' -import Button from '../../../atoms/Button' -import { useOcean } from '../../../../providers/Ocean' +import Loader from '../../../../atoms/Loader' +import { ComputeJobMetaData } from '../../../../../@types/ComputeJobMetaData' +import { ListItem } from '../../../../atoms/Lists' +import Button from '../../../../atoms/Button' +import { useOcean } from '../../../../../providers/Ocean' import styles from './Results.module.css' -import FormHelp from '../../../atoms/Input/Help' +import FormHelp from '../../../../atoms/Input/Help' import { graphql, useStaticQuery } from 'gatsby' export const contentQuery = graphql` query HistoryPageComputeResultsQuery { - content: allFile(filter: { relativePath: { eq: "pages/history.json" } }) { + content: allFile(filter: { relativePath: { eq: "pages/account.json" } }) { edges { node { childPagesJson { diff --git a/src/components/pages/History/ComputeJobs/index.module.css b/src/components/pages/Account/History/ComputeJobs/index.module.css similarity index 100% rename from src/components/pages/History/ComputeJobs/index.module.css rename to src/components/pages/Account/History/ComputeJobs/index.module.css diff --git a/src/components/pages/History/ComputeJobs/index.tsx b/src/components/pages/Account/History/ComputeJobs/index.tsx similarity index 91% rename from src/components/pages/History/ComputeJobs/index.tsx rename to src/components/pages/Account/History/ComputeJobs/index.tsx index 8d3ea9bed..162e81ca8 100644 --- a/src/components/pages/History/ComputeJobs/index.tsx +++ b/src/components/pages/Account/History/ComputeJobs/index.tsx @@ -1,32 +1,32 @@ import React, { ReactElement, useEffect, useState } from 'react' import web3 from 'web3' -import Time from '../../../atoms/Time' +import Time from '../../../../atoms/Time' import { Link } from 'gatsby' import { DDO, Logger, Service, Provider } from '@oceanprotocol/lib' -import { ComputeJobMetaData } from '../../../../@types/ComputeJobMetaData' +import { ComputeJobMetaData } from '../../../../../@types/ComputeJobMetaData' import Dotdotdot from 'react-dotdotdot' -import Table from '../../../atoms/Table' -import Button from '../../../atoms/Button' -import { useOcean } from '../../../../providers/Ocean' +import Table from '../../../../atoms/Table' +import Button from '../../../../atoms/Button' +import { useOcean } from '../../../../../providers/Ocean' import { gql } from 'urql' -import { useWeb3 } from '../../../../providers/Web3' +import { useWeb3 } from '../../../../../providers/Web3' import { queryMetadata, transformChainIdsListToQuery -} from '../../../../utils/aquarius' +} from '../../../../../utils/aquarius' import axios, { CancelToken } from 'axios' import Details from './Details' import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/Compute' -import { ReactComponent as Refresh } from '../../../../images/refresh.svg' +import { ReactComponent as Refresh } from '../../../../../images/refresh.svg' import styles from './index.module.css' -import { useUserPreferences } from '../../../../providers/UserPreferences' -import { getOceanConfig } from '../../../../utils/ocean' -import { fetchDataForMultipleChains } from '../../../../utils/subgraph' +import { useUserPreferences } from '../../../../../providers/UserPreferences' +import { getOceanConfig } from '../../../../../utils/ocean' +import { fetchDataForMultipleChains } from '../../../../../utils/subgraph' import { OrdersData_tokenOrders as OrdersData, OrdersData_tokenOrders_datatokenId as OrdersDatatoken -} from '../../../../@types/apollo/OrdersData' -import NetworkName from '../../../atoms/NetworkName' +} from '../../../../../@types/apollo/OrdersData' +import NetworkName from '../../../../atoms/NetworkName' const getComputeOrders = gql` query ComputeOrders($user: String!) { diff --git a/src/components/pages/History/Downloads.tsx b/src/components/pages/Account/History/Downloads.tsx similarity index 83% rename from src/components/pages/History/Downloads.tsx rename to src/components/pages/Account/History/Downloads.tsx index f12e08f69..33064fb9a 100644 --- a/src/components/pages/History/Downloads.tsx +++ b/src/components/pages/Account/History/Downloads.tsx @@ -1,18 +1,18 @@ import React, { ReactElement, useEffect, useState } from 'react' -import Table from '../../atoms/Table' +import Table from '../../../atoms/Table' import { gql } from 'urql' -import Time from '../../atoms/Time' +import Time from '../../../atoms/Time' import web3 from 'web3' -import AssetTitle from '../../molecules/AssetListTitle' -import { useWeb3 } from '../../../providers/Web3' +import AssetTitle from '../../../molecules/AssetListTitle' +import { useWeb3 } from '../../../../providers/Web3' import axios from 'axios' -import { retrieveDDO } from '../../../utils/aquarius' +import { retrieveDDO } from '../../../../utils/aquarius' import { Logger } from '@oceanprotocol/lib' -import { useSiteMetadata } from '../../../hooks/useSiteMetadata' -import { useUserPreferences } from '../../../providers/UserPreferences' -import { fetchDataForMultipleChains } from '../../../utils/subgraph' -import { OrdersData_tokenOrders as OrdersData } from '../../../@types/apollo/OrdersData' -import NetworkName from '../../atoms/NetworkName' +import { useSiteMetadata } from '../../../../hooks/useSiteMetadata' +import { useUserPreferences } from '../../../../providers/UserPreferences' +import { fetchDataForMultipleChains } from '../../../../utils/subgraph' +import { OrdersData_tokenOrders as OrdersData } from '../../../../@types/apollo/OrdersData' +import NetworkName from '../../../atoms/NetworkName' const getTokenOrders = gql` query OrdersData($user: String!) { diff --git a/src/components/pages/History/PoolShares.module.css b/src/components/pages/Account/History/PoolShares.module.css similarity index 100% rename from src/components/pages/History/PoolShares.module.css rename to src/components/pages/Account/History/PoolShares.module.css diff --git a/src/components/pages/History/PoolShares.tsx b/src/components/pages/Account/History/PoolShares.tsx similarity index 91% rename from src/components/pages/History/PoolShares.tsx rename to src/components/pages/Account/History/PoolShares.tsx index 2413a4318..882657801 100644 --- a/src/components/pages/History/PoolShares.tsx +++ b/src/components/pages/Account/History/PoolShares.tsx @@ -1,22 +1,22 @@ import React, { ReactElement, useEffect, useState } from 'react' -import Table from '../../atoms/Table' -import Conversion from '../../atoms/Price/Conversion' +import Table from '../../../atoms/Table' +import Conversion from '../../../atoms/Price/Conversion' import styles from './PoolShares.module.css' -import AssetTitle from '../../molecules/AssetListTitle' +import AssetTitle from '../../../molecules/AssetListTitle' import { gql } from 'urql' import { PoolShares as PoolSharesList, PoolShares_poolShares as PoolShare, PoolShares_poolShares_poolId_tokens as PoolSharePoolIdTokens -} from '../../../@types/apollo/PoolShares' +} from '../../../../@types/apollo/PoolShares' import web3 from 'web3' -import Token from '../../organisms/AssetActions/Pool/Token' -import { useWeb3 } from '../../../providers/Web3' -import { useUserPreferences } from '../../../providers/UserPreferences' -import { fetchDataForMultipleChains } from '../../../utils/subgraph' -import NetworkName from '../../atoms/NetworkName' +import Token from '../../../organisms/AssetActions/Pool/Token' +import { useWeb3 } from '../../../../providers/Web3' +import { useUserPreferences } from '../../../../providers/UserPreferences' +import { fetchDataForMultipleChains } from '../../../../utils/subgraph' +import NetworkName from '../../../atoms/NetworkName' import axios from 'axios' -import { retrieveDDO } from '../../../utils/aquarius' +import { retrieveDDO } from '../../../../utils/aquarius' const REFETCH_INTERVAL = 20000 diff --git a/src/components/pages/History/PublishedList.tsx b/src/components/pages/Account/History/PublishedList.tsx similarity index 86% rename from src/components/pages/History/PublishedList.tsx rename to src/components/pages/Account/History/PublishedList.tsx index 536f161ad..461697579 100644 --- a/src/components/pages/History/PublishedList.tsx +++ b/src/components/pages/Account/History/PublishedList.tsx @@ -1,15 +1,15 @@ import { Logger } from '@oceanprotocol/lib' import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache' import React, { ReactElement, useEffect, useState } from 'react' -import AssetList from '../../organisms/AssetList' +import AssetList from '../../../organisms/AssetList' import axios from 'axios' import { queryMetadata, transformChainIdsListToQuery -} from '../../../utils/aquarius' -import { useWeb3 } from '../../../providers/Web3' -import { useSiteMetadata } from '../../../hooks/useSiteMetadata' -import { useUserPreferences } from '../../../providers/UserPreferences' +} from '../../../../utils/aquarius' +import { useWeb3 } from '../../../../providers/Web3' +import { useSiteMetadata } from '../../../../hooks/useSiteMetadata' +import { useUserPreferences } from '../../../../providers/UserPreferences' export default function PublishedList(): ReactElement { const { accountId } = useWeb3() diff --git a/src/components/pages/History/index.module.css b/src/components/pages/Account/History/index.module.css similarity index 100% rename from src/components/pages/History/index.module.css rename to src/components/pages/Account/History/index.module.css diff --git a/src/components/pages/History/index.tsx b/src/components/pages/Account/History/index.tsx similarity index 82% rename from src/components/pages/History/index.tsx rename to src/components/pages/Account/History/index.tsx index aa0cfe2b8..34d5b4f7d 100644 --- a/src/components/pages/History/index.tsx +++ b/src/components/pages/Account/History/index.tsx @@ -1,13 +1,13 @@ import React, { ReactElement } from 'react' -import Tabs from '../../atoms/Tabs' +import Tabs from '../../../atoms/Tabs' import PoolShares from './PoolShares' -import PoolTransactions from '../../molecules/PoolTransactions' +import PoolTransactions from '../../../molecules/PoolTransactions' import PublishedList from './PublishedList' import Downloads from './Downloads' import ComputeJobs from './ComputeJobs' import styles from './index.module.css' -import { useUserPreferences } from '../../../providers/UserPreferences' -import OceanProvider from '../../../providers/Ocean' +import { useUserPreferences } from '../../../../providers/UserPreferences' +import OceanProvider from '../../../../providers/Ocean' const tabs = [ { diff --git a/src/components/pages/Account/index.tsx b/src/components/pages/Account/index.tsx new file mode 100644 index 000000000..9faf8affb --- /dev/null +++ b/src/components/pages/Account/index.tsx @@ -0,0 +1,23 @@ +import React, { ReactElement } from 'react' +import HistoryPage from './History' +import { useWeb3 } from '../../../providers/Web3' + +export default function AccountPage({ + accountIdentifier +}: { + accountIdentifier: ReactElement | string +}): ReactElement { + const { accountId } = useWeb3() + if (!accountIdentifier) accountIdentifier = accountId + + return ( +
+ {accountIdentifier ? ( +

WIP Account metadata header for user: {accountIdentifier}

+ ) : ( +

Please connect your Web3 wallet.

+ )} + +
+ ) +} diff --git a/src/pages/account/index.tsx b/src/pages/account/index.tsx new file mode 100644 index 000000000..f7c1fe9da --- /dev/null +++ b/src/pages/account/index.tsx @@ -0,0 +1,35 @@ +import React, { ReactElement, useState, useEffect } from 'react' +import Page from '../../components/templates/Page' +import { graphql, PageProps } from 'gatsby' +import AccountPage from '../../components/pages/Account' + +export default function PageGatsbyAccount(props: PageProps): ReactElement { + const content = (props.data as any).content.edges[0].node.childPagesJson + const { title } = content + const [accountId, setAccountId] = useState() + + useEffect(() => { + setAccountId(props.location.pathname.split('/')[2]) + }, [props.location.pathname]) + + return ( + + + + ) +} + +export const contentQuery = graphql` + query AccountPageQuery { + content: allFile(filter: { relativePath: { eq: "pages/account.json" } }) { + edges { + node { + childPagesJson { + title + description + } + } + } + } + } +` diff --git a/src/pages/history.tsx b/src/pages/history.tsx deleted file mode 100644 index bd9896014..000000000 --- a/src/pages/history.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React, { ReactElement } from 'react' -import PageHistory from '../components/pages/History' -import Page from '../components/templates/Page' -import { graphql, PageProps } from 'gatsby' - -export default function PageGatsbyHistory(props: PageProps): ReactElement { - const content = (props.data as any).content.edges[0].node.childPagesJson - const { title, description } = content - - return ( - - - - ) -} - -export const contentQuery = graphql` - query HistoryPageQuery { - content: allFile(filter: { relativePath: { eq: "pages/history.json" } }) { - edges { - node { - childPagesJson { - title - description - } - } - } - } - } -` diff --git a/tests/unit/__fixtures__/siteMetadata.json b/tests/unit/__fixtures__/siteMetadata.json index 37d545223..fba721a67 100644 --- a/tests/unit/__fixtures__/siteMetadata.json +++ b/tests/unit/__fixtures__/siteMetadata.json @@ -23,8 +23,8 @@ "link": "/publish" }, { - "name": "History", - "link": "/history" + "name": "Account", + "link": "/account" } ] } From 86a8c3b374bd6d433a394f0207380f23b6438ddf Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Wed, 4 Aug 2021 15:55:27 +0300 Subject: [PATCH 02/31] fixed import error for compute jobs --- gatsby-node.js | 11 +++++------ .../organisms/AssetActions/Compute/index.tsx | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index bb9ed6192..cc88386ba 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -36,14 +36,13 @@ exports.onCreatePage = async ({ page, actions }) => { const handleClientSideOnlyAsset = page.path.match(/^\/asset/) const handleClientSideOnlyAccount = page.path.match(/^\/account/) - if (handleClientSideOnlyAsset || handleClientSideOnlyAccount) { - page.matchPath = handleClientSideOnlyAsset - ? '/asset/*' - : handleClientSideOnlyAsset - ? '/account/*' - : '/' + if (handleClientSideOnlyAsset) { + page.matchPath = '/asset/*' // Update the page. createPage(page) + } else if (handleClientSideOnlyAccount) { + page.matchPath = '/account/*' + createPage(page) } } diff --git a/src/components/organisms/AssetActions/Compute/index.tsx b/src/components/organisms/AssetActions/Compute/index.tsx index c2a47a7aa..d4c669650 100644 --- a/src/components/organisms/AssetActions/Compute/index.tsx +++ b/src/components/organisms/AssetActions/Compute/index.tsx @@ -39,7 +39,7 @@ import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelectio import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute' import { getPreviousOrders, getPrice } from '../../../../utils/subgraph' import AssetActionHistoryTable from '../../AssetActionHistoryTable' -import ComputeJobs from '../../../pages/History/ComputeJobs' +import ComputeJobs from '../../../pages/Account/History/ComputeJobs' const SuccessAction = () => ( ) diff --git a/src/components/pages/Account/index.tsx b/src/components/pages/Account/index.tsx deleted file mode 100644 index 954599e35..000000000 --- a/src/components/pages/Account/index.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React, { ReactElement } from 'react' -import HistoryPage from './History' -import { useWeb3 } from '../../../providers/Web3' - -export default function AccountPage({ - accountIdentifier -}: { - accountIdentifier: string -}): ReactElement { - const { accountId } = useWeb3() - if (!accountIdentifier) accountIdentifier = accountId - - return ( -
- {accountIdentifier ? ( -

WIP Account metadata header for user: {accountIdentifier}

- ) : ( -

Please connect your Web3 wallet.

- )} - -
- ) -} diff --git a/src/components/pages/Profile/Account.module.css b/src/components/pages/Profile/Account.module.css new file mode 100644 index 000000000..678f3c716 --- /dev/null +++ b/src/components/pages/Profile/Account.module.css @@ -0,0 +1,62 @@ +.account { + text-align: center; +} + +.account p { + margin: 0; +} + +@media (min-width: 40rem) { + .account { + text-align: left; + display: grid; + grid-template-columns: 0.2fr 1.8fr; + gap: calc(var(--spacer) / 2); + align-items: center; + } +} + +.imageWrap { + width: 96px; + height: 96px; + border-radius: 50%; + overflow: hidden; + margin-bottom: calc(var(--spacer) / 4); + border: 1px solid var(--border-color); + box-shadow: 0 6px 17px 0 var(--box-shadow-color); +} + +.image { + max-width: unset; +} + +.name { + font-size: var(--font-size-h3); + margin-bottom: calc(var(--spacer) / 8); +} + +.accountId { + display: block; + font-size: var(--font-size-small); + color: var(--color-secondary); + word-wrap: break-word; + white-space: pre-wrap; + padding: 0; + margin: 0; +} + +.explorer { + font-size: var(--font-size-mini); + margin-right: calc(var(--spacer) / 1.5); + display: inline-flex; + align-items: center; +} + +.explorer svg:first-child { + width: var(--font-size-mini); + height: var(--font-size-mini); +} + +.explorer svg:last-child { + margin-left: calc(var(--spacer) / 12); +} diff --git a/src/components/pages/Profile/Account.tsx b/src/components/pages/Profile/Account.tsx new file mode 100644 index 000000000..91bfccb6a --- /dev/null +++ b/src/components/pages/Profile/Account.tsx @@ -0,0 +1,75 @@ +import { toDataUrl } from 'ethereum-blockies' +import React, { ReactElement } from 'react' +import { useUserPreferences } from '../../../providers/UserPreferences' +import { accountTruncate } from '../../../utils/web3' +import ExplorerLink from '../../atoms/ExplorerLink' +import NetworkName from '../../atoms/NetworkName' +import jellyfish from '@oceanprotocol/art/creatures/jellyfish/jellyfish-grid.svg' +import styles from './Account.module.css' +import Copy from '../../atoms/Copy' + +const Blockies = ({ account }: { account: string | undefined }) => { + if (!account) return null + + const blockies = toDataUrl(account) + + return ( + + ) +} + +export default function Account({ + name, + image, + accountId +}: { + name: string + image: string + accountId: string +}): ReactElement { + const { chainIds } = useUserPreferences() + + return ( +
+
+ {image ? ( + + ) : accountId ? ( + + ) : ( + + )} +
+ +
+

{name || accountTruncate(accountId)}

+ + {accountId} + +

+ {accountId && + chainIds.map((value) => ( + + + + ))} +

+
+
+ ) +} diff --git a/src/components/pages/Profile/Header.module.css b/src/components/pages/Profile/Header.module.css new file mode 100644 index 000000000..98bf59bca --- /dev/null +++ b/src/components/pages/Profile/Header.module.css @@ -0,0 +1,54 @@ +.grid { + composes: box from '../../atoms/Box.module.css'; + background: var(--background-body-transparent); + backdrop-filter: blur(3px); + position: relative; +} + +.description { + color: var(--color-secondary); + font-size: var(--font-size-small); + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + margin-top: var(--spacer); +} + +.description p:last-child { + margin-bottom: 0; +} + +@media (min-width: 50rem) { + .grid { + display: grid; + gap: var(--spacer); + /* lazy golden ratio */ + grid-template-columns: 1.618fr 1fr; + } + + .description { + margin-top: calc(var(--spacer) / 2); + -webkit-line-clamp: 7 !important; + } +} + +.publisherLinks { + margin-top: calc(var(--spacer) / 2); + margin-bottom: calc(var(--spacer) / 2); +} + +.more { + font-size: var(--font-size-mini); + margin-left: calc(var(--spacer) / 8); + cursor: pointer; +} + +.meta { + color: var(--color-secondary); + font-size: var(--font-size-mini); + position: absolute; + right: calc(var(--spacer) / 3); + bottom: calc(var(--spacer) / 6); +} diff --git a/src/components/pages/Profile/Header.tsx b/src/components/pages/Profile/Header.tsx new file mode 100644 index 000000000..c697bb387 --- /dev/null +++ b/src/components/pages/Profile/Header.tsx @@ -0,0 +1,109 @@ +import React, { ReactElement, useEffect, useState } from 'react' +import get3BoxProfile from '../../../utils/profile' +import { ProfileLink } from '../../../models/Profile' +import { accountTruncate } from '../../../utils/web3' +import axios from 'axios' +import PublisherLinks from './PublisherLinks' +import Markdown from '../../atoms/Markdown' +import Stats from './Stats' +import Account from './Account' +import styles from './Header.module.css' + +const isDescriptionTextClamped = () => { + const el = document.getElementById('description') + if (el) return el.scrollHeight > el.clientHeight +} + +export default function AccountHeader({ + accountId +}: { + accountId: string +}): ReactElement { + const [image, setImage] = useState() + const [name, setName] = useState(accountTruncate(accountId)) + const [description, setDescription] = useState() + const [links, setLinks] = useState() + const [isShowMore, setIsShowMore] = useState(false) + + const toogleShowMore = () => { + setIsShowMore(!isShowMore) + } + + useEffect(() => { + if (!accountId) { + setName(null) + setDescription(null) + setImage(null) + setLinks([]) + return + } + + const source = axios.CancelToken.source() + + async function getInfoFrom3Box() { + const profile = await get3BoxProfile(accountId, source.token) + if (profile) { + const { name, emoji, description, image, links } = profile + setName(`${emoji || ''} ${name || accountTruncate(accountId)}`) + setDescription(description || null) + setImage(image || null) + setLinks(links || []) + } else { + setName(null) + setDescription(null) + setImage(null) + setLinks([]) + } + } + getInfoFrom3Box() + + return () => { + source.cancel() + } + }, [accountId]) + + return ( +
+
+ + +
+ +
+ + {isDescriptionTextClamped() ? ( + + + Read more on 3box + + + ) : ( + '' + )} + {links?.length > 0 && ( + + )} +
+
+ Profile data from{' '} + + 3Box Hub + +
+
+ ) +} diff --git a/src/components/pages/Account/History/ComputeJobs/Details.module.css b/src/components/pages/Profile/History/ComputeJobs/Details.module.css similarity index 100% rename from src/components/pages/Account/History/ComputeJobs/Details.module.css rename to src/components/pages/Profile/History/ComputeJobs/Details.module.css diff --git a/src/components/pages/Account/History/ComputeJobs/Details.tsx b/src/components/pages/Profile/History/ComputeJobs/Details.tsx similarity index 98% rename from src/components/pages/Account/History/ComputeJobs/Details.tsx rename to src/components/pages/Profile/History/ComputeJobs/Details.tsx index ace32cf41..3620b2f99 100644 --- a/src/components/pages/Account/History/ComputeJobs/Details.tsx +++ b/src/components/pages/Profile/History/ComputeJobs/Details.tsx @@ -7,7 +7,6 @@ import Modal from '../../../../atoms/Modal' import MetaItem from '../../../../organisms/AssetContent/MetaItem' import { ReactComponent as External } from '../../../../../images/external.svg' import { retrieveDDO } from '../../../../../utils/aquarius' -import { useOcean } from '../../../../../providers/Ocean' import Results from './Results' import styles from './Details.module.css' import { useSiteMetadata } from '../../../../../hooks/useSiteMetadata' diff --git a/src/components/pages/Account/History/ComputeJobs/Results.module.css b/src/components/pages/Profile/History/ComputeJobs/Results.module.css similarity index 100% rename from src/components/pages/Account/History/ComputeJobs/Results.module.css rename to src/components/pages/Profile/History/ComputeJobs/Results.module.css diff --git a/src/components/pages/Account/History/ComputeJobs/Results.tsx b/src/components/pages/Profile/History/ComputeJobs/Results.tsx similarity index 100% rename from src/components/pages/Account/History/ComputeJobs/Results.tsx rename to src/components/pages/Profile/History/ComputeJobs/Results.tsx diff --git a/src/components/pages/Account/History/ComputeJobs/index.module.css b/src/components/pages/Profile/History/ComputeJobs/index.module.css similarity index 100% rename from src/components/pages/Account/History/ComputeJobs/index.module.css rename to src/components/pages/Profile/History/ComputeJobs/index.module.css diff --git a/src/components/pages/Account/History/ComputeJobs/index.tsx b/src/components/pages/Profile/History/ComputeJobs/index.tsx similarity index 98% rename from src/components/pages/Account/History/ComputeJobs/index.tsx rename to src/components/pages/Profile/History/ComputeJobs/index.tsx index b3f549f24..5dad65cf0 100644 --- a/src/components/pages/Account/History/ComputeJobs/index.tsx +++ b/src/components/pages/Profile/History/ComputeJobs/index.tsx @@ -22,10 +22,7 @@ import styles from './index.module.css' import { useUserPreferences } from '../../../../../providers/UserPreferences' import { getOceanConfig } from '../../../../../utils/ocean' import { fetchDataForMultipleChains } from '../../../../../utils/subgraph' -import { - OrdersData_tokenOrders as OrdersData, - OrdersData_tokenOrders_datatokenId as OrdersDatatoken -} from '../../../../../@types/apollo/OrdersData' +import { OrdersData_tokenOrders_datatokenId as OrdersDatatoken } from '../../../../../@types/apollo/OrdersData' import NetworkName from '../../../../atoms/NetworkName' const getComputeOrders = gql` diff --git a/src/components/pages/Account/History/Downloads.tsx b/src/components/pages/Profile/History/Downloads.tsx similarity index 98% rename from src/components/pages/Account/History/Downloads.tsx rename to src/components/pages/Profile/History/Downloads.tsx index aa8f5e81c..0d206b631 100644 --- a/src/components/pages/Account/History/Downloads.tsx +++ b/src/components/pages/Profile/History/Downloads.tsx @@ -4,7 +4,6 @@ import { gql } from 'urql' import Time from '../../../atoms/Time' import web3 from 'web3' import AssetTitle from '../../../molecules/AssetListTitle' -import { useWeb3 } from '../../../../providers/Web3' import axios from 'axios' import { retrieveDDO } from '../../../../utils/aquarius' import { Logger } from '@oceanprotocol/lib' diff --git a/src/components/pages/Account/History/PoolShares.module.css b/src/components/pages/Profile/History/PoolShares.module.css similarity index 100% rename from src/components/pages/Account/History/PoolShares.module.css rename to src/components/pages/Profile/History/PoolShares.module.css diff --git a/src/components/pages/Account/History/PoolShares.tsx b/src/components/pages/Profile/History/PoolShares.tsx similarity index 92% rename from src/components/pages/Account/History/PoolShares.tsx rename to src/components/pages/Profile/History/PoolShares.tsx index 39f03db93..de24051d7 100644 --- a/src/components/pages/Account/History/PoolShares.tsx +++ b/src/components/pages/Profile/History/PoolShares.tsx @@ -5,15 +5,16 @@ import styles from './PoolShares.module.css' import AssetTitle from '../../../molecules/AssetListTitle' import { gql } from 'urql' import { - PoolShares as PoolSharesList, PoolShares_poolShares as PoolShare, PoolShares_poolShares_poolId_tokens as PoolSharePoolIdTokens } from '../../../../@types/apollo/PoolShares' import web3 from 'web3' import Token from '../../../organisms/AssetActions/Pool/Token' -import { useWeb3 } from '../../../../providers/Web3' import { useUserPreferences } from '../../../../providers/UserPreferences' -import { fetchDataForMultipleChains } from '../../../../utils/subgraph' +import { + fetchDataForMultipleChains, + calculateUserLiquidity +} from '../../../../utils/subgraph' import NetworkName from '../../../atoms/NetworkName' import axios from 'axios' import { retrieveDDO } from '../../../../utils/aquarius' @@ -59,17 +60,6 @@ interface Asset { createTime: number } -function calculateUserLiquidity(poolShare: PoolShare) { - const ocean = - (poolShare.balance / poolShare.poolId.totalShares) * - poolShare.poolId.oceanReserve - const datatokens = - (poolShare.balance / poolShare.poolId.totalShares) * - poolShare.poolId.datatokenReserve - const totalLiquidity = ocean + datatokens * poolShare.poolId.consumePrice - return totalLiquidity -} - function findValidToken(tokens: PoolSharePoolIdTokens[]) { const symbol = tokens.find((token) => token.tokenId !== null) return symbol.tokenId.symbol diff --git a/src/components/pages/Account/History/PublishedList.tsx b/src/components/pages/Profile/History/PublishedList.tsx similarity index 96% rename from src/components/pages/Account/History/PublishedList.tsx rename to src/components/pages/Profile/History/PublishedList.tsx index c9f4cda3c..da7c42c6a 100644 --- a/src/components/pages/Account/History/PublishedList.tsx +++ b/src/components/pages/Profile/History/PublishedList.tsx @@ -1,6 +1,6 @@ import { Logger } from '@oceanprotocol/lib' import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache' -import React, { ReactElement, useEffect, useState, useReducer } from 'react' +import React, { ReactElement, useEffect, useState } from 'react' import AssetList from '../../../organisms/AssetList' import axios from 'axios' import { diff --git a/src/components/pages/Account/History/index.module.css b/src/components/pages/Profile/History/index.module.css similarity index 98% rename from src/components/pages/Account/History/index.module.css rename to src/components/pages/Profile/History/index.module.css index 7bfacd3ef..75db8b925 100644 --- a/src/components/pages/Account/History/index.module.css +++ b/src/components/pages/Profile/History/index.module.css @@ -16,7 +16,7 @@ } } -.content { +.tabs { margin-top: var(--spacer); background-color: var(--background-body); } diff --git a/src/components/pages/Account/History/index.tsx b/src/components/pages/Profile/History/index.tsx similarity index 83% rename from src/components/pages/Account/History/index.tsx rename to src/components/pages/Profile/History/index.tsx index 2a54e7b98..dc817fb50 100644 --- a/src/components/pages/Account/History/index.tsx +++ b/src/components/pages/Profile/History/index.tsx @@ -5,8 +5,8 @@ import PoolTransactions from '../../../molecules/PoolTransactions' import PublishedList from './PublishedList' import Downloads from './Downloads' import ComputeJobs from './ComputeJobs' +import { useLocation } from '@reach/router' import styles from './index.module.css' -import { useUserPreferences } from '../../../../providers/UserPreferences' import OceanProvider from '../../../../providers/Ocean' import { useWeb3 } from '../../../../providers/Web3' @@ -53,20 +53,17 @@ export default function HistoryPage({ }: { accountIdentifier: string }): ReactElement { - const { chainIds } = useUserPreferences() const { accountId } = useWeb3() - const url = new URL(window.location.href) + const location = useLocation() + + const url = new URL(location.href) const defaultTab = url.searchParams.get('defaultTab') const tabs = getTabs(accountIdentifier, accountId) + let defaultTabIndex = 0 defaultTab === 'ComputeJobs' ? (defaultTabIndex = 4) : (defaultTabIndex = 0) + return ( -
- -
+ ) } diff --git a/src/components/atoms/Publisher/PublisherLinks.module.css b/src/components/pages/Profile/PublisherLinks.module.css similarity index 69% rename from src/components/atoms/Publisher/PublisherLinks.module.css rename to src/components/pages/Profile/PublisherLinks.module.css index fb52e55ef..c24bb9f98 100644 --- a/src/components/atoms/Publisher/PublisherLinks.module.css +++ b/src/components/pages/Profile/PublisherLinks.module.css @@ -1,3 +1,7 @@ +.links { + width: 100%; +} + .links, .links a { font-size: var(--font-size-small); @@ -7,6 +11,7 @@ .links a { margin-left: calc(var(--spacer) / 3); color: inherit; + display: inline-block; } .links a:first-child { @@ -19,5 +24,5 @@ } .linksExternal { - composes: linksExternal from './index.module.css'; + composes: linksExternal from '../../atoms/Publisher/index.module.css'; } diff --git a/src/components/atoms/Publisher/PublisherLinks.tsx b/src/components/pages/Profile/PublisherLinks.tsx similarity index 80% rename from src/components/atoms/Publisher/PublisherLinks.tsx rename to src/components/pages/Profile/PublisherLinks.tsx index 46ec0cba4..40b422a62 100644 --- a/src/components/atoms/Publisher/PublisherLinks.tsx +++ b/src/components/pages/Profile/PublisherLinks.tsx @@ -1,15 +1,25 @@ import React, { ReactElement } from 'react' -import styles from './PublisherLinks.module.css' +import classNames from 'classnames/bind' import { ProfileLink } from '../../../models/Profile' import { ReactComponent as External } from '../../../images/external.svg' +import styles from './PublisherLinks.module.css' + +const cx = classNames.bind(styles) export default function PublisherLinks({ - links + links, + className }: { links: ProfileLink[] + className: string }): ReactElement { + const styleClasses = cx({ + links: true, + [className]: className + }) + return ( -
+
{' — '} {links?.map((link: ProfileLink) => { const href = diff --git a/src/components/pages/Profile/Stats.module.css b/src/components/pages/Profile/Stats.module.css new file mode 100644 index 000000000..8878438c8 --- /dev/null +++ b/src/components/pages/Profile/Stats.module.css @@ -0,0 +1,6 @@ +.stats { + display: grid; + gap: var(--spacer); + grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); + margin-top: calc(var(--spacer) / 2); +} diff --git a/src/components/pages/Profile/Stats.tsx b/src/components/pages/Profile/Stats.tsx new file mode 100644 index 000000000..fd43dccb4 --- /dev/null +++ b/src/components/pages/Profile/Stats.tsx @@ -0,0 +1,103 @@ +import { DDO, Logger } from '@oceanprotocol/lib' +import React, { useEffect, useState } from 'react' +import { ReactElement } from 'react-markdown' +import { useUserPreferences } from '../../../providers/UserPreferences' +import { + getAccountLiquidityInOwnAssets, + getAccountNumberOfOrders, + getAssetsBestPrices, + UserTVL +} from '../../../utils/subgraph' +import Conversion from '../../atoms/Price/Conversion' +import NumberUnit from '../../molecules/NumberUnit' +import styles from './Stats.module.css' +import { + queryMetadata, + transformChainIdsListToQuery +} from '../../../utils/aquarius' +import axios from 'axios' + +export default function Stats({ + accountId +}: { + accountId: string +}): ReactElement { + const { chainIds } = useUserPreferences() + + const [publishedAssets, setPublishedAssets] = useState() + const [numberOfAssets, setNumberOfAssets] = useState(0) + const [sold, setSold] = useState(0) + const [tvl, setTvl] = useState() + + useEffect(() => { + if (!accountId) { + setNumberOfAssets(0) + setSold(0) + setTvl({ price: '0', oceanBalance: '0' }) + return + } + + async function getPublished() { + const queryPublishedAssets = { + query: { + query_string: { + query: `(publicKey.owner:${accountId}) AND (${transformChainIdsListToQuery( + chainIds + )})` + } + } + } + try { + const source = axios.CancelToken.source() + const result = await queryMetadata(queryPublishedAssets, source.token) + setPublishedAssets(result.results) + setNumberOfAssets(result.totalResults) + } catch (error) { + Logger.error(error.message) + } + } + getPublished() + + async function getAccountSoldValue() { + const nrOrders = await getAccountNumberOfOrders(accountId, chainIds) + setSold(nrOrders) + } + getAccountSoldValue() + }, [accountId, chainIds]) + + useEffect(() => { + if (!publishedAssets) return + + async function getAccountTVL() { + try { + const accountPoolAdresses: string[] = [] + const assetsPrices = await getAssetsBestPrices(publishedAssets) + for (const priceInfo of assetsPrices) { + if (priceInfo.price.type === 'pool') { + accountPoolAdresses.push(priceInfo.price.address.toLowerCase()) + } + } + const userTvl: UserTVL = await getAccountLiquidityInOwnAssets( + accountId, + chainIds, + accountPoolAdresses + ) + setTvl(userTvl) + } catch (error) { + Logger.error(error.message) + } + } + getAccountTVL() + }, [publishedAssets]) + + return ( +
+ + + } + /> +
+ ) +} diff --git a/src/components/pages/Profile/index.tsx b/src/components/pages/Profile/index.tsx new file mode 100644 index 000000000..d4eafd450 --- /dev/null +++ b/src/components/pages/Profile/index.tsx @@ -0,0 +1,16 @@ +import React, { ReactElement } from 'react' +import HistoryPage from './History' +import AccountHeader from './Header' + +export default function AccountPage({ + accountId +}: { + accountId: string +}): ReactElement { + return ( + <> + + + + ) +} diff --git a/src/components/templates/Page.tsx b/src/components/templates/Page.tsx index 1672d4dbf..b91717999 100644 --- a/src/components/templates/Page.tsx +++ b/src/components/templates/Page.tsx @@ -5,7 +5,7 @@ import Container from '../atoms/Container' export interface PageProps { children: ReactNode - title: string + title?: string uri: string description?: string noPageHeader?: boolean diff --git a/src/pages/account/index.tsx b/src/pages/account/index.tsx deleted file mode 100644 index f7c1fe9da..000000000 --- a/src/pages/account/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { ReactElement, useState, useEffect } from 'react' -import Page from '../../components/templates/Page' -import { graphql, PageProps } from 'gatsby' -import AccountPage from '../../components/pages/Account' - -export default function PageGatsbyAccount(props: PageProps): ReactElement { - const content = (props.data as any).content.edges[0].node.childPagesJson - const { title } = content - const [accountId, setAccountId] = useState() - - useEffect(() => { - setAccountId(props.location.pathname.split('/')[2]) - }, [props.location.pathname]) - - return ( - - - - ) -} - -export const contentQuery = graphql` - query AccountPageQuery { - content: allFile(filter: { relativePath: { eq: "pages/account.json" } }) { - edges { - node { - childPagesJson { - title - description - } - } - } - } - } -` diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx new file mode 100644 index 000000000..451a639ea --- /dev/null +++ b/src/pages/profile/index.tsx @@ -0,0 +1,39 @@ +import React, { ReactElement, useEffect, useState } from 'react' +import Page from '../../components/templates/Page' +import { graphql, PageProps } from 'gatsby' +import ProfilePage from '../../components/pages/Profile' +import { accountTruncate } from '../../utils/web3' +import { useWeb3 } from '../../providers/Web3' + +export default function PageGatsbyProfile(props: PageProps): ReactElement { + const { accountId } = useWeb3() + const [finalAccountId, setFinalAccountId] = useState() + + // Have accountId in path take over, if not present fall back to web3 + useEffect(() => { + const pathAccountId = props.location.pathname.split('/')[2] + const finalAccountId = pathAccountId || accountId + setFinalAccountId(finalAccountId) + }, [props.location.pathname, accountId]) + + return ( + + + + ) +} + +export const contentQuery = graphql` + query ProfilePageQuery { + content: allFile(filter: { relativePath: { eq: "pages/profile.json" } }) { + edges { + node { + childPagesJson { + title + description + } + } + } + } + } +` diff --git a/src/utils/subgraph.ts b/src/utils/subgraph.ts index 0d11cef74..53c7b16aa 100644 --- a/src/utils/subgraph.ts +++ b/src/utils/subgraph.ts @@ -20,6 +20,15 @@ import { HighestLiquidityAssets_pools as HighestLiquidityAssetsPools, HighestLiquidityAssets as HighestLiquidityGraphAssets } from '../@types/apollo/HighestLiquidityAssets' +import { + PoolShares as PoolSharesList, + PoolShares_poolShares as PoolShare +} from '../@types/apollo/PoolShares' + +export interface UserTVL { + price: string + oceanBalance: string +} export interface PriceList { [key: string]: string @@ -141,6 +150,43 @@ const HighestLiquidityAssets = gql` } ` +const TotalAccountOrders = gql` + query TotalAccountOrders($payer: String) { + tokenOrders(orderBy: id, where: { payer: $payer }) { + id + payer { + id + } + } + } +` +const UserSharesQuery = gql` + query UserSharesQuery($user: String, $pools: [String!]) { + poolShares(where: { userAddress: $user, poolId_in: $pools }) { + id + balance + userAddress { + id + } + poolId { + id + datatokenAddress + valueLocked + tokens { + tokenId { + symbol + } + } + oceanReserve + datatokenReserve + totalShares + consumePrice + spotPrice + createTime + } + } + } +` export function getSubgraphUri(chainId: number): string { const config = getOceanConfig(chainId) return config.subgraphUri @@ -497,3 +543,64 @@ export async function getHighestLiquidityDIDs( .replace(/(did:op:)/g, '0x') return [searchDids, didList.length] } + +export async function getAccountNumberOfOrders( + accountId: string, + chainIds: number[] +): Promise { + const queryVariables = { + payer: accountId.toLowerCase() + } + const results = await fetchDataForMultipleChains( + TotalAccountOrders, + queryVariables, + chainIds + ) + let numberOfOrders = 0 + for (const result of results) { + numberOfOrders += result.tokenOrders.length + } + return numberOfOrders +} + +export function calculateUserLiquidity(poolShare: PoolShare) { + const ocean = + (poolShare.balance / poolShare.poolId.totalShares) * + poolShare.poolId.oceanReserve + const datatokens = + (poolShare.balance / poolShare.poolId.totalShares) * + poolShare.poolId.datatokenReserve + const totalLiquidity = ocean + datatokens * poolShare.poolId.consumePrice + return totalLiquidity +} + +export async function getAccountLiquidityInOwnAssets( + accountId: string, + chainIds: number[], + pools: string[] +): Promise { + const queryVariables = { + user: accountId.toLowerCase(), + pools: pools + } + const results: PoolSharesList[] = await fetchDataForMultipleChains( + UserSharesQuery, + queryVariables, + chainIds + ) + let totalLiquidity = 0 + let totalOceanLiquidity = 0 + for (const result of results) { + for (const poolShare of result.poolShares) { + const userShare = poolShare.balance / poolShare.poolId.totalShares + const userBalance = userShare * poolShare.poolId.oceanReserve + totalOceanLiquidity += userBalance + const poolLiquidity = calculateUserLiquidity(poolShare) + totalLiquidity += poolLiquidity + } + } + return { + price: totalLiquidity.toString(), + oceanBalance: totalOceanLiquidity.toString() + } +} diff --git a/tests/unit/__fixtures__/siteMetadata.json b/tests/unit/__fixtures__/siteMetadata.json index fba721a67..a00cd86a2 100644 --- a/tests/unit/__fixtures__/siteMetadata.json +++ b/tests/unit/__fixtures__/siteMetadata.json @@ -23,8 +23,8 @@ "link": "/publish" }, { - "name": "Account", - "link": "/account" + "name": "Profile", + "link": "/profile" } ] } From b30fcf0c4b02d1214db6293c0297240da1cbe518 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 1 Sep 2021 14:07:28 +0200 Subject: [PATCH 11/31] move Blockies into separate component --- src/components/atoms/Blockies.module.css | 8 +++++++ src/components/atoms/Blockies.tsx | 23 +++++++++++++++++++ .../molecules/Wallet/Account.module.css | 10 +------- src/components/molecules/Wallet/Account.tsx | 18 ++------------- .../pages/Profile/Account.module.css | 6 ++++- src/components/pages/Profile/Account.tsx | 19 ++------------- 6 files changed, 41 insertions(+), 43 deletions(-) create mode 100644 src/components/atoms/Blockies.module.css create mode 100644 src/components/atoms/Blockies.tsx diff --git a/src/components/atoms/Blockies.module.css b/src/components/atoms/Blockies.module.css new file mode 100644 index 000000000..928123b18 --- /dev/null +++ b/src/components/atoms/Blockies.module.css @@ -0,0 +1,8 @@ +.blockies { + width: var(--font-size-large); + height: var(--font-size-large); + border-radius: 50%; + overflow: hidden; + display: inline-block; + vertical-align: middle; +} diff --git a/src/components/atoms/Blockies.tsx b/src/components/atoms/Blockies.tsx new file mode 100644 index 000000000..4a02becbe --- /dev/null +++ b/src/components/atoms/Blockies.tsx @@ -0,0 +1,23 @@ +import { toDataUrl } from 'ethereum-blockies' +import React, { ReactElement } from 'react' +import styles from './Blockies.module.css' + +export default function Blockies({ + accountId, + className +}: { + accountId: string + className?: string +}): ReactElement { + if (!accountId) return null + const blockies = toDataUrl(accountId) + + return ( + + ) +} diff --git a/src/components/molecules/Wallet/Account.module.css b/src/components/molecules/Wallet/Account.module.css index 0a4d0d6be..1dbce49f8 100644 --- a/src/components/molecules/Wallet/Account.module.css +++ b/src/components/molecules/Wallet/Account.module.css @@ -41,20 +41,12 @@ } } -.blockies { - width: var(--font-size-large); - height: var(--font-size-large); - border-radius: 50%; - overflow: hidden; - display: inline-block; - vertical-align: middle; -} - .address { display: none; text-transform: none; border-right: 1px solid var(--border-color); padding-right: calc(var(--spacer) / 3); + padding-left: calc(var(--spacer) / 8); } @media screen and (min-width: 60rem) { diff --git a/src/components/molecules/Wallet/Account.tsx b/src/components/molecules/Wallet/Account.tsx index 7b3be33fc..22c2ad249 100644 --- a/src/components/molecules/Wallet/Account.tsx +++ b/src/components/molecules/Wallet/Account.tsx @@ -1,24 +1,10 @@ -import { toDataUrl } from 'ethereum-blockies' import React, { FormEvent } from 'react' import { ReactComponent as Caret } from '../../../images/caret.svg' import { accountTruncate } from '../../../utils/web3' import Loader from '../../atoms/Loader' import styles from './Account.module.css' import { useWeb3 } from '../../../providers/Web3' - -const Blockies = ({ account }: { account: string | undefined }) => { - if (!account) return null - const blockies = toDataUrl(account) - - return ( - - ) -} +import Blockies from '../../atoms/Blockies' // Forward ref for Tippy.js // eslint-disable-next-line @@ -44,7 +30,7 @@ const Account = React.forwardRef((props, ref: any) => { ref={ref} onClick={(e) => e.preventDefault()} > - + {accountTruncate(accountId)} diff --git a/src/components/pages/Profile/Account.module.css b/src/components/pages/Profile/Account.module.css index 678f3c716..2c58d49ef 100644 --- a/src/components/pages/Profile/Account.module.css +++ b/src/components/pages/Profile/Account.module.css @@ -16,9 +16,13 @@ } } -.imageWrap { +.imageWrap, +.image { width: 96px; height: 96px; +} + +.imageWrap { border-radius: 50%; overflow: hidden; margin-bottom: calc(var(--spacer) / 4); diff --git a/src/components/pages/Profile/Account.tsx b/src/components/pages/Profile/Account.tsx index 91bfccb6a..8c68ac039 100644 --- a/src/components/pages/Profile/Account.tsx +++ b/src/components/pages/Profile/Account.tsx @@ -1,4 +1,3 @@ -import { toDataUrl } from 'ethereum-blockies' import React, { ReactElement } from 'react' import { useUserPreferences } from '../../../providers/UserPreferences' import { accountTruncate } from '../../../utils/web3' @@ -7,21 +6,7 @@ import NetworkName from '../../atoms/NetworkName' import jellyfish from '@oceanprotocol/art/creatures/jellyfish/jellyfish-grid.svg' import styles from './Account.module.css' import Copy from '../../atoms/Copy' - -const Blockies = ({ account }: { account: string | undefined }) => { - if (!account) return null - - const blockies = toDataUrl(account) - - return ( - - ) -} +import Blockies from '../../atoms/Blockies' export default function Account({ name, @@ -40,7 +25,7 @@ export default function Account({ {image ? ( ) : accountId ? ( - + ) : ( Date: Wed, 1 Sep 2021 14:30:55 +0200 Subject: [PATCH 12/31] refactor state, make use of existing Profile model --- src/components/pages/Profile/Account.tsx | 8 +- src/components/pages/Profile/Header.tsx | 97 +++++++++++++----------- src/components/pages/Profile/Stats.tsx | 4 +- src/models/Profile.ts | 2 +- src/utils/profile.ts | 1 - 5 files changed, 60 insertions(+), 52 deletions(-) diff --git a/src/components/pages/Profile/Account.tsx b/src/components/pages/Profile/Account.tsx index 8c68ac039..6928bfe2d 100644 --- a/src/components/pages/Profile/Account.tsx +++ b/src/components/pages/Profile/Account.tsx @@ -38,9 +38,11 @@ export default function Account({

{name || accountTruncate(accountId)}

- - {accountId} - + {accountId && ( + + {accountId} + + )}

{accountId && chainIds.map((value) => ( diff --git a/src/components/pages/Profile/Header.tsx b/src/components/pages/Profile/Header.tsx index c697bb387..59105744e 100644 --- a/src/components/pages/Profile/Header.tsx +++ b/src/components/pages/Profile/Header.tsx @@ -1,6 +1,6 @@ import React, { ReactElement, useEffect, useState } from 'react' import get3BoxProfile from '../../../utils/profile' -import { ProfileLink } from '../../../models/Profile' +import { Profile } from '../../../models/Profile' import { accountTruncate } from '../../../utils/web3' import axios from 'axios' import PublisherLinks from './PublisherLinks' @@ -14,15 +14,36 @@ const isDescriptionTextClamped = () => { if (el) return el.scrollHeight > el.clientHeight } +const clearedProfile: Profile = { + name: null, + image: null, + description: null, + links: null +} + +const Link3Box = ({ accountId, text }: { accountId: string; text: string }) => { + return ( + + {text} + + ) +} + export default function AccountHeader({ accountId }: { accountId: string }): ReactElement { - const [image, setImage] = useState() - const [name, setName] = useState(accountTruncate(accountId)) - const [description, setDescription] = useState() - const [links, setLinks] = useState() + const [profile, setProfile] = useState({ + name: accountTruncate(accountId), + image: null, + description: null, + links: null + }) const [isShowMore, setIsShowMore] = useState(false) const toogleShowMore = () => { @@ -31,28 +52,26 @@ export default function AccountHeader({ useEffect(() => { if (!accountId) { - setName(null) - setDescription(null) - setImage(null) - setLinks([]) + setProfile(clearedProfile) return } const source = axios.CancelToken.source() async function getInfoFrom3Box() { - const profile = await get3BoxProfile(accountId, source.token) - if (profile) { - const { name, emoji, description, image, links } = profile - setName(`${emoji || ''} ${name || accountTruncate(accountId)}`) - setDescription(description || null) - setImage(image || null) - setLinks(links || []) + const profile3Box = await get3BoxProfile(accountId, source.token) + if (profile3Box) { + const { name, emoji, description, image, links } = profile3Box + const newName = `${emoji || ''} ${name || accountTruncate(accountId)}` + const newProfile = { + name: newName, + image, + description, + links + } + setProfile(newProfile) } else { - setName(null) - setDescription(null) - setImage(null) - setLinks([]) + setProfile(clearedProfile) } } getInfoFrom3Box() @@ -65,44 +84,32 @@ export default function AccountHeader({ return (

- +
- + {isDescriptionTextClamped() ? ( - - Read more on 3box - + ) : ( '' )} - {links?.length > 0 && ( - + {profile.links?.length > 0 && ( + )}
- Profile data from{' '} - - 3Box Hub - + Profile data from
) diff --git a/src/components/pages/Profile/Stats.tsx b/src/components/pages/Profile/Stats.tsx index fd43dccb4..ebf25df0d 100644 --- a/src/components/pages/Profile/Stats.tsx +++ b/src/components/pages/Profile/Stats.tsx @@ -92,12 +92,12 @@ export default function Stats({ return (
- - } /> + +
) } diff --git a/src/models/Profile.ts b/src/models/Profile.ts index e1850b445..a653dbb53 100644 --- a/src/models/Profile.ts +++ b/src/models/Profile.ts @@ -4,7 +4,7 @@ export interface ProfileLink { } export interface Profile { - did: string + did?: string name?: string description?: string emoji?: string diff --git a/src/utils/profile.ts b/src/utils/profile.ts index f78d2c71b..c6d760585 100644 --- a/src/utils/profile.ts +++ b/src/utils/profile.ts @@ -1,7 +1,6 @@ import { Profile, ProfileLink, ResponseData3Box } from '../models/Profile' import axios, { AxiosResponse, CancelToken } from 'axios' import jwtDecode from 'jwt-decode' -import { Logger } from '@oceanprotocol/lib' // https://docs.3box.io/api/rest-api const apiUri = 'https://3box.oceanprotocol.com' From e998dc777aeec29dda49fe57c318146164b313b8 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 1 Sep 2021 15:01:39 +0200 Subject: [PATCH 13/31] refactor that huge ComputeJobs index component --- .../Profile/History/ComputeJobs/index.tsx | 246 ++---------------- .../Profile/History/ComputeJobs/utils.ts | 232 +++++++++++++++++ 2 files changed, 254 insertions(+), 224 deletions(-) create mode 100644 src/components/pages/Profile/History/ComputeJobs/utils.ts diff --git a/src/components/pages/Profile/History/ComputeJobs/index.tsx b/src/components/pages/Profile/History/ComputeJobs/index.tsx index 5dad65cf0..77af736cf 100644 --- a/src/components/pages/Profile/History/ComputeJobs/index.tsx +++ b/src/components/pages/Profile/History/ComputeJobs/index.tsx @@ -1,76 +1,20 @@ -import React, { ReactElement, useEffect, useState } from 'react' -import web3 from 'web3' +import React, { ReactElement, useEffect, useState, useCallback } from 'react' import Time from '../../../../atoms/Time' import { Link } from 'gatsby' -import { DDO, Logger, Service, Provider } from '@oceanprotocol/lib' +import { Logger } from '@oceanprotocol/lib' import { ComputeJobMetaData } from '../../../../../@types/ComputeJobMetaData' import Dotdotdot from 'react-dotdotdot' import Table from '../../../../atoms/Table' import Button from '../../../../atoms/Button' import { useOcean } from '../../../../../providers/Ocean' -import { gql } from 'urql' import { useWeb3 } from '../../../../../providers/Web3' -import { - queryMetadata, - transformChainIdsListToQuery -} from '../../../../../utils/aquarius' -import axios, { CancelToken } from 'axios' import Details from './Details' -import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/Compute' import { ReactComponent as Refresh } from '../../../../../images/refresh.svg' -import styles from './index.module.css' import { useUserPreferences } from '../../../../../providers/UserPreferences' import { getOceanConfig } from '../../../../../utils/ocean' -import { fetchDataForMultipleChains } from '../../../../../utils/subgraph' -import { OrdersData_tokenOrders_datatokenId as OrdersDatatoken } from '../../../../../@types/apollo/OrdersData' import NetworkName from '../../../../atoms/NetworkName' - -const getComputeOrders = gql` - query ComputeOrders($user: String!) { - tokenOrders( - orderBy: timestamp - orderDirection: desc - where: { payer: $user } - ) { - id - serviceId - datatokenId { - address - } - tx - timestamp - } - } -` - -const getComputeOrdersByDatatokenAddress = gql` - query ComputeOrdersByDatatokenAddress( - $user: String! - $datatokenAddress: String! - ) { - tokenOrders( - orderBy: timestamp - orderDirection: desc - where: { payer: $user, datatokenId: $datatokenAddress } - ) { - id - serviceId - datatokenId { - address - } - tx - timestamp - } - } -` - -interface TokenOrder { - id: string - serviceId: number - datatokenId: OrdersDatatoken - tx: any | null - timestamp: number -} +import { getComputeJobs } from './utils' +import styles from './index.module.css' export function Status({ children }: { children: string }): ReactElement { return
{children}
@@ -123,28 +67,6 @@ const columns = [ } ] -async function getAssetMetadata( - queryDtList: string, - cancelToken: CancelToken, - chainIds: number[] -): Promise { - const queryDid = { - page: 1, - offset: 100, - query: { - query_string: { - query: `(${queryDtList}) AND (${transformChainIdsListToQuery( - chainIds - )}) AND service.attributes.main.type:dataset AND service.type:compute`, - fields: ['dataToken'] - } - } - } - - const result = await queryMetadata(queryDid, cancelToken) - return result.results -} - export default function ComputeJobs({ minimal, assetDTAddress, @@ -170,161 +92,37 @@ export default function ComputeJobs({ if (ocean === undefined) { initOcean() } - }, [networkId, ocean]) + }, [networkId, ocean, connect]) - async function getJobs() { - if (!accountId) return - setIsLoading(true) - const variables = assetDTAddress - ? { - user: accountId?.toLowerCase(), - datatokenAddress: assetDTAddress.toLowerCase() - } - : { - user: accountId?.toLowerCase() - } - const result = await fetchDataForMultipleChains( - assetDTAddress ? getComputeOrdersByDatatokenAddress : getComputeOrders, - variables, - assetDTAddress ? [chainId] : chainIds - ) - let data: TokenOrder[] = [] - for (let i = 0; i < result.length; i++) { - if (!result[i].tokenOrders) continue - result[i].tokenOrders.forEach((tokenOrder: TokenOrder) => { - data.push(tokenOrder) - }) - } - if (!ocean || !account || !data) { - return - } - data = data.sort((a, b) => b.timestamp - a.timestamp) - const dtList = [] - const computeJobs: ComputeJobMetaData[] = [] - for (let i = 0; i < data.length; i++) { - dtList.push(data[i].datatokenId.address) - } - const queryDtList = JSON.stringify(dtList) - .replace(/,/g, ' ') - .replace(/"/g, '') - .replace(/(\[|\])/g, '') - if (queryDtList === '') { - setJobs([]) + const fetchJobs = useCallback(async () => { + if (!chainIds || !accountId) { setIsLoading(false) return } try { setIsLoading(true) - const source = axios.CancelToken.source() - const assets = await getAssetMetadata(queryDtList, source.token, chainIds) - const providers: Provider[] = [] - const serviceEndpoints: string[] = [] - for (let i = 0; i < data.length; i++) { - try { - const did = web3.utils - .toChecksumAddress(data[i].datatokenId.address) - .replace('0x', 'did:op:') - const ddo = assets.filter((x) => x.id === did)[0] - if (ddo === undefined) continue - const service = ddo.service.filter( - (x: Service) => x.index === data[i].serviceId - )[0] - - if (!service || service.type !== 'compute') continue - const { serviceEndpoint } = service - - const wasProviderQueried = - serviceEndpoints.filter((x) => x === serviceEndpoint).length > 0 - - if (wasProviderQueried) continue - serviceEndpoints.push(serviceEndpoint) - } catch (err) { - Logger.error(err) - } - } - - try { - setIsLoading(true) - for (let i = 0; i < serviceEndpoints.length; i++) { - const instanceConfig = { - config, - web3: config.web3Provider, - logger: Logger, - ocean: ocean - } - const provider = await Provider.getInstance(instanceConfig) - await provider.setBaseUrl(serviceEndpoints[i]) - const hasSameCompute = - providers.filter( - (x) => x.computeAddress === provider.computeAddress - ).length > 0 - if (!hasSameCompute) providers.push(provider) - } - } catch (err) { - Logger.error(err) - } - for (let i = 0; i < providers.length; i++) { - try { - const providerComputeJobs = (await providers[i].computeStatus( - '', - account, - undefined, - undefined, - false - )) as ComputeJob[] - - // means the provider uri is not good, so we ignore it and move on - if (!providerComputeJobs) continue - providerComputeJobs.sort((a, b) => { - if (a.dateCreated > b.dateCreated) { - return -1 - } - if (a.dateCreated < b.dateCreated) { - return 1 - } - return 0 - }) - - for (let j = 0; j < providerComputeJobs.length; j++) { - const job = providerComputeJobs[j] - const did = job.inputDID[0] - const ddo = assets.filter((x) => x.id === did)[0] - - if (!ddo) continue - const serviceMetadata = ddo.service.filter( - (x: Service) => x.type === 'metadata' - )[0] - - const compJob: ComputeJobMetaData = { - ...job, - assetName: serviceMetadata.attributes.main.name, - assetDtSymbol: ddo.dataTokenInfo.symbol, - networkId: ddo.chainId - } - computeJobs.push(compJob) - } - } catch (err) { - Logger.error(err) - } - } - setJobs(computeJobs) + const jobs = await getComputeJobs( + accountId, + assetDTAddress, + chainIds, + chainId, + config, + ocean, + account + ) + setJobs(jobs) } catch (error) { - Logger.log(error.message) + Logger.error(error.message) } finally { setIsLoading(false) } - return true - } + }, [account, accountId, assetDTAddress, chainIds, chainId, config, ocean]) useEffect(() => { - if (!chainIds || !accountId) { - setIsLoading(false) - return - } - getJobs() - }, [ocean, account, chainIds, accountId]) + fetchJobs() + }, [fetchJobs]) return accountId ? ( <> @@ -333,7 +131,7 @@ export default function ComputeJobs({ style="text" size="small" title="Refresh compute jobs" - onClick={() => getJobs()} + onClick={async () => await fetchJobs()} disabled={isLoading} className={styles.refresh} > diff --git a/src/components/pages/Profile/History/ComputeJobs/utils.ts b/src/components/pages/Profile/History/ComputeJobs/utils.ts new file mode 100644 index 000000000..0f65f9011 --- /dev/null +++ b/src/components/pages/Profile/History/ComputeJobs/utils.ts @@ -0,0 +1,232 @@ +import { + DDO, + Service, + Logger, + Provider, + Config, + Ocean, + Account +} from '@oceanprotocol/lib' +import web3 from 'web3' +import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/Compute' +import axios, { CancelToken } from 'axios' +import { gql } from 'urql' +import { ComputeJobMetaData } from '../../../../../@types/ComputeJobMetaData' +import { + transformChainIdsListToQuery, + queryMetadata +} from '../../../../../utils/aquarius' +import { fetchDataForMultipleChains } from '../../../../../utils/subgraph' +import { OrdersData_tokenOrders_datatokenId as OrdersDatatoken } from '../../../../../@types/apollo/OrdersData' + +const getComputeOrders = gql` + query ComputeOrders($user: String!) { + tokenOrders( + orderBy: timestamp + orderDirection: desc + where: { payer: $user } + ) { + id + serviceId + datatokenId { + address + } + tx + timestamp + } + } +` + +const getComputeOrdersByDatatokenAddress = gql` + query ComputeOrdersByDatatokenAddress( + $user: String! + $datatokenAddress: String! + ) { + tokenOrders( + orderBy: timestamp + orderDirection: desc + where: { payer: $user, datatokenId: $datatokenAddress } + ) { + id + serviceId + datatokenId { + address + } + tx + timestamp + } + } +` + +interface TokenOrder { + id: string + serviceId: number + datatokenId: OrdersDatatoken + tx: any | null + timestamp: number +} + +async function getAssetMetadata( + queryDtList: string, + cancelToken: CancelToken, + chainIds: number[] +): Promise { + const queryDid = { + page: 1, + offset: 100, + query: { + query_string: { + query: `(${queryDtList}) AND (${transformChainIdsListToQuery( + chainIds + )}) AND service.attributes.main.type:dataset AND service.type:compute`, + fields: ['dataToken'] + } + } + } + + const result = await queryMetadata(queryDid, cancelToken) + return result.results +} + +export async function getComputeJobs( + accountId: string, + assetDTAddress: string, + chainIds: number[], + chainId: number, + config: Config, + ocean: Ocean, + account: Account +): Promise { + const variables = assetDTAddress + ? { + user: accountId?.toLowerCase(), + datatokenAddress: assetDTAddress.toLowerCase() + } + : { + user: accountId?.toLowerCase() + } + const result = await fetchDataForMultipleChains( + assetDTAddress ? getComputeOrdersByDatatokenAddress : getComputeOrders, + variables, + assetDTAddress ? [chainId] : chainIds + ) + let data: TokenOrder[] = [] + for (let i = 0; i < result.length; i++) { + if (!result[i].tokenOrders) continue + result[i].tokenOrders.forEach((tokenOrder: TokenOrder) => { + data.push(tokenOrder) + }) + } + + if (!ocean || !account || !data) return [] + + data = data.sort((a, b) => b.timestamp - a.timestamp) + const dtList = [] + const computeJobs: ComputeJobMetaData[] = [] + + for (let i = 0; i < data.length; i++) { + dtList.push(data[i].datatokenId.address) + } + const queryDtList = JSON.stringify(dtList) + .replace(/,/g, ' ') + .replace(/"/g, '') + .replace(/(\[|\])/g, '') + + if (queryDtList === '') return [] + + const source = axios.CancelToken.source() + const assets = await getAssetMetadata(queryDtList, source.token, chainIds) + const providers: Provider[] = [] + const serviceEndpoints: string[] = [] + + try { + for (let i = 0; i < data.length; i++) { + try { + const did = web3.utils + .toChecksumAddress(data[i].datatokenId.address) + .replace('0x', 'did:op:') + const ddo = assets.filter((x) => x.id === did)[0] + if (ddo === undefined) continue + + const service = ddo.service.filter( + (x: Service) => x.index === data[i].serviceId + )[0] + + if (!service || service.type !== 'compute') continue + const { serviceEndpoint } = service + + const wasProviderQueried = + serviceEndpoints.filter((x) => x === serviceEndpoint).length > 0 + + if (wasProviderQueried) continue + serviceEndpoints.push(serviceEndpoint) + } catch (err) { + Logger.error(err) + } + } + + for (let i = 0; i < serviceEndpoints.length; i++) { + const instanceConfig = { + config, + web3: config.web3Provider, + logger: Logger, + ocean + } + const provider = await Provider.getInstance(instanceConfig) + await provider.setBaseUrl(serviceEndpoints[i]) + const hasSameCompute = + providers.filter((x) => x.computeAddress === provider.computeAddress) + .length > 0 + if (!hasSameCompute) providers.push(provider) + } + } catch (err) { + Logger.error(err) + } + + for (let i = 0; i < providers.length; i++) { + try { + const providerComputeJobs = (await providers[i].computeStatus( + '', + account, + undefined, + undefined, + false + )) as ComputeJob[] + + // means the provider uri is not good, so we ignore it and move on + if (!providerComputeJobs) continue + providerComputeJobs.sort((a, b) => { + if (a.dateCreated > b.dateCreated) { + return -1 + } + if (a.dateCreated < b.dateCreated) { + return 1 + } + return 0 + }) + + for (let j = 0; j < providerComputeJobs.length; j++) { + const job = providerComputeJobs[j] + const did = job.inputDID[0] + const ddo = assets.filter((x) => x.id === did)[0] + + if (!ddo) continue + const serviceMetadata = ddo.service.filter( + (x: Service) => x.type === 'metadata' + )[0] + + const compJob: ComputeJobMetaData = { + ...job, + assetName: serviceMetadata.attributes.main.name, + assetDtSymbol: ddo.dataTokenInfo.symbol, + networkId: ddo.chainId + } + computeJobs.push(compJob) + } + } catch (err) { + Logger.error(err) + } + } + + return computeJobs +} From e3900e8326d1762cba880a65b7ad57261c8b69ee Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 1 Sep 2021 15:15:25 +0200 Subject: [PATCH 14/31] more ComputeJobs refactor --- .../organisms/AssetActions/Compute/index.tsx | 6 +----- .../pages/Profile/History/ComputeJobs/index.tsx | 17 +++++++---------- .../pages/Profile/History/ComputeJobs/utils.ts | 10 +++++----- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/components/organisms/AssetActions/Compute/index.tsx b/src/components/organisms/AssetActions/Compute/index.tsx index 7984835d7..7d5432523 100644 --- a/src/components/organisms/AssetActions/Compute/index.tsx +++ b/src/components/organisms/AssetActions/Compute/index.tsx @@ -473,11 +473,7 @@ export default function Compute({ {accountId && ( - + )} diff --git a/src/components/pages/Profile/History/ComputeJobs/index.tsx b/src/components/pages/Profile/History/ComputeJobs/index.tsx index 77af736cf..35b2ee211 100644 --- a/src/components/pages/Profile/History/ComputeJobs/index.tsx +++ b/src/components/pages/Profile/History/ComputeJobs/index.tsx @@ -15,6 +15,7 @@ import { getOceanConfig } from '../../../../../utils/ocean' import NetworkName from '../../../../atoms/NetworkName' import { getComputeJobs } from './utils' import styles from './index.module.css' +import { useAsset } from '../../../../../providers/Asset' export function Status({ children }: { children: string }): ReactElement { return
{children}
@@ -68,16 +69,13 @@ const columns = [ ] export default function ComputeJobs({ - minimal, - assetDTAddress, - chainId + minimal }: { minimal?: boolean - assetDTAddress?: string - chainId?: number }): ReactElement { const { ocean, account, config, connect } = useOcean() const { accountId, networkId } = useWeb3() + const { ddo } = useAsset() const [isLoading, setIsLoading] = useState(true) const { chainIds } = useUserPreferences() const [jobs, setJobs] = useState([]) @@ -104,10 +102,9 @@ export default function ComputeJobs({ setIsLoading(true) const jobs = await getComputeJobs( - accountId, - assetDTAddress, + ddo?.dataTokenInfo?.address, chainIds, - chainId, + ddo?.chainId, config, ocean, account @@ -118,7 +115,7 @@ export default function ComputeJobs({ } finally { setIsLoading(false) } - }, [account, accountId, assetDTAddress, chainIds, chainId, config, ocean]) + }, [account, accountId, chainIds, ddo, config, ocean]) useEffect(() => { fetchJobs() @@ -126,7 +123,7 @@ export default function ComputeJobs({ return accountId ? ( <> - {jobs.length <= 0 || minimal || ( + {(jobs?.length || !minimal) && (