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

Merge branch 'main' into feature/1400-shared-components-stories

This commit is contained in:
EnzoVezzaro 2022-07-07 06:38:01 -04:00
commit c85593c262
29 changed files with 359 additions and 389 deletions

92
package-lock.json generated
View File

@ -38,7 +38,7 @@
"react": "^18.2.0",
"react-chartjs-2": "^4.2.0",
"react-clipboard.js": "^2.0.16",
"react-data-table-component": "^6.11.7",
"react-data-table-component": "^7.5.2",
"react-dom": "^18.1.0",
"react-dotdotdot": "^1.3.1",
"react-modal": "^3.15.1",
@ -32349,11 +32349,6 @@
"resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
"integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA="
},
"node_modules/lodash.orderby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.orderby/-/lodash.orderby-4.6.0.tgz",
"integrity": "sha1-5pfwTOXXhSL1TZM4syuBozk+TrM="
},
"node_modules/lodash.pickby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
@ -35017,9 +35012,9 @@
}
},
"node_modules/parse-path": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz",
"integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.4.tgz",
"integrity": "sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==",
"dev": true,
"dependencies": {
"is-ssh": "^1.3.0",
@ -35047,14 +35042,14 @@
}
},
"node_modules/parse-url": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz",
"integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.2.tgz",
"integrity": "sha512-uCSjOvD3T+6B/sPWhR+QowAZcU/o4bjPrVBQBGFxcDF6J6FraCGIaDBsdoQawiaaAVdHvtqBe3w3vKlfBKySOQ==",
"dev": true,
"dependencies": {
"is-ssh": "^1.3.0",
"normalize-url": "^6.1.0",
"parse-path": "^4.0.0",
"parse-path": "^4.0.4",
"protocols": "^1.4.0"
}
},
@ -36379,17 +36374,15 @@
}
},
"node_modules/react-data-table-component": {
"version": "6.11.8",
"resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-6.11.8.tgz",
"integrity": "sha512-ukKJKaKNDU5+jEEZFo16+4zwQPRvw1Z13S7FOj4dr73JWRf/lKkE108jciK2tj1JPMub3qXG2h0zXDn5y2WUfQ==",
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-7.5.2.tgz",
"integrity": "sha512-sOmeEEZiORJcnzf8fwcwA5+JbhIChjf+tQV/dLYvlhU8UT8rJZ33aBSOJNjNYq/5+t3lj/xCJXtSa2kgoZTDVQ==",
"dependencies": {
"deepmerge": "^4.2.2",
"lodash.orderby": "^4.6.0",
"shortid": "^2.2.16"
"deepmerge": "^4.2.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0",
"styled-components": "^4.0.0 || ^5.0.0"
"react": ">= 16.8.3",
"styled-components": ">= 4"
}
},
"node_modules/react-docgen": {
@ -38594,19 +38587,6 @@
"node": ">= 0.10"
}
},
"node_modules/shortid": {
"version": "2.2.16",
"resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"dependencies": {
"nanoid": "^2.1.0"
}
},
"node_modules/shortid/node_modules/nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@ -68279,11 +68259,6 @@
"resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
"integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA="
},
"lodash.orderby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.orderby/-/lodash.orderby-4.6.0.tgz",
"integrity": "sha1-5pfwTOXXhSL1TZM4syuBozk+TrM="
},
"lodash.pickby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
@ -70398,9 +70373,9 @@
}
},
"parse-path": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz",
"integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.4.tgz",
"integrity": "sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==",
"dev": true,
"requires": {
"is-ssh": "^1.3.0",
@ -70424,14 +70399,14 @@
}
},
"parse-url": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz",
"integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.2.tgz",
"integrity": "sha512-uCSjOvD3T+6B/sPWhR+QowAZcU/o4bjPrVBQBGFxcDF6J6FraCGIaDBsdoQawiaaAVdHvtqBe3w3vKlfBKySOQ==",
"dev": true,
"requires": {
"is-ssh": "^1.3.0",
"normalize-url": "^6.1.0",
"parse-path": "^4.0.0",
"parse-path": "^4.0.4",
"protocols": "^1.4.0"
}
},
@ -71440,13 +71415,11 @@
}
},
"react-data-table-component": {
"version": "6.11.8",
"resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-6.11.8.tgz",
"integrity": "sha512-ukKJKaKNDU5+jEEZFo16+4zwQPRvw1Z13S7FOj4dr73JWRf/lKkE108jciK2tj1JPMub3qXG2h0zXDn5y2WUfQ==",
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-7.5.2.tgz",
"integrity": "sha512-sOmeEEZiORJcnzf8fwcwA5+JbhIChjf+tQV/dLYvlhU8UT8rJZ33aBSOJNjNYq/5+t3lj/xCJXtSa2kgoZTDVQ==",
"requires": {
"deepmerge": "^4.2.2",
"lodash.orderby": "^4.6.0",
"shortid": "^2.2.16"
"deepmerge": "^4.2.2"
}
},
"react-docgen": {
@ -73222,21 +73195,6 @@
}
}
},
"shortid": {
"version": "2.2.16",
"resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"requires": {
"nanoid": "^2.1.0"
},
"dependencies": {
"nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
}
}
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",

View File

@ -50,7 +50,7 @@
"react": "^18.2.0",
"react-chartjs-2": "^4.2.0",
"react-clipboard.js": "^2.0.16",
"react-data-table-component": "^6.11.7",
"react-data-table-component": "^7.5.2",
"react-dom": "^18.1.0",
"react-dotdotdot": "^1.3.1",
"react-modal": "^3.15.1",

View File

@ -9,6 +9,7 @@ interface BaseQueryParams {
nestedQuery?: any
esPaginationOptions?: EsPaginationOptions
sortOptions?: SortOptions
aggs?: any
filters?: FilterTerm[]
ignorePurgatory?: boolean
}

View File

@ -3,4 +3,5 @@ interface PagedAssets {
page: number
totalPages: number
totalResults: number
aggregations: any
}

View File

@ -5,7 +5,8 @@ export enum SortDirectionOptions {
export enum SortTermOptions {
Created = 'metadata.created',
Relevance = '_score'
Relevance = '_score',
Stats = 'stats.orders'
}
// Note: could not figure out how to get `enum` to be ambiant
@ -43,5 +44,6 @@ declare global {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
query: any
sort?: { [jsonPath: string]: SortDirectionOptions }
aggs?: any
}
}

View File

@ -55,6 +55,10 @@ export function generateBaseQuery(
}
} as SearchQuery
if (baseQueryParams.aggs !== undefined) {
generatedQuery.aggs = baseQueryParams.aggs
}
if (baseQueryParams.sortOptions !== undefined)
generatedQuery.sort = {
[baseQueryParams.sortOptions.sortBy]:
@ -74,12 +78,15 @@ export function transformQueryResult(
results: [],
page: 0,
totalPages: 0,
totalResults: 0
totalResults: 0,
aggregations: []
}
result.results = (queryResult.hits.hits || []).map(
(hit) => hit._source as Asset
)
result.aggregations = queryResult.aggregations
result.totalResults = queryResult.hits.total.value
result.totalPages =
result.totalResults / size < 1
@ -307,6 +314,13 @@ export async function getPublishedAssets(
sortBy: SortTermOptions.Created,
sortDirection: SortDirectionOptions.Descending
},
aggs: {
totalOrders: {
sum: {
field: SortTermOptions.Stats
}
}
},
esPaginationOptions: {
from: (Number(page) - 1 || 0) * 9,
size: 9
@ -314,6 +328,62 @@ export async function getPublishedAssets(
} as BaseQueryParams
const query = generateBaseQuery(baseQueryParams)
try {
const result = await queryMetadata(query, cancelToken)
return result
} catch (error) {
if (axios.isCancel(error)) {
LoggerInstance.log(error.message)
} else {
LoggerInstance.error(error.message)
}
}
}
export async function getTopPublishers(
chainIds: number[],
cancelToken: CancelToken,
page?: number,
type?: string,
accesType?: string
): Promise<PagedAssets> {
const filters: FilterTerm[] = []
accesType !== undefined &&
filters.push(getFilterTerm('services.type', accesType))
type !== undefined && filters.push(getFilterTerm('metadata.type', type))
const baseQueryParams = {
chainIds,
filters,
sortOptions: {
sortBy: SortTermOptions.Created,
sortDirection: SortDirectionOptions.Descending
},
aggs: {
topPublishers: {
terms: {
field: 'nft.owner.keyword',
order: { totalSales: 'desc' }
},
aggs: {
totalSales: {
sum: {
field: SortTermOptions.Stats
}
}
}
}
},
esPaginationOptions: {
from: (Number(page) - 1 || 0) * 9,
size: 9
}
} as BaseQueryParams
const query = generateBaseQuery(baseQueryParams)
try {
const result = await queryMetadata(query, cancelToken)
return result

View File

@ -18,7 +18,7 @@ import { OpcFeesQuery as OpcFeesData } from '../@types/subgraph/OpcFeesQuery'
import { calcSingleOutGivenPoolIn } from './pool'
import Decimal from 'decimal.js'
import { MAX_DECIMALS } from './constants'
import { getPublishedAssets, getTopPublishers } from '@utils/aquarius'
export interface UserLiquidity {
price: string
oceanBalance: string
@ -172,19 +172,11 @@ const UserSalesQuery = gql`
}
`
// TODO: figure out some way to get this
const TopSalesQuery = gql`
query TopSalesQuery {
users(
first: 20
orderBy: sharesOwned
orderDirection: desc
where: { tokenBalancesOwned_not: "0" }
) {
users(first: 20, orderBy: totalSales, orderDirection: desc) {
id
tokenBalancesOwned {
value
}
totalSales
}
}
`
@ -419,20 +411,10 @@ export async function getUserSales(
accountId: string,
chainIds: number[]
): Promise<number> {
const variables = { user: accountId?.toLowerCase() }
try {
const userSales = await fetchDataForMultipleChains(
UserSalesQuery,
variables,
chainIds
)
let salesSum = 0
for (let i = 0; i < userSales.length; i++) {
if (userSales[i].users.length > 0) {
salesSum += parseInt(userSales[i].users[0].totalSales)
}
}
return salesSum
const result = await getPublishedAssets(accountId, chainIds, null)
const { totalOrders } = result.aggregations
return totalOrders.value
} catch (error) {
LoggerInstance.error('Error getUserSales', error.message)
}
@ -442,33 +424,19 @@ export async function getTopAssetsPublishers(
chainIds: number[],
nrItems = 9
): Promise<AccountTeaserVM[]> {
const publisherSales: AccountTeaserVM[] = []
const publishers: AccountTeaserVM[] = []
for (const chain of chainIds) {
const queryContext = getQueryContext(Number(chain))
const fetchedUsers: OperationResult<UsersSalesList> = await fetchData(
TopSalesQuery,
null,
queryContext
)
for (let i = 0; i < fetchedUsers.data.users.length; i++) {
const publishersIndex = publisherSales.findIndex(
(user) => fetchedUsers.data.users[i].id === user.address
)
if (publishersIndex === -1) {
const publisher: AccountTeaserVM = {
address: fetchedUsers.data.users[i].id,
nrSales: fetchedUsers.data.users[i].totalSales
}
publisherSales.push(publisher)
} else {
publisherSales[publishersIndex].nrSales +=
publisherSales[publishersIndex].nrSales
}
}
const result = await getTopPublishers(chainIds, null)
const { topPublishers } = result.aggregations
for (let i = 0; i < topPublishers.buckets.length; i++) {
publishers.push({
address: topPublishers.buckets[i].key,
nrSales: parseInt(topPublishers.buckets[i].totalSales.value)
})
}
publisherSales.sort((a, b) => b.nrSales - a.nrSales)
publishers.sort((a, b) => b.nrSales - a.nrSales)
return publisherSales.slice(0, nrItems)
return publishers.slice(0, nrItems)
}

View File

@ -1,3 +1,16 @@
.accountList {
display: grid;
grid-template-columns: 1fr;
gap: calc(var(--spacer) / 2);
}
@media screen and (min-width: 25rem) {
.accountList {
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
gap: var(--spacer);
}
}
.empty {
color: var(--color-secondary);
font-size: var(--font-size-small);

View File

@ -28,7 +28,7 @@ export default function AccountList({
chainIds
}: AccountListProps): ReactElement {
const styleClasses = cx({
assetList: true,
accountList: true,
[className]: className
})

View File

@ -1,46 +1,39 @@
.blockies {
aspect-ratio: 1/1;
width: 13%;
height: 13%;
width: calc(var(--font-size-large) * 2) !important;
height: calc(var(--font-size-large) * 2) !important;
border-radius: 50%;
margin-left: 0;
margin-right: calc(var(--spacer) / 4);
margin-right: calc(var(--spacer) / 3);
}
.teaser {
max-width: 40rem;
height: 100%;
}
.link {
composes: box from '../atoms/Box.module.css';
padding: calc(var(--spacer) / 2) !important;
font-size: var(--font-size-mini);
height: 90%;
padding: calc(var(--spacer) / 3) calc(var(--spacer) / 2);
color: var(--color-secondary);
position: relative;
display: flex;
align-items: center;
}
.link span {
font-size: var(--font-size-large);
margin-right: calc(var(--spacer) / 3);
}
.name {
margin-bottom: 0;
font-size: var(--font-size-base) !important;
padding-top: calc(var(--spacer) / 4);
}
.header {
display: flex;
flex-direction: row;
align-items: center;
}
.sales {
font-size: small;
margin-top: -5px !important;
margin-bottom: clac(var(--spacer) / 2);
.place {
font-size: var(--font-size-large);
margin-right: calc(var(--spacer) / 2);
}
.name {
margin-bottom: 0;
font-size: var(--font-size-base);
padding-top: calc(var(--spacer) / 5);
color: var(--font-color-text);
}
.sales {
margin: 0;
}
.sales span {
font-weight: var(--font-weight-bold);
color: var(--font-color-text);
}

View File

@ -33,34 +33,26 @@ export default function AccountTeaser({
}, [accountTeaserVM, newCancelToken])
return (
<article className={styles.teaser}>
<Link href={`/profile/${accountTeaserVM.address}`}>
<header className={styles.header}>
{place && <span>{place}</span>}
{profile?.image ? (
<img src={profile.image} className={styles.blockies} />
) : (
<Blockies
accountId={accountTeaserVM.address}
className={styles.blockies}
/>
)}
<div>
<Dotdotdot clamp={3}>
<h3 className={styles.name}>
{profile?.name
? profile?.name
: accountTruncate(accountTeaserVM.address)}
</h3>
</Dotdotdot>
<p className={styles.sales}>
{`${accountTeaserVM.nrSales} ${
accountTeaserVM.nrSales === 1 ? 'sale' : 'sales'
}`}
</p>
</div>
</header>
</Link>
</article>
<Link href={`/profile/${accountTeaserVM.address}`}>
<a className={styles.teaser}>
{place && <span className={styles.place}>{place}</span>}
<Blockies
accountId={accountTeaserVM.address}
className={styles.blockies}
image={profile?.image}
/>
<div>
<Dotdotdot tagName="h4" clamp={2} className={styles.name}>
{profile?.name
? profile?.name
: accountTruncate(accountTeaserVM.address)}
</Dotdotdot>
<p className={styles.sales}>
<span>{accountTeaserVM.nrSales}</span>
{`${accountTeaserVM.nrSales === 1 ? ' sale' : ' sales'}`}
</p>
</div>
</a>
</Link>
)
}

View File

@ -24,14 +24,16 @@ export default function AssetTeaser({
const isCompute = Boolean(getServiceByName(asset, 'compute'))
const accessType = isCompute ? 'compute' : 'access'
const { owner } = asset.nft
const { orders } = asset.stats
return (
<article className={`${styles.teaser} ${styles[type]}`}>
<Link href={`/asset/${asset.id}`}>
<a className={styles.link}>
<header className={styles.header}>
<div className={styles.symbol}>{datatokens[0]?.symbol}</div>
<Dotdotdot clamp={3}>
<h1 className={styles.title}>{name}</h1>
<Dotdotdot tagName="h1" clamp={3} className={styles.title}>
{name}
</Dotdotdot>
{!noPublisher && (
<Publisher account={owner} minimal className={styles.publisher} />
@ -42,6 +44,7 @@ export default function AssetTeaser({
type={type}
accessType={accessType}
className={styles.typeDetails}
totalSales={orders}
/>
<div className={styles.content}>

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react'
import styles from './index.module.css'
import classNames from 'classnames/bind'
import styles from './index.module.css'
import Compute from '@images/compute.svg'
import Download from '@images/download.svg'
import Lock from '@images/lock.svg'
@ -11,18 +11,20 @@ export interface AssetTypeProps {
type: string
accessType: string
className?: string
totalSales?: number
}
export default function AssetType({
type,
accessType,
className
className,
totalSales
}: AssetTypeProps): ReactElement {
const styleClasses = cx({
[className]: className
})
return (
<div className={styleClasses}>
<div className={className || null}>
{accessType === 'access' ? (
<Download role="img" aria-label="Download" className={styles.icon} />
) : accessType === 'compute' && type === 'algorithm' ? (
@ -34,6 +36,12 @@ export default function AssetType({
<div className={styles.typeLabel}>
{type === 'dataset' ? 'data set' : 'algorithm'}
</div>
{totalSales ? (
<div className={styles.typeLabel}>
{`${totalSales} ${totalSales === 1 ? 'sale' : 'sales'}`}
</div>
) : null}
</div>
)
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
import Time from '@shared/atoms/Time'
import Table from '@shared/atoms/Table'
import Table, { TableOceanColumn } from '@shared/atoms/Table'
import AssetTitle from '@shared/AssetList/AssetListTitle'
import { useUserPreferences } from '@context/UserPreferences'
import { gql } from 'urql'
@ -84,38 +84,30 @@ export interface PoolTransaction extends TransactionHistoryPoolTransactions {
asset: Asset
}
const columns = [
const columns: TableOceanColumn<PoolTransaction>[] = [
{
name: 'Title',
selector: function getTitleRow(row: PoolTransaction) {
return <Title row={row} />
}
selector: (row) => <Title row={row} />
},
{
name: 'Data Set',
selector: function getAssetRow(row: PoolTransaction) {
return <AssetTitle asset={row.asset} />
}
selector: (row) => <AssetTitle asset={row.asset} />
},
{
name: 'Network',
selector: function getNetwork(row: PoolTransaction) {
return <NetworkName networkId={row.networkId} />
},
selector: (row) => <NetworkName networkId={row.networkId} />,
maxWidth: '12rem'
},
{
name: 'Time',
selector: function getTimeRow(row: PoolTransaction) {
return (
<Time
className={styles.time}
date={row.timestamp.toString()}
relative
isUnix
/>
)
},
selector: (row) => (
<Time
className={styles.time}
date={row.timestamp.toString()}
relative
isUnix
/>
),
maxWidth: '10rem'
}
]

View File

@ -5,11 +5,13 @@ import styles from './index.module.css'
export interface BlockiesProps {
accountId: string
className?: string
image?: string
}
export default function Blockies({
accountId,
className
className,
image
}: BlockiesProps): ReactElement {
if (!accountId) return null
@ -18,7 +20,7 @@ export default function Blockies({
return (
<img
className={`${className || ''} ${styles.blockies} `}
src={blockies}
src={image || blockies}
alt="Blockies"
aria-hidden="true"
/>

View File

@ -0,0 +1,7 @@
.empty {
width: 100%;
text-align: left;
color: var(--color-secondary);
font-size: var(--font-size-small);
font-style: italic;
}

View File

@ -0,0 +1,6 @@
import React, { ReactElement } from 'react'
import styles from './Empty.module.css'
export default function Empty({ message }: { message?: string }): ReactElement {
return <div className={styles.empty}>{message || 'No results found'}</div>
}

View File

@ -0,0 +1,57 @@
import { createTheme, TableStyles, Theme } from 'react-data-table-component'
// https://github.com/jbetancur/react-data-table-component/blob/master/src/DataTable/themes.ts
const theme: Partial<Theme> = {
text: {
primary: 'var(--font-color-text)',
secondary: 'var(--color-secondary)',
disabled: 'var(--color-secondary)'
},
background: {
default: 'transparent'
},
divider: {
default: 'var(--border-color)'
},
button: {
default: 'var(--font-color-text)',
focus: 'var(--color-primary)',
hover: 'var(--color-primary)',
disabled: 'var(--color-secondary)'
}
}
createTheme('ocean', theme)
// https://github.com/jbetancur/react-data-table-component/blob/master/src/DataTable/styles.ts
export const customStyles: TableStyles = {
table: {
style: {
scrollbarWidth: 'thin'
}
},
head: {
style: {
fontSize: 'var(--font-size-small)',
fontWeight: 'var(--font-weight-base)'
}
},
headCells: {
style: {
textTransform: 'uppercase',
color: 'var(--color-secondary)',
fontSize: 'var(--font-size-small)'
}
},
cells: {
style: {
minWidth: '0 !important'
}
},
rows: {
style: {
fontSize: 'var(--font-size-small)',
fontWeight: 'var(--font-weight-base)'
}
}
}

View File

@ -1,82 +0,0 @@
.table div {
background-color: transparent !important;
}
.table [role='table'],
.table [role='row'] {
color: var(--font-color-text);
font-size: var(--font-size-small);
min-width: 0;
}
.table [class~='rdt_TableCol'] {
border-bottom: 1px solid var(--border-color);
}
.table [role='columnheader'] {
text-transform: uppercase;
font-size: var(--font-size-small);
}
.table [role='columnheader'] > span,
.table [role='columnheader'] > div {
color: var(--color-secondary);
}
.table [role='gridcell'] {
min-width: 0;
}
.table [role='row'] {
border-bottom: 1px solid var(--border-color) !important;
}
.table + div [class*='rdt_Pagination'] {
font-size: var(--font-size-small);
font-weight: var(--font-weight-bold);
color: var(--color-secondary);
background: none;
min-height: 0;
padding-top: calc(var(--spacer) / 2);
}
.table + div [class*='rdt_Pagination'] svg {
fill: var(--color-secondary);
}
.table + div [class*='rdt_Pagination'] [disabled] svg {
fill: var(--background-highlight);
}
.table + div [class*='rdt_Pagination'] button:hover:not(:disabled) {
background: none;
}
.table + div [class*='rdt_Pagination'] button:hover:not(:disabled) svg {
fill: var(--brand-pink);
}
.table + div [class*='rdt_Pagination'] button[aria-label='First Page'],
.table + div [class*='rdt_Pagination'] button[aria-label='Last Page'] {
display: none;
}
.table [class*='Table-module'] {
scrollbar-width: thin;
}
.empty {
width: 100%;
text-align: left;
color: var(--color-secondary);
font-size: var(--font-size-small);
font-style: italic;
}
.arrow {
composes: arrow from '@shared/Pagination/index.module.css';
}
.previous {
composes: previous from '@shared/Pagination/index.module.css';
}

View File

@ -1,6 +1,6 @@
import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'
import Table, { TableProps } from '@shared/atoms/Table'
import Table, { TableOceanProps } from '@shared/atoms/Table'
export default {
title: 'Component/@shared/atoms/Table',
@ -10,7 +10,7 @@ export default {
const Template: ComponentStory<typeof Table> = (args) => <Table {...args} />
interface Props {
args: TableProps
args: TableOceanProps<any>
}
const columns = [

View File

@ -1,10 +1,19 @@
import React, { ReactElement, ReactNode } from 'react'
import DataTable, { IDataTableProps } from 'react-data-table-component'
import React, { ReactElement } from 'react'
import DataTable, { TableProps, TableColumn } from 'react-data-table-component'
import Loader from '../Loader'
import Pagination from '@shared/Pagination'
import styles from './index.module.css'
import { PaginationComponent } from 'react-data-table-component/dist/src/DataTable/types'
import Empty from './Empty'
import { customStyles } from './_styles'
export interface TableProps extends IDataTableProps {
// Hack in support for returning components for each row, as this works,
// but is not supported by the typings.
export interface TableOceanColumn<T> extends TableColumn<T> {
selector?: (row: T) => any
}
export interface TableOceanProps<T> extends TableProps<T> {
columns: TableOceanColumn<T>[]
isLoading?: boolean
emptyMessage?: string
sortField?: string
@ -12,10 +21,6 @@ export interface TableProps extends IDataTableProps {
className?: string
}
function Empty({ message }: { message?: string }): ReactElement {
return <div className={styles.empty}>{message || 'No results found'}</div>
}
export default function Table({
data,
columns,
@ -27,22 +32,24 @@ export default function Table({
sortAsc,
className,
...props
}: TableProps): ReactElement {
}: TableOceanProps<any>): ReactElement {
return (
<DataTable
columns={columns}
data={data}
className={className ? styles.table + ` ${className}` : styles.table}
noHeader
pagination={pagination || data?.length >= 9}
paginationPerPage={paginationPerPage || 10}
noDataComponent={<Empty message={emptyMessage} />}
progressPending={isLoading}
progressComponent={<Loader />}
paginationComponent={Pagination as unknown as ReactNode}
defaultSortField={sortField}
defaultSortAsc={sortAsc}
{...props}
/>
<div className={className}>
<DataTable
columns={columns}
data={data}
pagination={pagination || data?.length >= 9}
paginationPerPage={paginationPerPage || 10}
noDataComponent={<Empty message={emptyMessage} />}
progressPending={isLoading}
progressComponent={<Loader />}
paginationComponent={Pagination as unknown as PaginationComponent}
defaultSortFieldId={sortField}
defaultSortAsc={sortAsc}
theme="ocean"
customStyles={customStyles}
{...props}
/>
</div>
)
}

View File

@ -10,6 +10,7 @@
padding: calc(var(--spacer) / 2);
display: flex;
overflow-x: auto;
scrollbar-width: none;
}
.tab {

View File

@ -1,6 +1,6 @@
import { useUserPreferences } from '@context/UserPreferences'
import React, { ReactElement, useEffect, useState } from 'react'
import Table from '@shared/atoms/Table'
import Table, { TableOceanColumn } from '@shared/atoms/Table'
import { LoggerInstance } from '@oceanprotocol/lib'
import Price from '@shared/Price'
import Tooltip from '@shared/atoms/Tooltip'
@ -12,14 +12,10 @@ import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
import { useWeb3 } from '@context/Web3'
import { useMarketMetadata } from '@context/MarketMetadata'
export function PriceComponent(row: AssetExtended) {
return <Price accessDetails={row.accessDetails} size="small" />
}
const columns = [
const columns: TableOceanColumn<AssetExtended>[] = [
{
name: 'Data Set',
selector: function getAssetRow(row: AssetExtended) {
selector: (row) => {
const { metadata } = row
return <AssetTitle title={metadata.name} asset={row} />
},
@ -28,20 +24,16 @@ const columns = [
},
{
name: 'Datatoken Symbol',
selector: function getAssetRow(row: AssetExtended) {
return (
<Tooltip content={row.datatokens[0].name}>
<>{row.datatokens[0].symbol}</>
</Tooltip>
)
},
selector: (row) => (
<Tooltip content={row.datatokens[0].name}>
<>{row.datatokens[0].symbol}</>
</Tooltip>
),
maxWidth: '10rem'
},
{
name: 'Price',
selector: function getAssetRow(row: AssetExtended) {
return PriceComponent(row)
},
selector: (row) => <Price accessDetails={row.accessDetails} size="small" />,
right: true
}
]

View File

@ -1,8 +1,9 @@
import { useUserPreferences } from '@context/UserPreferences'
import { LoggerInstance } from '@oceanprotocol/lib'
import AccountList from '@shared/AccountList'
import { getTopAssetsPublishers } from '@utils/subgraph'
import React, { ReactElement, useEffect, useState } from 'react'
import styles from './Home.module.css'
import styles from './index.module.css'
export default function PublishersWithMostSales({
title,
@ -17,18 +18,19 @@ export default function PublishersWithMostSales({
useEffect(() => {
async function init() {
setLoading(true)
if (chainIds.length === 0) {
const result: AccountTeaserVM[] = []
setResult(result)
setLoading(false)
} else {
try {
setLoading(true)
const publishers = await getTopAssetsPublishers(chainIds)
setResult(publishers)
setLoading(false)
} catch (error) {
// Logger.error(error.message)
LoggerInstance.error(error.message)
setLoading(false)
}
}
}

View File

@ -14,6 +14,7 @@ import styles from './index.module.css'
import { useIsMounted } from '@hooks/useIsMounted'
import { useCancelToken } from '@hooks/useCancelToken'
import { SortTermOptions } from '../../@types/aquarius/SearchQuery'
import PublishersWithMostSales from './PublishersWithMostSales'
import { useWeb3 } from '@context/Web3'
async function getQueryHighest(
@ -68,7 +69,8 @@ function SectionQueryResult({
results: [],
page: 0,
totalPages: 0,
totalResults: 0
totalResults: 0,
aggregations: undefined
}
setResult(result)
setLoading(false)
@ -157,6 +159,8 @@ export default function HomePage(): ReactElement {
</Button>
}
/>
<PublishersWithMostSales title="Publishers With Most Sales" />
</>
)
}

View File

@ -1,7 +1,7 @@
import React, { ReactElement, useEffect, useState, useCallback } from 'react'
import Time from '@shared/atoms/Time'
import { LoggerInstance } from '@oceanprotocol/lib'
import Table from '@shared/atoms/Table'
import Table, { TableOceanColumn } from '@shared/atoms/Table'
import Button from '@shared/atoms/Button'
import { useWeb3 } from '@context/Web3'
import Details from './Details'
@ -19,46 +19,33 @@ export function Status({ children }: { children: string }): ReactElement {
return <div className={styles.status}>{children}</div>
}
const columns = [
const columns: TableOceanColumn<ComputeJobMetaData>[] = [
{
name: 'Data Set',
selector: function getAssetRow(row: ComputeJobMetaData) {
return <AssetListTitle did={row.inputDID[0]} title={row.assetName} />
}
selector: (row) => (
<AssetListTitle did={row.inputDID[0]} title={row.assetName} />
)
},
{
name: 'Network',
selector: function getNetwork(row: ComputeJobMetaData) {
return <NetworkName networkId={row.networkId} />
}
selector: (row) => <NetworkName networkId={row.networkId} />
},
{
name: 'Created',
selector: function getTimeRow(row: ComputeJobMetaData) {
return <Time date={row.dateCreated} isUnix relative />
}
selector: (row) => <Time date={row.dateCreated} isUnix relative />
},
{
name: 'Finished',
selector: function getTimeRow(row: ComputeJobMetaData) {
return row.dateFinished ? (
<Time date={row.dateFinished} isUnix relative />
) : (
''
)
}
selector: (row) =>
row.dateFinished ? <Time date={row.dateFinished} isUnix relative /> : ''
},
{
name: 'Status',
selector: function getStatus(row: ComputeJobMetaData) {
return <Status>{row.statusText}</Status>
}
selector: (row) => <Status>{row.statusText}</Status>
},
{
name: 'Actions',
selector: function getActions(row: ComputeJobMetaData) {
return <Details job={row} />
}
selector: (row) => <Details job={row} />
}
]
@ -125,7 +112,7 @@ export default function ComputeJobs({
columns={minimal ? columnsMinimal : columns}
data={jobs}
isLoading={isLoading}
defaultSortField="row.dateCreated"
defaultSortFieldId="row.dateCreated"
defaultSortAsc={false}
emptyMessage={chainIds.length === 0 ? 'No network selected' : null}
/>

View File

@ -1,34 +1,27 @@
import React, { ReactElement } from 'react'
import Table from '@shared/atoms/Table'
import Table, { TableOceanColumn } from '@shared/atoms/Table'
import Time from '@shared/atoms/Time'
import AssetTitle from '@shared/AssetList/AssetListTitle'
import NetworkName from '@shared/NetworkName'
import { useProfile } from '@context/Profile'
import { useUserPreferences } from '@context/UserPreferences'
const columns = [
const columns: TableOceanColumn<DownloadedAsset>[] = [
{
name: 'Data Set',
selector: function getAssetRow(row: DownloadedAsset) {
return <AssetTitle asset={row.asset} />
}
selector: (row) => <AssetTitle asset={row.asset} />
},
{
name: 'Network',
selector: function getNetwork(row: DownloadedAsset) {
return <NetworkName networkId={row.networkId} />
}
selector: (row) => <NetworkName networkId={row.networkId} />
},
{
name: 'Datatoken',
selector: function getTitleRow(row: DownloadedAsset) {
return row.dtSymbol
}
selector: (row) => row.dtSymbol
},
{
name: 'Time',
selector: function getTimeRow(row: DownloadedAsset) {
return <Time date={row.timestamp.toString()} relative isUnix />
}
selector: (row) => <Time date={row.timestamp.toString()} relative isUnix />
}
]

View File

@ -1,5 +1,5 @@
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
import Table from '@shared/atoms/Table'
import Table, { TableOceanColumn } from '@shared/atoms/Table'
import styles from './index.module.css'
import AssetTitle from '@shared/AssetList/AssetListTitle'
import { PoolShares_poolShares as PoolShare } from '../../../../@types/subgraph/PoolShares'
@ -23,32 +23,24 @@ export interface AssetPoolShare {
asset: Asset
}
const columns = [
const columns: TableOceanColumn<AssetPoolShare>[] = [
{
name: 'Data Set',
selector: function getAssetRow(row: AssetPoolShare) {
return <AssetTitle asset={row.asset} />
},
selector: (row) => <AssetTitle asset={row.asset} />,
grow: 2
},
{
name: 'Network',
selector: function getNetwork(row: AssetPoolShare) {
return <NetworkName networkId={row.networkId} />
}
selector: (row) => <NetworkName networkId={row.networkId} />
},
{
name: 'Your liquidity',
selector: function getAssetRow(row: AssetPoolShare) {
return <Liquidity row={row} type="user" />
},
selector: (row) => <Liquidity row={row} type="user" />,
right: true
},
{
name: 'Total Value Locked',
selector: function getAssetRow(row: AssetPoolShare) {
return <Liquidity row={row} type="pool" />
},
selector: (row) => <Liquidity row={row} type="pool" />,
right: true
}
]

View File

@ -34,6 +34,7 @@
.tabs div[class*='tabContent'] {
border: 1px solid var(--border-color);
border-top: 0;
padding-bottom: 0;
}