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

merged multinetwork into poc-urql

This commit is contained in:
Bogdan Fazakas 2021-07-07 11:08:39 +03:00
commit 4fbac1e2e0
35 changed files with 410 additions and 222 deletions

View File

@ -127,6 +127,7 @@ const queryLatest = {
offset: 9, offset: 9,
query: { query: {
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html // https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
query_string: { query: `-isInPurgatory:true` } query_string: { query: `-isInPurgatory:true` }
}, },
sort: { created: -1 } sort: { created: -1 }
@ -141,11 +142,7 @@ function Component() {
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
async function init() { async function init() {
const result = await queryMetadata( const result = await queryMetadata(query, source.token)
query,
appConfig.metadataCacheUri,
source.token
)
setResult(result) setResult(result)
} }
init() init()

19
package-lock.json generated
View File

@ -13,7 +13,7 @@
"@coingecko/cryptoformat": "^0.4.2", "@coingecko/cryptoformat": "^0.4.2",
"@loadable/component": "^5.15.0", "@loadable/component": "^5.15.0",
"@oceanprotocol/art": "^3.0.0", "@oceanprotocol/art": "^3.0.0",
"@oceanprotocol/lib": "^0.16.1", "@oceanprotocol/lib": "^0.16.2",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.4", "@portis/web3": "^4.0.4",
"@sindresorhus/slugify": "^2.1.0", "@sindresorhus/slugify": "^2.1.0",
@ -5439,9 +5439,9 @@
} }
}, },
"node_modules/@oceanprotocol/lib": { "node_modules/@oceanprotocol/lib": {
"version": "0.16.1", "version": "0.16.2",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.1.tgz", "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.2.tgz",
"integrity": "sha512-zSVs1VaC8T+BBo9MeL88odU6wFNRHAptaLPHT6qGf2Nvc8MyhHdP15TdnHpeLJF4Ez0k6WKemnOQ1DNuaW8FlA==", "integrity": "sha512-hESsrSjTf/6O4oLrJgBzzTn7EkANtpa+Sl+fp/VXBZ3YvJRbp4instlKJMCqWHi+CA4dYr/uLRmaXeY/PGyx5w==",
"dependencies": { "dependencies": {
"@ethereum-navigator/navigator": "^0.5.3", "@ethereum-navigator/navigator": "^0.5.3",
"@oceanprotocol/contracts": "^0.6.4", "@oceanprotocol/contracts": "^0.6.4",
@ -46361,11 +46361,6 @@
"safer-buffer": "^2.0.2", "safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0" "tweetnacl": "~0.14.0"
}, },
"bin": {
"sshpk-conv": "bin/sshpk-conv",
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -57659,9 +57654,9 @@
} }
}, },
"@oceanprotocol/lib": { "@oceanprotocol/lib": {
"version": "0.16.1", "version": "0.16.2",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.1.tgz", "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.16.2.tgz",
"integrity": "sha512-zSVs1VaC8T+BBo9MeL88odU6wFNRHAptaLPHT6qGf2Nvc8MyhHdP15TdnHpeLJF4Ez0k6WKemnOQ1DNuaW8FlA==", "integrity": "sha512-hESsrSjTf/6O4oLrJgBzzTn7EkANtpa+Sl+fp/VXBZ3YvJRbp4instlKJMCqWHi+CA4dYr/uLRmaXeY/PGyx5w==",
"requires": { "requires": {
"@ethereum-navigator/navigator": "^0.5.3", "@ethereum-navigator/navigator": "^0.5.3",
"@oceanprotocol/contracts": "^0.6.4", "@oceanprotocol/contracts": "^0.6.4",

View File

@ -26,7 +26,7 @@
"@coingecko/cryptoformat": "^0.4.2", "@coingecko/cryptoformat": "^0.4.2",
"@loadable/component": "^5.15.0", "@loadable/component": "^5.15.0",
"@oceanprotocol/art": "^3.0.0", "@oceanprotocol/art": "^3.0.0",
"@oceanprotocol/lib": "^0.16.1", "@oceanprotocol/lib": "^0.16.2",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.4", "@portis/web3": "^4.0.4",
"@sindresorhus/slugify": "^2.1.0", "@sindresorhus/slugify": "^2.1.0",

View File

@ -5,21 +5,20 @@ import { ReactComponent as Compute } from '../../images/compute.svg'
import { ReactComponent as Download } from '../../images/download.svg' import { ReactComponent as Download } from '../../images/download.svg'
import { ReactComponent as Lock } from '../../images/lock.svg' import { ReactComponent as Lock } from '../../images/lock.svg'
import NetworkName from './NetworkName' import NetworkName from './NetworkName'
import { useOcean } from '../../providers/Ocean'
const cx = classNames.bind(styles) const cx = classNames.bind(styles)
export default function AssetType({ export default function AssetType({
type, type,
accessType, accessType,
className className,
chainId
}: { }: {
type: string type: string
accessType: string accessType: string
chainId: number
className?: string className?: string
}): ReactElement { }): ReactElement {
const { config } = useOcean()
const styleClasses = cx({ const styleClasses = cx({
[className]: className [className]: className
}) })
@ -37,12 +36,8 @@ export default function AssetType({
{type === 'dataset' ? 'data set' : 'algorithm'} {type === 'dataset' ? 'data set' : 'algorithm'}
</div> </div>
{/* TODO: networkId needs to come from the multinetwork DDO for each asset */} {/* TODO: networkId needs to come from the multinetwork DDO for each asset */}
{(config?.networkId || 1) && ( {chainId && (
<NetworkName <NetworkName networkId={chainId} className={styles.network} minimal />
networkId={config?.networkId || 1}
className={styles.network}
minimal
/>
)} )}
</div> </div>
) )

View File

@ -12,6 +12,8 @@ interface ButtonBuyProps {
dtBalance: string dtBalance: string
assetType: string assetType: string
assetTimeout: string assetTimeout: string
isConsumable: boolean
consumableFeedback: string
hasPreviousOrderSelectedComputeAsset?: boolean hasPreviousOrderSelectedComputeAsset?: boolean
hasDatatokenSelectedComputeAsset?: boolean hasDatatokenSelectedComputeAsset?: boolean
dtSymbolSelectedComputeAsset?: string dtSymbolSelectedComputeAsset?: string
@ -23,6 +25,7 @@ interface ButtonBuyProps {
type?: 'submit' type?: 'submit'
priceType?: string priceType?: string
algorithmPriceType?: string algorithmPriceType?: string
algorithmConsumableStatus?: number
} }
function getConsumeHelpText( function getConsumeHelpText(
@ -30,13 +33,18 @@ function getConsumeHelpText(
dtSymbol: string, dtSymbol: string,
hasDatatoken: boolean, hasDatatoken: boolean,
hasPreviousOrder: boolean, hasPreviousOrder: boolean,
assetType: string assetType: string,
isConsumable: boolean,
consumableFeedback: string
) { ) {
const text = hasPreviousOrder const text =
? `You bought this ${assetType} already allowing you to use it without paying again.` isConsumable === false
: hasDatatoken ? consumableFeedback
? `You own ${dtBalance} ${dtSymbol} allowing you to use this data set by spending 1 ${dtSymbol}, but without paying OCEAN again.` : hasPreviousOrder
: `For using this ${assetType}, you will buy 1 ${dtSymbol} and immediately spend it back to the publisher and pool.` ? `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 return text
} }
@ -47,22 +55,34 @@ function getComputeAssetHelpText(
dtSymbol: string, dtSymbol: string,
dtBalance: string, dtBalance: string,
assetType: string, assetType: string,
isConsumable: boolean,
consumableFeedback: string,
hasPreviousOrderSelectedComputeAsset?: boolean, hasPreviousOrderSelectedComputeAsset?: boolean,
hasDatatokenSelectedComputeAsset?: boolean, hasDatatokenSelectedComputeAsset?: boolean,
dtSymbolSelectedComputeAsset?: string, dtSymbolSelectedComputeAsset?: string,
dtBalanceSelectedComputeAsset?: string, dtBalanceSelectedComputeAsset?: string,
selectedComputeAssetType?: string selectedComputeAssetType?: string,
algorithmConsumableStatus?: number
) { ) {
const computeAssetHelpText = getConsumeHelpText( const computeAssetHelpText = getConsumeHelpText(
dtBalance, dtBalance,
dtSymbol, dtSymbol,
hasDatatoken, hasDatatoken,
hasPreviousOrder, hasPreviousOrder,
assetType assetType,
isConsumable,
consumableFeedback
) )
const text = 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 : hasPreviousOrderSelectedComputeAsset
? `You already bought the selected ${selectedComputeAssetType}, allowing you to use it without paying again.` ? `You already bought the selected ${selectedComputeAssetType}, allowing you to use it without paying again.`
: hasDatatokenSelectedComputeAsset : hasDatatokenSelectedComputeAsset
@ -81,6 +101,8 @@ export default function ButtonBuy({
dtBalance, dtBalance,
assetType, assetType,
assetTimeout, assetTimeout,
isConsumable,
consumableFeedback,
hasPreviousOrderSelectedComputeAsset, hasPreviousOrderSelectedComputeAsset,
hasDatatokenSelectedComputeAsset, hasDatatokenSelectedComputeAsset,
dtSymbolSelectedComputeAsset, dtSymbolSelectedComputeAsset,
@ -91,7 +113,8 @@ export default function ButtonBuy({
isLoading, isLoading,
type, type,
priceType, priceType,
algorithmPriceType algorithmPriceType,
algorithmConsumableStatus
}: ButtonBuyProps): ReactElement { }: ButtonBuyProps): ReactElement {
const buttonText = const buttonText =
action === 'download' action === 'download'
@ -127,7 +150,9 @@ export default function ButtonBuy({
dtSymbol, dtSymbol,
hasDatatoken, hasDatatoken,
hasPreviousOrder, hasPreviousOrder,
assetType assetType,
isConsumable,
consumableFeedback
) )
: getComputeAssetHelpText( : getComputeAssetHelpText(
hasPreviousOrder, hasPreviousOrder,
@ -135,11 +160,14 @@ export default function ButtonBuy({
dtSymbol, dtSymbol,
dtBalance, dtBalance,
assetType, assetType,
isConsumable,
consumableFeedback,
hasPreviousOrderSelectedComputeAsset, hasPreviousOrderSelectedComputeAsset,
hasDatatokenSelectedComputeAsset, hasDatatokenSelectedComputeAsset,
dtSymbolSelectedComputeAsset, dtSymbolSelectedComputeAsset,
dtBalanceSelectedComputeAsset, dtBalanceSelectedComputeAsset,
selectedComputeAssetType selectedComputeAssetType,
algorithmConsumableStatus
)} )}
</div> </div>
</> </>

View File

@ -27,6 +27,13 @@ export interface InputProps {
| ChangeEvent<HTMLSelectElement> | ChangeEvent<HTMLSelectElement>
| ChangeEvent<HTMLTextAreaElement> | ChangeEvent<HTMLTextAreaElement>
): void ): void
onKeyPress?(
e:
| React.KeyboardEvent<HTMLInputElement>
| React.KeyboardEvent<HTMLInputElement>
| React.KeyboardEvent<HTMLSelectElement>
| React.KeyboardEvent<HTMLTextAreaElement>
): void
rows?: number rows?: number
multiple?: boolean multiple?: boolean
pattern?: string pattern?: string
@ -42,6 +49,7 @@ export interface InputProps {
defaultChecked?: boolean defaultChecked?: boolean
size?: 'mini' | 'small' | 'large' | 'default' size?: 'mini' | 'small' | 'large' | 'default'
className?: string className?: string
divClassName?: string
} }
export default function Input(props: Partial<InputProps>): ReactElement { export default function Input(props: Partial<InputProps>): ReactElement {
@ -50,10 +58,13 @@ export default function Input(props: Partial<InputProps>): ReactElement {
const hasError = const hasError =
props.form?.touched[field.name] && props.form?.errors[field.name] props.form?.touched[field.name] && props.form?.errors[field.name]
const styleClasses = cx({ const styleClasses = cx(
field: true, {
hasError: hasError field: true,
}) hasError: hasError
},
props.divClassName
)
return ( return (
<div <div

View File

@ -30,11 +30,7 @@ export default function AssetListTitle({
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
async function getAssetName() { async function getAssetName() {
const title = await getAssetsNames( const title = await getAssetsNames([did], source.token)
[did],
appConfig.metadataCacheUri,
source.token
)
setAssetTitle(title[did]) setAssetTitle(title[did])
} }

View File

@ -11,7 +11,7 @@ import { useOcean } from '../../providers/Ocean'
import styles from './AssetTeaser.module.css' import styles from './AssetTeaser.module.css'
declare type AssetTeaserProps = { declare type AssetTeaserProps = {
ddo: DDO ddo: any
price: BestPrice price: BestPrice
} }
@ -42,6 +42,7 @@ const AssetTeaser: React.FC<AssetTeaserProps> = ({
type={type} type={type}
accessType={accessType} accessType={accessType}
className={styles.typeDetails} className={styles.typeDetails}
chainId={ddo.chainId}
/> />
<div className={styles.content}> <div className={styles.content}>

View File

@ -6,13 +6,16 @@ import { useOcean } from '../../providers/Ocean'
import Price from '../atoms/Price' import Price from '../atoms/Price'
import Tooltip from '../atoms/Tooltip' import Tooltip from '../atoms/Tooltip'
import AssetTitle from './AssetListTitle' import AssetTitle from './AssetListTitle'
import { queryMetadata } from '../../utils/aquarius' import {
queryMetadata,
transformChainIdsListToQuery
} from '../../utils/aquarius'
import axios, { CancelToken } from 'axios' import axios, { CancelToken } from 'axios'
import { useSiteMetadata } from '../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../hooks/useSiteMetadata'
async function getAssetsBookmarked( async function getAssetsBookmarked(
bookmarks: string[], bookmarks: string[],
metadataCacheUri: string, chainIds: number[],
cancelToken: CancelToken cancelToken: CancelToken
) { ) {
const searchDids = JSON.stringify(bookmarks) const searchDids = JSON.stringify(bookmarks)
@ -27,7 +30,9 @@ async function getAssetsBookmarked(
offset: 100, offset: 100,
query: { query: {
query_string: { query_string: {
query: searchDids, query: `(${searchDids}) AND (${transformChainIdsListToQuery(
chainIds
)})`,
fields: ['dataToken'], fields: ['dataToken'],
default_operator: 'OR' default_operator: 'OR'
} }
@ -36,11 +41,7 @@ async function getAssetsBookmarked(
} }
try { try {
const result = await queryMetadata( const result = await queryMetadata(queryBookmarks, cancelToken)
queryBookmarks,
metadataCacheUri,
cancelToken
)
return result return result
} catch (error) { } catch (error) {
@ -84,6 +85,7 @@ export default function Bookmarks(): ReactElement {
const [pinned, setPinned] = useState<DDO[]>() const [pinned, setPinned] = useState<DDO[]>()
const [isLoading, setIsLoading] = useState<boolean>() const [isLoading, setIsLoading] = useState<boolean>()
const { chainIds } = useUserPreferences()
useEffect(() => { useEffect(() => {
if (!appConfig.metadataCacheUri || bookmarks === []) return if (!appConfig.metadataCacheUri || bookmarks === []) return
@ -101,7 +103,7 @@ export default function Bookmarks(): ReactElement {
try { try {
const resultPinned = await getAssetsBookmarked( const resultPinned = await getAssetsBookmarked(
bookmarks, bookmarks,
appConfig.metadataCacheUri, chainIds,
source.token source.token
) )
setPinned(resultPinned?.results) setPinned(resultPinned?.results)
@ -116,7 +118,7 @@ export default function Bookmarks(): ReactElement {
return () => { return () => {
source.cancel() source.cancel()
} }
}, [bookmarks, appConfig.metadataCacheUri]) }, [bookmarks, chainIds])
return ( return (
<Table <Table

View File

@ -30,11 +30,11 @@ export default function Credentials(props: InputProps) {
toast.error('Wallet address is invalid') toast.error('Wallet address is invalid')
return return
} }
if (arrayInput.includes(value)) { if (arrayInput.includes(value.toLowerCase())) {
toast.error('Wallet address already added into list') toast.error('Wallet address already added into list')
return return
} }
setArrayInput((arrayInput) => [...arrayInput, value]) setArrayInput((arrayInput) => [...arrayInput, value.toLowerCase()])
setValue('') setValue('')
} }

View File

@ -9,36 +9,76 @@
.logo { .logo {
white-space: nowrap; white-space: nowrap;
display: flex; display: flex;
flex: 0 0 auto;
flex-direction: row;
justify-content: center;
align-items: center; align-items: center;
order: 1;
} }
.navigation { .navigation {
order: 3; width: auto;
width: 100%; margin: 0;
margin-top: calc(var(--spacer) / 2); text-align: left;
text-align: center; border: none;
border-top: 1px solid var(--border-color); }
border-bottom: 1px solid var(--border-color);
margin-left: -1rem; .search {
margin-right: -1rem; display: flex;
width: calc(100% + 2rem); flex: 1 0 auto;
justify-content: center;
align-items: center;
align-self: flex-start;
padding-left: 20px;
margin-left: auto;
} }
.actions { .actions {
display: flex; display: flex;
flex: 0 0 auto;
flex-direction: row;
justify-content: center;
align-items: center;
align-self: flex-start; align-self: flex-start;
margin-left: auto;
order: 2;
} }
.title { .title {
display: none; 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) { @media screen and (min-width: 42rem) {
.navigation { .navigation {
order: 2;
width: auto; width: auto;
margin: 0; margin: 0;
text-align: left; text-align: left;

View File

@ -8,6 +8,7 @@ import UserPreferences from './UserPreferences'
import Badge from '../atoms/Badge' import Badge from '../atoms/Badge'
import Logo from '../atoms/Logo' import Logo from '../atoms/Logo'
import Networks from './UserPreferences/Networks' import Networks from './UserPreferences/Networks'
import SearchBar from './SearchBar'
const Wallet = loadable(() => import('./Wallet')) const Wallet = loadable(() => import('./Wallet'))
@ -51,6 +52,9 @@ export default function Menu(): ReactElement {
))} ))}
</ul> </ul>
<div className={styles.search}>
<SearchBar />
</div>
<div className={styles.actions}> <div className={styles.actions}>
<Networks /> <Networks />
<Wallet /> <Wallet />

View File

@ -12,6 +12,7 @@ import { gql, useQuery } from 'urql'
import web3 from 'web3' import web3 from 'web3'
import { useWeb3 } from '../../providers/Web3' import { useWeb3 } from '../../providers/Web3'
import { getOceanConfig } from '../../utils/ocean'
const txHistoryQueryByPool = gql` const txHistoryQueryByPool = gql`
query TransactionHistoryByPool($user: String, $pool: String) { query TransactionHistoryByPool($user: String, $pool: String) {

View File

@ -1,17 +1,49 @@
.form { .search {
margin-bottom: var(--spacer); display: flex;
width: 100%; flex: 1 0 auto;
max-width: 30rem; 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; margin: 0;
} }
.form label { .search label {
display: none; display: none;
} }
.form input { .search input {
background-color: var(--background-content); background-color: var(--background-content);
} }

View File

@ -10,5 +10,3 @@ export default {
export const Normal = () => <SearchBar /> export const Normal = () => <SearchBar />
export const WithInitialValue = () => <SearchBar initialValue="Water" /> export const WithInitialValue = () => <SearchBar initialValue="Water" />
export const WithFilters = () => <SearchBar filters />

View File

@ -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 { navigate } from 'gatsby'
import queryString from 'query-string'
import styles from './SearchBar.module.css' import styles from './SearchBar.module.css'
import Button from '../atoms/Button' import Button from '../atoms/Button'
import Input from '../atoms/Input' import Input from '../atoms/Input'
import InputGroup from '../atoms/Input/InputGroup' import InputGroup from '../atoms/Input/InputGroup'
import { addExistingParamsToUrl } from '../templates/Search/utils' import { addExistingParamsToUrl } from '../templates/Search/utils'
import { ReactComponent as SearchIcon } from '../../images/search.svg'
export default function SearchBar({ export default function SearchBar({
placeholder, placeholder,
initialValue, initialValue,
filters,
size size
}: { }: {
placeholder?: string placeholder?: string
initialValue?: string initialValue?: string
filters?: boolean
size?: 'small' | 'large' size?: 'small' | 'large'
}): ReactElement { }): ReactElement {
let [value, setValue] = useState(initialValue || '') 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<HTMLButtonElement>) { async function startSearch(e: FormEvent<HTMLButtonElement>) {
e.preventDefault() e.preventDefault()
if (value === '') value = ' ' if (value === '') value = ' '
@ -50,27 +61,33 @@ export default function SearchBar({
} }
return ( return (
<form className={styles.form}> <form className={styles.search}>
<InputGroup> <Input
<Input type="search"
type="search" name="search"
name="search" placeholder={placeholder || 'What are you looking for?'}
placeholder={placeholder || 'What are you looking for?'} value={value}
value={value} onChange={handleChange}
onChange={handleChange} required
required size="small"
size={size} divClassName={styles.searchInput}
/> className={styles.input}
<Button onKeyPress={async (e: React.KeyboardEvent<HTMLInputElement>) => {
onClick={async (e: FormEvent<HTMLButtonElement>) => if (e.key === 'Enter') {
await startSearch(e) await startSearch(e)
} }
> }}
Search />
</Button> <Button
</InputGroup> onClick={async (e: FormEvent<HTMLButtonElement>) =>
await startSearch(e)
{filters && <fieldset className={styles.filters}>Type, Price</fieldset>} }
style="text"
size="small"
className={styles.button}
>
<SearchIcon className={styles.searchIcon} />
</Button>
</form> </form>
) )
} }

View File

@ -1,3 +1,4 @@
.wallet { .wallet {
display: flex; display: flex;
align-self: stretch;
} }

View File

@ -9,6 +9,8 @@ import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelectio
import ButtonBuy from '../../../atoms/ButtonBuy' import ButtonBuy from '../../../atoms/ButtonBuy'
import PriceOutput from './PriceOutput' import PriceOutput from './PriceOutput'
import { useAsset } from '../../../../providers/Asset' import { useAsset } from '../../../../providers/Asset'
import { useOcean } from '../../../../providers/Ocean'
import { useWeb3 } from '../../../../providers/Web3'
const contentQuery = graphql` const contentQuery = graphql`
query StartComputeDatasetQuery { query StartComputeDatasetQuery {
@ -58,7 +60,9 @@ export default function FormStartCompute({
selectedComputeAssetType, selectedComputeAssetType,
selectedComputeAssetTimeout, selectedComputeAssetTimeout,
stepText, stepText,
algorithmPrice algorithmPrice,
isConsumable,
consumableFeedback
}: { }: {
algorithms: AssetSelectionAsset[] algorithms: AssetSelectionAsset[]
ddoListAlgorithms: DDO[] ddoListAlgorithms: DDO[]
@ -78,6 +82,8 @@ export default function FormStartCompute({
selectedComputeAssetTimeout?: string selectedComputeAssetTimeout?: string
stepText: string stepText: string
algorithmPrice: BestPrice algorithmPrice: BestPrice
isConsumable: boolean
consumableFeedback: string
}): ReactElement { }): ReactElement {
const data = useStaticQuery(contentQuery) const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childPagesJson const content = data.content.edges[0].node.childPagesJson
@ -86,6 +92,10 @@ export default function FormStartCompute({
useFormikContext() useFormikContext()
const { price, ddo, isAssetNetwork } = useAsset() const { price, ddo, isAssetNetwork } = useAsset()
const [totalPrice, setTotalPrice] = useState(price?.value) const [totalPrice, setTotalPrice] = useState(price?.value)
const { accountId } = useWeb3()
const { ocean } = useOcean()
const [algorithmConsumableStatus, setAlgorithmConsumableStatus] =
useState<number>()
function getAlgorithmAsset(algorithmId: string): DDO { function getAlgorithmAsset(algorithmId: string): DDO {
let assetDdo = null let assetDdo = null
@ -97,8 +107,19 @@ export default function FormStartCompute({
useEffect(() => { useEffect(() => {
if (!values.algorithm) return if (!values.algorithm) return
setSelectedAlgorithm(getAlgorithmAsset(values.algorithm)) const algorithmDDO = getAlgorithmAsset(values.algorithm)
}, [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 // Set price for calculation output
@ -149,7 +170,12 @@ export default function FormStartCompute({
<ButtonBuy <ButtonBuy
action="compute" action="compute"
disabled={isComputeButtonDisabled || !isValid || !isAssetNetwork} disabled={
isComputeButtonDisabled ||
!isValid ||
!isAssetNetwork ||
algorithmConsumableStatus > 0
}
hasPreviousOrder={hasPreviousOrder} hasPreviousOrder={hasPreviousOrder}
hasDatatoken={hasDatatoken} hasDatatoken={hasDatatoken}
dtSymbol={ddo.dataTokenInfo.symbol} dtSymbol={ddo.dataTokenInfo.symbol}
@ -168,6 +194,9 @@ export default function FormStartCompute({
type="submit" type="submit"
priceType={price?.type} priceType={price?.type}
algorithmPriceType={algorithmPrice?.type} algorithmPriceType={algorithmPrice?.type}
isConsumable={isConsumable}
consumableFeedback={consumableFeedback}
algorithmConsumableStatus={algorithmConsumableStatus}
/> />
</Form> </Form>
) )

View File

@ -38,6 +38,7 @@ import { secondsToString } from '../../../../utils/metadata'
import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelection' import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelection'
import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute' import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute'
import { getPreviousOrders, getPrice } from '../../../../utils/subgraph' import { getPreviousOrders, getPrice } from '../../../../utils/subgraph'
import { chainIds } from '../../../../../app.config'
const SuccessAction = () => ( const SuccessAction = () => (
<Button style="text" to="/history?defaultTab=ComputeJobs" size="small"> <Button style="text" to="/history?defaultTab=ComputeJobs" size="small">
@ -49,12 +50,16 @@ export default function Compute({
isBalanceSufficient, isBalanceSufficient,
dtBalance, dtBalance,
file, file,
fileIsLoading fileIsLoading,
isConsumable,
consumableFeedback
}: { }: {
isBalanceSufficient: boolean isBalanceSufficient: boolean
dtBalance: string dtBalance: string
file: FileMetadata file: FileMetadata
fileIsLoading?: boolean fileIsLoading?: boolean
isConsumable?: boolean
consumableFeedback?: string
}): ReactElement { }): ReactElement {
const { appConfig } = useSiteMetadata() const { appConfig } = useSiteMetadata()
const { accountId } = useWeb3() const { accountId } = useWeb3()
@ -81,7 +86,11 @@ export default function Compute({
const [algorithmTimeout, setAlgorithmTimeout] = useState<string>() const [algorithmTimeout, setAlgorithmTimeout] = useState<string>()
const isComputeButtonDisabled = const isComputeButtonDisabled =
isJobStarting === true || file === null || !ocean || !isBalanceSufficient isJobStarting === true ||
file === null ||
!ocean ||
!isBalanceSufficient ||
!isConsumable
const hasDatatoken = Number(dtBalance) >= 1 const hasDatatoken = Number(dtBalance) >= 1
async function checkPreviousOrders(ddo: DDO) { async function checkPreviousOrders(ddo: DDO) {
@ -153,7 +162,6 @@ export default function Compute({
getQuerryString( getQuerryString(
computeService.attributes.main.privacy.publisherTrustedAlgorithms computeService.attributes.main.privacy.publisherTrustedAlgorithms
), ),
appConfig.metadataCacheUri,
source.token source.token
) )
setDdoAlgorithmList(gueryResults.results) setDdoAlgorithmList(gueryResults.results)
@ -161,7 +169,6 @@ export default function Compute({
algorithmSelectionList = await transformDDOToAssetSelection( algorithmSelectionList = await transformDDOToAssetSelection(
datasetComputeService?.serviceEndpoint, datasetComputeService?.serviceEndpoint,
gueryResults.results, gueryResults.results,
appConfig.metadataCacheUri,
[] []
) )
} }
@ -419,6 +426,8 @@ export default function Compute({
selectedComputeAssetTimeout={algorithmTimeout} selectedComputeAssetTimeout={algorithmTimeout}
stepText={pricingStepText || 'Starting Compute Job...'} stepText={pricingStepText || 'Starting Compute Job...'}
algorithmPrice={algorithmPrice} algorithmPrice={algorithmPrice}
isConsumable={isConsumable}
consumableFeedback={consumableFeedback}
/> />
</Formik> </Formik>
)} )}

View File

@ -35,13 +35,17 @@ export default function Consume({
file, file,
isBalanceSufficient, isBalanceSufficient,
dtBalance, dtBalance,
fileIsLoading fileIsLoading,
isConsumable,
consumableFeedback
}: { }: {
ddo: DDO ddo: DDO
file: FileMetadata file: FileMetadata
isBalanceSufficient: boolean isBalanceSufficient: boolean
dtBalance: string dtBalance: string
fileIsLoading?: boolean fileIsLoading?: boolean
isConsumable?: boolean
consumableFeedback?: string
}): ReactElement { }): ReactElement {
const { accountId } = useWeb3() const { accountId } = useWeb3()
const { ocean } = useOcean() const { ocean } = useOcean()
@ -54,7 +58,7 @@ export default function Consume({
const { consumeStepText, consume, consumeError, isLoading } = useConsume() const { consumeStepText, consume, consumeError, isLoading } = useConsume()
const [isDisabled, setIsDisabled] = useState(true) const [isDisabled, setIsDisabled] = useState(true)
const [hasDatatoken, setHasDatatoken] = useState(false) const [hasDatatoken, setHasDatatoken] = useState(false)
const [isConsumable, setIsConsumable] = useState(true) const [isConsumablePrice, setIsConsumablePrice] = useState(true)
const [assetTimeout, setAssetTimeout] = useState('') const [assetTimeout, setAssetTimeout] = useState('')
const [result] = useQuery<OrdersData>({ const [result] = useQuery<OrdersData>({
query: previousOrderQuery, query: previousOrderQuery,
@ -94,7 +98,7 @@ export default function Consume({
useEffect(() => { useEffect(() => {
if (!price) return if (!price) return
setIsConsumable( setIsConsumablePrice(
price.isConsumable !== undefined ? price.isConsumable === 'true' : true price.isConsumable !== undefined ? price.isConsumable === 'true' : true
) )
}, [price]) }, [price])
@ -105,14 +109,15 @@ export default function Consume({
useEffect(() => { useEffect(() => {
setIsDisabled( setIsDisabled(
(!ocean || !isConsumable ||
!isBalanceSufficient || ((!ocean ||
!isAssetNetwork || !isBalanceSufficient ||
typeof consumeStepText !== 'undefined' || !isAssetNetwork ||
pricingIsLoading || typeof consumeStepText !== 'undefined' ||
!isConsumable) && pricingIsLoading ||
!hasPreviousOrder && !isConsumablePrice) &&
!hasDatatoken !hasPreviousOrder &&
!hasDatatoken)
) )
}, [ }, [
ocean, ocean,
@ -121,8 +126,9 @@ export default function Consume({
isAssetNetwork, isAssetNetwork,
consumeStepText, consumeStepText,
pricingIsLoading, pricingIsLoading,
isConsumable, isConsumablePrice,
hasDatatoken hasDatatoken,
isConsumable
]) ])
async function handleConsume() { async function handleConsume() {
@ -163,6 +169,8 @@ export default function Consume({
stepText={consumeStepText || pricingStepText} stepText={consumeStepText || pricingStepText}
isLoading={pricingIsLoading || isLoading} isLoading={pricingIsLoading || isLoading}
priceType={price?.type} priceType={price?.type}
isConsumable={isConsumable}
consumableFeedback={consumableFeedback}
/> />
) )

View File

@ -17,6 +17,7 @@ import { ComputePrivacyForm } from '../../../../models/FormEditComputeDataset'
import { publisherTrustedAlgorithm as PublisherTrustedAlgorithm } from '@oceanprotocol/lib' import { publisherTrustedAlgorithm as PublisherTrustedAlgorithm } from '@oceanprotocol/lib'
import axios from 'axios' import axios from 'axios'
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
import { chainIds } from '../../../../../app.config'
export default function FormEditComputeDataset({ export default function FormEditComputeDataset({
data, data,
@ -51,16 +52,11 @@ export default function FormEditComputeDataset({
}, },
sort: { created: -1 } sort: { created: -1 }
} }
const querryResult = await queryMetadata( const querryResult = await queryMetadata(query, source.token)
query,
appConfig.metadataCacheUri,
source.token
)
const datasetComputeService = ddo.findServiceByType('compute') const datasetComputeService = ddo.findServiceByType('compute')
const algorithmSelectionList = await transformDDOToAssetSelection( const algorithmSelectionList = await transformDDOToAssetSelection(
datasetComputeService?.serviceEndpoint, datasetComputeService?.serviceEndpoint,
querryResult.results, querryResult.results,
appConfig.metadataCacheUri,
publisherTrustedAlgorithms publisherTrustedAlgorithms
) )
return algorithmSelectionList return algorithmSelectionList

View File

@ -26,6 +26,24 @@ export default function AssetActions(): ReactElement {
const [fileIsLoading, setFileIsLoading] = useState<boolean>(false) const [fileIsLoading, setFileIsLoading] = useState<boolean>(false)
const isCompute = Boolean(ddo?.findServiceByType('compute')) const isCompute = Boolean(ddo?.findServiceByType('compute'))
const [isConsumable, setIsConsumable] = useState<boolean>(true)
const [consumableFeedback, setConsumableFeedback] = useState<string>('')
useEffect(() => {
if (!ddo || !accountId) return
async function checkIsConsumable() {
const consumable: any = await ocean.assets.isConsumable(
ddo,
accountId.toLowerCase()
)
if (consumable) {
setIsConsumable(consumable.result)
setConsumableFeedback(consumable.message)
}
}
checkIsConsumable()
}, [accountId, ddo])
useEffect(() => { useEffect(() => {
const { attributes } = ddo.findServiceByType('metadata') const { attributes } = ddo.findServiceByType('metadata')
setFileMetadata(attributes.main.files[0]) setFileMetadata(attributes.main.files[0])
@ -88,6 +106,8 @@ export default function AssetActions(): ReactElement {
isBalanceSufficient={isBalanceSufficient} isBalanceSufficient={isBalanceSufficient}
file={fileMetadata} file={fileMetadata}
fileIsLoading={fileIsLoading} fileIsLoading={fileIsLoading}
isConsumable={isConsumable}
consumableFeedback={consumableFeedback}
/> />
) : ( ) : (
<Consume <Consume
@ -96,6 +116,8 @@ export default function AssetActions(): ReactElement {
isBalanceSufficient={isBalanceSufficient} isBalanceSufficient={isBalanceSufficient}
file={fileMetadata} file={fileMetadata}
fileIsLoading={fileIsLoading} fileIsLoading={fileIsLoading}
isConsumable={isConsumable}
consumableFeedback={consumableFeedback}
/> />
) )

View File

@ -20,6 +20,7 @@ export default function MetaMain(): ReactElement {
<AssetType <AssetType
type={type} type={type}
accessType={accessType} accessType={accessType}
chainId={ddo.chainId}
className={styles.assetType} className={styles.assetType}
/> />
<ExplorerLink <ExplorerLink

View File

@ -50,11 +50,7 @@ function DetailsAssets({ job }: { job: ComputeJobMetaData }) {
async function getAlgoMetadata() { async function getAlgoMetadata() {
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
const ddo = await retrieveDDO( const ddo = await retrieveDDO(job.algoDID, source.token)
job.algoDID,
appConfig.metadataCacheUri,
source.token
)
setAlgoDtSymbol(ddo.dataTokenInfo.symbol) setAlgoDtSymbol(ddo.dataTokenInfo.symbol)
const { attributes } = ddo.findServiceByType('metadata') const { attributes } = ddo.findServiceByType('metadata')

View File

@ -10,13 +10,17 @@ import Button from '../../../atoms/Button'
import { useOcean } from '../../../../providers/Ocean' import { useOcean } from '../../../../providers/Ocean'
import { gql, useQuery } from 'urql' import { gql, useQuery } from 'urql'
import { useWeb3 } from '../../../../providers/Web3' import { useWeb3 } from '../../../../providers/Web3'
import { queryMetadata } from '../../../../utils/aquarius' import {
queryMetadata,
transformChainIdsListToQuery
} from '../../../../utils/aquarius'
import axios, { CancelToken } from 'axios' import axios, { CancelToken } from 'axios'
import Details from './Details' import Details from './Details'
import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/Compute' 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 styles from './index.module.css'
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
import { useUserPreferences } from '../../../../providers/UserPreferences'
const getComputeOrders = gql` const getComputeOrders = gql`
query ComputeOrders($user: String!) { query ComputeOrders($user: String!) {
@ -83,31 +87,35 @@ const columns = [
async function getAssetMetadata( async function getAssetMetadata(
queryDtList: string, queryDtList: string,
metadataCacheUri: string, cancelToken: CancelToken,
cancelToken: CancelToken chainIds: number[]
): Promise<DDO[]> { ): Promise<DDO[]> {
const queryDid = { const queryDid = {
page: 1, page: 1,
offset: 100, offset: 100,
query: { query: {
query_string: { query_string: {
query: `(${queryDtList}) AND service.attributes.main.type:dataset AND service.type:compute`, query: `(${queryDtList}) (${transformChainIdsListToQuery(
chainIds
)}) AND (${transformChainIdsListToQuery(
chainIds
)}) AND service.attributes.main.type:dataset AND service.type:compute`,
fields: ['dataToken'] fields: ['dataToken']
} }
} }
} }
const result = await queryMetadata(queryDid, metadataCacheUri, cancelToken) const result = await queryMetadata(queryDid, cancelToken)
return result.results return result.results
} }
export default function ComputeJobs(): ReactElement { export default function ComputeJobs(): ReactElement {
const { appConfig } = useSiteMetadata()
const { ocean, account, config } = useOcean() const { ocean, account, config } = useOcean()
const { accountId } = useWeb3() const { accountId } = useWeb3()
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)
const [jobs, setJobs] = useState<ComputeJobMetaData[]>([]) const [jobs, setJobs] = useState<ComputeJobMetaData[]>([])
const { chainIds } = useUserPreferences()
const [result] = useQuery<ComputeOrders>({ const [result] = useQuery<ComputeOrders>({
query: getComputeOrders, query: getComputeOrders,
variables: { variables: {
@ -117,8 +125,7 @@ export default function ComputeJobs(): ReactElement {
const { data } = result const { data } = result
async function getJobs() { async function getJobs() {
if (!ocean || !account) return if (!accountId) return
setIsLoading(true) setIsLoading(true)
// await refetch() // await refetch()
@ -134,11 +141,7 @@ export default function ComputeJobs(): ReactElement {
try { try {
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
const assets = await getAssetMetadata( const assets = await getAssetMetadata(queryDtList, source.token, chainIds)
queryDtList,
appConfig.metadataCacheUri,
source.token
)
const providers: Provider[] = [] const providers: Provider[] = []
const serviceEndpoints: string[] = [] const serviceEndpoints: string[] = []
for (let i = 0; i < data.tokenOrders.length; i++) { for (let i = 0; i < data.tokenOrders.length; i++) {
@ -240,12 +243,12 @@ export default function ComputeJobs(): ReactElement {
} }
useEffect(() => { useEffect(() => {
if (data === undefined || !appConfig.metadataCacheUri) { if (data === undefined || !chainIds) {
setIsLoading(false) setIsLoading(false)
return return
} }
getJobs() getJobs()
}, [ocean, account, data, appConfig.metadataCacheUri]) }, [ocean, account, data, chainIds])
return ( return (
<> <>

View File

@ -78,11 +78,7 @@ export default function ComputeDownloads(): ReactElement {
const did = web3.utils const did = web3.utils
.toChecksumAddress(data.tokenOrders[i].datatokenId.address) .toChecksumAddress(data.tokenOrders[i].datatokenId.address)
.replace('0x', 'did:op:') .replace('0x', 'did:op:')
const ddo = await retrieveDDO( const ddo = await retrieveDDO(did, source.token)
did,
appConfig.metadataCacheUri,
source.token
)
if (ddo.service[1].type === 'access') { if (ddo.service[1].type === 'access') {
filteredOrders.push({ filteredOrders.push({
did: did, did: did,

View File

@ -3,7 +3,10 @@ import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/Metadata
import React, { ReactElement, useEffect, useState } from 'react' import React, { ReactElement, useEffect, useState } from 'react'
import AssetList from '../../organisms/AssetList' import AssetList from '../../organisms/AssetList'
import axios from 'axios' import axios from 'axios'
import { queryMetadata } from '../../../utils/aquarius' import {
queryMetadata,
transformChainIdsListToQuery
} from '../../../utils/aquarius'
import { useWeb3 } from '../../../providers/Web3' import { useWeb3 } from '../../../providers/Web3'
import { useSiteMetadata } from '../../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
import { useUserPreferences } from '../../../providers/UserPreferences' import { useUserPreferences } from '../../../providers/UserPreferences'
@ -27,7 +30,9 @@ export default function PublishedList(): ReactElement {
offset: 9, offset: 9,
query: { query: {
query_string: { query_string: {
query: `(publicKey.owner:${accountId})` query: `(publicKey.owner:${accountId}) AND (${transformChainIdsListToQuery(
chainIds
)})`
} }
}, },
sort: { created: -1 } sort: { created: -1 }
@ -36,11 +41,7 @@ export default function PublishedList(): ReactElement {
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
queryResult || setIsLoading(true) queryResult || setIsLoading(true)
const result = await queryMetadata( const result = await queryMetadata(queryPublishedAssets, source.token)
queryPublishedAssets,
appConfig.metadataCacheUri,
source.token
)
setQueryResult(result) setQueryResult(result)
} catch (error) { } catch (error) {
Logger.error(error.message) Logger.error(error.message)

View File

@ -10,7 +10,10 @@ import Container from '../atoms/Container'
import Button from '../atoms/Button' import Button from '../atoms/Button'
import Bookmarks from '../molecules/Bookmarks' import Bookmarks from '../molecules/Bookmarks'
import axios from 'axios' import axios from 'axios'
import { queryMetadata } from '../../utils/aquarius' import {
queryMetadata,
transformChainIdsListToQuery
} from '../../utils/aquarius'
import Permission from '../organisms/Permission' import Permission from '../organisms/Permission'
import { getHighestLiquidityDIDs } from '../../utils/subgraph' import { getHighestLiquidityDIDs } from '../../utils/subgraph'
import { DDO, Logger } from '@oceanprotocol/lib' import { DDO, Logger } from '@oceanprotocol/lib'
@ -28,7 +31,9 @@ async function getQueryHighest(
offset: 15, offset: 15,
query: { query: {
query_string: { query_string: {
query: `(${dids}) AND -isInPurgatory:true`, query: `(${dids}) AND (${transformChainIdsListToQuery(
chainIds
)}) AND -isInPurgatory:true`,
fields: ['dataToken'] fields: ['dataToken']
} }
} }
@ -44,7 +49,9 @@ function getQueryLatest(chainIds: number[]): SearchQuery {
offset: 9, offset: 9,
query: { query: {
query_string: { query_string: {
query: `-isInPurgatory:true` query: `(${transformChainIdsListToQuery(
chainIds
)}) AND -isInPurgatory:true `
} }
}, },
sort: { created: -1 } sort: { created: -1 }
@ -72,6 +79,7 @@ function SectionQueryResult({
const { appConfig } = useSiteMetadata() const { appConfig } = useSiteMetadata()
const [result, setResult] = useState<QueryResult>() const [result, setResult] = useState<QueryResult>()
const [loading, setLoading] = useState<boolean>() const [loading, setLoading] = useState<boolean>()
const { chainIds } = useUserPreferences()
useEffect(() => { useEffect(() => {
if (!appConfig.metadataCacheUri) return if (!appConfig.metadataCacheUri) return
@ -80,11 +88,7 @@ function SectionQueryResult({
async function init() { async function init() {
try { try {
setLoading(true) setLoading(true)
const result = await queryMetadata( const result = await queryMetadata(query, source.token)
query,
appConfig.metadataCacheUri,
source.token
)
if (queryData && result.totalResults > 0 && result.totalResults <= 15) { if (queryData && result.totalResults > 0 && result.totalResults <= 15) {
const searchDIDs = queryData.split(' ') const searchDIDs = queryData.split(' ')
const sortedAssets = sortElements(result.results, searchDIDs) const sortedAssets = sortElements(result.results, searchDIDs)
@ -134,10 +138,6 @@ export default function HomePage(): ReactElement {
return ( return (
<Permission eventType="browse"> <Permission eventType="browse">
<> <>
<Container narrow className={styles.searchWrap}>
<SearchBar size="large" />
</Container>
<section className={styles.section}> <section className={styles.section}>
<h3>Bookmarks</h3> <h3>Bookmarks</h3>
<Bookmarks /> <Bookmarks />

View File

@ -1,7 +1,6 @@
import React, { ReactElement, useState, useEffect } from 'react' import React, { ReactElement, useState, useEffect } from 'react'
import Permission from '../../organisms/Permission' import Permission from '../../organisms/Permission'
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache' import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import SearchBar from '../../molecules/SearchBar'
import AssetList from '../../organisms/AssetList' import AssetList from '../../organisms/AssetList'
import styles from './index.module.css' import styles from './index.module.css'
import queryString from 'query-string' import queryString from 'query-string'
@ -11,6 +10,7 @@ import { getResults } from './utils'
import { navigate } from 'gatsby' import { navigate } from 'gatsby'
import { updateQueryStringParameter } from '../../../utils' import { updateQueryStringParameter } from '../../../utils'
import { useSiteMetadata } from '../../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
import { useUserPreferences } from '../../../providers/UserPreferences'
export default function SearchPage({ export default function SearchPage({
location, location,
@ -22,6 +22,7 @@ export default function SearchPage({
const { appConfig } = useSiteMetadata() const { appConfig } = useSiteMetadata()
const parsed = queryString.parse(location.search) const parsed = queryString.parse(location.search)
const { text, owner, tags, page, sort, sortOrder, serviceType } = parsed const { text, owner, tags, page, sort, sortOrder, serviceType } = parsed
const { chainIds } = useUserPreferences()
const [queryResult, setQueryResult] = useState<QueryResult>() const [queryResult, setQueryResult] = useState<QueryResult>()
const [loading, setLoading] = useState<boolean>() const [loading, setLoading] = useState<boolean>()
const [service, setServiceType] = useState<string>(serviceType as string) const [service, setServiceType] = useState<string>(serviceType as string)
@ -35,7 +36,11 @@ export default function SearchPage({
async function initSearch() { async function initSearch() {
setLoading(true) setLoading(true)
setTotalResults(undefined) setTotalResults(undefined)
const queryResult = await getResults(parsed, appConfig.metadataCacheUri) const queryResult = await getResults(
parsed,
appConfig.metadataCacheUri,
chainIds
)
setQueryResult(queryResult) setQueryResult(queryResult)
setTotalResults(queryResult.totalResults) setTotalResults(queryResult.totalResults)
setLoading(false) setLoading(false)
@ -49,7 +54,8 @@ export default function SearchPage({
page, page,
serviceType, serviceType,
sortOrder, sortOrder,
appConfig.metadataCacheUri appConfig.metadataCacheUri,
chainIds
]) ])
function setPage(page: number) { function setPage(page: number) {
@ -65,9 +71,6 @@ export default function SearchPage({
<Permission eventType="browse"> <Permission eventType="browse">
<> <>
<div className={styles.search}> <div className={styles.search}>
{(text || owner || tags) && (
<SearchBar initialValue={(text || owner) as string} />
)}
<div className={styles.row}> <div className={styles.row}>
<ServiceFilter <ServiceFilter
serviceType={service} serviceType={service}

View File

@ -1,6 +1,11 @@
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache' import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import { MetadataCache, Logger } from '@oceanprotocol/lib' import { MetadataCache, Logger } from '@oceanprotocol/lib'
import {
queryMetadata,
transformChainIdsListToQuery
} from '../../../utils/aquarius'
import queryString from 'query-string' import queryString from 'query-string'
import axios from 'axios'
export const SortTermOptions = { export const SortTermOptions = {
Created: 'created', Created: 'created',
@ -46,6 +51,7 @@ function getSortType(sortParam: string): string {
} }
export function getSearchQuery( export function getSearchQuery(
chainIds: number[],
text?: string, text?: string,
owner?: string, owner?: string,
tags?: string, tags?: string,
@ -137,6 +143,11 @@ export function getSearchQuery(
] ]
} }
}, },
{
query_string: {
query: `${transformChainIdsListToQuery(chainIds)}`
}
},
{ {
term: { term: {
isInPurgatory: false isInPurgatory: false
@ -163,7 +174,8 @@ export async function getResults(
sortOrder?: string sortOrder?: string
serviceType?: string serviceType?: string
}, },
metadataCacheUri: string metadataCacheUri: string,
chainIds: number[]
): Promise<QueryResult> { ): Promise<QueryResult> {
const { const {
text, text,
@ -176,9 +188,9 @@ export async function getResults(
sortOrder, sortOrder,
serviceType serviceType
} = params } = params
const metadataCache = new MetadataCache(metadataCacheUri, Logger)
const searchQuery = getSearchQuery( const searchQuery = getSearchQuery(
chainIds,
text, text,
owner, owner,
tags, tags,
@ -189,7 +201,9 @@ export async function getResults(
sortOrder, sortOrder,
serviceType serviceType
) )
const queryResult = await metadataCache.queryMetadata(searchQuery) const source = axios.CancelToken.source()
// const queryResult = await metadataCache.queryMetadata(searchQuery)
const queryResult = await queryMetadata(searchQuery, source.token)
return queryResult return queryResult
} }

1
src/images/search.svg Normal file
View File

@ -0,0 +1 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"><path d="M15.853 16.56c-1.683 1.517-3.911 2.44-6.353 2.44-5.243 0-9.5-4.257-9.5-9.5s4.257-9.5 9.5-9.5 9.5 4.257 9.5 9.5c0 2.442-.923 4.67-2.44 6.353l7.44 7.44-.707.707-7.44-7.44zm-6.353-15.56c4.691 0 8.5 3.809 8.5 8.5s-3.809 8.5-8.5 8.5-8.5-3.809-8.5-8.5 3.809-8.5 8.5-8.5z"/></svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@ -14,14 +14,13 @@ import axios, { CancelToken } from 'axios'
import { retrieveDDO } from '../utils/aquarius' import { retrieveDDO } from '../utils/aquarius'
import { getPrice } from '../utils/subgraph' import { getPrice } from '../utils/subgraph'
import { MetadataMarket } from '../@types/MetaData' import { MetadataMarket } from '../@types/MetaData'
import { DDO_TEMPORARY } from './Ocean'
import { useWeb3 } from './Web3' import { useWeb3 } from './Web3'
import { useSiteMetadata } from '../hooks/useSiteMetadata' import { useSiteMetadata } from '../hooks/useSiteMetadata'
interface AssetProviderValue { interface AssetProviderValue {
isInPurgatory: boolean isInPurgatory: boolean
purgatoryData: PurgatoryData purgatoryData: PurgatoryData
ddo: DDO ddo: any
did: string did: string
metadata: MetadataMarket metadata: MetadataMarket
title: string title: string
@ -51,7 +50,7 @@ function AssetProvider({
const { networkId } = useWeb3() const { networkId } = useWeb3()
const [isInPurgatory, setIsInPurgatory] = useState(false) const [isInPurgatory, setIsInPurgatory] = useState(false)
const [purgatoryData, setPurgatoryData] = useState<PurgatoryData>() const [purgatoryData, setPurgatoryData] = useState<PurgatoryData>()
const [ddo, setDDO] = useState<DDO>() const [ddo, setDDO] = useState<any>()
const [did, setDID] = useState<string>() const [did, setDID] = useState<string>()
const [metadata, setMetadata] = useState<MetadataMarket>() const [metadata, setMetadata] = useState<MetadataMarket>()
const [title, setTitle] = useState<string>() const [title, setTitle] = useState<string>()
@ -65,11 +64,7 @@ function AssetProvider({
const fetchDdo = async (token?: CancelToken) => { const fetchDdo = async (token?: CancelToken) => {
Logger.log('[asset] Init asset, get DDO') Logger.log('[asset] Init asset, get DDO')
setLoading(true) setLoading(true)
const ddo = await retrieveDDO( const ddo = await retrieveDDO(asset as string, token)
asset as string,
appConfig.metadataCacheUri,
token
)
if (!ddo) { if (!ddo) {
setError( setError(
@ -126,7 +121,7 @@ function AssetProvider({
} }
}, []) }, [])
const initMetadata = useCallback(async (ddo: DDO): Promise<void> => { const initMetadata = useCallback(async (ddo: any): Promise<void> => {
if (!ddo) return if (!ddo) return
setLoading(true) setLoading(true)
const returnedPrice = await getPrice(ddo) const returnedPrice = await getPrice(ddo)
@ -155,7 +150,7 @@ function AssetProvider({
if (!networkId || !ddo) return if (!networkId || !ddo) return
// TODO: remove typing once present in ocean.js' DDO typing // TODO: remove typing once present in ocean.js' DDO typing
const isAssetNetwork = networkId === (ddo as DDO_TEMPORARY).chainId const isAssetNetwork = networkId === ddo?.chainId
setIsAssetNetwork(isAssetNetwork) setIsAssetNetwork(isAssetNetwork)
}, [networkId, ddo]) }, [networkId, ddo])

View File

@ -28,11 +28,6 @@ interface OceanProviderValue {
const OceanContext = createContext({} as OceanProviderValue) const OceanContext = createContext({} as OceanProviderValue)
// TODO: remove temporary typing once ddo.chainId is present in ocean.js
export interface DDO_TEMPORARY extends DDO {
chainId: number
}
function OceanProvider({ children }: { children: ReactNode }): ReactElement { function OceanProvider({ children }: { children: ReactNode }): ReactElement {
const { web3, accountId } = useWeb3() const { web3, accountId } = useWeb3()
const { ddo } = useAsset() const { ddo } = useAsset()
@ -71,13 +66,13 @@ function OceanProvider({ children }: { children: ReactNode }): ReactElement {
// ----------------------------------- // -----------------------------------
useEffect(() => { useEffect(() => {
// TODO: remove DDO typing once ocean.js has it // TODO: remove DDO typing once ocean.js has it
if (!(ddo as DDO_TEMPORARY)?.chainId) return if (!ddo?.chainId) return
const config = { const config = {
...getOceanConfig((ddo as DDO_TEMPORARY)?.chainId), ...getOceanConfig(ddo?.chainId),
// add local dev values // add local dev values
...((ddo as DDO_TEMPORARY)?.chainId === 8996 && { ...(ddo?.chainId === 8996 && {
...getDevelopmentConfig() ...getDevelopmentConfig()
}) })
} }

View File

@ -12,7 +12,6 @@ import {
import { AssetSelectionAsset } from '../components/molecules/FormFields/AssetSelection' import { AssetSelectionAsset } from '../components/molecules/FormFields/AssetSelection'
import { PriceList, getAssetsPriceList } from './subgraph' import { PriceList, getAssetsPriceList } from './subgraph'
import axios, { CancelToken, AxiosResponse } from 'axios' import axios, { CancelToken, AxiosResponse } from 'axios'
import { DDO_TEMPORARY } from '../providers/Ocean'
function getQueryForAlgorithmDatasets(algorithmDid: string) { function getQueryForAlgorithmDatasets(algorithmDid: string) {
return { return {
@ -50,18 +49,25 @@ export function transformQueryResult(
} }
} }
export function transformChainIdsListToQuery(chainIds: number[]) {
let chainQuery = ''
chainIds.forEach((chainId) => {
chainQuery += `chainId:${chainId} OR `
})
chainQuery = chainQuery.slice(0, chainQuery.length - 4)
return chainQuery
}
export async function queryMetadata( export async function queryMetadata(
query: SearchQuery, query: SearchQuery,
metadataCacheUri: string,
cancelToken: CancelToken cancelToken: CancelToken
): Promise<QueryResult> { ): Promise<any> {
try { try {
const response: AxiosResponse<QueryResult> = await axios.post( const response: AxiosResponse<any> = await axios.post(
`${metadataCacheUri}/api/v1/aquarius/assets/ddo/query`, `https://multiaqua.oceanprotocol.com/api/v1/aquarius/assets/ddo/query`,
{ ...query, cancelToken } { ...query, cancelToken }
) )
if (!response || response.status !== 200 || !response.data) return if (!response || response.status !== 200 || !response.data) return
return transformQueryResult(response.data) return transformQueryResult(response.data)
} catch (error) { } catch (error) {
if (axios.isCancel(error)) { if (axios.isCancel(error)) {
@ -74,19 +80,17 @@ export async function queryMetadata(
export async function retrieveDDO( export async function retrieveDDO(
did: string | DID, did: string | DID,
metadataCacheUri: string,
cancelToken: CancelToken cancelToken: CancelToken
): Promise<DDO_TEMPORARY> { ): Promise<DDO> {
try { try {
const response: AxiosResponse<DDO> = await axios.get( const response: AxiosResponse<DDO> = await axios.get(
`${metadataCacheUri}/api/v1/aquarius/assets/ddo/${did}`, `https://multiaqua.oceanprotocol.com/api/v1/aquarius/assets/ddo/${did}`,
{ cancelToken } { cancelToken }
) )
if (!response || response.status !== 200 || !response.data) return if (!response || response.status !== 200 || !response.data) return
// TODO: remove hacking in chainId in DDO response once Aquarius gives us that const data = { ...response.data }
const data = { ...response.data, chainId: 1 } return new DDO(data)
return new DDO(data) as DDO_TEMPORARY
} catch (error) { } catch (error) {
if (axios.isCancel(error)) { if (axios.isCancel(error)) {
Logger.log(error.message) Logger.log(error.message)
@ -98,12 +102,11 @@ export async function retrieveDDO(
export async function getAssetsNames( export async function getAssetsNames(
didList: string[] | DID[], didList: string[] | DID[],
metadataCacheUri: string,
cancelToken: CancelToken cancelToken: CancelToken
): Promise<Record<string, string>> { ): Promise<Record<string, string>> {
try { try {
const response: AxiosResponse<Record<string, string>> = await axios.post( const response: AxiosResponse<Record<string, string>> = await axios.post(
`${metadataCacheUri}/api/v1/aquarius/assets/names`, `https://multiaqua.oceanprotocol.com/api/v1/aquarius/assets/names`,
{ {
didList, didList,
cancelToken cancelToken
@ -123,7 +126,6 @@ export async function getAssetsNames(
export async function transformDDOToAssetSelection( export async function transformDDOToAssetSelection(
datasetProviderEndpoint: string, datasetProviderEndpoint: string,
ddoList: DDO[], ddoList: DDO[],
metadataCacheUri: string,
selectedAlgorithms?: PublisherTrustedAlgorithm[] selectedAlgorithms?: PublisherTrustedAlgorithm[]
): Promise<AssetSelectionAsset[]> { ): Promise<AssetSelectionAsset[]> {
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
@ -138,7 +140,7 @@ export async function transformDDOToAssetSelection(
algoComputeService?.serviceEndpoint && algoComputeService?.serviceEndpoint &&
(didProviderEndpointMap[ddo.id] = algoComputeService?.serviceEndpoint) (didProviderEndpointMap[ddo.id] = algoComputeService?.serviceEndpoint)
} }
const ddoNames = await getAssetsNames(didList, metadataCacheUri, source.token) const ddoNames = await getAssetsNames(didList, source.token)
const algorithmList: AssetSelectionAsset[] = [] const algorithmList: AssetSelectionAsset[] = []
didList?.forEach((did: string) => { didList?.forEach((did: string) => {
if ( if (
@ -180,7 +182,6 @@ export async function getAlgorithmDatasetsForCompute(
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
const computeDatasets = await queryMetadata( const computeDatasets = await queryMetadata(
getQueryForAlgorithmDatasets(algorithmId), getQueryForAlgorithmDatasets(algorithmId),
metadataCacheUri,
source.token source.token
) )
const computeDatasetsForCurrentAlgorithm: DDO[] = [] const computeDatasetsForCurrentAlgorithm: DDO[] = []
@ -198,7 +199,6 @@ export async function getAlgorithmDatasetsForCompute(
const datasets = await transformDDOToAssetSelection( const datasets = await transformDDOToAssetSelection(
datasetProviderUri, datasetProviderUri,
computeDatasetsForCurrentAlgorithm, computeDatasetsForCurrentAlgorithm,
metadataCacheUri,
[] []
) )
return datasets return datasets

View File

@ -116,6 +116,7 @@ export function transformPublishFormToMetadata(
name, name,
author, author,
dateCreated: ddo ? ddo.created : currentTime, dateCreated: ddo ? ddo.created : currentTime,
datePublished: '',
files: typeof files !== 'string' && files, files: typeof files !== 'string' && files,
license: 'https://market.oceanprotocol.com/terms' license: 'https://market.oceanprotocol.com/terms'
}, },