1
0
mirror of https://github.com/oceanprotocol/commons.git synced 2023-03-15 18:03:00 +01:00

Merge branch 'master' into fix/metadata

This commit is contained in:
Matthias Kretschmann 2019-02-15 15:36:31 +01:00
commit 45798fca23
Signed by: m
GPG Key ID: 606EEEF3C479A91F
16 changed files with 342 additions and 61 deletions

10
package-lock.json generated
View File

@ -11800,6 +11800,11 @@
"resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.8.0.tgz", "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.8.0.tgz",
"integrity": "sha512-Gwj4KnJOW15YeTJKO5frFd/WDO5Mc0zxXqL9oHx3+e9rBqW8EVARqQHSaIXznUdljrD6pvbNGW2ZGXKPEfYJfw==" "integrity": "sha512-Gwj4KnJOW15YeTJKO5frFd/WDO5Mc0zxXqL9oHx3+e9rBqW8EVARqQHSaIXznUdljrD6pvbNGW2ZGXKPEfYJfw=="
}, },
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"mout": { "mout": {
"version": "0.11.1", "version": "0.11.1",
"resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz",
@ -16564,6 +16569,11 @@
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
}, },
"react-moment": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.8.4.tgz",
"integrity": "sha512-QhI19OcfhiAn60/O6bMR0w8ApXrPFCjv6+eV0I/P9/AswzjgEAx4L7VxMBCpS/jrythLa12Q9v88req+ys4YpA=="
},
"react-router": { "react-router": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",

View File

@ -23,10 +23,12 @@
"classnames": "^2.2.6", "classnames": "^2.2.6",
"eslint": "^5.6.0", "eslint": "^5.6.0",
"is-url": "^1.2.4", "is-url": "^1.2.4",
"moment": "^2.24.0",
"query-string": "^6.2.0", "query-string": "^6.2.0",
"react": "^16.8.1", "react": "^16.8.1",
"react-dom": "^16.8.1", "react-dom": "^16.8.1",
"react-helmet": "^5.2.0", "react-helmet": "^5.2.0",
"react-moment": "^0.8.4",
"react-router-dom": "^4.3.1", "react-router-dom": "^4.3.1",
"react-transition-group": "^2.5.3", "react-transition-group": "^2.5.3",
"slugify": "^1.3.4", "slugify": "^1.3.4",

View File

@ -2,7 +2,7 @@ import React from 'react'
import { Route, Switch } from 'react-router-dom' import { Route, Switch } from 'react-router-dom'
import About from './routes/About' import About from './routes/About'
import Details from './routes/Details' import Details from './routes/Details/'
import Home from './routes/Home' import Home from './routes/Home'
import NotFound from './routes/NotFound' import NotFound from './routes/NotFound'
import Publish from './routes/Publish/' import Publish from './routes/Publish/'

View File

@ -1,8 +1,10 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import cx from 'classnames'
import styles from './Button.module.scss' import styles from './Button.module.scss'
interface ButtonProps { interface ButtonProps {
children: string children: string
className?: string
primary?: boolean primary?: boolean
link?: boolean link?: boolean
href?: string href?: string
@ -12,7 +14,14 @@ interface ButtonProps {
export default class Button extends PureComponent<ButtonProps, any> { export default class Button extends PureComponent<ButtonProps, any> {
public render() { public render() {
let classes let classes
const { primary, link, href, children, ...props } = this.props const {
primary,
link,
href,
children,
className,
...props
} = this.props
if (primary) { if (primary) {
classes = styles.buttonPrimary classes = styles.buttonPrimary
@ -23,11 +32,11 @@ export default class Button extends PureComponent<ButtonProps, any> {
} }
return href ? ( return href ? (
<a href={href} className={classes} {...props}> <a href={href} className={cx(classes, className)} {...props}>
{children} {children}
</a> </a>
) : ( ) : (
<button className={classes} {...props}> <button className={cx(classes, className)} {...props}>
{children} {children}
</button> </button>
) )

View File

@ -2,7 +2,7 @@
.content { .content {
padding: 0 $spacer / 1.5; padding: 0 $spacer / 1.5;
max-width: $break-point--small; max-width: 47rem;
margin: 0 auto; margin: 0 auto;
@media (min-width: $break-point--small) { @media (min-width: $break-point--small) {

View File

@ -0,0 +1,38 @@
@import '../../styles/variables';
.asset {
> a {
display: block;
height: 100%;
padding: $spacer;
border: 1px solid $brand-grey-lighter;
border-radius: $border-radius;
background: $brand-white;
color: inherit;
&:hover,
&:focus {
color: inherit;
border-color: $brand-pink;
transform: none;
}
}
h1 {
font-size: $font-size-large;
margin-top: 0;
}
p {
margin-bottom: 0;
font-size: $font-size-small;
}
}
.assetFooter {
border-top: 1px solid $brand-grey-lighter;
padding-top: $spacer / 2;
margin-top: $spacer / 2;
font-size: $font-size-small;
color: $brand-grey-light;
}

View File

@ -0,0 +1,27 @@
import React from 'react'
import { Link } from 'react-router-dom'
import styles from './Asset.module.scss'
const AssetLink = ({ asset }: { asset: any }) => {
const { metadata } = asset.findServiceByType('Metadata')
const { base } = metadata
return (
<article className={styles.asset}>
<Link to={`/asset/${asset.id}`}>
<h1>{base.name}</h1>
<p>{base.description.substring(0, 90)}</p>
<footer className={styles.assetFooter}>
{base.categories ? (
<div>{base.category}</div>
) : (
<div>Fake Category</div>
)}
</footer>
</Link>
</article>
)
}
export default AssetLink

View File

@ -2,7 +2,7 @@
.header { .header {
margin-top: $spacer; margin-top: $spacer;
margin-bottom: $spacer * 2; margin-bottom: $spacer;
h1 { h1 {
margin: 0; margin: 0;

View File

@ -24,12 +24,14 @@ const Route = ({
</Helmet> </Helmet>
<Content wide={wide}> <Content wide={wide}>
<header className={styles.header}> <article>
<h1>{title}</h1> <header className={styles.header}>
{description && <p>{description}</p>} <h1>{title}</h1>
</header> {description && <p>{description}</p>}
</header>
{children} {children}
</article>
</Content> </Content>
</div> </div>
) )

View File

@ -26,7 +26,6 @@
"type": { "type": {
"label": "Type", "label": "Type",
"type": "select", "type": "select",
"required": true,
"options": ["Data set", "Algorithm", "Container", "Workflow", "Other"] "options": ["Data set", "Algorithm", "Container", "Workflow", "Other"]
}, },
"author": { "author": {
@ -58,7 +57,6 @@
"categories": { "categories": {
"label": "Categories", "label": "Categories",
"type": "select", "type": "select",
"required": true,
"options": [ "options": [
"Image Recognition", "Image Recognition",
"Dataset Of Datasets", "Dataset Of Datasets",

View File

@ -0,0 +1,95 @@
@import '../../styles/variables';
.metaPrimary {
margin-bottom: $spacer;
}
.copyrightHolder {
color: $brand-grey-light;
font-size: $font-size-large;
border-bottom: 1px solid $brand-grey-lighter;
margin-bottom: $spacer / $line-height;
padding-bottom: $spacer / $line-height;
}
.metaPrimaryData {
font-size: $font-size-small;
color: $brand-grey-light;
> * {
display: block;
white-space: nowrap;
}
@media (min-width: $break-point--small) {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
> * {
flex: 0 0 48%;
}
}
@media (min-width: $break-point--medium) {
> * {
flex: 0;
}
}
}
.description {
// respect line breaks from textarea
white-space: pre-line;
}
.meta {
border-top: 1px solid $brand-grey-lighter;
border-bottom: 1px solid $brand-grey-lighter;
padding-top: $spacer;
padding-bottom: $spacer;
margin-top: $spacer;
margin-bottom: $spacer;
list-style: none;
padding-left: 0;
font-size: $font-size-small;
li {
width: 100%;
margin-bottom: $spacer;
@media (min-width: $break-point--small) {
display: flex;
margin-bottom: 0;
}
&:before {
display: none;
}
}
}
.metaLabel {
display: block;
@media (min-width: $break-point--small) {
width: 30%;
}
}
.metaValue {
display: block;
&,
code {
overflow-wrap: break-word;
}
code {
display: inline;
}
@media (min-width: $break-point--small) {
width: 70%;
}
}

View File

@ -0,0 +1,93 @@
import React, { PureComponent } from 'react'
import { Link } from 'react-router-dom'
import Button from '../../components/atoms/Button'
import Moment from 'react-moment'
import styles from './AssetDetails.module.scss'
interface AssetDetailsProps {
metadata: any
ddo: any
purchaseAsset: any
}
export default class AssetDetails extends PureComponent<AssetDetailsProps> {
public render() {
const { metadata, ddo, purchaseAsset } = this.props
const { base } = metadata
return (
<>
<aside className={styles.metaPrimary}>
<h2
className={styles.copyrightHolder}
title="Copyright Holder"
>
{base.copyrightHolder}
</h2>
<div className={styles.metaPrimaryData}>
<span title="Date published">
<Moment
date={base.dateCreated}
format="L"
interval={0}
/>
</span>
{base.categories ? (
// TODO: Make this link to search for respective category
<Link to={'search?q='}>{base.categories[0]}</Link>
) : (
<Link to={'search?q='}>Fake Category</Link>
)}
<span>fake json contentType</span>
<span>fake 18.5 MB</span>
</div>
</aside>
<div className={styles.description}>{base.description}</div>
<ul className={styles.meta}>
<li>
<span className={styles.metaLabel}>
<strong>Author</strong>
</span>
<span className={styles.metaValue}>{base.author}</span>
</li>
<li>
<span className={styles.metaLabel}>
<strong>License</strong>
</span>
<span className={styles.metaValue}>{base.license}</span>
</li>
<li>
<span className={styles.metaLabel}>
<strong>File Encoding</strong>
</span>
<span className={styles.metaValue}>fake UTF-8</span>
</li>
<li>
<span className={styles.metaLabel}>
<strong>Compression</strong>
</span>
<span className={styles.metaValue}>fake None</span>
</li>
<li>
<span className={styles.metaLabel}>
<strong>DID</strong>
</span>
<span className={styles.metaValue}>
<code>{ddo.id}</code>
</span>
</li>
</ul>
<Button onClick={() => purchaseAsset(ddo)}>
Download asset
</Button>
<pre>
<code>{JSON.stringify(metadata, null, 2)}</code>
</pre>
</>
)
}
}

View File

@ -1,13 +1,15 @@
import { Logger } from '@oceanprotocol/squid'
import React, { Component } from 'react' import React, { Component } from 'react'
import Route from '../components/templates/Route' import { Logger } from '@oceanprotocol/squid'
import Button from '../components/atoms/Button' import queryString from 'query-string'
import { User } from '../context/User' import Route from '../../components/templates/Route'
import quertString from 'query-string' import Spinner from '../../components/atoms/Spinner'
import { User } from '../../context/User'
import AssetDetails from './AssetDetails'
import stylesApp from '../../App.module.scss'
interface DetailsState { interface DetailsState {
ddo: any ddo: any
metadata: any metadata: { base: { name: string } }
} }
interface DetailsProps { interface DetailsProps {
@ -16,14 +18,14 @@ interface DetailsProps {
} }
export default class Details extends Component<DetailsProps, DetailsState> { export default class Details extends Component<DetailsProps, DetailsState> {
public state = { ddo: null, metadata: null } public state = { ddo: {}, metadata: { base: { name: '' } } }
public async componentDidMount() { public async componentDidMount() {
const ddo = await this.context.ocean.resolveDID( const ddo = await this.context.ocean.resolveDID(
this.props.match.params.did this.props.match.params.did
) )
const { metadata } = ddo.findServiceByType('Metadata') const { metadata } = ddo.findServiceByType('Metadata')
this.setState({ ddo, metadata }) this.setState({ ddo, metadata: { base: metadata.base } })
} }
private purchaseAsset = async (ddo: any) => { private purchaseAsset = async (ddo: any) => {
@ -43,7 +45,7 @@ export default class Details extends Component<DetailsProps, DetailsState> {
(files: any) => { (files: any) => {
Logger.log('downloading files', files) Logger.log('downloading files', files)
files.forEach((file: any) => { files.forEach((file: any) => {
const parsedUrl: any = quertString.parseUrl(file) const parsedUrl: any = queryString.parseUrl(file)
setTimeout(() => { setTimeout(() => {
// eslint-disable-next-line // eslint-disable-next-line
window.open(parsedUrl.query.url) window.open(parsedUrl.query.url)
@ -57,25 +59,23 @@ export default class Details extends Component<DetailsProps, DetailsState> {
} }
} }
private showDetails = (ddo: any) => {
return (
<>
<div>{JSON.stringify(this.state.metadata)}</div>
<Button onClick={() => this.purchaseAsset(ddo)}>
Purchase asset
</Button>
</>
)
}
public render() { public render() {
const { metadata, ddo } = this.state
return ( return (
<Route title={'Details'}> <Route
{this.state.metadata ? ( title={metadata.base ? metadata.base.name : 'Loading Details'}
this.showDetails(this.state.ddo) >
{metadata && metadata.base.name ? (
<AssetDetails
metadata={metadata}
ddo={ddo}
purchaseAsset={this.purchaseAsset}
/>
) : ( ) : (
<div>Loading</div> <div className={stylesApp.loader}>
<Spinner message={'Loading asset...'} />
</div>
)} )}
</Route> </Route>
) )

View File

@ -0,0 +1,16 @@
@import '../styles/variables';
.results {
display: grid;
grid-template-columns: 1fr;
grid-gap: $spacer;
max-width: 100%;
@media (min-width: $break-point--small) {
grid-template-columns: 2fr 2fr;
}
@media (min-width: $break-point--medium) {
grid-template-columns: 2fr 2fr 2fr;
}
}

View File

@ -1,8 +1,9 @@
import queryString from 'query-string' import queryString from 'query-string'
import React, { Component } from 'react' import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import Route from '../components/templates/Route' import Route from '../components/templates/Route'
import { User } from '../context/User' import { User } from '../context/User'
import Asset from '../components/molecules/Asset'
import styles from './Search.module.scss'
interface SearchState { interface SearchState {
results: any[] results: any[]
@ -31,25 +32,21 @@ export default class Search extends Component<SearchProps, SearchState> {
this.setState({ results: assets }) this.setState({ results: assets })
} }
private renderAssetBox = (asset: any) => { public renderResults = () =>
const { metadata } = asset.findServiceByType('Metadata') this.state.results.length ? (
return ( <div className={styles.results}>
<Link key={asset.id} to={`/asset/${asset.id}`}> {this.state.results.map(asset => (
<div>{asset.id}</div> <Asset key={asset} asset={asset} />
<div>{metadata.base.name}</div> ))}
<div>{metadata.base.description}</div> </div>
</Link> ) : (
<div>No data sets yet</div>
) )
}
public render() { public render() {
return ( return (
<Route title="Search Results" wide> <Route title="Search Results" wide>
{this.state.results.length ? ( {this.renderResults()}
this.state.results.map(asset => this.renderAssetBox(asset))
) : (
<div>No data sets yet</div>
)}
</Route> </Route>
) )
} }

View File

@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
@ -19,7 +15,5 @@
"noEmit": true, "noEmit": true,
"jsx": "preserve" "jsx": "preserve"
}, },
"include": [ "include": ["src"]
"src"
]
} }