diff --git a/package-lock.json b/package-lock.json
index 6be48043e..744c08cc1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -65001,11 +65001,6 @@
"clsx": "^1.1.1"
}
},
- "reactjs-popup": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/reactjs-popup/-/reactjs-popup-2.0.4.tgz",
- "integrity": "sha512-G5jTXL2JkClKAYAdqedf+K9QvbNsFWvdbrXW1/vWiyanuCU/d7DtQzQux+uKOz2HeNVRsFQHvs7abs0Z7VLAhg=="
- },
"read": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
diff --git a/src/components/molecules/AssetComputeList.module.css b/src/components/molecules/AssetComputeList.module.css
new file mode 100644
index 000000000..bf304f55e
--- /dev/null
+++ b/src/components/molecules/AssetComputeList.module.css
@@ -0,0 +1,59 @@
+.display {
+ composes: selection from './FormFields/AssetSelection.module.css';
+}
+
+.display [class*='loaderWrap'] {
+ margin: calc(var(--spacer) / 3);
+}
+
+.scroll {
+ composes: scroll from './FormFields/AssetSelection.module.css';
+ margin-top: 0;
+ border-top: none;
+ width: 100%;
+}
+
+.row {
+ composes: row from './FormFields/AssetSelection.module.css';
+}
+
+.row:last-child {
+ border-bottom: none;
+}
+
+.row:first-child {
+ border-top: none;
+}
+
+.row:hover {
+ background-color: var(--background-content);
+}
+
+.info {
+ display: block;
+ width: 100%;
+}
+
+.title {
+ composes: title from './FormFields/AssetSelection.module.css';
+}
+
+.hover:hover {
+ color: var(--color-primary);
+}
+
+.price {
+ composes: price from './FormFields/AssetSelection.module.css';
+}
+
+.price [class*='symbol'] {
+ font-size: calc(var(--font-size-small) / 1.2) !important;
+}
+
+.did {
+ composes: did from './FormFields/AssetSelection.module.css';
+}
+
+.empty {
+ composes: empty from './FormFields/AssetSelection.module.css';
+}
diff --git a/src/components/molecules/AssetComputeList.tsx b/src/components/molecules/AssetComputeList.tsx
new file mode 100644
index 000000000..e5f4419d2
--- /dev/null
+++ b/src/components/molecules/AssetComputeList.tsx
@@ -0,0 +1,49 @@
+import React from 'react'
+import Dotdotdot from 'react-dotdotdot'
+import { Link } from 'gatsby'
+import PriceUnit from '../atoms/Price/PriceUnit'
+import Loader from '../atoms/Loader'
+import styles from './AssetComputeList.module.css'
+import { AssetSelectionAsset } from './FormFields/AssetSelection'
+
+function Empty() {
+ return
No assets found.
+}
+
+export default function AssetComputeSelection({
+ assets
+}: {
+ assets: AssetSelectionAsset[]
+}): JSX.Element {
+ return (
+
+
+ {!assets ? (
+
+ ) : assets && !assets.length ? (
+
+ ) : (
+ assets.map((asset: AssetSelectionAsset) => (
+
+
+
+
+ {asset.name}
+
+
+
+ {asset.symbol} | {asset.did}
+
+
+
+
+ ))
+ )}
+
+
+ )
+}
diff --git a/src/components/organisms/AssetActions/Compute/index.tsx b/src/components/organisms/AssetActions/Compute/index.tsx
index 9f5fc8ee2..71a101fb5 100644
--- a/src/components/organisms/AssetActions/Compute/index.tsx
+++ b/src/components/organisms/AssetActions/Compute/index.tsx
@@ -29,7 +29,6 @@ import {
ComputeAlgorithm,
ComputeOutput
} from '@oceanprotocol/lib/dist/node/ocean/interfaces/Compute'
-import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelection'
import { SearchQuery } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import axios from 'axios'
import FormStartComputeDataset from './FormComputeDataset'
@@ -37,6 +36,8 @@ import styles from './index.module.css'
import SuccessConfetti from '../../../atoms/SuccessConfetti'
import Button from '../../../atoms/Button'
import { secondsToString } from '../../../../utils/metadata'
+import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelection'
+import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute'
import { getPreviousOrders, getPrice } from '../../../../utils/subgraph'
const SuccessAction = () => (
@@ -377,10 +378,13 @@ export default function Compute({
{type === 'algorithm' ? (
-
+ <>
+
+
+ >
) : (
}
+ {type === 'algorithm' && (
+
+ )}
diff --git a/src/components/organisms/AssetContent/AlgorithmDatasetsListForCompute.module.css b/src/components/organisms/AssetContent/AlgorithmDatasetsListForCompute.module.css
new file mode 100644
index 000000000..54cd6f2c1
--- /dev/null
+++ b/src/components/organisms/AssetContent/AlgorithmDatasetsListForCompute.module.css
@@ -0,0 +1,29 @@
+.datasetsContainer {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: center;
+ width: auto;
+ margin-left: -2rem;
+ margin-right: -2rem;
+ border-top: 1px solid var(--border-color);
+ margin-top: calc(var(--spacer) / 2);
+}
+
+.datasetsContainer div[class*='AssetSelection-module--selection'] {
+ width: 100%;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-left: 0;
+ border-right: 0;
+ padding: 0;
+}
+
+.datasetsContainer .text {
+ margin-bottom: calc(var(--spacer) / 2);
+ margin-top: calc(var(--spacer) / 2);
+ text-align: center;
+ color: var(--font-color-text);
+ font-size: var(--font-size-base);
+ font-family: var(--font-family-heading);
+}
diff --git a/src/components/organisms/AssetContent/AlgorithmDatasetsListForCompute.tsx b/src/components/organisms/AssetContent/AlgorithmDatasetsListForCompute.tsx
new file mode 100644
index 000000000..7531ef390
--- /dev/null
+++ b/src/components/organisms/AssetContent/AlgorithmDatasetsListForCompute.tsx
@@ -0,0 +1,36 @@
+import React, { ReactElement, useEffect, useState } from 'react'
+import styles from './AlgorithmDatasetsListForCompute.module.css'
+import { getAlgorithmDatasetsForCompute } from '../../../utils/aquarius'
+import { AssetSelectionAsset } from '../../molecules/FormFields/AssetSelection'
+import AssetComputeList from '../../molecules/AssetComputeList'
+import { useOcean } from '../../../providers/Ocean'
+import { useAsset } from '../../../providers/Asset'
+
+export default function AlgorithmDatasetsListForCompute({
+ algorithmDid
+}: {
+ algorithmDid: string
+}): ReactElement {
+ const { config } = useOcean()
+ const { type } = useAsset()
+ const [datasetsForCompute, setDatasetsForCompute] =
+ useState()
+
+ useEffect(() => {
+ async function getDatasetsAllowedForCompute() {
+ const datasets = await getAlgorithmDatasetsForCompute(
+ algorithmDid,
+ config.metadataCacheUri
+ )
+ setDatasetsForCompute(datasets)
+ }
+ type === 'algorithm' && getDatasetsAllowedForCompute()
+ }, [type])
+
+ return (
+
+
Datasets algorithm is allowed to run on
+
+
+ )
+}
diff --git a/src/components/organisms/AssetContent/MetaFull.tsx b/src/components/organisms/AssetContent/MetaFull.tsx
index 93f6d2bf5..233cc4357 100644
--- a/src/components/organisms/AssetContent/MetaFull.tsx
+++ b/src/components/organisms/AssetContent/MetaFull.tsx
@@ -6,12 +6,10 @@ import { useAsset } from '../../../providers/Asset'
export default function MetaFull(): ReactElement {
const { ddo, metadata, isInPurgatory, type } = useAsset()
+ const { algorithm } = ddo.findServiceByType('metadata').attributes.main
function DockerImage() {
- const algorithmContainer =
- ddo.findServiceByType('metadata').attributes.main.algorithm.container
- const { image } = algorithmContainer
- const { tag } = algorithmContainer
+ const { image, tag } = algorithm.container
return {`${image}:${tag}`}
}
@@ -25,7 +23,7 @@ export default function MetaFull(): ReactElement {
content={}
/>
- {type === 'algorithm' && (
+ {type === 'algorithm' && algorithm && (
} />
)}
{ddo?.id}} />
diff --git a/src/components/templates/PageAssetDetails.tsx b/src/components/templates/PageAssetDetails.tsx
index 9f7773cc4..a48361210 100644
--- a/src/components/templates/PageAssetDetails.tsx
+++ b/src/components/templates/PageAssetDetails.tsx
@@ -11,7 +11,7 @@ export default function PageTemplateAssetDetails({
}: {
uri: string
}): ReactElement {
- const { ddo, title, error, isInPurgatory } = useAsset()
+ const { ddo, title, error, isInPurgatory, loading } = useAsset()
const [pageTitle, setPageTitle] = useState()
useEffect(() => {
@@ -23,7 +23,7 @@ export default function PageTemplateAssetDetails({
setPageTitle(isInPurgatory ? '' : title)
}, [ddo, error, isInPurgatory, title])
- return ddo && pageTitle !== undefined ? (
+ return ddo && pageTitle !== undefined && !loading ? (
<>
diff --git a/src/providers/Asset.tsx b/src/providers/Asset.tsx
index f49bf6ef2..885fc5cde 100644
--- a/src/providers/Asset.tsx
+++ b/src/providers/Asset.tsx
@@ -28,6 +28,7 @@ interface AssetProviderValue {
type: MetadataMain['type'] | undefined
error?: string
refreshInterval: number
+ loading: boolean
refreshDdo: (token?: CancelToken) => Promise
}
@@ -53,9 +54,11 @@ function AssetProvider({
const [owner, setOwner] = useState()
const [error, setError] = useState()
const [type, setType] = useState()
+ const [loading, setLoading] = useState(false)
const fetchDdo = async (token?: CancelToken) => {
Logger.log('[asset] Init asset, get DDO')
+ setLoading(true)
const ddo = await retrieveDDO(
asset as string,
config.metadataCacheUri,
@@ -69,13 +72,16 @@ function AssetProvider({
} else {
setError(undefined)
}
+ setLoading(false)
return ddo
}
const refreshDdo = async (token?: CancelToken) => {
+ setLoading(true)
const ddo = await fetchDdo(token)
Logger.debug('[asset] Got DDO', ddo)
setDDO(ddo)
+ setLoading(false)
}
//
@@ -116,7 +122,7 @@ function AssetProvider({
const initMetadata = useCallback(async (ddo: DDO): Promise => {
if (!ddo) return
-
+ setLoading(true)
const returnedPrice = await getPrice(ddo)
setPrice({ ...returnedPrice })
@@ -130,6 +136,7 @@ function AssetProvider({
setIsInPurgatory(ddo.isInPurgatory === 'true')
await setPurgatory(ddo.id)
+ setLoading(false)
}, [])
useEffect(() => {
@@ -152,6 +159,7 @@ function AssetProvider({
isInPurgatory,
purgatoryData,
refreshInterval,
+ loading,
refreshDdo
} as AssetProviderValue
}
diff --git a/src/utils/aquarius.ts b/src/utils/aquarius.ts
index db8b09d83..d8f2c57c0 100644
--- a/src/utils/aquarius.ts
+++ b/src/utils/aquarius.ts
@@ -13,6 +13,17 @@ import { AssetSelectionAsset } from '../components/molecules/FormFields/AssetSel
import { PriceList, getAssetsPriceList } from './subgraph'
import axios, { CancelToken, AxiosResponse } from 'axios'
+function getQueryForAlgorithmDatasets(algorithmDid: string) {
+ return {
+ query: {
+ query_string: {
+ query: `service.attributes.main.privacy.publisherTrustedAlgorithms.did:${algorithmDid}`
+ }
+ },
+ sort: { created: -1 }
+ }
+}
+
// TODO: import directly from ocean.js somehow.
// Transforming Aquarius' direct response is needed for getting actual DDOs
// and not just strings of DDOs. For now, taken from
@@ -148,3 +159,33 @@ export async function transformDDOToAssetSelection(
})
return algorithmList
}
+
+export async function getAlgorithmDatasetsForCompute(
+ algorithmId: string,
+ metadataCacheUri: string
+): Promise {
+ const source = axios.CancelToken.source()
+ const computeDatasets = await queryMetadata(
+ getQueryForAlgorithmDatasets(algorithmId),
+ metadataCacheUri,
+ source.token
+ )
+ const computeDatasetsForCurrentAlgorithm: DDO[] = []
+ computeDatasets.results.forEach((data: DDO) => {
+ const algorithm = data
+ .findServiceByType('compute')
+ .attributes.main.privacy.publisherTrustedAlgorithms.find(
+ (algo) => algo.did === algorithmId
+ )
+ algorithm && computeDatasetsForCurrentAlgorithm.push(data)
+ })
+ if (computeDatasetsForCurrentAlgorithm.length === 0) {
+ return []
+ }
+ const datasets = await transformDDOToAssetSelection(
+ computeDatasetsForCurrentAlgorithm,
+ metadataCacheUri,
+ []
+ )
+ return datasets
+}