diff --git a/src/components/organisms/AssetActions/Consume.tsx b/src/components/organisms/AssetActions/Consume.tsx
index 42b4b4bdb..de13eb25c 100644
--- a/src/components/organisms/AssetActions/Consume.tsx
+++ b/src/components/organisms/AssetActions/Consume.tsx
@@ -48,7 +48,7 @@ export default function Consume({
const { marketFeeAddress } = useSiteMetadata()
const [hasPreviousOrder, setHasPreviousOrder] = useState(false)
const [previousOrderId, setPreviousOrderId] = useState()
- const { isInPurgatory, price } = useAsset()
+ const { isInPurgatory, price, type } = useAsset()
const { buyDT, pricingStepText, pricingError, pricingIsLoading } = usePricing(
ddo
)
@@ -158,17 +158,10 @@ export default function Consume({
@@ -17,6 +25,9 @@ export default function MetaFull(): ReactElement {
title="Owner"
content={
}
/>
+ {type === 'algorithm' && (
+
} />
+ )}
{/*
}
diff --git a/src/components/organisms/AssetContent/MetaMain.module.css b/src/components/organisms/AssetContent/MetaMain.module.css
index 428652473..a93f3d6a7 100644
--- a/src/components/organisms/AssetContent/MetaMain.module.css
+++ b/src/components/organisms/AssetContent/MetaMain.module.css
@@ -9,5 +9,17 @@
.date {
font-size: var(--font-size-mini);
- margin-top: calc(var(--spacer) / 2);
+}
+
+.typeAndDate {
+ margin-top: calc(var(--spacer) / 2);
+ display: flex;
+}
+
+.typeDetails {
+ border-right: 1px solid var(--border-color);
+ padding-right: calc(var(--spacer) / 3.5);
+ margin-right: calc(var(--spacer) / 4);
+ width: auto;
+ font-size: var(--font-size-mini);
}
diff --git a/src/components/organisms/AssetContent/MetaMain.tsx b/src/components/organisms/AssetContent/MetaMain.tsx
index ec5236a37..e4f513d87 100644
--- a/src/components/organisms/AssetContent/MetaMain.tsx
+++ b/src/components/organisms/AssetContent/MetaMain.tsx
@@ -5,10 +5,13 @@ import EtherscanLink from '../../atoms/EtherscanLink'
import Publisher from '../../atoms/Publisher'
import Time from '../../atoms/Time'
import styles from './MetaMain.module.css'
+import AssetType from '../../atoms/AssetType'
export default function MetaMain(): ReactElement {
- const { ddo, owner } = useAsset()
+ const { ddo, owner, type } = useAsset()
const { networkId } = useOcean()
+ const isCompute = Boolean(ddo?.findServiceByType('compute'))
+ const accessType = isCompute ? 'compute' : 'access'
return (
)
}
diff --git a/src/components/templates/Search/filterPrice.module.css b/src/components/templates/Search/filterPrice.module.css
index 06b0b51c5..c5d3ed19d 100644
--- a/src/components/templates/Search/filterPrice.module.css
+++ b/src/components/templates/Search/filterPrice.module.css
@@ -1,7 +1,12 @@
-/* .filterList {
- display: inline-flex;
- float: left;
-} */
+.filterList,
+div.filterList {
+ white-space: normal;
+ margin-bottom: 0;
+}
+
+.filter {
+ display: inline-block;
+}
.filter,
button.filter,
@@ -9,14 +14,14 @@ button.filter,
.filter:active,
.filter:focus {
border: 1px solid var(--border-color);
- text-transform: uppercase;
border-radius: var(--border-radius);
margin-right: calc(var(--spacer) / 6);
+ margin-bottom: calc(var(--spacer) / 6);
color: var(--color-secondary);
- background: var(--background-body);
+ background: var(--background-content);
/* the only thing not possible to overwrite button style="text" with more specifity of selectors, so sledgehammer */
- padding: calc(var(--spacer) / 5) !important;
+ padding: calc(var(--spacer) / 6) !important;
}
.filter:hover,
@@ -32,6 +37,24 @@ button.filter,
border-color: var(--background-body);
}
+.filter.selected::after {
+ content: '✕';
+ margin-left: calc(var(--spacer) / 6);
+ color: var(--background-body);
+}
+
.filterList:first-of-type {
margin-bottom: calc(var(--spacer) / 6);
}
+
+.showClear {
+ display: inline-flex;
+ text-transform: capitalize;
+ color: var(--color-secondary);
+ font-weight: var(--font-weight-base);
+ margin-left: calc(var(--spacer) / 6);
+}
+
+.hideClear {
+ display: none !important;
+}
diff --git a/src/components/templates/Search/filterPrice.tsx b/src/components/templates/Search/filterPrice.tsx
index 620138eba..d722bdc01 100644
--- a/src/components/templates/Search/filterPrice.tsx
+++ b/src/components/templates/Search/filterPrice.tsx
@@ -1,4 +1,4 @@
-import React, { ReactElement } from 'react'
+import React, { ReactElement, useEffect, useState } from 'react'
import { useNavigate } from '@reach/router'
import styles from './filterPrice.module.css'
import classNames from 'classnames/bind'
@@ -11,22 +11,22 @@ import Button from '../../atoms/Button'
const cx = classNames.bind(styles)
-const filterItemsPrice = [
- { display: 'all', value: undefined },
+const clearFilters = [{ display: 'Clear', value: '' }]
+
+const priceFilterItems = [
{ 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 }
+const serviceFilterItems = [
+ { display: 'data sets', value: FilterByTypeOptions.Data },
+ { display: 'algorithms', value: FilterByTypeOptions.Algorithm }
]
export default function FilterPrice({
priceType,
- setPriceType,
serviceType,
+ setPriceType,
setServiceType
}: {
priceType: string
@@ -36,7 +36,10 @@ export default function FilterPrice({
}): ReactElement {
const navigate = useNavigate()
- async function applyFilter(filterBy: string) {
+ const [priceSelections, setPriceSelections] = useState
([])
+ const [serviceSelections, setServiceSelections] = useState([])
+
+ async function applyPriceFilter(filterBy: string) {
let urlLocation = await addExistingParamsToUrl(location, 'priceType')
if (filterBy) {
urlLocation = `${urlLocation}&priceType=${filterBy}`
@@ -45,59 +48,141 @@ export default function FilterPrice({
navigate(urlLocation)
}
- async function applyTypeFilter(filterBy: string) {
+ async function applyServiceFilter(filterBy: string) {
let urlLocation = await addExistingParamsToUrl(location, 'serviceType')
- if (filterBy) {
+ if (filterBy && location.search.indexOf('&serviceType') === -1) {
urlLocation = `${urlLocation}&serviceType=${filterBy}`
}
setServiceType(filterBy)
navigate(urlLocation)
}
+ async function handleSelectedFilter(isSelected: boolean, value: string) {
+ if (
+ value === FilterByPriceOptions.Fixed ||
+ value === FilterByPriceOptions.Dynamic
+ ) {
+ if (isSelected) {
+ if (priceSelections.length > 1) {
+ // both selected -> select the other one
+ const otherValue = priceFilterItems.find((p) => p.value !== value)
+ .value
+ await applyPriceFilter(otherValue)
+ } else {
+ // only the current one selected -> deselect it
+ await applyPriceFilter(undefined)
+ }
+ } else {
+ if (priceSelections.length > 0) {
+ // one already selected -> both selected
+ await applyPriceFilter(FilterByPriceOptions.All)
+ setPriceSelections(priceFilterItems.map((p) => p.value))
+ } else {
+ // none selected -> select
+ await applyPriceFilter(value)
+ setPriceSelections([value])
+ }
+ }
+ } else {
+ if (isSelected) {
+ if (serviceSelections.length > 1) {
+ const otherValue = serviceFilterItems.find((p) => p.value !== value)
+ .value
+ await applyServiceFilter(otherValue)
+ setServiceSelections([otherValue])
+ } else {
+ await applyServiceFilter(undefined)
+ }
+ } else {
+ if (serviceSelections.length) {
+ await applyServiceFilter(undefined)
+ setServiceSelections(serviceFilterItems.map((p) => p.value))
+ } else {
+ await applyServiceFilter(value)
+ setServiceSelections([value])
+ }
+ }
+ }
+ }
+
+ async function applyClearFilter() {
+ let urlLocation = await addExistingParamsToUrl(
+ location,
+ 'priceType',
+ 'serviceType'
+ )
+
+ urlLocation = `${urlLocation}`
+
+ setServiceSelections([])
+ setPriceSelections([])
+
+ setPriceType(undefined)
+ setServiceType(undefined)
+ navigate(urlLocation)
+ }
+
return (
-
-
- {filterItemsType.map((e, index) => {
- const filter = cx({
- [styles.selected]: e.value === serviceType,
- [styles.filter]: true
- })
- return (
-
- )
- })}
-
-
- {filterItemsPrice.map((e, index) => {
- const filter = cx({
- [styles.selected]: e.value === priceType,
- [styles.filter]: true
- })
- return (
-
- )
- })}
-
+
+ {priceFilterItems.map((e, index) => {
+ const isPriceSelected =
+ e.value === priceType || priceSelections.includes(e.value)
+ const selectFilter = cx({
+ [styles.selected]: isPriceSelected,
+ [styles.filter]: true
+ })
+ return (
+
+ )
+ })}
+ {serviceFilterItems.map((e, index) => {
+ const isServiceSelected =
+ e.value === serviceType || serviceSelections.includes(e.value)
+ const selectFilter = cx({
+ [styles.selected]: isServiceSelected,
+ [styles.filter]: true
+ })
+ return (
+
+ )
+ })}
+ {clearFilters.map((e, index) => {
+ const showClear =
+ priceSelections.length > 0 || serviceSelections.length > 0
+ return (
+
+ )
+ })}
)
}
diff --git a/src/components/templates/Search/index.tsx b/src/components/templates/Search/index.tsx
index dc11ee940..f89af6d24 100644
--- a/src/components/templates/Search/index.tsx
+++ b/src/components/templates/Search/index.tsx
@@ -34,7 +34,7 @@ export default function SearchPage({
const [queryResult, setQueryResult] = useState
()
const [loading, setLoading] = useState()
const [price, setPriceType] = useState(priceType as string)
- const [type, setType] = useState(serviceType as string)
+ const [service, setServiceType] = useState(serviceType as string)
const [sortType, setSortType] = useState(sort as string)
const [sortDirection, setSortDirection] = useState(
sortOrder as string
@@ -82,9 +82,9 @@ export default function SearchPage({
diff --git a/src/components/templates/Search/sort.module.css b/src/components/templates/Search/sort.module.css
index dc72f57df..dfcf1ce46 100644
--- a/src/components/templates/Search/sort.module.css
+++ b/src/components/templates/Search/sort.module.css
@@ -1,11 +1,18 @@
.sortList {
- align-self: flex-end;
- padding: calc(var(--spacer) / 10);
+ padding: 0 calc(var(--spacer) / 10);
display: flex;
align-items: center;
border-radius: var(--border-radius);
border: 1px solid var(--border-color);
- background: var(--background-body);
+ background: var(--background-content);
+ overflow-y: auto;
+}
+
+@media (min-width: 40rem) {
+ .sortList {
+ align-self: flex-end;
+ overflow-y: unset;
+ }
}
.sortLabel {
@@ -15,6 +22,7 @@
margin-right: calc(var(--spacer) / 1.5);
text-transform: uppercase;
color: var(--color-secondary);
+ font-size: var(--font-size-small);
}
.sorted {
@@ -25,7 +33,7 @@
text-transform: capitalize;
border-radius: 0;
font-weight: var(--font-weight-base);
- background: var(--background-body);
+ background: var(--background-content);
box-shadow: none;
}
diff --git a/src/components/templates/Search/sort.tsx b/src/components/templates/Search/sort.tsx
index 331d1876c..908937dbf 100644
--- a/src/components/templates/Search/sort.tsx
+++ b/src/components/templates/Search/sort.tsx
@@ -24,13 +24,15 @@ export default function Sort({
setSortType,
sortDirection,
setSortDirection,
- setPriceType
+ setPriceType,
+ setServiceType
}: {
sortType: string
setSortType: React.Dispatch>
sortDirection: string
setSortDirection: React.Dispatch>
setPriceType: React.Dispatch>
+ setServiceType: React.Dispatch>
}): ReactElement {
const navigate = useNavigate()
const directionArrow = String.fromCharCode(
@@ -44,8 +46,6 @@ export default function Sort({
if (sortBy === SortTermOptions.Liquidity) {
urlLocation = `${urlLocation}&priceType=${FilterByPriceOptions.Dynamic}`
setPriceType(FilterByPriceOptions.Dynamic)
- } else {
- setPriceType(undefined)
}
setSortType(sortBy)
} else if (direction) {
diff --git a/src/components/templates/Search/utils.ts b/src/components/templates/Search/utils.ts
index 4a6046413..661dd1b6c 100644
--- a/src/components/templates/Search/utils.ts
+++ b/src/components/templates/Search/utils.ts
@@ -28,7 +28,8 @@ type SortValueOptions = typeof SortValueOptions[keyof typeof SortValueOptions]
export const FilterByPriceOptions = {
Fixed: 'exchange',
- Dynamic: 'pool'
+ Dynamic: 'pool',
+ All: 'all'
} as const
type FilterByPriceOptions = typeof FilterByPriceOptions[keyof typeof FilterByPriceOptions]
@@ -38,12 +39,20 @@ export const FilterByTypeOptions = {
} as const
type FilterByTypeOptions = typeof FilterByTypeOptions[keyof typeof FilterByTypeOptions]
-function addPriceFilterToQuerry(sortTerm: string, priceFilter: string): string {
- sortTerm = priceFilter
- ? sortTerm === ''
- ? `price.type:${priceFilter}`
- : `${sortTerm} AND price.type:${priceFilter}`
- : sortTerm
+function addPriceFilterToQuery(sortTerm: string, priceFilter: string): string {
+ if (priceFilter === FilterByPriceOptions.All) {
+ sortTerm = priceFilter
+ ? sortTerm === ''
+ ? `(price.type:${FilterByPriceOptions.Fixed} OR price.type:${FilterByPriceOptions.Dynamic})`
+ : `${sortTerm} AND (price.type:${FilterByPriceOptions.Dynamic} OR price.type:${FilterByPriceOptions.Fixed})`
+ : sortTerm
+ } else {
+ sortTerm = priceFilter
+ ? sortTerm === ''
+ ? `price.type:${priceFilter}`
+ : `${sortTerm} AND price.type:${priceFilter}`
+ : sortTerm
+ }
return sortTerm
}
@@ -89,9 +98,9 @@ export function getSearchQuery(
? // eslint-disable-next-line no-useless-escape
`(service.attributes.additionalInformation.categories:\"${categories}\")`
: text || ''
- searchTerm = addPriceFilterToQuerry(searchTerm, priceType)
searchTerm = addTypeFilterToQuery(searchTerm, serviceType)
- console.log('search', searchTerm, serviceType)
+ searchTerm = addPriceFilterToQuery(searchTerm, priceType)
+
return {
page: Number(page) || 1,
offset: Number(offset) || 21,
diff --git a/src/global/_variables.css b/src/global/_variables.css
index a27190ad1..3d67114cf 100644
--- a/src/global/_variables.css
+++ b/src/global/_variables.css
@@ -25,7 +25,7 @@
/* Only use these vars for most color referencing for easy light/dark mode */
--font-color-text: #41474e;
--font-color-heading: #141414;
- --background-body: #fafafa;
+ --background-body: #fcfcfc;
--background-body-transparent: rgba(255, 255, 255, 0.8);
--background-content: #fff;
--background-highlight: #f7f7f7;
diff --git a/src/pages/search.tsx b/src/pages/search.tsx
index 2e8a3454f..145b3c348 100644
--- a/src/pages/search.tsx
+++ b/src/pages/search.tsx
@@ -27,7 +27,7 @@ export default function PageGatsbySearch(props: PageProps): ReactElement {
(totalResults > 1 ? ' results' : ' result') +
' for ' +
searchValue
- : totalResults + ' datasets'
+ : totalResults + ' results'
: 'Searching...'
}`
diff --git a/src/providers/Asset.tsx b/src/providers/Asset.tsx
index aa8629465..c6778892e 100644
--- a/src/providers/Asset.tsx
+++ b/src/providers/Asset.tsx
@@ -7,7 +7,7 @@ import React, {
useCallback,
ReactNode
} from 'react'
-import { Logger, DDO, BestPrice } from '@oceanprotocol/lib'
+import { Logger, DDO, BestPrice, MetadataMain } from '@oceanprotocol/lib'
import { PurgatoryData } from '@oceanprotocol/lib/dist/node/ddo/interfaces/PurgatoryData'
import { getDataTokenPrice, useOcean } from '@oceanprotocol/react'
import getAssetPurgatoryData from '../utils/purgatory'
@@ -25,6 +25,7 @@ interface AssetProviderValue {
title: string | undefined
owner: string | undefined
price: BestPrice | undefined
+ type: MetadataMain['type'] | undefined
error?: string
refreshInterval: number
refreshDdo: (token?: CancelToken) => Promise
@@ -52,6 +53,7 @@ function AssetProvider({
const [price, setPrice] = useState()
const [owner, setOwner] = useState()
const [error, setError] = useState()
+ const [type, setType] = useState()
const refreshPrice = useCallback(async () => {
if (
@@ -160,6 +162,7 @@ function AssetProvider({
const { attributes } = ddo.findServiceByType('metadata')
setMetadata((attributes as unknown) as MetadataMarket)
setTitle(attributes?.main.name)
+ setType(attributes.main.type)
setOwner(ddo.publicKey[0].owner)
setIsInPurgatory(ddo.isInPurgatory === 'true')
@@ -184,6 +187,7 @@ function AssetProvider({
title,
owner,
price,
+ type,
error,
isInPurgatory,
purgatoryData,
diff --git a/src/utils/aquarius.ts b/src/utils/aquarius.ts
index a11657a7e..0e88a7949 100644
--- a/src/utils/aquarius.ts
+++ b/src/utils/aquarius.ts
@@ -73,3 +73,27 @@ export async function retrieveDDO(
}
}
}
+
+export async function getAssetsNames(
+ didList: string[] | DID[],
+ metadataCacheUri: string,
+ cancelToken: CancelToken
+): Promise> {
+ try {
+ const response: AxiosResponse> = await axios.post(
+ `${metadataCacheUri}/api/v1/aquarius/assets/names`,
+ {
+ didList,
+ cancelToken
+ }
+ )
+ if (!response || response.status !== 200 || !response.data) return
+ return response.data
+ } catch (error) {
+ if (axios.isCancel(error)) {
+ Logger.log(error.message)
+ } else {
+ Logger.error(error.message)
+ }
+ }
+}
diff --git a/src/utils/profile.ts b/src/utils/profile.ts
index ccc368cad..f78d2c71b 100644
--- a/src/utils/profile.ts
+++ b/src/utils/profile.ts
@@ -5,7 +5,7 @@ import { Logger } from '@oceanprotocol/lib'
// https://docs.3box.io/api/rest-api
const apiUri = 'https://3box.oceanprotocol.com'
-const ipfsUrl = 'https://ipfs.oceanprotocol.com'
+const ipfsUrl = 'https://dweb.link'
function decodeProof(proofJWT: string) {
if (!proofJWT) return