Merge pull request #36 from oceanprotocol/feature/assets-styling
More assets styling
@ -2,8 +2,8 @@ import React, { Component } from 'react'
|
||||
import Web3 from 'web3'
|
||||
import { BrowserRouter as Router } from 'react-router-dom'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import Header from './components/Header'
|
||||
import Footer from './components/Footer'
|
||||
import Header from './components/organisms/Header'
|
||||
import Footer from './components/organisms/Footer'
|
||||
import Spinner from './components/atoms/Spinner'
|
||||
import { User } from './context/User'
|
||||
import { provideOcean } from './ocean'
|
||||
|
@ -8,7 +8,7 @@ import NotFound from './routes/NotFound'
|
||||
import Publish from './routes/Publish/'
|
||||
import Search from './routes/Search'
|
||||
import Faucet from './routes/Faucet'
|
||||
import Invoices from './routes/Invoices'
|
||||
import History from './routes/History'
|
||||
import Styleguide from './routes/Styleguide'
|
||||
|
||||
const Routes = () => (
|
||||
@ -20,7 +20,7 @@ const Routes = () => (
|
||||
<Route component={Search} path="/search" />
|
||||
<Route component={Details} path="/asset/:did" />
|
||||
<Route component={Faucet} path="/faucet" />
|
||||
<Route component={Invoices} path="/invoices" />
|
||||
<Route component={History} path="/history" />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
)
|
||||
|
9
client/src/components/atoms/CategoryImage.module.scss
Normal file
@ -0,0 +1,9 @@
|
||||
@import '../../styles/variables';
|
||||
|
||||
.categoryImage {
|
||||
height: 4rem;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
margin-bottom: $spacer / $line-height;
|
||||
background-color: $brand-grey-lighter;
|
||||
}
|
121
client/src/components/atoms/CategoryImage.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import styles from './CategoryImage.module.scss'
|
||||
|
||||
import agriculture from '../../img/categories/agriculture.jpg'
|
||||
import anthroarche from '../../img/categories/anthroarche.jpg'
|
||||
import astronomy from '../../img/categories/astronomy.jpg'
|
||||
import biology from '../../img/categories/biology.jpg'
|
||||
import business from '../../img/categories/business.jpg'
|
||||
import chemistry from '../../img/categories/chemistry.jpg'
|
||||
import communication from '../../img/categories/communication.jpg'
|
||||
import computer from '../../img/categories/computer.jpg'
|
||||
import dataofdata from '../../img/categories/dataofdata.jpg'
|
||||
import deeplearning from '../../img/categories/deeplearning.jpg'
|
||||
import demographics from '../../img/categories/demographics.jpg'
|
||||
import earth from '../../img/categories/earth.jpg'
|
||||
import economics from '../../img/categories/economics.jpg'
|
||||
import engineering from '../../img/categories/engineering.jpg'
|
||||
import history from '../../img/categories/history.jpg'
|
||||
import imagesets from '../../img/categories/imagesets.jpg'
|
||||
import language from '../../img/categories/language.jpg'
|
||||
import law from '../../img/categories/law.jpg'
|
||||
import mathematics from '../../img/categories/mathematics.jpg'
|
||||
import medicine from '../../img/categories/medicine.jpg'
|
||||
import other from '../../img/categories/other.jpg'
|
||||
import performingarts from '../../img/categories/performingarts.jpg'
|
||||
import philosophy from '../../img/categories/philosophy.jpg'
|
||||
import physics from '../../img/categories/physics.jpg'
|
||||
import politics from '../../img/categories/politics.jpg'
|
||||
import psychology from '../../img/categories/psychology.jpg'
|
||||
import sociology from '../../img/categories/sociology.jpg'
|
||||
import sports from '../../img/categories/sports.jpg'
|
||||
import theology from '../../img/categories/theology.jpg'
|
||||
import transport from '../../img/categories/transport.jpg'
|
||||
import urbanplanning from '../../img/categories/urbanplanning.jpg'
|
||||
import visualart from '../../img/categories/visualart.jpg'
|
||||
|
||||
const categoryImageFile = (category: string) => {
|
||||
switch (category) {
|
||||
case 'agriculture':
|
||||
return agriculture
|
||||
case 'anthroarche':
|
||||
return anthroarche
|
||||
case 'astronomy':
|
||||
return astronomy
|
||||
case 'biology':
|
||||
return biology
|
||||
case 'business':
|
||||
return business
|
||||
case 'chemistry':
|
||||
return chemistry
|
||||
case 'communication':
|
||||
return communication
|
||||
case 'computer':
|
||||
return computer
|
||||
case 'dataofdata':
|
||||
return dataofdata
|
||||
case 'deeplearning':
|
||||
return deeplearning
|
||||
case 'demographics':
|
||||
return demographics
|
||||
case 'earth':
|
||||
return earth
|
||||
case 'economics-and-finance':
|
||||
return economics
|
||||
case 'engineering':
|
||||
return engineering
|
||||
case 'history':
|
||||
return history
|
||||
case 'imagesets':
|
||||
return imagesets
|
||||
case 'language':
|
||||
return language
|
||||
case 'law':
|
||||
return law
|
||||
case 'mathematics':
|
||||
return mathematics
|
||||
case 'medicine':
|
||||
return medicine
|
||||
case 'other':
|
||||
return other
|
||||
case 'performingarts':
|
||||
return performingarts
|
||||
case 'philosophy':
|
||||
return philosophy
|
||||
case 'physics':
|
||||
return physics
|
||||
case 'politics':
|
||||
return politics
|
||||
case 'psychology':
|
||||
return psychology
|
||||
case 'sociology':
|
||||
return sociology
|
||||
case 'sports':
|
||||
return sports
|
||||
case 'theology':
|
||||
return theology
|
||||
case 'transport':
|
||||
return transport
|
||||
case 'urbanplanning':
|
||||
return urbanplanning
|
||||
case 'visualart':
|
||||
return visualart
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
export default class CategoryImage extends PureComponent<{ category: string }> {
|
||||
public render() {
|
||||
const image = categoryImageFile(this.props.category)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.categoryImage}
|
||||
style={{
|
||||
backgroundImage: `url(${image})`
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
border-radius: $border-radius;
|
||||
background: $brand-white;
|
||||
color: inherit;
|
||||
position: relative;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -29,9 +30,36 @@
|
||||
}
|
||||
}
|
||||
|
||||
.assetList {
|
||||
> a {
|
||||
color: $brand-grey-dark;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
padding-top: $spacer / 2;
|
||||
padding-bottom: $spacer / 2;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $brand-pink;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: $font-size-base;
|
||||
color: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: $font-size-small;
|
||||
color: $brand-grey-light;
|
||||
}
|
||||
|
||||
.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;
|
||||
|
@ -1,23 +1,31 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import moment from 'moment'
|
||||
import styles from './Asset.module.scss'
|
||||
import CategoryImage from '../atoms/CategoryImage'
|
||||
|
||||
const AssetLink = ({ asset }: { asset: any }) => {
|
||||
const AssetLink = ({ asset, list }: { asset: any; list?: boolean }) => {
|
||||
const { metadata } = asset.findServiceByType('Metadata')
|
||||
const { base } = metadata
|
||||
|
||||
return (
|
||||
<article className={styles.asset}>
|
||||
return list ? (
|
||||
<article className={styles.assetList}>
|
||||
<Link to={`/asset/${asset.id}`}>
|
||||
<h1>{base.name}</h1>
|
||||
<p>{base.description.substring(0, 90)}</p>
|
||||
<div className={styles.date} title={base.dateCreated}>
|
||||
{moment(base.dateCreated, 'YYYYMMDD').fromNow()}
|
||||
</div>
|
||||
</Link>
|
||||
</article>
|
||||
) : (
|
||||
<article className={styles.asset}>
|
||||
<Link to={`/asset/${asset.id}`}>
|
||||
<CategoryImage category={base.categories[0][0]} />
|
||||
<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>
|
||||
)}
|
||||
{base.categories && <div>{base.categories[0][0]}</div>}
|
||||
</footer>
|
||||
</Link>
|
||||
</article>
|
||||
|
@ -1,34 +0,0 @@
|
||||
@import '../../styles/variables';
|
||||
|
||||
.assetsUser {
|
||||
margin-top: $spacer * 3;
|
||||
margin-bottom: $spacer;
|
||||
|
||||
> div {
|
||||
text-align: center;
|
||||
margin-top: $spacer;
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
}
|
||||
|
||||
.assets {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
font-size: $font-size-h4;
|
||||
color: $brand-grey-light;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
padding-bottom: $spacer / 2;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { User } from '../../context/User'
|
||||
import Spinner from '../atoms/Spinner'
|
||||
import Asset from '../molecules/Asset'
|
||||
import styles from './AssetsUser.module.scss'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
|
||||
export default class AssetsUser extends PureComponent {
|
||||
public state = { results: [], isLoading: true }
|
||||
|
||||
public componentDidMount() {
|
||||
this.searchOcean()
|
||||
}
|
||||
|
||||
private async searchOcean() {
|
||||
this.context.ocean.keeper.didRegistry.contract.getPastEvents(
|
||||
'DIDAttributeRegistered',
|
||||
{
|
||||
filter: { _owner: this.context.account },
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
},
|
||||
async (error: any, events: any) => {
|
||||
if (error) {
|
||||
Logger.log('error retrieving', error)
|
||||
this.setState({ isLoading: false })
|
||||
} else {
|
||||
const results = []
|
||||
for (const event of events) {
|
||||
const ddo = await this.context.ocean.assets.resolve(
|
||||
`did:op:${event.returnValues._did.substring(2)}`
|
||||
)
|
||||
results.push(ddo)
|
||||
}
|
||||
this.setState({ results, isLoading: false })
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div className={styles.assetsUser}>
|
||||
<h2 className={styles.subTitle}>Your Data Sets</h2>
|
||||
|
||||
{this.state.isLoading ? (
|
||||
<Spinner />
|
||||
) : this.state.results.length ? (
|
||||
<div className={styles.assets}>
|
||||
{this.state.results
|
||||
.filter(asset => !!asset)
|
||||
.map((asset: any) => (
|
||||
<Asset key={asset.id} asset={asset} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<p>None yet.</p>
|
||||
<Link to="/publish">+ Publish A Data Set</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AssetsUser.contextType = User
|
25
client/src/components/organisms/AssetsUser.module.scss
Normal file
@ -0,0 +1,25 @@
|
||||
@import '../../styles/variables';
|
||||
|
||||
.assetsUser {
|
||||
margin-top: $spacer;
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
font-size: $font-size-h4;
|
||||
color: $brand-grey-light;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
padding-bottom: $spacer / 2;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.link {
|
||||
display: block;
|
||||
margin-top: $spacer / 2;
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
margin-top: $spacer;
|
||||
color: $brand-grey-light;
|
||||
}
|
96
client/src/components/organisms/AssetsUser.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import { User } from '../../context/User'
|
||||
import Spinner from '../atoms/Spinner'
|
||||
import Asset from '../molecules/Asset'
|
||||
import styles from './AssetsUser.module.scss'
|
||||
|
||||
export default class AssetsUser extends PureComponent<
|
||||
{ list?: boolean; recent?: number },
|
||||
{ results: any[]; isLoading: boolean }
|
||||
> {
|
||||
public state = { results: [], isLoading: true }
|
||||
|
||||
public componentDidMount() {
|
||||
this.searchOcean()
|
||||
}
|
||||
|
||||
private async searchOcean() {
|
||||
if (this.context.account) {
|
||||
this.context.ocean.keeper.didRegistry.contract.getPastEvents(
|
||||
'DIDAttributeRegistered',
|
||||
{
|
||||
filter: { _owner: this.context.account },
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
},
|
||||
async (error: any, events: any) => {
|
||||
if (error) {
|
||||
Logger.log('error retrieving', error)
|
||||
this.setState({ isLoading: false })
|
||||
} else {
|
||||
const results = []
|
||||
for (const event of events) {
|
||||
const ddo = await this.context.ocean.assets.resolve(
|
||||
`did:op:${event.returnValues._did.substring(2)}`
|
||||
)
|
||||
results.push(ddo)
|
||||
}
|
||||
this.setState({ results, isLoading: false })
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
this.setState({ isLoading: false })
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
this.context.account && (
|
||||
<div className={styles.assetsUser}>
|
||||
{this.props.recent && (
|
||||
<h2 className={styles.subTitle}>
|
||||
Your Latest Data Sets
|
||||
</h2>
|
||||
)}
|
||||
|
||||
{this.state.isLoading ? (
|
||||
<Spinner />
|
||||
) : this.state.results.length ? (
|
||||
<>
|
||||
{this.state.results
|
||||
.slice(
|
||||
0,
|
||||
this.props.recent
|
||||
? this.props.recent
|
||||
: undefined
|
||||
)
|
||||
.filter(asset => !!asset)
|
||||
.map((asset: any) => (
|
||||
<Asset
|
||||
list={this.props.list}
|
||||
key={asset.id}
|
||||
asset={asset}
|
||||
/>
|
||||
))}
|
||||
{this.props.recent && (
|
||||
<Link className={styles.link} to={'/history'}>
|
||||
All Data Sets
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className={styles.empty}>
|
||||
<p>No Data Sets Yet.</p>
|
||||
<Link to="/publish">+ Publish A Data Set</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AssetsUser.contextType = User
|
@ -1,4 +1,4 @@
|
||||
@import '../styles/variables';
|
||||
@import '../../styles/variables';
|
||||
|
||||
.footer {
|
||||
color: $brand-grey-light;
|
@ -1,8 +1,8 @@
|
||||
import React from 'react'
|
||||
import Content from '../components/atoms/Content'
|
||||
import Content from '../atoms/Content'
|
||||
import styles from './Footer.module.scss'
|
||||
|
||||
import meta from '../data/meta.json'
|
||||
import meta from '../../data/meta.json'
|
||||
|
||||
const Footer = () => (
|
||||
<footer className={styles.footer}>
|
@ -1,4 +1,4 @@
|
||||
@import '../styles/variables';
|
||||
@import '../../styles/variables';
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
@ -6,7 +6,7 @@
|
||||
}
|
||||
|
||||
.headerContent {
|
||||
composes: wide from './atoms/Content.module.scss';
|
||||
composes: wide from '../atoms/Content.module.scss';
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
import React from 'react'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import { ReactComponent as Logo } from '@oceanprotocol/art/logo/logo.svg'
|
||||
import AccountStatus from './molecules/AccountStatus/'
|
||||
import AccountStatus from '../molecules/AccountStatus'
|
||||
import styles from './Header.module.scss'
|
||||
|
||||
import menu from '../data/menu.json'
|
||||
import meta from '../data/meta.json'
|
||||
import menu from '../../data/menu.json'
|
||||
import meta from '../../data/meta.json'
|
||||
|
||||
const Header = () => (
|
||||
<header className={styles.header}>
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import Button from '../atoms/Button'
|
||||
import AccountStatus from './AccountStatus/'
|
||||
import AccountStatus from '../molecules/AccountStatus'
|
||||
import styles from './Web3message.module.scss'
|
||||
import { User } from '../../context/User'
|
||||
|
@ -4,8 +4,8 @@
|
||||
"link": "/publish"
|
||||
},
|
||||
{
|
||||
"title": "Invoices",
|
||||
"link": "/invoices"
|
||||
"title": "History",
|
||||
"link": "/history"
|
||||
},
|
||||
{
|
||||
"title": "Faucet",
|
||||
|
BIN
client/src/img/categories/agriculture.jpg
Executable file
After Width: | Height: | Size: 20 KiB |
BIN
client/src/img/categories/anthroarche.jpg
Executable file
After Width: | Height: | Size: 18 KiB |
BIN
client/src/img/categories/astronomy.jpg
Executable file
After Width: | Height: | Size: 16 KiB |
BIN
client/src/img/categories/biology.jpg
Executable file
After Width: | Height: | Size: 14 KiB |
BIN
client/src/img/categories/business.jpg
Executable file
After Width: | Height: | Size: 16 KiB |
BIN
client/src/img/categories/chemistry.jpg
Executable file
After Width: | Height: | Size: 30 KiB |
BIN
client/src/img/categories/communication.jpg
Executable file
After Width: | Height: | Size: 29 KiB |
BIN
client/src/img/categories/computer.jpg
Executable file
After Width: | Height: | Size: 26 KiB |
BIN
client/src/img/categories/dataofdata.jpg
Executable file
After Width: | Height: | Size: 31 KiB |
BIN
client/src/img/categories/deeplearning.jpg
Executable file
After Width: | Height: | Size: 33 KiB |
BIN
client/src/img/categories/demographics.jpg
Executable file
After Width: | Height: | Size: 21 KiB |
BIN
client/src/img/categories/earth.jpg
Executable file
After Width: | Height: | Size: 27 KiB |
BIN
client/src/img/categories/economics.jpg
Executable file
After Width: | Height: | Size: 23 KiB |
BIN
client/src/img/categories/engineering.jpg
Executable file
After Width: | Height: | Size: 26 KiB |
BIN
client/src/img/categories/history.jpg
Executable file
After Width: | Height: | Size: 25 KiB |
BIN
client/src/img/categories/imagesets.jpg
Executable file
After Width: | Height: | Size: 24 KiB |
BIN
client/src/img/categories/language.jpg
Executable file
After Width: | Height: | Size: 30 KiB |
BIN
client/src/img/categories/law.jpg
Executable file
After Width: | Height: | Size: 13 KiB |
BIN
client/src/img/categories/mathematics.jpg
Executable file
After Width: | Height: | Size: 17 KiB |
BIN
client/src/img/categories/medicine.jpg
Executable file
After Width: | Height: | Size: 22 KiB |
BIN
client/src/img/categories/other.jpg
Executable file
After Width: | Height: | Size: 49 KiB |
BIN
client/src/img/categories/performingarts.jpg
Executable file
After Width: | Height: | Size: 24 KiB |
BIN
client/src/img/categories/philosophy.jpg
Executable file
After Width: | Height: | Size: 16 KiB |
BIN
client/src/img/categories/physics.jpg
Executable file
After Width: | Height: | Size: 12 KiB |
BIN
client/src/img/categories/politics.jpg
Executable file
After Width: | Height: | Size: 19 KiB |
BIN
client/src/img/categories/psychology.jpg
Executable file
After Width: | Height: | Size: 14 KiB |
BIN
client/src/img/categories/sociology.jpg
Executable file
After Width: | Height: | Size: 36 KiB |
BIN
client/src/img/categories/sports.jpg
Executable file
After Width: | Height: | Size: 22 KiB |
BIN
client/src/img/categories/theology.jpg
Executable file
After Width: | Height: | Size: 14 KiB |
BIN
client/src/img/categories/transport.jpg
Executable file
After Width: | Height: | Size: 32 KiB |
BIN
client/src/img/categories/urbanplanning.jpg
Executable file
After Width: | Height: | Size: 22 KiB |
BIN
client/src/img/categories/visualart.jpg
Executable file
After Width: | Height: | Size: 22 KiB |
@ -1,18 +1,18 @@
|
||||
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'
|
||||
import AssetFilesDetails from './AssetFilesDetails'
|
||||
|
||||
interface AssetDetailsProps {
|
||||
ocean: any
|
||||
metadata: any
|
||||
ddo: any
|
||||
purchaseAsset: any
|
||||
}
|
||||
|
||||
export default class AssetDetails extends PureComponent<AssetDetailsProps> {
|
||||
public render() {
|
||||
const { metadata, ddo, purchaseAsset } = this.props
|
||||
const { ocean, metadata, ddo } = this.props
|
||||
const { base } = metadata
|
||||
|
||||
return (
|
||||
@ -25,6 +25,15 @@ export default class AssetDetails extends PureComponent<AssetDetailsProps> {
|
||||
{base.copyrightHolder}
|
||||
</h2>
|
||||
<div className={styles.metaPrimaryData}>
|
||||
{base.categories ? (
|
||||
// TODO: Make this link to search for respective category
|
||||
<Link to={`/search?q=${base.categories[0]}`}>
|
||||
{base.categories[0]}
|
||||
</Link>
|
||||
) : (
|
||||
<Link to={'/search?q='}>Fake Category</Link>
|
||||
)}
|
||||
|
||||
<span title="Date published">
|
||||
<Moment
|
||||
date={base.dateCreated}
|
||||
@ -32,14 +41,10 @@ export default class AssetDetails extends PureComponent<AssetDetailsProps> {
|
||||
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>
|
||||
|
||||
{base.files && (
|
||||
<span>{base.files.length} data files</span>
|
||||
)}
|
||||
<span>fake json contentType</span>
|
||||
<span>fake 18.5 MB</span>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@ -58,18 +63,6 @@ export default class AssetDetails extends PureComponent<AssetDetailsProps> {
|
||||
</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>
|
||||
@ -80,9 +73,11 @@ export default class AssetDetails extends PureComponent<AssetDetailsProps> {
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<Button onClick={() => purchaseAsset(ddo)}>
|
||||
Download asset
|
||||
</Button>
|
||||
<AssetFilesDetails
|
||||
files={base.files ? base.files : []}
|
||||
ddo={ddo}
|
||||
ocean={ocean}
|
||||
/>
|
||||
|
||||
<pre>
|
||||
<code>{JSON.stringify(metadata, null, 2)}</code>
|
||||
|
13
client/src/routes/Details/AssetFilesDetails.module.scss
Normal file
@ -0,0 +1,13 @@
|
||||
@import '../../styles/variables';
|
||||
|
||||
.buttonMain {
|
||||
margin: auto;
|
||||
margin-bottom: $spacer / 2;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.error {
|
||||
text-align: center;
|
||||
color: $red;
|
||||
font-size: $font-size-small;
|
||||
}
|
93
client/src/routes/Details/AssetFilesDetails.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import Button from '../../components/atoms/Button'
|
||||
import Spinner from '../../components/atoms/Spinner'
|
||||
import styles from './AssetFilesDetails.module.scss'
|
||||
|
||||
interface AssetFilesDetailsProps {
|
||||
ocean: any
|
||||
files: any[]
|
||||
ddo: any
|
||||
}
|
||||
|
||||
export default class AssetFilesDetails extends PureComponent<
|
||||
AssetFilesDetailsProps
|
||||
> {
|
||||
public state = { decryptedFiles: [], isLoading: false, error: null }
|
||||
|
||||
private purchaseAsset = async (ddo: any) => {
|
||||
this.setState({ isLoading: true, error: null })
|
||||
try {
|
||||
const account = await this.props.ocean.getAccounts()
|
||||
const service = ddo.findServiceByType('Access')
|
||||
const serviceAgreementSignatureResult = await this.props.ocean.signServiceAgreement(
|
||||
ddo.id,
|
||||
service.serviceDefinitionId,
|
||||
account[0]
|
||||
)
|
||||
await this.props.ocean.initializeServiceAgreement(
|
||||
ddo.id,
|
||||
service.serviceDefinitionId,
|
||||
serviceAgreementSignatureResult.agreementId,
|
||||
serviceAgreementSignatureResult.signature,
|
||||
(files: any) => this.setState({ decryptedFiles: files }),
|
||||
account[0]
|
||||
)
|
||||
|
||||
this.setState({ isLoading: false })
|
||||
} catch (error) {
|
||||
Logger.log('error', error)
|
||||
this.setState({ isLoading: false, error: error.message })
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { files, ddo } = this.props
|
||||
const filesArray =
|
||||
this.state.decryptedFiles.length > 0
|
||||
? this.state.decryptedFiles
|
||||
: files
|
||||
|
||||
return (
|
||||
<>
|
||||
{this.state.decryptedFiles.length > 0 ? (
|
||||
filesArray.forEach(file => (
|
||||
<>
|
||||
<ul>
|
||||
{/*
|
||||
TODO: getting this metadata depends on a change to to OEP-8,
|
||||
see: https://github.com/oceanprotocol/OEPs/pull/154
|
||||
*/}
|
||||
{/* <li>{file.contentType}</li> */}
|
||||
<li>{file.contentLength}</li>
|
||||
{/* <li>{file.encoding}</li> */}
|
||||
{/* <li>{file.compression}</li> */}
|
||||
</ul>
|
||||
|
||||
{file.url && (
|
||||
<Button href={file.url}>Download asset</Button>
|
||||
)}
|
||||
</>
|
||||
))
|
||||
) : this.state.isLoading ? (
|
||||
<Spinner message="Decrypting files, please sign with your wallet..." />
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
primary
|
||||
className={styles.buttonMain}
|
||||
onClick={() => this.purchaseAsset(ddo)}
|
||||
>
|
||||
Get asset files
|
||||
</Button>
|
||||
{this.state.error && (
|
||||
<div className={styles.error}>
|
||||
{this.state.error}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import Route from '../../components/templates/Route'
|
||||
import Spinner from '../../components/atoms/Spinner'
|
||||
import { User } from '../../context/User'
|
||||
@ -27,29 +26,6 @@ export default class Details extends Component<DetailsProps, DetailsState> {
|
||||
this.setState({ ddo, metadata: { base: metadata.base } })
|
||||
}
|
||||
|
||||
private purchaseAsset = async (ddo: any) => {
|
||||
try {
|
||||
const account = await this.context.ocean.accounts.list()
|
||||
const accessService = ddo.findServiceByType('Access')
|
||||
const agreementId = await this.context.ocean.assets.order(
|
||||
ddo.id,
|
||||
accessService.serviceDefinitionId,
|
||||
account[0]
|
||||
)
|
||||
const folder = ''
|
||||
const path = await this.context.ocean.assets.consume(
|
||||
agreementId,
|
||||
ddo.id,
|
||||
accessService.serviceDefinitionId,
|
||||
account[0],
|
||||
folder
|
||||
)
|
||||
Logger.log('path', path)
|
||||
} catch (e) {
|
||||
Logger.log('error', e)
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { metadata, ddo } = this.state
|
||||
|
||||
@ -59,9 +35,9 @@ export default class Details extends Component<DetailsProps, DetailsState> {
|
||||
>
|
||||
{metadata && metadata.base.name ? (
|
||||
<AssetDetails
|
||||
ocean={this.context.ocean}
|
||||
metadata={metadata}
|
||||
ddo={ddo}
|
||||
purchaseAsset={this.purchaseAsset}
|
||||
/>
|
||||
) : (
|
||||
<div className={stylesApp.loader}>
|
||||
|
@ -3,7 +3,7 @@ import Route from '../components/templates/Route'
|
||||
import Button from '../components/atoms/Button'
|
||||
import Spinner from '../components/atoms/Spinner'
|
||||
import { User } from '../context/User'
|
||||
import Web3message from '../components/molecules/Web3message'
|
||||
import Web3message from '../components/organisms/Web3message'
|
||||
import styles from './Faucet.module.scss'
|
||||
|
||||
interface FaucetState {
|
||||
|
13
client/src/routes/History.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React, { Component } from 'react'
|
||||
import Route from '../components/templates/Route'
|
||||
import AssetsUser from '../components/organisms/AssetsUser'
|
||||
|
||||
export default class History extends Component {
|
||||
public render() {
|
||||
return (
|
||||
<Route title="History">
|
||||
<AssetsUser list />
|
||||
</Route>
|
||||
)
|
||||
}
|
||||
}
|
@ -3,6 +3,10 @@
|
||||
.home {
|
||||
display: block;
|
||||
|
||||
form {
|
||||
margin-bottom: $spacer * 3;
|
||||
}
|
||||
|
||||
label {
|
||||
height: 0;
|
||||
margin: 0;
|
||||
|
@ -3,7 +3,7 @@ import Button from '../components/atoms/Button'
|
||||
import Form from '../components/atoms/Form/Form'
|
||||
import Input from '../components/atoms/Form/Input'
|
||||
import Route from '../components/templates/Route'
|
||||
import AssetsUser from '../components/molecules/AssetsUser'
|
||||
import AssetsUser from '../components/organisms/AssetsUser'
|
||||
import styles from './Home.module.scss'
|
||||
|
||||
import meta from '../data/meta.json'
|
||||
@ -41,7 +41,7 @@ class Home extends Component<HomeProps, HomeState> {
|
||||
}
|
||||
/>
|
||||
</Form>
|
||||
<AssetsUser />
|
||||
<AssetsUser recent={5} list />
|
||||
</Route>
|
||||
)
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import Route from '../components/templates/Route'
|
||||
import { User } from '../context/User'
|
||||
import Asset from '../components/molecules/Asset'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import styles from './Search.module.scss'
|
||||
|
||||
interface InvoicesState {
|
||||
results: any[]
|
||||
}
|
||||
|
||||
export default class Invoices extends Component<{}, InvoicesState> {
|
||||
public state = { results: [] }
|
||||
|
||||
public async componentDidMount() {
|
||||
// this is currently my published assets
|
||||
this.context.ocean.keeper.didRegistry.contract.getPastEvents(
|
||||
'DIDAttributeRegistered',
|
||||
{
|
||||
filter: { _owner: this.context.account },
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
},
|
||||
async (error: any, events: any) => {
|
||||
if (error) {
|
||||
Logger.log('error retrieving', error)
|
||||
} else {
|
||||
const results = []
|
||||
for (const event of events) {
|
||||
const ddo = await this.context.ocean.assets.resolve(
|
||||
`did:op:${event.returnValues._did.substring(2)}`
|
||||
)
|
||||
results.push(ddo)
|
||||
}
|
||||
this.setState({ results })
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
public renderResults = () =>
|
||||
this.state.results.length ? (
|
||||
<div className={styles.results}>
|
||||
{this.state.results
|
||||
.filter(asset => !!asset)
|
||||
.map((asset, index) => (
|
||||
<Asset key={index} asset={asset} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div>No invoices yet</div>
|
||||
)
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<Route title="Your invoices" wide>
|
||||
{this.renderResults()}
|
||||
</Route>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Invoices.contextType = User
|
@ -1,9 +1,9 @@
|
||||
@import '../../../styles/variables';
|
||||
|
||||
.linkUrl {
|
||||
font-size: $font-size-mini;
|
||||
font-size: $font-size-small;
|
||||
display: block;
|
||||
font-family: $font-family-base;
|
||||
margin-bottom: $spacer / 8;
|
||||
|
||||
// TODO: truncate long urls with ellipsis
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
position: absolute;
|
||||
top: $spacer / 4;
|
||||
top: $spacer / 8;
|
||||
right: 0;
|
||||
transition: .2s ease-out;
|
||||
|
||||
@ -35,10 +35,9 @@
|
||||
|
||||
.details {
|
||||
font-size: $font-size-mini;
|
||||
font-size: .85rem;
|
||||
color: #6e7e93;
|
||||
color: $brand-grey-light;
|
||||
|
||||
span {
|
||||
padding-right: .5rem;
|
||||
padding-right: $spacer;
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,17 @@ import filesize from 'filesize'
|
||||
|
||||
const Item = ({ item, removeItem }: { item: any; removeItem: any }) => (
|
||||
<li>
|
||||
<a href={item.url}>{item.url}</a>
|
||||
<a href={item.url} className={styles.linkUrl}>
|
||||
{item.url}
|
||||
</a>
|
||||
<div className={styles.details}>
|
||||
<span>url: {item.found ? 'confirmed' : 'unconfirmed'}</span>
|
||||
<span>URL {item.found ? 'confirmed' : ' not confirmed'}</span>
|
||||
<span>
|
||||
{item.found && item.contentLength
|
||||
? filesize(item.contentLength)
|
||||
: 'unknown size'}
|
||||
{item.found && item.size ? filesize(item.size) : 'unknown size'}
|
||||
</span>
|
||||
<span>
|
||||
{item.found && item.contentType
|
||||
? item.contentType
|
||||
{item.found && item.type
|
||||
? item.type.split('/')[1]
|
||||
: 'unknown type'}
|
||||
</span>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import Web3message from '../../components/molecules/Web3message'
|
||||
import Web3message from '../../components/organisms/Web3message'
|
||||
import Spinner from '../../components/atoms/Spinner'
|
||||
import styles from './StepRegisterContent.module.scss'
|
||||
|
||||
|