1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

transactions page

This commit is contained in:
mihaisc 2020-05-25 15:53:38 +03:00
parent 26c2902f2b
commit 9ce0af7d63
17 changed files with 532 additions and 19 deletions

82
package-lock.json generated
View File

@ -1,5 +1,5 @@
{
"name": "dexfreight",
"name": "market",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
@ -3397,14 +3397,38 @@
"integrity": "sha512-915dcnzCHEuvsmRKqVj0RxHT3T386lSJh8WREe4dsnrXHsi1ULNYxX0Ts/cvalv6bRL+aqyaZ6gN3l3nkfwEDg=="
},
"@oceanprotocol/react": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@oceanprotocol/react/-/react-0.0.6.tgz",
"integrity": "sha512-rwdTGHKS6ZBxuBULfx74h3Xej3o+8rWaS4I1nUNoS1twHRxAoFv+5cg3QlbjDs1r6FZ+useoQHdBV2Ln/gGzsQ==",
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/@oceanprotocol/react/-/react-0.0.9.tgz",
"integrity": "sha512-wCaBAHufEhhWApWHZucOXgEjyEUnuGG6OdBdkQjoPpLatkNs8X8tEpqMN6pZQoTIXyC6rYnnBPnrURiFW1RDHg==",
"requires": {
"@oceanprotocol/squid": "^2.1.1",
"@oceanprotocol/squid": "^2.2.0",
"axios": "^0.19.2",
"react": "^16.13.1",
"web3connect": "^1.0.0-beta.33"
},
"dependencies": {
"@oceanprotocol/squid": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-2.2.0.tgz",
"integrity": "sha512-ISI+8mGl5lCPqLw/YPS/e0PhaqgexuGiwxKcCGAMSo1p8sgunr6FOrMVoYhYr52QpfodxOY8Iiy3zv4HC8O2Mg==",
"requires": {
"@ethereum-navigator/navigator": "^0.5.0",
"@oceanprotocol/keeper-contracts": "^0.13.2",
"@oceanprotocol/secret-store-client": "^0.0.15",
"bignumber.js": "^9.0.0",
"deprecated-decorator": "^0.1.6",
"node-fetch": "^2.6.0",
"save-file": "^2.3.1",
"uuid": "^8.0.0",
"web3": "^1.2.6",
"whatwg-url": "^8.0.0"
}
},
"uuid": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="
}
}
},
"@oceanprotocol/secret-store-client": {
@ -3416,9 +3440,9 @@
}
},
"@oceanprotocol/squid": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-2.1.1.tgz",
"integrity": "sha512-aoZttkArQ3qKsAHcaQfv6kFLpaSeGFHUSDRdK/MllJ5UFzclkDkBJd4P7XIJ5lS8uXOOBrrvQPxDU8wvf2yyMQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-2.2.0.tgz",
"integrity": "sha512-ISI+8mGl5lCPqLw/YPS/e0PhaqgexuGiwxKcCGAMSo1p8sgunr6FOrMVoYhYr52QpfodxOY8Iiy3zv4HC8O2Mg==",
"requires": {
"@ethereum-navigator/navigator": "^0.5.0",
"@oceanprotocol/keeper-contracts": "^0.13.2",
@ -3427,15 +3451,15 @@
"deprecated-decorator": "^0.1.6",
"node-fetch": "^2.6.0",
"save-file": "^2.3.1",
"uuid": "^7.0.2",
"uuid": "^8.0.0",
"web3": "^1.2.6",
"whatwg-url": "^8.0.0"
},
"dependencies": {
"uuid": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
"integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="
}
}
},
@ -10051,6 +10075,11 @@
"integrity": "sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw==",
"dev": true
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
},
"defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
@ -19107,6 +19136,11 @@
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"lodash.orderby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.orderby/-/lodash.orderby-4.6.0.tgz",
"integrity": "sha1-5pfwTOXXhSL1TZM4syuBozk+TrM="
},
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@ -20615,6 +20649,11 @@
"tslib": "^1.10.0"
}
},
"no-scroll": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/no-scroll/-/no-scroll-2.1.1.tgz",
"integrity": "sha512-YTzGAJOo/B6hkodeT5SKKHpOhAzjMfkUCCXjLJwjWk2F4/InIg+HbdH9kmT7bKpleDuqLZDTRy2OdNtAj0IVyQ=="
},
"node-dir": {
"version": "0.1.17",
"resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz",
@ -22284,6 +22323,16 @@
"@babel/runtime": "^7.0.0"
}
},
"react-data-table-component": {
"version": "6.9.2",
"resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-6.9.2.tgz",
"integrity": "sha512-U7wHNes+NnWyoc9UoHBYgnOuW1OiFPLW9Bm4AwtDny+6czJVs6u5zE53yIj3LgqtX0wE11E83UoLxUd44B/T/g==",
"requires": {
"deepmerge": "^4.2.2",
"lodash.orderby": "^4.6.0",
"shortid": "^2.2.15"
}
},
"react-datepicker": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-2.14.0.tgz",
@ -22740,6 +22789,15 @@
"@types/react": "^16.0.40"
}
},
"react-responsive-modal": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/react-responsive-modal/-/react-responsive-modal-5.0.2.tgz",
"integrity": "sha512-7QzL5NIhzYKe+jnl3QQVBWlpVCQv6QDCKtlJQvBxEbnjNSMkwFep2uSTu4CQFt9QItFEBV7onC/1i6O0t78nYg==",
"requires": {
"classnames": "^2.2.6",
"no-scroll": "^2.1.1"
}
},
"react-sizeme": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-2.6.12.tgz",

View File

@ -19,8 +19,8 @@
},
"dependencies": {
"@oceanprotocol/art": "^2.2.0",
"@oceanprotocol/react": "0.0.6",
"@oceanprotocol/squid": "^2.1.1",
"@oceanprotocol/react": "0.0.9",
"@oceanprotocol/squid": "^2.2.0",
"@oceanprotocol/typographies": "^0.1.0",
"@sindresorhus/slugify": "^1.0.0",
"@types/classnames": "^2.2.10",
@ -36,6 +36,7 @@
"nprogress": "^0.2.0",
"numeral": "^2.0.6",
"react": "^16.13.1",
"react-data-table-component": "^6.9.2",
"react-datepicker": "^2.14.0",
"react-dom": "^16.13.1",
"react-dotdotdot": "^1.3.1",
@ -44,6 +45,7 @@
"react-markdown": "^4.3.1",
"react-paginate": "^6.3.2",
"react-rating": "^2.0.4",
"react-responsive-modal": "^5.0.2",
"react-toastify": "^5.5.0",
"shortid": "^2.2.15",
"slugify": "^1.4.0",

View File

@ -26,6 +26,10 @@ module.exports = {
{
name: 'Publish',
link: '/publish'
},
{
name: 'Transactions',
link: '/transactions'
}
]
}

View File

@ -9,3 +9,8 @@
color: var(--color-secondary);
font-size: var(--font-size-small);
}
.small {
transform: scale(0.8);
transform-origin: left 80%;
}

View File

@ -4,12 +4,16 @@ import styles from './Price.module.css'
export default function Price({
price,
className
className,
small
}: {
price: string
className?: string
small?: boolean
}) {
const classes = className ? `${styles.price} ${className}` : styles.price
const classes = small
? `${styles.price} ${styles.small} ${className}`
: `${styles.price} ${className}`
const isFree = price === '0'
const displayPrice = isFree ? (
'Free'

View File

@ -0,0 +1,7 @@
import React from 'react'
import Time from '../Time'
export default function DateCell({ date }: { date: any }) {
console.log(date)
return date && <Time date={date} />
}

View File

@ -0,0 +1,11 @@
import React from 'react'
import Time from '../Time'
import Link from 'next/link'
export default function DdoLinkCell({ id, name }: { id: any; name: any }) {
return (
<Link href="/asset/[did]" as={`/asset/${id}`} passHref>
<a>{name}</a>
</Link>
)
}

View File

View File

@ -0,0 +1,35 @@
import React from 'react'
import DataTable from 'react-data-table-component'
export declare type AssetTablePagination = {
count: number
rowsPerPage: number
page: number
handleChangePage: (
event: React.MouseEvent<HTMLButtonElement> | null,
page: number
) => void
handleChangeRowsPerPage: React.ChangeEventHandler<
HTMLTextAreaElement | HTMLInputElement
>
}
export default function Table({
columns,
data,
pagination
}: {
columns: any
data: any
pagination?: AssetTablePagination
}) {
return (
<div>
{data && data.length ? (
<DataTable noHeader columns={columns} data={data} />
) : (
<div>No Data Sets Yet.</div>
)}
</div>
)
}

View File

@ -0,0 +1,95 @@
import React, { useEffect, useState } from 'react'
import Loader from '../atoms/Loader'
import { useWeb3, useOcean, OceanConnectionStatus } from '@oceanprotocol/react'
import Table from '../atoms/Table'
import Price from '../atoms/Price'
import { fromWei } from 'web3-utils'
import DateCell from '../atoms/Table/DateCell'
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
const consumedColumns = [
{
name: 'Published',
selector: 'published',
sortable: true,
cell: function getCell(row: any) {
return <DateCell date={row.published} />
}
},
{
name: 'Name',
selector: 'name',
sortable: true,
cell: function getCell(row: any) {
return <DdoLinkCell id={row.id} name={row.name} />
}
},
{
name: 'Price',
selector: 'price',
sortable: true,
cell: function getCell(row: any) {
return <Price price={fromWei(row.price)} small />
}
}
]
export default function ConsumedList() {
const { account } = useWeb3()
const { ocean, status } = useOcean()
const [consumedList, setConsumedList] = useState<any>([])
const [isLoading, setIsLoading] = useState(false)
useEffect(() => {
async function getConsumed() {
if (!account || !ocean || status !== OceanConnectionStatus.CONNECTED)
return
setIsLoading(true)
// const consumedItems = await getConsumedList()
// TODO: test this before updating react lib and after backend workd properly
// const consumed = await ocean.assets.consumerAssets(accountId)
// const consumedItemss = await Promise.all(
// consumed.map(async (did) => {
// const ddo = await ocean.assets.resolve(did)
// if (ddo) {
// // Since we are getting assets from chain there might be
// // assets from other marketplaces. So return only those assets
// // whose serviceEndpoint contains the configured Aquarius URI.
// const { serviceEndpoint } = ddo.findServiceByType('metadata')
// if (serviceEndpoint?.includes(config.aquariusUri as string)) return ddo
// }
// })
// )
// const consumedItems = (consumedItemss.filter(value => typeof value !== 'undefined')) as DDO[]
// console.log('consumedss', consumedItems)
// const data = consumedItems.map((ddo) => {
// const { attributes } = findServiceByType(ddo, 'metadata')
// const { name, price, datePublished } = attributes.main as MetaDataMain
// return {
// published: datePublished,
// name: name,
// price: price
// }
// })
const data = [
{ published: '2020-05-14T10:00:49Z', name: 'asdf', price: '0', id: 1 },
{ published: '2020-05-21T10:00:49Z', name: 'test', price: '0', id: 2 }
]
setConsumedList(data)
setIsLoading(false)
}
getConsumed()
}, [account, ocean, status])
return isLoading ? (
<Loader />
) : account && ocean ? (
<Table data={consumedList} columns={consumedColumns} />
) : (
<div>Connect your wallet to see your consumed data sets.</div>
)
}

View File

@ -0,0 +1,117 @@
import React, { useEffect, useState } from 'react'
import Loader from '../atoms/Loader'
import {
useOcean,
OceanConnectionStatus,
useSearch,
ComputeItem
} from '@oceanprotocol/react'
import Time from '../atoms/Time'
import Link from 'next/link'
import Price from '../atoms/Price'
import { fromWei } from 'web3-utils'
import { findServiceByType } from '../../utils'
import Table from '../atoms/Table'
import Button from '../atoms/Button'
import { MetaDataMain } from '@oceanprotocol/squid'
import DateCell from '../atoms/Table/DateCell'
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
const columns = [
{
name: 'Created',
selector: 'dateCreated',
sortable: true,
cell: function getCell(row: any) {
return <DateCell date={row.dateCreated} />
}
},
{
name: 'Finished',
selector: 'dateFinished',
sortable: true,
cell: function getCell(row: any) {
return <DateCell date={row.dateFinished} />
}
},
{
name: 'Name',
selector: 'name',
sortable: true,
cell: function getCell(row: any) {
return <DdoLinkCell id={row.id} name={row.name} />
}
},
{
name: 'Price',
selector: 'price',
sortable: true,
cell: function getCell(row: any) {
return <Price price={fromWei(row.price)} small />
}
},
{
name: 'Status',
selector: 'status'
},
{
name: 'Actions',
selector: 'actions'
}
]
export default function JobsList() {
const { ocean, status, account } = useOcean()
const [jobList, setJobList] = useState<any[]>([])
const [isLoading, setIsLoading] = useState(false)
const [userAgreed, setUserAgreed] = useState(false)
const { getComputeItems } = useSearch()
const getJobs = async () => {
if (!account || !ocean || status !== OceanConnectionStatus.CONNECTED) return
setIsLoading(true)
setUserAgreed(true)
try {
const computeItems = await getComputeItems()
const data = computeItems.map(item => {
const { attributes } = findServiceByType(item.ddo, 'metadata')
const { name, price } = attributes.main as MetaDataMain
return {
dateCreated: item.job.dateCreated,
dateFinished: item.job.dateFinished,
status: item.job.statusText,
name: name,
price: price,
id: item.ddo.id
}
})
setJobList(data)
setIsLoading(false)
} catch (err) {
// TODO: no error handling
} finally {
setIsLoading(false)
}
}
return isLoading ? (
<Loader />
) : account && ocean ? (
userAgreed ? (
<Table data={jobList} columns={columns} />
) : (
<>
<div>
<Button primary onClick={getJobs}>
Sign to retrieve jobs
</Button>
</div>
</>
)
) : (
<div>Connect your wallet to see your compute jobs.</div>
)
}

View File

@ -0,0 +1,95 @@
import React, { useEffect, useState } from 'react'
import Loader from '../atoms/Loader'
import { DDO, MetaDataMain } from '@oceanprotocol/squid'
import {
useOcean,
OceanConnectionStatus,
useSearch
} from '@oceanprotocol/react'
import Table from '../atoms/Table'
import Time from '../atoms/Time'
import Link from 'next/link'
import Price from '../atoms/Price'
import { fromWei } from 'web3-utils'
import { findServiceByType } from '../../utils'
import DateCell from '../atoms/Table/DateCell'
import DdoLinkCell from '../atoms/Table/DdoLinkCell'
const publishedColumns = [
{
name: 'Published',
selector: 'published',
sortable: true,
cell: function getCell(row: any) {
return <DateCell date={row.published} />
}
},
{
name: 'Name',
selector: 'name',
sortable: true,
cell: function getCell(row: any) {
return <DdoLinkCell id={row.id} name={row.name} />
}
},
{
name: 'Price',
selector: 'price',
sortable: true,
cell: function getCell(row: any) {
return <Price price={fromWei(row.price)} small />
}
}
]
export default function PublishedList() {
const { ocean, status, account } = useOcean()
const { getPublishedList } = useSearch()
const [publishedList, setPublishedList] = useState<any[]>([])
const [isLoading, setIsLoading] = useState(false)
const [paginationParams, setPaginationParams] = useState({
count: 1,
rowsPerPage: 10,
page: 1
})
useEffect(() => {
async function getPublished() {
if (!account || !ocean || status !== OceanConnectionStatus.CONNECTED)
return
setIsLoading(true)
const publishedItems = await getPublishedList(
paginationParams.page,
paginationParams.rowsPerPage
)
setPaginationParams({
...paginationParams,
count: publishedItems.totalPages
})
const data = publishedItems.results.map(ddo => {
const { attributes } = findServiceByType(ddo, 'metadata')
const { name, price, datePublished } = attributes.main as MetaDataMain
return {
published: datePublished,
name: name,
price: price,
id: ddo.id
}
})
setPublishedList(data)
setIsLoading(false)
}
getPublished()
}, [account, ocean, status])
return isLoading ? (
<Loader />
) : account && ocean ? (
<Table data={publishedList} columns={publishedColumns} />
) : (
<div>Connect your wallet to see your published data sets.</div>
)
}

View File

@ -0,0 +1,17 @@
.grid {
display: grid;
gap: calc(var(--spacer) * 1.5);
position: relative;
}
@media (min-width: 55rem) {
.grid {
/* lazy golden ratio */
grid-template-columns: 1.618fr 1fr;
}
.sticky {
position: sticky;
top: var(--spacer);
}
}

View File

@ -0,0 +1,57 @@
import React from 'react'
import Layout from '../../Layout'
import styles from './Transactions.module.css'
import Web3Feedback from '../molecules/Web3Feedback'
import ConsumedList from '../organisms/ConsumedList'
import PublishedList from '../organisms/PublishedList'
import JobsList from '../organisms/JobsList'
const title = 'Transactions'
const description = 'Find the data sets and jobs that you previously accessed'
const sections = [
{
title: 'Published',
component: <PublishedList />
},
{
title: 'Downloaded',
component: <ConsumedList />
},
{
title: 'Compute Jobs',
component: <JobsList />
}
]
const Section = ({ title, component }: { title: string; component: any }) => {
return (
<div className={styles.section}>
<h2 className={styles.sectionTitle}>{title}</h2>
{component}
</div>
)
}
const TransactionsPage: React.FC = () => {
return (
<Layout title={title} description={description}>
<article className={styles.grid}>
<div>
{sections.map(section => {
const { title, component } = section
return <Section key={title} title={title} component={component} />
})}
</div>
<aside>
<div className={styles.sticky}>
<Web3Feedback />
</div>
</aside>
</article>
</Layout>
)
}
export default TransactionsPage

View File

@ -18,9 +18,6 @@ export const getServerSideProps: GetServerSideProps = async context => {
created: -1
}
} as SearchQuery
console.log(config)
console.log('process aquarius',process.env.AQUARIUS_URI)
console.log('process env',process.env)
const aquarius = new Aquarius(config.aquariusUri as string, Logger)
const queryResult = await aquarius.queryMetadata(searchQuery)
// Note: stringifying the results cause Next.js otherwise complains about

View File

@ -0,0 +1,9 @@
import { NextPage } from 'next'
import React from 'react'
import TransactionsPage from '../components/pages/Transactions'
const Transactions: NextPage = () => {
return <TransactionsPage />
}
export default Transactions