1
0
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:
Matthias Kretschmann 2020-07-01 17:11:45 +02:00
parent 6106b8f037
commit af62e9f5d4
Signed by: m
GPG Key ID: 606EEEF3C479A91F
14 changed files with 169 additions and 169 deletions

View File

@ -2,7 +2,7 @@
"site": { "site": {
"siteTitle": "Ocean Market", "siteTitle": "Ocean Market",
"siteTagline": "A marketplace to find and publish open data sets in the Ocean Network.", "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", "siteIcon": "node_modules/@oceanprotocol/art/logo/favicon-white.png",
"siteImage": "../src/images/share.png", "siteImage": "../src/images/share.png",
"copyright": "All Rights Reserved. Powered by [Ocean Protocol](https://oceanprotocol.com)", "copyright": "All Rights Reserved. Powered by [Ocean Protocol](https://oceanprotocol.com)",

View File

@ -1,3 +1,7 @@
const path = require('path')
const axios = require('axios')
// const { config } = require('./src/config/ocean')
exports.onCreateWebpackConfig = ({ actions }) => { exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({ actions.setWebpackConfig({
node: { 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 }
})
})
}

View File

@ -1,15 +1,5 @@
import { MetaData, AdditionalInformation, Curation } from '@oceanprotocol/squid' import { MetaData, AdditionalInformation } from '@oceanprotocol/squid'
import { ServiceMetadata } from '@oceanprotocol/squid/dist/node/ddo/Service'
declare type DeliveryType = 'files' | 'api' | 'subscription'
declare type Granularity =
| 'hourly'
| 'daily'
| 'weekly'
| 'monthly'
| 'annually'
| 'Not updated periodically'
| ''
export interface Sample { export interface Sample {
name: string name: string
@ -21,14 +11,15 @@ export declare type AccessType = 'Download' | 'Compute'
export interface AdditionalInformationMarket extends AdditionalInformation { export interface AdditionalInformationMarket extends AdditionalInformation {
description: string description: string
links?: Sample[] // redefine existing key, cause not specific enough in Squid links?: Sample[] // redefine existing key, cause not specific enough in Squid
deliveryType: DeliveryType
termsAndConditions: boolean termsAndConditions: boolean
dateRange?: [string, string] dateRange?: [string, string]
supportName?: string
supportEmail?: string
access: AccessType access: AccessType
} }
export interface MetaDataMarket extends MetaData { export interface MetaDataMarket extends MetaData {
additionalInformation: AdditionalInformationMarket additionalInformation: AdditionalInformationMarket
} }
export interface ServiceMetaDataMarket extends ServiceMetadata {
attributes: MetaDataMarket
}

View File

@ -10,18 +10,18 @@ import { config } from '../config/ocean'
export interface LayoutProps { export interface LayoutProps {
children: ReactNode children: ReactNode
title?: string title: string
uri: string
description?: string description?: string
noPageHeader?: boolean noPageHeader?: boolean
location?: Location
} }
export default function Layout({ export default function Layout({
children, children,
title, title,
uri,
description, description,
noPageHeader, noPageHeader
location
}: LayoutProps): ReactElement { }: LayoutProps): ReactElement {
return ( return (
<Web3Provider> <Web3Provider>
@ -33,12 +33,7 @@ export default function Layout({
<meta name="theme-color" content="#ca2935" /> <meta name="theme-color" content="#ca2935" />
</Helmet> </Helmet>
<Seo <Seo title={title} description={description} uri={uri} />
title={title}
description={description}
uri={location.href}
location={location}
/>
<Header /> <Header />
<main className={styles.main}> <main className={styles.main}>

View File

@ -1,18 +1,16 @@
import React from 'react' import React, { ReactElement } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { useSiteMetadata } from '../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../hooks/useSiteMetadata'
export default function Seo({ export default function Seo({
title, title,
description, description,
uri, uri
location
}: { }: {
title?: string title?: string
description?: string description?: string
uri: string uri: string
location: Location }): ReactElement {
}) {
const { siteTitle, siteTagline, siteUrl, siteImage } = useSiteMetadata() const { siteTitle, siteTagline, siteUrl, siteImage } = useSiteMetadata()
// Remove trailing slash from all URLs // Remove trailing slash from all URLs
@ -37,7 +35,7 @@ export default function Seo({
<meta name="description" content={description} /> <meta name="description" content={description} />
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:description" content={description} /> <meta property="og:description" content={description} />
<meta property="og:url" content={location.href} /> <meta property="og:url" content={uri} />
<meta <meta
name="image" name="image"

View File

@ -1,6 +1,5 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect, ReactElement } from 'react'
import { DDO, Ocean } from '@oceanprotocol/squid' import { Ocean } from '@oceanprotocol/squid'
import { ServiceMetadata } from '@oceanprotocol/squid/dist/node/ddo/Service'
import { fromWei } from 'web3-utils' import { fromWei } from 'web3-utils'
import compareAsBN, { Comparisson } from '../../utils/compareAsBN' import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
import Loader from '../atoms/Loader' import Loader from '../atoms/Loader'
@ -15,18 +14,19 @@ import {
import styles from './Compute.module.css' import styles from './Compute.module.css'
import Button from '../atoms/Button' import Button from '../atoms/Button'
import Input from '../atoms/Input' import Input from '../atoms/Input'
import { MetaDataMarket } from '../../@types/MetaData'
export default function Compute({ export default function Compute({
ddo, did,
metadata,
balance, balance,
ocean ocean
}: { }: {
ddo: DDO | null did: string
metadata: MetaDataMarket
balance: string | null balance: string | null
ocean: Ocean | null ocean: Ocean | null
}) { }): ReactElement {
if (!ddo) return null
const { compute, isLoading, computeStepText, computeError } = useCompute() const { compute, isLoading, computeStepText, computeError } = useCompute()
const [isJobStarting, setIsJobStarting] = useState(false) const [isJobStarting, setIsJobStarting] = useState(false)
const [, setError] = useState('') const [, setError] = useState('')
@ -41,9 +41,7 @@ export default function Compute({
const [isPublished, setIsPublished] = useState(false) const [isPublished, setIsPublished] = useState(false)
const [file, setFile] = useState(null) const [file, setFile] = useState(null)
const metadata = ddo.findServiceByType('metadata') as ServiceMetadata const { price } = metadata.main
const { price } = metadata.attributes.main
const isFree = price === '0' const isFree = price === '0'
const [isTermsAgreed, setIsTermsAgreed] = useState(true) const [isTermsAgreed, setIsTermsAgreed] = useState(true)
@ -85,7 +83,7 @@ export default function Compute({
setIsPublished(false) setIsPublished(false)
setError('') setError('')
await compute(ddo.id, algorithmRawCode, computeContainer) await compute(did, algorithmRawCode, computeContainer)
setIsPublished(true) setIsPublished(true)
setFile(null) setFile(null)

View File

@ -1,25 +1,26 @@
import React from 'react' import React, { ReactElement } from 'react'
import { DDO } from '@oceanprotocol/squid'
import Web3 from 'web3' import Web3 from 'web3'
import compareAsBN, { Comparisson } from '../../utils/compareAsBN' import compareAsBN, { Comparisson } from '../../utils/compareAsBN'
import Button from '../atoms/Button' import Button from '../atoms/Button'
import File from '../atoms/File' import File from '../atoms/File'
import Price from '../atoms/Price' import Price from '../atoms/Price'
import { MetaDataMarket } from '../../@types/MetaData'
import Web3Feedback from '../molecules/Web3Feedback' import Web3Feedback from '../molecules/Web3Feedback'
import styles from './Consume.module.css' import styles from './Consume.module.css'
import Loader from '../atoms/Loader' 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 }) { export default function Consume({
if (!ddo) return null did,
metadata
const { web3 } = useWeb3() }: {
did: string
metadata: MetaDataMarket
}): ReactElement {
const { ocean, balanceInOcean } = useOcean() const { ocean, balanceInOcean } = useOcean()
const { consume, consumeStepText, isLoading } = useConsume() const { consume, consumeStepText, isLoading } = useConsume()
const { attributes } = ddo.findServiceByType('metadata') const { price } = metadata.main
const { price } = attributes.main const file = metadata.main.files[0]
const file = (attributes as any).main.files[0]
const isFree = price === '0' const isFree = price === '0'
const isBalanceSufficient = const isBalanceSufficient =
isFree || isFree ||
@ -34,7 +35,11 @@ export default function Consume({ ddo }: { ddo: DDO | undefined }) {
return isLoading ? ( return isLoading ? (
<Loader message={consumeStepText} isHorizontal /> <Loader message={consumeStepText} isHorizontal />
) : ( ) : (
<Button primary onClick={() => consume(ddo.id)} disabled={isDisabled}> <Button
style="primary"
onClick={() => consume(did)}
disabled={isDisabled}
>
{isFree ? 'Download' : 'Buy'} {isFree ? 'Download' : 'Buy'}
</Button> </Button>
) )

View File

@ -1,21 +1,20 @@
import React from 'react' import React, { ReactElement } from 'react'
import { DDO } from '@oceanprotocol/squid'
import { MetaDataMarket } from '../../../@types/MetaData'
import Time from '../../atoms/Time' import Time from '../../atoms/Time'
import MetaItem from './MetaItem' import MetaItem from './MetaItem'
import styles from './MetaFull.module.css' import styles from './MetaFull.module.css'
import { MetaDataMarket } from '../../../@types/MetaData'
export default function MetaFull({ export default function MetaFull({
ddo, did,
attributes metadata
}: { }: {
ddo: DDO | undefined did: string
attributes: MetaDataMarket metadata: MetaDataMarket
}) { }): ReactElement {
const { dateCreated, author, license } = attributes.main const { dateCreated, author, license } = metadata.main
let dateRange let dateRange
if (attributes && attributes.additionalInformation) { if (metadata && metadata.additionalInformation) {
;({ dateRange } = attributes.additionalInformation) ;({ dateRange } = metadata.additionalInformation)
} }
// In practice dateRange will always be defined, but in the rare case it isn't // 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> </div>
) )
} }

View File

@ -1,20 +1,18 @@
import React from 'react' import React, { ReactElement } from 'react'
import shortid from 'shortid' import shortid from 'shortid'
import { MetaDataMarket } from '../../../@types/MetaData'
import { ListItem } from '../../atoms/Lists' import { ListItem } from '../../atoms/Lists'
import { refundPolicy, assetTerms } from '../../../../site.config'
import MetaItem from './MetaItem' import MetaItem from './MetaItem'
import styles from './MetaSecondary.module.css' import styles from './MetaSecondary.module.css'
import { MetaDataMarket } from '../../../@types/MetaData'
export default function MetaSecondary({ export default function MetaSecondary({
attributes metadata
}: { }: {
attributes: MetaDataMarket metadata: MetaDataMarket
}) { }): ReactElement {
const { price } = attributes.main let links
let links, supportName, supportEmail if (metadata && metadata.additionalInformation) {
if (attributes && attributes.additionalInformation) { ;({ links } = metadata.additionalInformation)
;({ links, supportName, supportEmail } = attributes.additionalInformation)
} }
return ( return (
@ -35,37 +33,6 @@ export default function MetaSecondary({
/> />
</div> </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> </aside>
) )
} }

View File

@ -1,8 +1,9 @@
import React, { useState } from 'react' import React, { useState, ReactElement, useEffect } from 'react'
import { DDO } from '@oceanprotocol/squid' import { Aquarius, Logger } from '@oceanprotocol/squid'
import { Link } from 'gatsby' import { Link, PageProps } from 'gatsby'
import { config } from '../../../config/ocean'
import Layout from '../../../components/Layout' import Layout from '../../../components/Layout'
import { MetaDataMarket } from '../../../@types/MetaData' import { MetaDataMarket, ServiceMetaDataMarket } from '../../../@types/MetaData'
import Time from '../../atoms/Time' import Time from '../../atoms/Time'
import Markdown from '../../atoms/Markdown' import Markdown from '../../atoms/Markdown'
import Consume from '../../organisms/Consume' import Consume from '../../organisms/Consume'
@ -10,39 +11,30 @@ import Tags from '../../atoms/Tags'
import { Alert } from '../../atoms/Alert' import { Alert } from '../../atoms/Alert'
import MetaFull from './MetaFull' import MetaFull from './MetaFull'
import MetaSecondary from './MetaSecondary' import MetaSecondary from './MetaSecondary'
import Rating from '../../atoms/Rating' // import Rating from '../../atoms/Rating'
import RatingAction from './RatingAction' // import RatingAction from './RatingAction'
import styles from './index.module.css' import styles from './index.module.css'
import { useMetadata, useOcean } from '@oceanprotocol/react' import { useMetadata, useOcean } from '@oceanprotocol/react'
import Compute from '../../organisms/Compute' import Compute from '../../organisms/Compute'
import DeleteAction from '../../molecules/DeleteAsset' // import DeleteAction from '../../molecules/DeleteAsset'
export declare type AssetDetailsPageProps = {
title: string
ddo?: DDO
attributes?: MetaDataMarket
error?: string
}
const AssetDetailsPageMeta = ({ const AssetDetailsPageMeta = ({
attributes, metadata,
ddo did
}: { }: {
attributes: MetaDataMarket metadata: MetaDataMarket
ddo: DDO did: string
}) => { }) => {
if (!attributes) return null
const { ocean, balanceInOcean } = useOcean() const { ocean, balanceInOcean } = useOcean()
const { datePublished } = attributes.main const { datePublished } = metadata.main
const { const {
description, description,
copyrightHolder, copyrightHolder,
categories, categories,
tags, tags,
access access
} = attributes.additionalInformation } = metadata.additionalInformation
const { curation } = attributes const { curation } = metadata
const { getCuration } = useMetadata() const { getCuration } = useMetadata()
const [rating, setRating] = useState<number>(curation ? curation.rating : 0) const [rating, setRating] = useState<number>(curation ? curation.rating : 0)
@ -50,8 +42,9 @@ const AssetDetailsPageMeta = ({
curation ? curation.numVotes : 0 curation ? curation.numVotes : 0
) )
const isCompute = access && access === 'Compute' const isCompute = access && access === 'Compute'
const onVoteUpdate = async () => { const onVoteUpdate = async () => {
const { rating, numVotes } = await getCuration(ddo.id) const { rating, numVotes } = await getCuration(did)
setRating(rating) setRating(rating)
setNumVotes(numVotes) setNumVotes(numVotes)
@ -72,7 +65,7 @@ const AssetDetailsPageMeta = ({
</Link> </Link>
</p> </p>
)} )}
<Rating curation={{ rating, numVotes }} readonly /> {/* <Rating curation={{ rating, numVotes }} readonly /> */}
</aside> </aside>
<h2 className={styles.sectionTitle}>Summary</h2> <h2 className={styles.sectionTitle}>Summary</h2>
@ -80,7 +73,7 @@ const AssetDetailsPageMeta = ({
{tags && tags.length > 0 && <Tags items={tags} />} {tags && tags.length > 0 && <Tags items={tags} />}
<MetaFull ddo={ddo} attributes={attributes} /> <MetaFull did={did} metadata={metadata} />
<div className={styles.buttonGroup}> <div className={styles.buttonGroup}>
{/* <EditAction {/* <EditAction
ddo={ddo} ddo={ddo}
@ -88,48 +81,73 @@ const AssetDetailsPageMeta = ({
account={account} account={account}
refetchMetadata={refetchMetadata} refetchMetadata={refetchMetadata}
/> */} /> */}
<DeleteAction ddo={ddo} /> {/* <DeleteAction ddo={ddo} /> */}
</div> </div>
</div> </div>
<div> <div>
<div className={styles.sticky}> <div className={styles.sticky}>
{isCompute ? ( {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} /> {/* <RatingAction did={did} onVote={onVoteUpdate} /> */}
<MetaSecondary attributes={attributes} /> <MetaSecondary metadata={metadata} />
</div> </div>
</div> </div>
</> </>
) )
} }
const AssetDetailsPage = ({ export default function AssetDetailsPage(props: PageProps): ReactElement {
ddo, const [metadata, setMetadata] = useState<MetaDataMarket>()
attributes, const [title, setTitle] = useState<string>()
title, const [error, setError] = useState<string>()
error
}: AssetDetailsPageProps) => {
if (error) {
return (
<Layout title={title} noPageHeader>
<Alert title={title} text={error} state="error" />
</Layout>
)
}
return ( const { did } = props.pageContext as { did: string }
<Layout title={title}>
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
}
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}> <article className={styles.grid}>
{attributes && ( <AssetDetailsPageMeta did={did} metadata={metadata} />
<AssetDetailsPageMeta ddo={ddo as DDO} attributes={attributes} />
)}
</article> </article>
</Layout> </Layout>
) ) : null
} }
export default AssetDetailsPage

View File

@ -8,7 +8,7 @@ export default function PageGatsbyHistory(props: PageProps): ReactElement {
const { title, description } = content const { title, description } = content
return ( return (
<Layout title={title} description={description} location={props.location}> <Layout title={title} description={description} uri={props.uri}>
<PageHistory /> <PageHistory />
</Layout> </Layout>
) )

View File

@ -8,11 +8,7 @@ export default function PageGatsbyHome(props: PageProps): ReactElement {
const { siteTitle, siteTagline } = useSiteMetadata() const { siteTitle, siteTagline } = useSiteMetadata()
return ( return (
<Layout <Layout title={siteTitle} description={siteTagline} uri={props.uri}>
title={siteTitle}
description={siteTagline}
location={props.location}
>
<PageHome /> <PageHome />
</Layout> </Layout>
) )

View File

@ -8,7 +8,7 @@ export default function PageGatsbyPublish(props: PageProps): ReactElement {
const { title, description } = content const { title, description } = content
return ( return (
<Layout title={title} description={description} location={props.location}> <Layout title={title} description={description} uri={props.uri}>
<PagePublish /> <PagePublish />
</Layout> </Layout>
) )

View File

@ -9,7 +9,7 @@ export default function PageGatsbySearch(props: PageProps): ReactElement {
const { text, tag } = parsed const { text, tag } = parsed
return ( return (
<Layout title={`Search for ${text || tag}`} location={props.location}> <Layout title={`Search for ${text || tag}`} uri={props.uri}>
<PageSearch location={props.location} /> <PageSearch location={props.location} />
</Layout> </Layout>
) )