diff --git a/README.md b/README.md index 95f1cab2c..3ac3cb273 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ const queryLatest = { offset: 9, query: { // https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html + query_string: { query: `-isInPurgatory:true` } }, sort: { created: -1 } @@ -141,11 +142,7 @@ function Component() { const source = axios.CancelToken.source() async function init() { - const result = await queryMetadata( - query, - appConfig.metadataCacheUri, - source.token - ) + const result = await queryMetadata(query, source.token) setResult(result) } init() diff --git a/package-lock.json b/package-lock.json index b64462b53..538bddd6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@coingecko/cryptoformat": "^0.4.2", "@loadable/component": "^5.15.0", "@oceanprotocol/art": "^3.0.0", - "@oceanprotocol/lib": "^0.16.1", + "@oceanprotocol/lib": "^0.16.2", "@oceanprotocol/typographies": "^0.1.0", "@portis/web3": "^4.0.4", "@sindresorhus/slugify": "^2.1.0", @@ -5439,9 +5439,9 @@ } }, "node_modules/@oceanprotocol/lib": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.1.tgz", - "integrity": "sha512-zSVs1VaC8T+BBo9MeL88odU6wFNRHAptaLPHT6qGf2Nvc8MyhHdP15TdnHpeLJF4Ez0k6WKemnOQ1DNuaW8FlA==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.2.tgz", + "integrity": "sha512-hESsrSjTf/6O4oLrJgBzzTn7EkANtpa+Sl+fp/VXBZ3YvJRbp4instlKJMCqWHi+CA4dYr/uLRmaXeY/PGyx5w==", "dependencies": { "@ethereum-navigator/navigator": "^0.5.3", "@oceanprotocol/contracts": "^0.6.4", @@ -46361,11 +46361,6 @@ "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, "engines": { "node": ">=0.10.0" } @@ -57659,9 +57654,9 @@ } }, "@oceanprotocol/lib": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.1.tgz", - "integrity": "sha512-zSVs1VaC8T+BBo9MeL88odU6wFNRHAptaLPHT6qGf2Nvc8MyhHdP15TdnHpeLJF4Ez0k6WKemnOQ1DNuaW8FlA==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.2.tgz", + "integrity": "sha512-hESsrSjTf/6O4oLrJgBzzTn7EkANtpa+Sl+fp/VXBZ3YvJRbp4instlKJMCqWHi+CA4dYr/uLRmaXeY/PGyx5w==", "requires": { "@ethereum-navigator/navigator": "^0.5.3", "@oceanprotocol/contracts": "^0.6.4", diff --git a/package.json b/package.json index 2d153611d..9ad1cbba3 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@coingecko/cryptoformat": "^0.4.2", "@loadable/component": "^5.15.0", "@oceanprotocol/art": "^3.0.0", - "@oceanprotocol/lib": "^0.16.1", + "@oceanprotocol/lib": "^0.16.2", "@oceanprotocol/typographies": "^0.1.0", "@portis/web3": "^4.0.4", "@sindresorhus/slugify": "^2.1.0", diff --git a/src/components/atoms/AssetType.tsx b/src/components/atoms/AssetType.tsx index 7a3878551..17166fef9 100644 --- a/src/components/atoms/AssetType.tsx +++ b/src/components/atoms/AssetType.tsx @@ -5,21 +5,20 @@ 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 NetworkName from './NetworkName' -import { useOcean } from '../../providers/Ocean' const cx = classNames.bind(styles) export default function AssetType({ type, accessType, - className + className, + chainId }: { type: string accessType: string + chainId: number className?: string }): ReactElement { - const { config } = useOcean() - const styleClasses = cx({ [className]: className }) @@ -37,12 +36,8 @@ export default function AssetType({ {type === 'dataset' ? 'data set' : 'algorithm'} {/* TODO: networkId needs to come from the multinetwork DDO for each asset */} - {(config?.networkId || 1) && ( - + {chainId && ( + )} ) diff --git a/src/components/atoms/ButtonBuy.tsx b/src/components/atoms/ButtonBuy.tsx index 50acd944d..2846589f6 100644 --- a/src/components/atoms/ButtonBuy.tsx +++ b/src/components/atoms/ButtonBuy.tsx @@ -12,6 +12,8 @@ interface ButtonBuyProps { dtBalance: string assetType: string assetTimeout: string + isConsumable: boolean + consumableFeedback: string hasPreviousOrderSelectedComputeAsset?: boolean hasDatatokenSelectedComputeAsset?: boolean dtSymbolSelectedComputeAsset?: string @@ -23,6 +25,7 @@ interface ButtonBuyProps { type?: 'submit' priceType?: string algorithmPriceType?: string + algorithmConsumableStatus?: number } function getConsumeHelpText( @@ -30,13 +33,18 @@ function getConsumeHelpText( dtSymbol: string, hasDatatoken: boolean, hasPreviousOrder: boolean, - assetType: string + assetType: string, + isConsumable: boolean, + consumableFeedback: string ) { - const text = hasPreviousOrder - ? `You bought this ${assetType} already allowing you to use it without paying again.` - : hasDatatoken - ? `You own ${dtBalance} ${dtSymbol} allowing you to use this data set by spending 1 ${dtSymbol}, but without paying OCEAN again.` - : `For using this ${assetType}, you will buy 1 ${dtSymbol} and immediately spend it back to the publisher and pool.` + const text = + isConsumable === false + ? consumableFeedback + : hasPreviousOrder + ? `You bought this ${assetType} already allowing you to use it without paying again.` + : hasDatatoken + ? `You own ${dtBalance} ${dtSymbol} allowing you to use this data set by spending 1 ${dtSymbol}, but without paying OCEAN again.` + : `For using this ${assetType}, you will buy 1 ${dtSymbol} and immediately spend it back to the publisher and pool.` return text } @@ -47,22 +55,34 @@ function getComputeAssetHelpText( dtSymbol: string, dtBalance: string, assetType: string, + isConsumable: boolean, + consumableFeedback: string, hasPreviousOrderSelectedComputeAsset?: boolean, hasDatatokenSelectedComputeAsset?: boolean, dtSymbolSelectedComputeAsset?: string, dtBalanceSelectedComputeAsset?: string, - selectedComputeAssetType?: string + selectedComputeAssetType?: string, + algorithmConsumableStatus?: number ) { const computeAssetHelpText = getConsumeHelpText( dtBalance, dtSymbol, hasDatatoken, hasPreviousOrder, - assetType + assetType, + isConsumable, + consumableFeedback ) const text = - !dtSymbolSelectedComputeAsset && !dtBalanceSelectedComputeAsset + (!dtSymbolSelectedComputeAsset && !dtBalanceSelectedComputeAsset) || + isConsumable === false ? '' + : algorithmConsumableStatus === 1 + ? 'The selected algorithm has been temporarily disabled by the publisher, please try again later.' + : algorithmConsumableStatus === 2 + ? 'Access denied, your wallet address is not found on the selected algorithm allow list.' + : algorithmConsumableStatus === 3 + ? 'Access denied, your wallet address is found on the selected algorithm deny list.' : hasPreviousOrderSelectedComputeAsset ? `You already bought the selected ${selectedComputeAssetType}, allowing you to use it without paying again.` : hasDatatokenSelectedComputeAsset @@ -81,6 +101,8 @@ export default function ButtonBuy({ dtBalance, assetType, assetTimeout, + isConsumable, + consumableFeedback, hasPreviousOrderSelectedComputeAsset, hasDatatokenSelectedComputeAsset, dtSymbolSelectedComputeAsset, @@ -91,7 +113,8 @@ export default function ButtonBuy({ isLoading, type, priceType, - algorithmPriceType + algorithmPriceType, + algorithmConsumableStatus }: ButtonBuyProps): ReactElement { const buttonText = action === 'download' @@ -127,7 +150,9 @@ export default function ButtonBuy({ dtSymbol, hasDatatoken, hasPreviousOrder, - assetType + assetType, + isConsumable, + consumableFeedback ) : getComputeAssetHelpText( hasPreviousOrder, @@ -135,11 +160,14 @@ export default function ButtonBuy({ dtSymbol, dtBalance, assetType, + isConsumable, + consumableFeedback, hasPreviousOrderSelectedComputeAsset, hasDatatokenSelectedComputeAsset, dtSymbolSelectedComputeAsset, dtBalanceSelectedComputeAsset, - selectedComputeAssetType + selectedComputeAssetType, + algorithmConsumableStatus )} diff --git a/src/components/atoms/Input/index.tsx b/src/components/atoms/Input/index.tsx index 0aead33ab..7f4c406e7 100644 --- a/src/components/atoms/Input/index.tsx +++ b/src/components/atoms/Input/index.tsx @@ -27,6 +27,13 @@ export interface InputProps { | ChangeEvent | ChangeEvent ): void + onKeyPress?( + e: + | React.KeyboardEvent + | React.KeyboardEvent + | React.KeyboardEvent + | React.KeyboardEvent + ): void rows?: number multiple?: boolean pattern?: string @@ -42,6 +49,7 @@ export interface InputProps { defaultChecked?: boolean size?: 'mini' | 'small' | 'large' | 'default' className?: string + divClassName?: string } export default function Input(props: Partial): ReactElement { @@ -50,10 +58,13 @@ export default function Input(props: Partial): ReactElement { const hasError = props.form?.touched[field.name] && props.form?.errors[field.name] - const styleClasses = cx({ - field: true, - hasError: hasError - }) + const styleClasses = cx( + { + field: true, + hasError: hasError + }, + props.divClassName + ) return (
= ({ type={type} accessType={accessType} className={styles.typeDetails} + chainId={ddo.chainId} />
diff --git a/src/components/molecules/Bookmarks.tsx b/src/components/molecules/Bookmarks.tsx index 9fbeff3f3..0bd73a8c0 100644 --- a/src/components/molecules/Bookmarks.tsx +++ b/src/components/molecules/Bookmarks.tsx @@ -6,13 +6,16 @@ import { useOcean } from '../../providers/Ocean' import Price from '../atoms/Price' import Tooltip from '../atoms/Tooltip' import AssetTitle from './AssetListTitle' -import { queryMetadata } from '../../utils/aquarius' +import { + queryMetadata, + transformChainIdsListToQuery +} from '../../utils/aquarius' import axios, { CancelToken } from 'axios' import { useSiteMetadata } from '../../hooks/useSiteMetadata' async function getAssetsBookmarked( bookmarks: string[], - metadataCacheUri: string, + chainIds: number[], cancelToken: CancelToken ) { const searchDids = JSON.stringify(bookmarks) @@ -27,7 +30,9 @@ async function getAssetsBookmarked( offset: 100, query: { query_string: { - query: searchDids, + query: `(${searchDids}) AND (${transformChainIdsListToQuery( + chainIds + )})`, fields: ['dataToken'], default_operator: 'OR' } @@ -36,11 +41,7 @@ async function getAssetsBookmarked( } try { - const result = await queryMetadata( - queryBookmarks, - metadataCacheUri, - cancelToken - ) + const result = await queryMetadata(queryBookmarks, cancelToken) return result } catch (error) { @@ -84,6 +85,7 @@ export default function Bookmarks(): ReactElement { const [pinned, setPinned] = useState() const [isLoading, setIsLoading] = useState() + const { chainIds } = useUserPreferences() useEffect(() => { if (!appConfig.metadataCacheUri || bookmarks === []) return @@ -101,7 +103,7 @@ export default function Bookmarks(): ReactElement { try { const resultPinned = await getAssetsBookmarked( bookmarks, - appConfig.metadataCacheUri, + chainIds, source.token ) setPinned(resultPinned?.results) @@ -116,7 +118,7 @@ export default function Bookmarks(): ReactElement { return () => { source.cancel() } - }, [bookmarks, appConfig.metadataCacheUri]) + }, [bookmarks, chainIds]) return ( [...arrayInput, value]) + setArrayInput((arrayInput) => [...arrayInput, value.toLowerCase()]) setValue('') } diff --git a/src/components/molecules/Menu.module.css b/src/components/molecules/Menu.module.css index 88108d3d6..aaca09002 100644 --- a/src/components/molecules/Menu.module.css +++ b/src/components/molecules/Menu.module.css @@ -9,36 +9,76 @@ .logo { white-space: nowrap; display: flex; + flex: 0 0 auto; + flex-direction: row; + justify-content: center; align-items: center; - order: 1; } .navigation { - order: 3; - width: 100%; - margin-top: calc(var(--spacer) / 2); - text-align: center; - border-top: 1px solid var(--border-color); - border-bottom: 1px solid var(--border-color); - margin-left: -1rem; - margin-right: -1rem; - width: calc(100% + 2rem); + width: auto; + margin: 0; + text-align: left; + border: none; +} + +.search { + display: flex; + flex: 1 0 auto; + justify-content: center; + align-items: center; + align-self: flex-start; + padding-left: 20px; + margin-left: auto; } .actions { display: flex; + flex: 0 0 auto; + flex-direction: row; + justify-content: center; + align-items: center; align-self: flex-start; - margin-left: auto; - order: 2; } .title { display: none; } +@media (max-width: 38rem) { + .actions { + margin-left: auto; + } + .navigation { + order: 3; + display: block; + justify-content: center; + align-items: center; + margin-top: calc(var(--spacer) / 2); + text-align: center; + border-top: 1px solid var(--border-color); + border-bottom: 1px solid var(--border-color); + margin-left: -1rem; + margin-right: -1rem; + width: calc(50% + 2rem); + } +} + +@media (max-width: 75rem) { + .navigation { + flex: 1 0 auto; + justify-content: left; + align-items: left; + } + .search { + flex: 0 0 100%; + padding-top: 10px; + order: 4; + } +} + @media screen and (min-width: 42rem) { .navigation { - order: 2; width: auto; margin: 0; text-align: left; diff --git a/src/components/molecules/Menu.tsx b/src/components/molecules/Menu.tsx index d31305882..b6817e8d8 100644 --- a/src/components/molecules/Menu.tsx +++ b/src/components/molecules/Menu.tsx @@ -8,6 +8,7 @@ import UserPreferences from './UserPreferences' import Badge from '../atoms/Badge' import Logo from '../atoms/Logo' import Networks from './UserPreferences/Networks' +import SearchBar from './SearchBar' const Wallet = loadable(() => import('./Wallet')) @@ -51,6 +52,9 @@ export default function Menu(): ReactElement { ))} +
+ +
diff --git a/src/components/molecules/PoolTransactions.tsx b/src/components/molecules/PoolTransactions.tsx index 9d21da5c4..da7d5bd9d 100644 --- a/src/components/molecules/PoolTransactions.tsx +++ b/src/components/molecules/PoolTransactions.tsx @@ -12,6 +12,7 @@ import { gql, useQuery } from 'urql' import web3 from 'web3' import { useWeb3 } from '../../providers/Web3' +import { getOceanConfig } from '../../utils/ocean' const txHistoryQueryByPool = gql` query TransactionHistoryByPool($user: String, $pool: String) { diff --git a/src/components/molecules/SearchBar.module.css b/src/components/molecules/SearchBar.module.css index c40741f52..f7cd67491 100644 --- a/src/components/molecules/SearchBar.module.css +++ b/src/components/molecules/SearchBar.module.css @@ -1,17 +1,49 @@ -.form { - margin-bottom: var(--spacer); - width: 100%; - max-width: 30rem; +.search { + display: flex; + flex: 1 0 auto; + align-self: stretch; +} +.button { + padding: calc(var(--spacer) / 6) calc(var(--spacer) / 3); + cursor: pointer; + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + background-color: var(--background-content); + border-left: none; + white-space: nowrap; + min-width: 4rem; } -.form > div > div { +.button:hover, +.button:focus { + color: var(--brand-white); + text-decoration: none; + transform: translate3d(0, -0.05rem, 0); + box-shadow: 0 12px 30px 0 rgba(0, 0, 0, 0.1); +} + +.input { + height: 36px !important; + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; +} +.searchInput { + flex-grow: 2; + margin-bottom: 0px; +} + +.searchIcon { + fill: var(--brand-grey-light); + transition: 0.2s ease-out; +} +.search > div > div { margin: 0; } -.form label { +.search label { display: none; } -.form input { +.search input { background-color: var(--background-content); } diff --git a/src/components/molecules/SearchBar.stories.tsx b/src/components/molecules/SearchBar.stories.tsx index 31c512a99..d116b926e 100644 --- a/src/components/molecules/SearchBar.stories.tsx +++ b/src/components/molecules/SearchBar.stories.tsx @@ -10,5 +10,3 @@ export default { export const Normal = () => export const WithInitialValue = () => - -export const WithFilters = () => diff --git a/src/components/molecules/SearchBar.tsx b/src/components/molecules/SearchBar.tsx index 1dfb2c4d7..7978ce68e 100644 --- a/src/components/molecules/SearchBar.tsx +++ b/src/components/molecules/SearchBar.tsx @@ -1,24 +1,35 @@ -import React, { useState, ChangeEvent, FormEvent, ReactElement } from 'react' +import React, { + useState, + useEffect, + ChangeEvent, + FormEvent, + ReactElement +} from 'react' import { navigate } from 'gatsby' +import queryString from 'query-string' import styles from './SearchBar.module.css' import Button from '../atoms/Button' import Input from '../atoms/Input' import InputGroup from '../atoms/Input/InputGroup' import { addExistingParamsToUrl } from '../templates/Search/utils' +import { ReactComponent as SearchIcon } from '../../images/search.svg' export default function SearchBar({ placeholder, initialValue, - filters, size }: { placeholder?: string initialValue?: string - filters?: boolean size?: 'small' | 'large' }): ReactElement { let [value, setValue] = useState(initialValue || '') + const parsed = queryString.parse(location.search) + const { text, owner } = parsed + useEffect(() => { + ;(text || owner) && setValue((text || owner) as string) + }, [text, owner]) async function startSearch(e: FormEvent) { e.preventDefault() if (value === '') value = ' ' @@ -50,27 +61,33 @@ export default function SearchBar({ } return ( -
- - - - - - {filters &&
Type, Price
} + }} + /> + ) } diff --git a/src/components/molecules/Wallet/index.module.css b/src/components/molecules/Wallet/index.module.css index 68f94fd0b..2993716bf 100644 --- a/src/components/molecules/Wallet/index.module.css +++ b/src/components/molecules/Wallet/index.module.css @@ -1,3 +1,4 @@ .wallet { display: flex; + align-self: stretch; } diff --git a/src/components/organisms/AssetActions/Compute/FormComputeDataset.tsx b/src/components/organisms/AssetActions/Compute/FormComputeDataset.tsx index 3ce3c24ea..a8faa5334 100644 --- a/src/components/organisms/AssetActions/Compute/FormComputeDataset.tsx +++ b/src/components/organisms/AssetActions/Compute/FormComputeDataset.tsx @@ -9,6 +9,8 @@ import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelectio import ButtonBuy from '../../../atoms/ButtonBuy' import PriceOutput from './PriceOutput' import { useAsset } from '../../../../providers/Asset' +import { useOcean } from '../../../../providers/Ocean' +import { useWeb3 } from '../../../../providers/Web3' const contentQuery = graphql` query StartComputeDatasetQuery { @@ -58,7 +60,9 @@ export default function FormStartCompute({ selectedComputeAssetType, selectedComputeAssetTimeout, stepText, - algorithmPrice + algorithmPrice, + isConsumable, + consumableFeedback }: { algorithms: AssetSelectionAsset[] ddoListAlgorithms: DDO[] @@ -78,6 +82,8 @@ export default function FormStartCompute({ selectedComputeAssetTimeout?: string stepText: string algorithmPrice: BestPrice + isConsumable: boolean + consumableFeedback: string }): ReactElement { const data = useStaticQuery(contentQuery) const content = data.content.edges[0].node.childPagesJson @@ -86,6 +92,10 @@ export default function FormStartCompute({ useFormikContext() const { price, ddo, isAssetNetwork } = useAsset() const [totalPrice, setTotalPrice] = useState(price?.value) + const { accountId } = useWeb3() + const { ocean } = useOcean() + const [algorithmConsumableStatus, setAlgorithmConsumableStatus] = + useState() function getAlgorithmAsset(algorithmId: string): DDO { let assetDdo = null @@ -97,8 +107,19 @@ export default function FormStartCompute({ useEffect(() => { if (!values.algorithm) return - setSelectedAlgorithm(getAlgorithmAsset(values.algorithm)) - }, [values.algorithm]) + const algorithmDDO = getAlgorithmAsset(values.algorithm) + setSelectedAlgorithm(algorithmDDO) + + if (!accountId || !isConsumable) return + async function checkIsConsumable() { + const consumable = await ocean.assets.isConsumable( + algorithmDDO, + accountId.toLowerCase() + ) + if (consumable) setAlgorithmConsumableStatus(consumable.status) + } + checkIsConsumable() + }, [values.algorithm, accountId, isConsumable]) // // Set price for calculation output @@ -149,7 +170,12 @@ export default function FormStartCompute({ 0 + } hasPreviousOrder={hasPreviousOrder} hasDatatoken={hasDatatoken} dtSymbol={ddo.dataTokenInfo.symbol} @@ -168,6 +194,9 @@ export default function FormStartCompute({ type="submit" priceType={price?.type} algorithmPriceType={algorithmPrice?.type} + isConsumable={isConsumable} + consumableFeedback={consumableFeedback} + algorithmConsumableStatus={algorithmConsumableStatus} /> ) diff --git a/src/components/organisms/AssetActions/Compute/index.tsx b/src/components/organisms/AssetActions/Compute/index.tsx index 3f9885db2..1bedd93da 100644 --- a/src/components/organisms/AssetActions/Compute/index.tsx +++ b/src/components/organisms/AssetActions/Compute/index.tsx @@ -38,6 +38,7 @@ import { secondsToString } from '../../../../utils/metadata' import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelection' import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute' import { getPreviousOrders, getPrice } from '../../../../utils/subgraph' +import { chainIds } from '../../../../../app.config' const SuccessAction = () => (