diff --git a/package-lock.json b/package-lock.json index 52dfb27..026d84d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11800,6 +11800,11 @@ "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.8.0.tgz", "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": { "version": "0.11.1", "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", "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": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", diff --git a/package.json b/package.json index 3b898c0..ee147b1 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,12 @@ "classnames": "^2.2.6", "eslint": "^5.6.0", "is-url": "^1.2.4", + "moment": "^2.24.0", "query-string": "^6.2.0", "react": "^16.8.1", "react-dom": "^16.8.1", "react-helmet": "^5.2.0", + "react-moment": "^0.8.4", "react-router-dom": "^4.3.1", "react-transition-group": "^2.5.3", "slugify": "^1.3.4", diff --git a/src/Routes.tsx b/src/Routes.tsx index 0009c32..84fef08 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -2,7 +2,7 @@ import React from 'react' import { Route, Switch } from 'react-router-dom' import About from './routes/About' -import Details from './routes/Details' +import Details from './routes/Details/' import Home from './routes/Home' import NotFound from './routes/NotFound' import Publish from './routes/Publish/' diff --git a/src/components/atoms/Button.tsx b/src/components/atoms/Button.tsx index a309b7f..312565b 100644 --- a/src/components/atoms/Button.tsx +++ b/src/components/atoms/Button.tsx @@ -1,8 +1,10 @@ import React, { PureComponent } from 'react' +import cx from 'classnames' import styles from './Button.module.scss' interface ButtonProps { children: string + className?: string primary?: boolean link?: boolean href?: string @@ -12,7 +14,14 @@ interface ButtonProps { export default class Button extends PureComponent { public render() { let classes - const { primary, link, href, children, ...props } = this.props + const { + primary, + link, + href, + children, + className, + ...props + } = this.props if (primary) { classes = styles.buttonPrimary @@ -23,11 +32,11 @@ export default class Button extends PureComponent { } return href ? ( - + {children} ) : ( - ) diff --git a/src/components/atoms/Content.module.scss b/src/components/atoms/Content.module.scss index 2c0860d..64662ba 100644 --- a/src/components/atoms/Content.module.scss +++ b/src/components/atoms/Content.module.scss @@ -2,7 +2,7 @@ .content { padding: 0 $spacer / 1.5; - max-width: $break-point--small; + max-width: 47rem; margin: 0 auto; @media (min-width: $break-point--small) { diff --git a/src/components/molecules/Asset.module.scss b/src/components/molecules/Asset.module.scss new file mode 100644 index 0000000..855b840 --- /dev/null +++ b/src/components/molecules/Asset.module.scss @@ -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; +} diff --git a/src/components/molecules/Asset.tsx b/src/components/molecules/Asset.tsx new file mode 100644 index 0000000..fd2555b --- /dev/null +++ b/src/components/molecules/Asset.tsx @@ -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 ( +
+ +

{base.name}

+

{base.description.substring(0, 90)}

+ +
+ {base.categories ? ( +
{base.category}
+ ) : ( +
Fake Category
+ )} +
+ +
+ ) +} + +export default AssetLink diff --git a/src/components/templates/Route.module.scss b/src/components/templates/Route.module.scss index 00280f8..323783f 100644 --- a/src/components/templates/Route.module.scss +++ b/src/components/templates/Route.module.scss @@ -2,7 +2,7 @@ .header { margin-top: $spacer; - margin-bottom: $spacer * 2; + margin-bottom: $spacer; h1 { margin: 0; diff --git a/src/components/templates/Route.tsx b/src/components/templates/Route.tsx index 5153158..f5aa93f 100644 --- a/src/components/templates/Route.tsx +++ b/src/components/templates/Route.tsx @@ -24,12 +24,14 @@ const Route = ({ -
-

{title}

- {description &&

{description}

} -
+
+
+

{title}

+ {description &&

{description}

} +
- {children} + {children} +
) diff --git a/src/data/form-publish.json b/src/data/form-publish.json index 7fcb152..c758b98 100644 --- a/src/data/form-publish.json +++ b/src/data/form-publish.json @@ -26,7 +26,6 @@ "type": { "label": "Type", "type": "select", - "required": true, "options": ["Data set", "Algorithm", "Container", "Workflow", "Other"] }, "author": { @@ -58,7 +57,6 @@ "categories": { "label": "Categories", "type": "select", - "required": true, "options": [ "Image Recognition", "Dataset Of Datasets", diff --git a/src/routes/Details/AssetDetails.module.scss b/src/routes/Details/AssetDetails.module.scss new file mode 100644 index 0000000..de65a0c --- /dev/null +++ b/src/routes/Details/AssetDetails.module.scss @@ -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%; + } +} diff --git a/src/routes/Details/AssetDetails.tsx b/src/routes/Details/AssetDetails.tsx new file mode 100644 index 0000000..792a3ce --- /dev/null +++ b/src/routes/Details/AssetDetails.tsx @@ -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 { + public render() { + const { metadata, ddo, purchaseAsset } = this.props + const { base } = metadata + + return ( + <> + + +
{base.description}
+ +
    +
  • + + Author + + {base.author} +
  • +
  • + + License + + {base.license} +
  • +
  • + + File Encoding + + fake UTF-8 +
  • +
  • + + Compression + + fake None +
  • +
  • + + DID + + + {ddo.id} + +
  • +
+ + + +
+                    {JSON.stringify(metadata, null, 2)}
+                
+ + ) + } +} diff --git a/src/routes/Details.tsx b/src/routes/Details/index.tsx similarity index 62% rename from src/routes/Details.tsx rename to src/routes/Details/index.tsx index 4bbb1aa..4f5bb12 100644 --- a/src/routes/Details.tsx +++ b/src/routes/Details/index.tsx @@ -1,13 +1,15 @@ -import { Logger } from '@oceanprotocol/squid' import React, { Component } from 'react' -import Route from '../components/templates/Route' -import Button from '../components/atoms/Button' -import { User } from '../context/User' -import quertString from 'query-string' +import { Logger } from '@oceanprotocol/squid' +import queryString from 'query-string' +import Route from '../../components/templates/Route' +import Spinner from '../../components/atoms/Spinner' +import { User } from '../../context/User' +import AssetDetails from './AssetDetails' +import stylesApp from '../../App.module.scss' interface DetailsState { ddo: any - metadata: any + metadata: { base: { name: string } } } interface DetailsProps { @@ -16,14 +18,14 @@ interface DetailsProps { } export default class Details extends Component { - public state = { ddo: null, metadata: null } + public state = { ddo: {}, metadata: { base: { name: '' } } } public async componentDidMount() { const ddo = await this.context.ocean.resolveDID( this.props.match.params.did ) const { metadata } = ddo.findServiceByType('Metadata') - this.setState({ ddo, metadata }) + this.setState({ ddo, metadata: { base: metadata.base } }) } private purchaseAsset = async (ddo: any) => { @@ -43,7 +45,7 @@ export default class Details extends Component { (files: any) => { Logger.log('downloading files', files) files.forEach((file: any) => { - const parsedUrl: any = quertString.parseUrl(file) + const parsedUrl: any = queryString.parseUrl(file) setTimeout(() => { // eslint-disable-next-line window.open(parsedUrl.query.url) @@ -57,25 +59,23 @@ export default class Details extends Component { } } - private showDetails = (ddo: any) => { - return ( - <> -
{JSON.stringify(this.state.metadata)}
- - - - ) - } - public render() { + const { metadata, ddo } = this.state + return ( - - {this.state.metadata ? ( - this.showDetails(this.state.ddo) + + {metadata && metadata.base.name ? ( + ) : ( -
Loading
+
+ +
)}
) diff --git a/src/routes/Search.module.scss b/src/routes/Search.module.scss new file mode 100644 index 0000000..7d1d86a --- /dev/null +++ b/src/routes/Search.module.scss @@ -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; + } +} diff --git a/src/routes/Search.tsx b/src/routes/Search.tsx index 05e0bbd..901437f 100644 --- a/src/routes/Search.tsx +++ b/src/routes/Search.tsx @@ -1,8 +1,9 @@ import queryString from 'query-string' import React, { Component } from 'react' -import { Link } from 'react-router-dom' import Route from '../components/templates/Route' import { User } from '../context/User' +import Asset from '../components/molecules/Asset' +import styles from './Search.module.scss' interface SearchState { results: any[] @@ -31,25 +32,21 @@ export default class Search extends Component { this.setState({ results: assets }) } - private renderAssetBox = (asset: any) => { - const { metadata } = asset.findServiceByType('Metadata') - return ( - -
{asset.id}
-
{metadata.base.name}
-
{metadata.base.description}
- + public renderResults = () => + this.state.results.length ? ( +
+ {this.state.results.map(asset => ( + + ))} +
+ ) : ( +
No data sets yet
) - } public render() { return ( - {this.state.results.length ? ( - this.state.results.map(asset => this.renderAssetBox(asset)) - ) : ( -
No data sets yet
- )} + {this.renderResults()}
) } diff --git a/tsconfig.json b/tsconfig.json index 0980b23..2f4d2c3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, @@ -19,7 +15,5 @@ "noEmit": true, "jsx": "preserve" }, - "include": [ - "src" - ] + "include": ["src"] }