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

view algorithms on homepage (#388)

* view algorithms on homepage

* linting error fixed

* view algos on rinkeby/mainnet, added algos on search

* global color system tweak, apply on asset teaser system

* create subtle hierarchical distinction between background & content
* output asset type
* add asset type as css class
* bonus side effect: a nicer dark mode theme on OLED screens

* add icon assets

* compute/download icons added to asset teaser

* tooltip content fix

* tooltip content width fix


tooltip message shortened

* max-width added

* links renamed, all algos section removed

* datatoken tooltip removed

* spacing tweaks

* visual separation of asset & access type, flip order
* spacing/font size tweaks, aligning things

* fix search

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* light mode color tweak

* change dataset display name

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* data set label fixed

* query updated for data sets and algos

Co-authored-by: claudia.holhos <claudia.holhos@hpm.ro>
Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro>
This commit is contained in:
claudiaHash 2021-02-22 16:25:27 +02:00 committed by GitHub
parent 28555ffd1b
commit ce81777030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 189 additions and 60 deletions

View File

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

View File

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

View File

@ -14,6 +14,10 @@
flex-direction: column;
}
.algorithm .link {
background-color: var(--background-body);
}
.content {
margin-top: calc(var(--spacer) / 2);
overflow-wrap: break-word;
@ -49,18 +53,6 @@
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 {
display: block;
}
@ -69,3 +61,28 @@
font-size: var(--font-size-mini);
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 { DDO } from '@oceanprotocol/lib'
import removeMarkdown from 'remove-markdown'
import Tooltip from '../atoms/Tooltip'
import Publisher from '../atoms/Publisher'
import { useMetadata } from '@oceanprotocol/react'
import Time from '../atoms/Time'
import { ReactComponent as Compute } from '../../images/compute.svg'
import { ReactComponent as Download } from '../../images/download.svg'
declare type AssetTeaserProps = {
ddo: DDO
@ -17,27 +18,35 @@ declare type AssetTeaserProps = {
const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
const { owner } = useMetadata(ddo)
const { attributes } = ddo.findServiceByType('metadata')
const { name } = attributes.main
const { name, type } = attributes.main
const { dataTokenInfo } = ddo
const isCompute = Boolean(ddo.findServiceByType('compute'))
const accessType = ddo.service[1].type
return (
<article className={styles.teaser}>
<article className={`${styles.teaser} ${styles[type]}`}>
<Link to={`/asset/${ddo.id}`} className={styles.link}>
<header className={styles.header}>
<Tooltip
placement="left"
content={dataTokenInfo?.name}
className={styles.symbol}
>
{dataTokenInfo?.symbol}
</Tooltip>
<div className={styles.symbol}>{dataTokenInfo?.symbol}</div>
<Dotdotdot clamp={3}>
<h1 className={styles.title}>{name}</h1>
</Dotdotdot>
<Publisher account={owner} minimal className={styles.publisher} />
</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}>
<Dotdotdot tagName="p" clamp={3}>

View File

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

View File

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

View File

@ -31,3 +31,7 @@ button.filter,
background: var(--font-color-text);
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 styles from './filterPrice.module.css'
import classNames from 'classnames/bind'
import { addExistingParamsToUrl, FilterByPriceOptions } from './utils'
import {
addExistingParamsToUrl,
FilterByPriceOptions,
FilterByTypeOptions
} from './utils'
import Button from '../../atoms/Button'
const cx = classNames.bind(styles)
const filterItems = [
const filterItemsPrice = [
{ display: 'all', value: undefined },
{ display: 'fixed price', value: FilterByPriceOptions.Fixed },
{ 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({
priceType,
setPriceType
setPriceType,
serviceType,
setServiceType
}: {
priceType: string
setPriceType: React.Dispatch<React.SetStateAction<string>>
serviceType: string
setServiceType: React.Dispatch<React.SetStateAction<string>>
}): ReactElement {
const navigate = useNavigate()
@ -31,27 +45,59 @@ export default function FilterPrice({
navigate(urlLocation)
}
async function applyTypeFilter(filterBy: string) {
let urlLocation = await addExistingParamsToUrl(location, 'serviceType')
if (filterBy) {
urlLocation = `${urlLocation}&serviceType=${filterBy}`
}
setServiceType(filterBy)
navigate(urlLocation)
}
return (
<div>
{filterItems.map((e, index) => {
const filter = cx({
[styles.selected]: e.value === priceType,
[styles.filter]: true
})
return (
<Button
size="small"
style="text"
key={index}
className={filter}
onClick={async () => {
await applyFilter(e.value)
}}
>
{e.display}
</Button>
)
})}
<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({
[styles.selected]: e.value === priceType,
[styles.filter]: true
})
return (
<Button
size="small"
style="text"
key={index}
className={filter}
onClick={async () => {
await applyFilter(e.value)
}}
>
{e.display}
</Button>
)
})}
</div>
</div>
)
}

View File

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

View File

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

View File

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

View File

@ -4,6 +4,7 @@ import {
} from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import { MetadataCache, Logger } from '@oceanprotocol/lib'
import queryString from 'query-string'
import { TypeOf } from 'yup'
export const SortTermOptions = {
Liquidity: 'liquidity',
@ -31,6 +32,12 @@ export const FilterByPriceOptions = {
} as const
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 {
sortTerm = priceFilter
? sortTerm === ''
@ -40,6 +47,15 @@ function addPriceFilterToQuerry(sortTerm: string, priceFilter: string): string {
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 {
const sortTerm =
sortParam === SortTermOptions.Liquidity
@ -59,7 +75,8 @@ export function getSearchQuery(
offset?: string,
sort?: string,
sortOrder?: string,
priceType?: string
priceType?: string,
serviceType?: string
): SearchQuery {
const sortTerm = getSortType(sort)
const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1
@ -73,7 +90,8 @@ export function getSearchQuery(
`(service.attributes.additionalInformation.categories:\"${categories}\")`
: text || ''
searchTerm = addPriceFilterToQuerry(searchTerm, priceType)
searchTerm = addTypeFilterToQuery(searchTerm, serviceType)
console.log('search', searchTerm, serviceType)
return {
page: Number(page) || 1,
offset: Number(offset) || 21,
@ -112,6 +130,7 @@ export async function getResults(
sort?: string
sortOrder?: string
priceType?: string
serviceType?: string
},
metadataCacheUri: string
): Promise<QueryResult> {
@ -124,7 +143,8 @@ export async function getResults(
categories,
sort,
sortOrder,
priceType
priceType,
serviceType
} = params
const metadataCache = new MetadataCache(metadataCacheUri, Logger)
const searchQuery = getSearchQuery(
@ -136,7 +156,8 @@ export async function getResults(
offset,
sort,
sortOrder,
priceType
priceType,
serviceType
)
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 */
--font-color-text: #41474e;
--font-color-heading: #141414;
--background-body: #fff;
--background-body: #fafafa;
--background-body-transparent: rgba(255, 255, 255, 0.8);
--background-content: #fff;
--background-highlight: #f7f7f7;
--border-color: #e2e2e2;
--box-shadow-color: rgba(0, 0, 0, 0.05);
@ -70,8 +71,9 @@
.dark {
--font-color-text: #e2e2e2;
--font-color-heading: #f7f7f7;
--background-body: #141414;
--background-body-transparent: rgba(20, 20, 20, 0.9);
--background-body: rgb(10, 10, 10);
--background-body-transparent: rgba(10, 10, 10, 0.9);
--background-content: #141414;
--background-highlight: #201f1f;
--border-color: #303030;
--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