mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
generate pages for all existing assets, make asset details view work for them
This commit is contained in:
parent
6106b8f037
commit
af62e9f5d4
@ -2,7 +2,7 @@
|
||||
"site": {
|
||||
"siteTitle": "Ocean Market",
|
||||
"siteTagline": "A marketplace to find and publish open data sets in the Ocean Network.",
|
||||
"siteUrl": "https://market.oceanprotocol.now.sh/",
|
||||
"siteUrl": "https://market.oceanprotocol.now.sh",
|
||||
"siteIcon": "node_modules/@oceanprotocol/art/logo/favicon-white.png",
|
||||
"siteImage": "../src/images/share.png",
|
||||
"copyright": "All Rights Reserved. Powered by [Ocean Protocol](https://oceanprotocol.com)",
|
||||
|
@ -1,3 +1,7 @@
|
||||
const path = require('path')
|
||||
const axios = require('axios')
|
||||
// const { config } = require('./src/config/ocean')
|
||||
|
||||
exports.onCreateWebpackConfig = ({ actions }) => {
|
||||
actions.setWebpackConfig({
|
||||
node: {
|
||||
@ -6,3 +10,32 @@ exports.onCreateWebpackConfig = ({ actions }) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.createPages = async ({ actions, reporter }) => {
|
||||
const { createPage } = actions
|
||||
// Query for markdown nodes to use in creating pages.
|
||||
const result = await axios(
|
||||
`https://aquarius.marketplace.oceanprotocol.com/api/v1/aquarius/assets`
|
||||
)
|
||||
const assets = result.data.ids
|
||||
|
||||
// Handle errors
|
||||
if (result.errors) {
|
||||
reporter.panicOnBuild(`Error while querying Aquarius for all assets.`)
|
||||
return
|
||||
}
|
||||
|
||||
// Create pages for each DID
|
||||
const assetDetailsTemplate = path.resolve(
|
||||
`src/components/templates/AssetDetails/index.tsx`
|
||||
)
|
||||
assets.forEach((did) => {
|
||||
const path = `/asset/${did}`
|
||||
|
||||
createPage({
|
||||
path,
|
||||
component: assetDetailsTemplate,
|
||||
context: { did }
|
||||
})
|
||||
})
|
||||
}
|
||||
|
21
src/@types/MetaData.d.ts
vendored
21
src/@types/MetaData.d.ts
vendored
@ -1,15 +1,5 @@
|
||||
import { MetaData, AdditionalInformation, Curation } from '@oceanprotocol/squid'
|
||||
|
||||
declare type DeliveryType = 'files' | 'api' | 'subscription'
|
||||
|
||||
declare type Granularity =
|
||||
| 'hourly'
|
||||
| 'daily'
|
||||
| 'weekly'
|
||||
| 'monthly'
|
||||
| 'annually'
|
||||
| 'Not updated periodically'
|
||||
| ''
|
||||
import { MetaData, AdditionalInformation } from '@oceanprotocol/squid'
|
||||
import { ServiceMetadata } from '@oceanprotocol/squid/dist/node/ddo/Service'
|
||||
|
||||
export interface Sample {
|
||||
name: string
|
||||
@ -21,14 +11,15 @@ export declare type AccessType = 'Download' | 'Compute'
|
||||
export interface AdditionalInformationMarket extends AdditionalInformation {
|
||||
description: string
|
||||
links?: Sample[] // redefine existing key, cause not specific enough in Squid
|
||||
deliveryType: DeliveryType
|
||||
termsAndConditions: boolean
|
||||
dateRange?: [string, string]
|
||||
supportName?: string
|
||||
supportEmail?: string
|
||||
access: AccessType
|
||||
}
|
||||
|
||||
export interface MetaDataMarket extends MetaData {
|
||||
additionalInformation: AdditionalInformationMarket
|
||||
}
|
||||
|
||||
export interface ServiceMetaDataMarket extends ServiceMetadata {
|
||||
attributes: MetaDataMarket
|
||||
}
|
||||
|
@ -10,18 +10,18 @@ import { config } from '../config/ocean'
|
||||
|
||||
export interface LayoutProps {
|
||||
children: ReactNode
|
||||
title?: string
|
||||
title: string
|
||||
uri: string
|
||||
description?: string
|
||||
noPageHeader?: boolean
|
||||
location?: Location
|
||||
}
|
||||
|
||||
export default function Layout({
|
||||
children,
|
||||
title,
|
||||
uri,
|
||||
description,
|
||||
noPageHeader,
|
||||
location
|
||||
noPageHeader
|
||||
}: LayoutProps): ReactElement {
|
||||
return (
|
||||
<Web3Provider>
|
||||
@ -33,12 +33,7 @@ export default function Layout({
|
||||
<meta name="theme-color" content="#ca2935" />
|
||||
</Helmet>
|
||||
|
||||
<Seo
|
||||
title={title}
|
||||
description={description}
|
||||
uri={location.href}
|
||||
location={location}
|
||||
/>
|
||||
<Seo title={title} description={description} uri={uri} />
|
||||
|
||||
<Header />
|
||||
<main className={styles.main}>
|
||||
|
@ -1,18 +1,16 @@
|
||||
import React from 'react'
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
||||
|
||||
export default function Seo({
|
||||
title,
|
||||
description,
|
||||
uri,
|
||||
location
|
||||
uri
|
||||
}: {
|
||||
title?: string
|
||||
description?: string
|
||||
uri: string
|
||||
location: Location
|
||||
}) {
|
||||
}): ReactElement {
|
||||
const { siteTitle, siteTagline, siteUrl, siteImage } = useSiteMetadata()
|
||||
|
||||
// Remove trailing slash from all URLs
|
||||
@ -37,7 +35,7 @@ export default function Seo({
|
||||
<meta name="description" content={description} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:url" content={location.href} />
|
||||
<meta property="og:url" content={uri} />
|
||||
|
||||
<meta
|
||||
name="image"
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { DDO, Ocean } from '@oceanprotocol/squid'
|
||||
import { ServiceMetadata } from '@oceanprotocol/squid/dist/node/ddo/Service'
|
||||
import React, { useState, useEffect, ReactElement } from 'react'
|
||||
import { Ocean } from '@oceanprotocol/squid'
|
||||
import { fromWei } from 'web3-utils'
|
||||
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
||||
import Loader from '../atoms/Loader'
|
||||
@ -15,18 +14,19 @@ import {
|
||||
import styles from './Compute.module.css'
|
||||
import Button from '../atoms/Button'
|
||||
import Input from '../atoms/Input'
|
||||
import { MetaDataMarket } from '../../@types/MetaData'
|
||||
|
||||
export default function Compute({
|
||||
ddo,
|
||||
did,
|
||||
metadata,
|
||||
balance,
|
||||
ocean
|
||||
}: {
|
||||
ddo: DDO | null
|
||||
did: string
|
||||
metadata: MetaDataMarket
|
||||
balance: string | null
|
||||
ocean: Ocean | null
|
||||
}) {
|
||||
if (!ddo) return null
|
||||
|
||||
}): ReactElement {
|
||||
const { compute, isLoading, computeStepText, computeError } = useCompute()
|
||||
const [isJobStarting, setIsJobStarting] = useState(false)
|
||||
const [, setError] = useState('')
|
||||
@ -41,9 +41,7 @@ export default function Compute({
|
||||
const [isPublished, setIsPublished] = useState(false)
|
||||
const [file, setFile] = useState(null)
|
||||
|
||||
const metadata = ddo.findServiceByType('metadata') as ServiceMetadata
|
||||
const { price } = metadata.attributes.main
|
||||
|
||||
const { price } = metadata.main
|
||||
const isFree = price === '0'
|
||||
|
||||
const [isTermsAgreed, setIsTermsAgreed] = useState(true)
|
||||
@ -85,7 +83,7 @@ export default function Compute({
|
||||
setIsPublished(false)
|
||||
setError('')
|
||||
|
||||
await compute(ddo.id, algorithmRawCode, computeContainer)
|
||||
await compute(did, algorithmRawCode, computeContainer)
|
||||
|
||||
setIsPublished(true)
|
||||
setFile(null)
|
||||
|
@ -1,25 +1,26 @@
|
||||
import React from 'react'
|
||||
import { DDO } from '@oceanprotocol/squid'
|
||||
import React, { ReactElement } from 'react'
|
||||
import Web3 from 'web3'
|
||||
import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
|
||||
import Button from '../atoms/Button'
|
||||
import File from '../atoms/File'
|
||||
import Price from '../atoms/Price'
|
||||
import { MetaDataMarket } from '../../@types/MetaData'
|
||||
import Web3Feedback from '../molecules/Web3Feedback'
|
||||
import styles from './Consume.module.css'
|
||||
import Loader from '../atoms/Loader'
|
||||
import { useWeb3, useOcean, useConsume } from '@oceanprotocol/react'
|
||||
import { useOcean, useConsume } from '@oceanprotocol/react'
|
||||
import { MetaDataMarket } from '../../@types/MetaData'
|
||||
|
||||
export default function Consume({ ddo }: { ddo: DDO | undefined }) {
|
||||
if (!ddo) return null
|
||||
|
||||
const { web3 } = useWeb3()
|
||||
export default function Consume({
|
||||
did,
|
||||
metadata
|
||||
}: {
|
||||
did: string
|
||||
metadata: MetaDataMarket
|
||||
}): ReactElement {
|
||||
const { ocean, balanceInOcean } = useOcean()
|
||||
const { consume, consumeStepText, isLoading } = useConsume()
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
const { price } = attributes.main
|
||||
const file = (attributes as any).main.files[0]
|
||||
const { price } = metadata.main
|
||||
const file = metadata.main.files[0]
|
||||
const isFree = price === '0'
|
||||
const isBalanceSufficient =
|
||||
isFree ||
|
||||
@ -34,7 +35,11 @@ export default function Consume({ ddo }: { ddo: DDO | undefined }) {
|
||||
return isLoading ? (
|
||||
<Loader message={consumeStepText} isHorizontal />
|
||||
) : (
|
||||
<Button primary onClick={() => consume(ddo.id)} disabled={isDisabled}>
|
||||
<Button
|
||||
style="primary"
|
||||
onClick={() => consume(did)}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
{isFree ? 'Download' : 'Buy'}
|
||||
</Button>
|
||||
)
|
||||
|
@ -1,21 +1,20 @@
|
||||
import React from 'react'
|
||||
import { DDO } from '@oceanprotocol/squid'
|
||||
import { MetaDataMarket } from '../../../@types/MetaData'
|
||||
import React, { ReactElement } from 'react'
|
||||
import Time from '../../atoms/Time'
|
||||
import MetaItem from './MetaItem'
|
||||
import styles from './MetaFull.module.css'
|
||||
import { MetaDataMarket } from '../../../@types/MetaData'
|
||||
|
||||
export default function MetaFull({
|
||||
ddo,
|
||||
attributes
|
||||
did,
|
||||
metadata
|
||||
}: {
|
||||
ddo: DDO | undefined
|
||||
attributes: MetaDataMarket
|
||||
}) {
|
||||
const { dateCreated, author, license } = attributes.main
|
||||
did: string
|
||||
metadata: MetaDataMarket
|
||||
}): ReactElement {
|
||||
const { dateCreated, author, license } = metadata.main
|
||||
let dateRange
|
||||
if (attributes && attributes.additionalInformation) {
|
||||
;({ dateRange } = attributes.additionalInformation)
|
||||
if (metadata && metadata.additionalInformation) {
|
||||
;({ dateRange } = metadata.additionalInformation)
|
||||
}
|
||||
|
||||
// In practice dateRange will always be defined, but in the rare case it isn't
|
||||
@ -43,7 +42,7 @@ export default function MetaFull({
|
||||
}
|
||||
/>
|
||||
|
||||
<MetaItem title="DID" content={<code>{ddo?.id}</code>} />
|
||||
<MetaItem title="DID" content={<code>{did}</code>} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
import React from 'react'
|
||||
import React, { ReactElement } from 'react'
|
||||
import shortid from 'shortid'
|
||||
import { MetaDataMarket } from '../../../@types/MetaData'
|
||||
import { ListItem } from '../../atoms/Lists'
|
||||
import { refundPolicy, assetTerms } from '../../../../site.config'
|
||||
import MetaItem from './MetaItem'
|
||||
import styles from './MetaSecondary.module.css'
|
||||
import { MetaDataMarket } from '../../../@types/MetaData'
|
||||
|
||||
export default function MetaSecondary({
|
||||
attributes
|
||||
metadata
|
||||
}: {
|
||||
attributes: MetaDataMarket
|
||||
}) {
|
||||
const { price } = attributes.main
|
||||
let links, supportName, supportEmail
|
||||
if (attributes && attributes.additionalInformation) {
|
||||
;({ links, supportName, supportEmail } = attributes.additionalInformation)
|
||||
metadata: MetaDataMarket
|
||||
}): ReactElement {
|
||||
let links
|
||||
if (metadata && metadata.additionalInformation) {
|
||||
;({ links } = metadata.additionalInformation)
|
||||
}
|
||||
|
||||
return (
|
||||
@ -35,37 +33,6 @@ export default function MetaSecondary({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{(supportName || supportEmail) && (
|
||||
<MetaItem
|
||||
title="Support Contact"
|
||||
content={
|
||||
<>
|
||||
{supportName && <p>{supportName}</p>}
|
||||
{supportEmail && <p>{supportEmail}</p>}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{price !== '0' && (
|
||||
<MetaItem
|
||||
title="Refund Policy"
|
||||
content={
|
||||
<ul>
|
||||
{refundPolicy.map((item) => (
|
||||
<ListItem key={shortid.generate()}>{item}</ListItem>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{assetTerms.map((item) => (
|
||||
<MetaItem
|
||||
key={shortid.generate()}
|
||||
title={item.name}
|
||||
content={item.value}
|
||||
/>
|
||||
))}
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { useState } from 'react'
|
||||
import { DDO } from '@oceanprotocol/squid'
|
||||
import { Link } from 'gatsby'
|
||||
import React, { useState, ReactElement, useEffect } from 'react'
|
||||
import { Aquarius, Logger } from '@oceanprotocol/squid'
|
||||
import { Link, PageProps } from 'gatsby'
|
||||
import { config } from '../../../config/ocean'
|
||||
import Layout from '../../../components/Layout'
|
||||
import { MetaDataMarket } from '../../../@types/MetaData'
|
||||
import { MetaDataMarket, ServiceMetaDataMarket } from '../../../@types/MetaData'
|
||||
import Time from '../../atoms/Time'
|
||||
import Markdown from '../../atoms/Markdown'
|
||||
import Consume from '../../organisms/Consume'
|
||||
@ -10,39 +11,30 @@ import Tags from '../../atoms/Tags'
|
||||
import { Alert } from '../../atoms/Alert'
|
||||
import MetaFull from './MetaFull'
|
||||
import MetaSecondary from './MetaSecondary'
|
||||
import Rating from '../../atoms/Rating'
|
||||
import RatingAction from './RatingAction'
|
||||
// import Rating from '../../atoms/Rating'
|
||||
// import RatingAction from './RatingAction'
|
||||
import styles from './index.module.css'
|
||||
import { useMetadata, useOcean } from '@oceanprotocol/react'
|
||||
import Compute from '../../organisms/Compute'
|
||||
import DeleteAction from '../../molecules/DeleteAsset'
|
||||
|
||||
export declare type AssetDetailsPageProps = {
|
||||
title: string
|
||||
ddo?: DDO
|
||||
attributes?: MetaDataMarket
|
||||
error?: string
|
||||
}
|
||||
// import DeleteAction from '../../molecules/DeleteAsset'
|
||||
|
||||
const AssetDetailsPageMeta = ({
|
||||
attributes,
|
||||
ddo
|
||||
metadata,
|
||||
did
|
||||
}: {
|
||||
attributes: MetaDataMarket
|
||||
ddo: DDO
|
||||
metadata: MetaDataMarket
|
||||
did: string
|
||||
}) => {
|
||||
if (!attributes) return null
|
||||
|
||||
const { ocean, balanceInOcean } = useOcean()
|
||||
const { datePublished } = attributes.main
|
||||
const { datePublished } = metadata.main
|
||||
const {
|
||||
description,
|
||||
copyrightHolder,
|
||||
categories,
|
||||
tags,
|
||||
access
|
||||
} = attributes.additionalInformation
|
||||
const { curation } = attributes
|
||||
} = metadata.additionalInformation
|
||||
const { curation } = metadata
|
||||
|
||||
const { getCuration } = useMetadata()
|
||||
const [rating, setRating] = useState<number>(curation ? curation.rating : 0)
|
||||
@ -50,8 +42,9 @@ const AssetDetailsPageMeta = ({
|
||||
curation ? curation.numVotes : 0
|
||||
)
|
||||
const isCompute = access && access === 'Compute'
|
||||
|
||||
const onVoteUpdate = async () => {
|
||||
const { rating, numVotes } = await getCuration(ddo.id)
|
||||
const { rating, numVotes } = await getCuration(did)
|
||||
|
||||
setRating(rating)
|
||||
setNumVotes(numVotes)
|
||||
@ -72,7 +65,7 @@ const AssetDetailsPageMeta = ({
|
||||
</Link>
|
||||
</p>
|
||||
)}
|
||||
<Rating curation={{ rating, numVotes }} readonly />
|
||||
{/* <Rating curation={{ rating, numVotes }} readonly /> */}
|
||||
</aside>
|
||||
|
||||
<h2 className={styles.sectionTitle}>Summary</h2>
|
||||
@ -80,7 +73,7 @@ const AssetDetailsPageMeta = ({
|
||||
|
||||
{tags && tags.length > 0 && <Tags items={tags} />}
|
||||
|
||||
<MetaFull ddo={ddo} attributes={attributes} />
|
||||
<MetaFull did={did} metadata={metadata} />
|
||||
<div className={styles.buttonGroup}>
|
||||
{/* <EditAction
|
||||
ddo={ddo}
|
||||
@ -88,48 +81,73 @@ const AssetDetailsPageMeta = ({
|
||||
account={account}
|
||||
refetchMetadata={refetchMetadata}
|
||||
/> */}
|
||||
<DeleteAction ddo={ddo} />
|
||||
{/* <DeleteAction ddo={ddo} /> */}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className={styles.sticky}>
|
||||
{isCompute ? (
|
||||
<Compute ddo={ddo} ocean={ocean} balance={balanceInOcean} />
|
||||
<Compute
|
||||
did={did}
|
||||
metadata={metadata}
|
||||
ocean={ocean}
|
||||
balance={balanceInOcean}
|
||||
/>
|
||||
) : (
|
||||
<Consume ddo={ddo} />
|
||||
<Consume did={did} metadata={metadata} />
|
||||
)}
|
||||
|
||||
<RatingAction did={ddo.id} onVote={onVoteUpdate} />
|
||||
<MetaSecondary attributes={attributes} />
|
||||
{/* <RatingAction did={did} onVote={onVoteUpdate} /> */}
|
||||
<MetaSecondary metadata={metadata} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const AssetDetailsPage = ({
|
||||
ddo,
|
||||
attributes,
|
||||
title,
|
||||
error
|
||||
}: AssetDetailsPageProps) => {
|
||||
if (error) {
|
||||
return (
|
||||
<Layout title={title} noPageHeader>
|
||||
<Alert title={title} text={error} state="error" />
|
||||
</Layout>
|
||||
)
|
||||
export default function AssetDetailsPage(props: PageProps): ReactElement {
|
||||
const [metadata, setMetadata] = useState<MetaDataMarket>()
|
||||
const [title, setTitle] = useState<string>()
|
||||
const [error, setError] = useState<string>()
|
||||
|
||||
const { did } = props.pageContext as { did: string }
|
||||
|
||||
useEffect(() => {
|
||||
async function init() {
|
||||
try {
|
||||
const aquarius = new Aquarius(config.aquariusUri, Logger)
|
||||
const ddo = await aquarius.retrieveDDO(did)
|
||||
|
||||
if (!ddo) {
|
||||
setTitle('Could not retrieve asset')
|
||||
setError('The DDO was not found in Aquarius.')
|
||||
return
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout title={title}>
|
||||
const { attributes }: ServiceMetaDataMarket = ddo.findServiceByType(
|
||||
'metadata'
|
||||
)
|
||||
|
||||
setTitle(attributes.main.name)
|
||||
console.log(attributes)
|
||||
setMetadata(attributes)
|
||||
} catch (error) {
|
||||
setTitle('Error retrieving asset')
|
||||
setError(error.message)
|
||||
}
|
||||
}
|
||||
init()
|
||||
}, [])
|
||||
|
||||
return error ? (
|
||||
<Layout title={title} noPageHeader uri={props.path}>
|
||||
<Alert title={title} text={error} state="error" />
|
||||
</Layout>
|
||||
) : did && metadata ? (
|
||||
<Layout title={title} uri={props.path}>
|
||||
<article className={styles.grid}>
|
||||
{attributes && (
|
||||
<AssetDetailsPageMeta ddo={ddo as DDO} attributes={attributes} />
|
||||
)}
|
||||
<AssetDetailsPageMeta did={did} metadata={metadata} />
|
||||
</article>
|
||||
</Layout>
|
||||
)
|
||||
) : null
|
||||
}
|
||||
|
||||
export default AssetDetailsPage
|
||||
|
@ -8,7 +8,7 @@ export default function PageGatsbyHistory(props: PageProps): ReactElement {
|
||||
const { title, description } = content
|
||||
|
||||
return (
|
||||
<Layout title={title} description={description} location={props.location}>
|
||||
<Layout title={title} description={description} uri={props.uri}>
|
||||
<PageHistory />
|
||||
</Layout>
|
||||
)
|
||||
|
@ -8,11 +8,7 @@ export default function PageGatsbyHome(props: PageProps): ReactElement {
|
||||
const { siteTitle, siteTagline } = useSiteMetadata()
|
||||
|
||||
return (
|
||||
<Layout
|
||||
title={siteTitle}
|
||||
description={siteTagline}
|
||||
location={props.location}
|
||||
>
|
||||
<Layout title={siteTitle} description={siteTagline} uri={props.uri}>
|
||||
<PageHome />
|
||||
</Layout>
|
||||
)
|
||||
|
@ -8,7 +8,7 @@ export default function PageGatsbyPublish(props: PageProps): ReactElement {
|
||||
const { title, description } = content
|
||||
|
||||
return (
|
||||
<Layout title={title} description={description} location={props.location}>
|
||||
<Layout title={title} description={description} uri={props.uri}>
|
||||
<PagePublish />
|
||||
</Layout>
|
||||
)
|
||||
|
@ -9,7 +9,7 @@ export default function PageGatsbySearch(props: PageProps): ReactElement {
|
||||
const { text, tag } = parsed
|
||||
|
||||
return (
|
||||
<Layout title={`Search for ${text || tag}`} location={props.location}>
|
||||
<Layout title={`Search for ${text || tag}`} uri={props.uri}>
|
||||
<PageSearch location={props.location} />
|
||||
</Layout>
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user