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

Merge branch 'feature/compute' into feature/algorithm-details-view

This commit is contained in:
Norbi 2021-02-22 17:25:09 +02:00
commit 4a35d08880
15 changed files with 189 additions and 60 deletions

View File

@ -1,6 +1,6 @@
.box { .box {
display: block; display: block;
background: var(--background-body); background: var(--background-content);
border-radius: var(--border-radius); border-radius: var(--border-radius);
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
box-shadow: 0 6px 17px 0 var(--box-shadow-color); box-shadow: 0 6px 17px 0 var(--box-shadow-color);

View File

@ -5,7 +5,6 @@
.content { .content {
composes: box from './Box.module.css'; composes: box from './Box.module.css';
padding: calc(var(--spacer) / 4); padding: calc(var(--spacer) / 4);
width: calc(100% - var(--spacer) / 3);
max-width: 25rem; max-width: 25rem;
font-size: var(--font-size-small); font-size: var(--font-size-small);
} }

View File

@ -14,6 +14,10 @@
flex-direction: column; flex-direction: column;
} }
.algorithm .link {
background-color: var(--background-body);
}
.content { .content {
margin-top: calc(var(--spacer) / 2); margin-top: calc(var(--spacer) / 2);
overflow-wrap: break-word; overflow-wrap: break-word;
@ -49,18 +53,6 @@
margin: 0; margin: 0;
} }
.accessLabel {
font-size: var(--font-size-mini);
width: auto;
position: absolute;
top: 0;
right: 0;
color: var(--brand-black);
background: var(--brand-grey-lighter);
padding: 0.2rem 0.5rem;
border-bottom-left-radius: var(--border-radius);
}
.symbol { .symbol {
display: block; display: block;
} }
@ -69,3 +61,28 @@
font-size: var(--font-size-mini); font-size: var(--font-size-mini);
margin-top: calc(var(--spacer) / 2); margin-top: calc(var(--spacer) / 2);
} }
.typeDetails {
position: absolute;
top: calc(var(--spacer) / 3);
right: calc(var(--spacer) / 3);
width: auto;
font-size: var(--font-size-mini);
}
.icon {
fill: var(--brand-grey-light);
width: 1.1em;
height: 1.1em;
vertical-align: baseline;
margin-bottom: -0.2em;
display: inline-block;
}
.typeLabel {
display: inline-block;
text-transform: uppercase;
border-right: 1px solid var(--border-color);
padding-right: calc(var(--spacer) / 3.5);
margin-right: calc(var(--spacer) / 4);
}

View File

@ -5,10 +5,11 @@ import Price from '../atoms/Price'
import styles from './AssetTeaser.module.css' import styles from './AssetTeaser.module.css'
import { DDO } from '@oceanprotocol/lib' import { DDO } from '@oceanprotocol/lib'
import removeMarkdown from 'remove-markdown' import removeMarkdown from 'remove-markdown'
import Tooltip from '../atoms/Tooltip'
import Publisher from '../atoms/Publisher' import Publisher from '../atoms/Publisher'
import { useMetadata } from '@oceanprotocol/react' import { useMetadata } from '@oceanprotocol/react'
import Time from '../atoms/Time' import Time from '../atoms/Time'
import { ReactComponent as Compute } from '../../images/compute.svg'
import { ReactComponent as Download } from '../../images/download.svg'
declare type AssetTeaserProps = { declare type AssetTeaserProps = {
ddo: DDO ddo: DDO
@ -17,27 +18,35 @@ declare type AssetTeaserProps = {
const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => { const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
const { owner } = useMetadata(ddo) const { owner } = useMetadata(ddo)
const { attributes } = ddo.findServiceByType('metadata') const { attributes } = ddo.findServiceByType('metadata')
const { name } = attributes.main const { name, type } = attributes.main
const { dataTokenInfo } = ddo const { dataTokenInfo } = ddo
const isCompute = Boolean(ddo.findServiceByType('compute')) const accessType = ddo.service[1].type
return ( return (
<article className={styles.teaser}> <article className={`${styles.teaser} ${styles[type]}`}>
<Link to={`/asset/${ddo.id}`} className={styles.link}> <Link to={`/asset/${ddo.id}`} className={styles.link}>
<header className={styles.header}> <header className={styles.header}>
<Tooltip <div className={styles.symbol}>{dataTokenInfo?.symbol}</div>
placement="left"
content={dataTokenInfo?.name}
className={styles.symbol}
>
{dataTokenInfo?.symbol}
</Tooltip>
<Dotdotdot clamp={3}> <Dotdotdot clamp={3}>
<h1 className={styles.title}>{name}</h1> <h1 className={styles.title}>{name}</h1>
</Dotdotdot> </Dotdotdot>
<Publisher account={owner} minimal className={styles.publisher} /> <Publisher account={owner} minimal className={styles.publisher} />
</header> </header>
{isCompute && <div className={styles.accessLabel}>Compute</div>}
<aside className={styles.typeDetails}>
<div className={styles.typeLabel}>
{type === 'dataset' ? 'data set' : 'algorithm'}
</div>
{accessType === 'access' ? (
<Download
role="img"
aria-label="Download"
className={styles.icon}
/>
) : (
<Compute role="img" aria-label="Compute" className={styles.icon} />
)}
</aside>
<div className={styles.content}> <div className={styles.content}>
<Dotdotdot tagName="p" clamp={3}> <Dotdotdot tagName="p" clamp={3}>

View File

@ -11,3 +11,7 @@
.form label { .form label {
display: none; display: none;
} }
.form input {
background-color: var(--background-content);
}

View File

@ -111,7 +111,7 @@ export default function HomePage(): ReactElement {
style="text" style="text"
to="/search?priceType=pool&sort=liquidity&sortOrder=desc" to="/search?priceType=pool&sort=liquidity&sortOrder=desc"
> >
All data sets with pool Data sets and algorithms with pool
</Button> </Button>
} }
/> />
@ -121,7 +121,7 @@ export default function HomePage(): ReactElement {
query={queryLatest} query={queryLatest}
action={ action={
<Button style="text" to="/search?sort=created&sortOrder=desc"> <Button style="text" to="/search?sort=created&sortOrder=desc">
All data sets All data sets and algorithms
</Button> </Button>
} }
/> />

View File

@ -31,3 +31,7 @@ button.filter,
background: var(--font-color-text); background: var(--font-color-text);
border-color: var(--background-body); border-color: var(--background-body);
} }
.filterList:first-of-type{
margin-bottom: calc(var(--spacer) / 6);
}

View File

@ -2,23 +2,37 @@ import React, { ReactElement } from 'react'
import { useNavigate } from '@reach/router' import { useNavigate } from '@reach/router'
import styles from './filterPrice.module.css' import styles from './filterPrice.module.css'
import classNames from 'classnames/bind' import classNames from 'classnames/bind'
import { addExistingParamsToUrl, FilterByPriceOptions } from './utils' import {
addExistingParamsToUrl,
FilterByPriceOptions,
FilterByTypeOptions
} from './utils'
import Button from '../../atoms/Button' import Button from '../../atoms/Button'
const cx = classNames.bind(styles) const cx = classNames.bind(styles)
const filterItems = [ const filterItemsPrice = [
{ display: 'all', value: undefined }, { display: 'all', value: undefined },
{ display: 'fixed price', value: FilterByPriceOptions.Fixed }, { display: 'fixed price', value: FilterByPriceOptions.Fixed },
{ display: 'dynamic price', value: FilterByPriceOptions.Dynamic } { display: 'dynamic price', value: FilterByPriceOptions.Dynamic }
] ]
const filterItemsType = [
{ display: 'all', value: undefined },
{ display: 'algorithms', value: FilterByTypeOptions.Algorithm },
{ display: 'data sets', value: FilterByTypeOptions.Data }
]
export default function FilterPrice({ export default function FilterPrice({
priceType, priceType,
setPriceType setPriceType,
serviceType,
setServiceType
}: { }: {
priceType: string priceType: string
setPriceType: React.Dispatch<React.SetStateAction<string>> setPriceType: React.Dispatch<React.SetStateAction<string>>
serviceType: string
setServiceType: React.Dispatch<React.SetStateAction<string>>
}): ReactElement { }): ReactElement {
const navigate = useNavigate() const navigate = useNavigate()
@ -31,9 +45,40 @@ export default function FilterPrice({
navigate(urlLocation) navigate(urlLocation)
} }
async function applyTypeFilter(filterBy: string) {
let urlLocation = await addExistingParamsToUrl(location, 'serviceType')
if (filterBy) {
urlLocation = `${urlLocation}&serviceType=${filterBy}`
}
setServiceType(filterBy)
navigate(urlLocation)
}
return ( return (
<div> <div>
{filterItems.map((e, index) => { <div className={styles.filterList}>
{filterItemsType.map((e, index) => {
const filter = cx({
[styles.selected]: e.value === serviceType,
[styles.filter]: true
})
return (
<Button
size="small"
style="text"
key={index}
className={filter}
onClick={async () => {
await applyTypeFilter(e.value)
}}
>
{e.display}
</Button>
)
})}
</div>
<div className={styles.filterList}>
{filterItemsPrice.map((e, index) => {
const filter = cx({ const filter = cx({
[styles.selected]: e.value === priceType, [styles.selected]: e.value === priceType,
[styles.filter]: true [styles.filter]: true
@ -53,5 +98,6 @@ export default function FilterPrice({
) )
})} })}
</div> </div>
</div>
) )
} }

View File

@ -21,10 +21,20 @@ export default function SearchPage({
}): ReactElement { }): ReactElement {
const { config } = useOcean() const { config } = useOcean()
const parsed = queryString.parse(location.search) const parsed = queryString.parse(location.search)
const { text, owner, tags, page, sort, sortOrder, priceType } = parsed const {
text,
owner,
tags,
page,
sort,
sortOrder,
priceType,
serviceType
} = parsed
const [queryResult, setQueryResult] = useState<QueryResult>() const [queryResult, setQueryResult] = useState<QueryResult>()
const [loading, setLoading] = useState<boolean>() const [loading, setLoading] = useState<boolean>()
const [price, setPriceType] = useState<string>(priceType as string) const [price, setPriceType] = useState<string>(priceType as string)
const [type, setType] = useState<string>(serviceType as string)
const [sortType, setSortType] = useState<string>(sort as string) const [sortType, setSortType] = useState<string>(sort as string)
const [sortDirection, setSortDirection] = useState<string>( const [sortDirection, setSortDirection] = useState<string>(
sortOrder as string sortOrder as string
@ -49,6 +59,7 @@ export default function SearchPage({
sort, sort,
page, page,
priceType, priceType,
serviceType,
sortOrder, sortOrder,
config.metadataCacheUri config.metadataCacheUri
]) ])
@ -69,7 +80,12 @@ export default function SearchPage({
<SearchBar initialValue={(text || owner) as string} /> <SearchBar initialValue={(text || owner) as string} />
)} )}
<div className={styles.row}> <div className={styles.row}>
<PriceFilter priceType={price} setPriceType={setPriceType} /> <PriceFilter
priceType={price}
setPriceType={setPriceType}
serviceType={type}
setServiceType={setType}
/>
<Sort <Sort
sortType={sortType} sortType={sortType}
sortDirection={sortDirection} sortDirection={sortDirection}

View File

@ -1,4 +1,6 @@
.sortList { .sortList {
align-self: flex-end;
padding: calc(var(--spacer) / 10);
display: flex; display: flex;
align-items: center; align-items: center;
border-radius: var(--border-radius); border-radius: var(--border-radius);

View File

@ -4,7 +4,8 @@ import {
addExistingParamsToUrl, addExistingParamsToUrl,
SortTermOptions, SortTermOptions,
SortValueOptions, SortValueOptions,
FilterByPriceOptions FilterByPriceOptions,
FilterByTypeOptions
} from './utils' } from './utils'
import Button from '../../atoms/Button' import Button from '../../atoms/Button'
import styles from './sort.module.css' import styles from './sort.module.css'

View File

@ -4,6 +4,7 @@ import {
} from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache' } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import { MetadataCache, Logger } from '@oceanprotocol/lib' import { MetadataCache, Logger } from '@oceanprotocol/lib'
import queryString from 'query-string' import queryString from 'query-string'
import { TypeOf } from 'yup'
export const SortTermOptions = { export const SortTermOptions = {
Liquidity: 'liquidity', Liquidity: 'liquidity',
@ -31,6 +32,12 @@ export const FilterByPriceOptions = {
} as const } as const
type FilterByPriceOptions = typeof FilterByPriceOptions[keyof typeof FilterByPriceOptions] type FilterByPriceOptions = typeof FilterByPriceOptions[keyof typeof FilterByPriceOptions]
export const FilterByTypeOptions = {
Data: 'dataset',
Algorithm: 'algorithm'
} as const
type FilterByTypeOptions = typeof FilterByTypeOptions[keyof typeof FilterByTypeOptions]
function addPriceFilterToQuerry(sortTerm: string, priceFilter: string): string { function addPriceFilterToQuerry(sortTerm: string, priceFilter: string): string {
sortTerm = priceFilter sortTerm = priceFilter
? sortTerm === '' ? sortTerm === ''
@ -40,6 +47,15 @@ function addPriceFilterToQuerry(sortTerm: string, priceFilter: string): string {
return sortTerm return sortTerm
} }
function addTypeFilterToQuery(sortTerm: string, typeFilter: string): string {
sortTerm = typeFilter
? sortTerm === ''
? `service.attributes.main.type:${typeFilter}`
: `${sortTerm} AND service.attributes.main.type:${typeFilter}`
: sortTerm
return sortTerm
}
function getSortType(sortParam: string): string { function getSortType(sortParam: string): string {
const sortTerm = const sortTerm =
sortParam === SortTermOptions.Liquidity sortParam === SortTermOptions.Liquidity
@ -59,7 +75,8 @@ export function getSearchQuery(
offset?: string, offset?: string,
sort?: string, sort?: string,
sortOrder?: string, sortOrder?: string,
priceType?: string priceType?: string,
serviceType?: string
): SearchQuery { ): SearchQuery {
const sortTerm = getSortType(sort) const sortTerm = getSortType(sort)
const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1 const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1
@ -73,7 +90,8 @@ export function getSearchQuery(
`(service.attributes.additionalInformation.categories:\"${categories}\")` `(service.attributes.additionalInformation.categories:\"${categories}\")`
: text || '' : text || ''
searchTerm = addPriceFilterToQuerry(searchTerm, priceType) searchTerm = addPriceFilterToQuerry(searchTerm, priceType)
searchTerm = addTypeFilterToQuery(searchTerm, serviceType)
console.log('search', searchTerm, serviceType)
return { return {
page: Number(page) || 1, page: Number(page) || 1,
offset: Number(offset) || 21, offset: Number(offset) || 21,
@ -112,6 +130,7 @@ export async function getResults(
sort?: string sort?: string
sortOrder?: string sortOrder?: string
priceType?: string priceType?: string
serviceType?: string
}, },
metadataCacheUri: string metadataCacheUri: string
): Promise<QueryResult> { ): Promise<QueryResult> {
@ -124,7 +143,8 @@ export async function getResults(
categories, categories,
sort, sort,
sortOrder, sortOrder,
priceType priceType,
serviceType
} = params } = params
const metadataCache = new MetadataCache(metadataCacheUri, Logger) const metadataCache = new MetadataCache(metadataCacheUri, Logger)
const searchQuery = getSearchQuery( const searchQuery = getSearchQuery(
@ -136,7 +156,8 @@ export async function getResults(
offset, offset,
sort, sort,
sortOrder, sortOrder,
priceType priceType,
serviceType
) )
const queryResult = await metadataCache.queryMetadata(searchQuery) const queryResult = await metadataCache.queryMetadata(searchQuery)

View File

@ -25,8 +25,9 @@
/* Only use these vars for most color referencing for easy light/dark mode */ /* Only use these vars for most color referencing for easy light/dark mode */
--font-color-text: #41474e; --font-color-text: #41474e;
--font-color-heading: #141414; --font-color-heading: #141414;
--background-body: #fff; --background-body: #fafafa;
--background-body-transparent: rgba(255, 255, 255, 0.8); --background-body-transparent: rgba(255, 255, 255, 0.8);
--background-content: #fff;
--background-highlight: #f7f7f7; --background-highlight: #f7f7f7;
--border-color: #e2e2e2; --border-color: #e2e2e2;
--box-shadow-color: rgba(0, 0, 0, 0.05); --box-shadow-color: rgba(0, 0, 0, 0.05);
@ -70,8 +71,9 @@
.dark { .dark {
--font-color-text: #e2e2e2; --font-color-text: #e2e2e2;
--font-color-heading: #f7f7f7; --font-color-heading: #f7f7f7;
--background-body: #141414; --background-body: rgb(10, 10, 10);
--background-body-transparent: rgba(20, 20, 20, 0.9); --background-body-transparent: rgba(10, 10, 10, 0.9);
--background-content: #141414;
--background-highlight: #201f1f; --background-highlight: #201f1f;
--border-color: #303030; --border-color: #303030;
--box-shadow-color: rgba(0, 0, 0, 0.2); --box-shadow-color: rgba(0, 0, 0, 0.2);

5
src/images/compute.svg Normal file
View File

@ -0,0 +1,5 @@
<svg width="19" height="19" viewBox="0 0 19 19" xmlns="http://www.w3.org/2000/svg">
<path d="M14 0H5V9H14V0ZM7 2H12V7H7V2Z" />
<path d="M9 10V19H0V10H9ZM7 12H2V17H7V12Z" />
<path d="M19 10V19H10V10H19ZM17 12H12V17H17V12Z" />
</svg>

After

Width:  |  Height:  |  Size: 232 B

3
src/images/download.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="18" height="20" viewBox="0 0 18 20" xmlns="http://www.w3.org/2000/svg">
<path d="M8.11978 0.980591L8.11977 16.4369L1.25897 9.38744L0.0134277 10.6671L8.99989 19.8995L17.9864 10.6671L16.7425 9.38744L9.88001 16.4369L9.88001 0.980591L8.11978 0.980591Z" />
</svg>

After

Width:  |  Height:  |  Size: 271 B