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

Merge branch 'main' into feature/account_page

This commit is contained in:
Matthias Kretschmann 2021-09-15 12:22:05 +02:00
commit eacd0c56a0
Signed by: m
GPG Key ID: 606EEEF3C479A91F
9 changed files with 235 additions and 104 deletions

View File

@ -23,6 +23,7 @@ export default function Alert({
action?: { action?: {
name: string name: string
style?: 'text' | 'primary' | 'ghost' style?: 'text' | 'primary' | 'ghost'
disabled?: boolean
handleAction: (e: FormEvent<HTMLButtonElement>) => void handleAction: (e: FormEvent<HTMLButtonElement>) => void
} }
onDismiss?: () => void onDismiss?: () => void
@ -48,6 +49,7 @@ export default function Alert({
size="small" size="small"
style={action.style || 'primary'} style={action.style || 'primary'}
onClick={action.handleAction} onClick={action.handleAction}
disabled={action.disabled}
> >
{action.name} {action.name}
</Button> </Button>

View File

@ -21,9 +21,7 @@
.content { .content {
margin-top: calc(var(--spacer) / 2); margin-top: calc(var(--spacer) / 2);
overflow-wrap: break-word; overflow-wrap: break-word;
word-wrap: break-word; hyphens: auto;
word-break: break-all;
/* for sticking footer to bottom */ /* for sticking footer to bottom */
flex: 1; flex: 1;
} }
@ -36,6 +34,7 @@
font-size: var(--font-size-large); font-size: var(--font-size-large);
margin: 0; margin: 0;
padding-bottom: calc(var(--spacer) / 6); padding-bottom: calc(var(--spacer) / 6);
overflow-wrap: break-word;
} }
.publisher { .publisher {

View File

@ -5,7 +5,8 @@ import File from '../../atoms/File'
import Price from '../../atoms/Price' import Price from '../../atoms/Price'
import { useSiteMetadata } from '../../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
import { useAsset } from '../../../providers/Asset' import { useAsset } from '../../../providers/Asset'
import { gql, useQuery } from 'urql' import { gql } from 'urql'
import { fetchData, getQueryContext } from '../../../utils/subgraph'
import { OrdersData } from '../../../@types/apollo/OrdersData' import { OrdersData } from '../../../@types/apollo/OrdersData'
import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import { useOcean } from '../../../providers/Ocean' import { useOcean } from '../../../providers/Ocean'
@ -63,15 +64,19 @@ export default function Consume({
const [maxDt, setMaxDT] = useState<number>(1) const [maxDt, setMaxDT] = useState<number>(1)
const [isConsumablePrice, setIsConsumablePrice] = useState(true) const [isConsumablePrice, setIsConsumablePrice] = useState(true)
const [assetTimeout, setAssetTimeout] = useState('') const [assetTimeout, setAssetTimeout] = useState('')
const [result] = useQuery<OrdersData>({ const [data, setData] = useState<OrdersData>()
query: previousOrderQuery,
variables: { useEffect(() => {
if (!ddo || !accountId) return
const context = getQueryContext(ddo.chainId)
const variables = {
id: ddo.dataToken?.toLowerCase(), id: ddo.dataToken?.toLowerCase(),
account: accountId?.toLowerCase() account: accountId?.toLowerCase()
} }
// pollInterval: 5000 fetchData(previousOrderQuery, variables, context).then((result: any) => {
setData(result.data)
}) })
const { data } = result }, [ddo, accountId, hasPreviousOrder])
async function checkMaxAvaialableTokens(price: BestPrice) { async function checkMaxAvaialableTokens(price: BestPrice) {
if (!ocean || !price) return if (!ocean || !price) return
@ -83,7 +88,8 @@ export default function Consume({
} }
useEffect(() => { useEffect(() => {
if (!data || !assetTimeout || data.tokenOrders.length === 0) return if (!data || !assetTimeout || data.tokenOrders.length === 0 || !accountId)
return
const lastOrder = data.tokenOrders[0] const lastOrder = data.tokenOrders[0]
if (assetTimeout === '0') { if (assetTimeout === '0') {
@ -99,7 +105,7 @@ export default function Consume({
setHasPreviousOrder(false) setHasPreviousOrder(false)
} }
} }
}, [data, assetTimeout]) }, [data, assetTimeout, accountId])
useEffect(() => { useEffect(() => {
const { timeout } = ddo.findServiceByType('access').attributes.main const { timeout } = ddo.findServiceByType('access').attributes.main
@ -120,6 +126,7 @@ export default function Consume({
}, [dtBalance]) }, [dtBalance])
useEffect(() => { useEffect(() => {
if (!accountId) return
setIsDisabled( setIsDisabled(
!isConsumable || !isConsumable ||
((!ocean || ((!ocean ||
@ -141,6 +148,7 @@ export default function Consume({
pricingIsLoading, pricingIsLoading,
isConsumablePrice, isConsumablePrice,
hasDatatoken, hasDatatoken,
accountId,
isConsumable isConsumable
]) ])

View File

@ -10,6 +10,7 @@ import Feedback from './Feedback'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import { usePricing } from '../../../../hooks/usePricing' import { usePricing } from '../../../../hooks/usePricing'
import styles from './index.module.css' import styles from './index.module.css'
import { useAsset } from '../../../../providers/Asset'
const query = graphql` const query = graphql`
query PricingQuery { query PricingQuery {
@ -67,6 +68,7 @@ export default function Pricing({ ddo }: { ddo: DDO }): ReactElement {
const { createPricing, pricingIsLoading, pricingError, pricingStepText } = const { createPricing, pricingIsLoading, pricingError, pricingStepText } =
usePricing() usePricing()
const { isAssetNetwork } = useAsset()
const hasFeedback = pricingIsLoading || typeof success !== 'undefined' const hasFeedback = pricingIsLoading || typeof success !== 'undefined'
@ -133,6 +135,7 @@ export default function Pricing({ ddo }: { ddo: DDO }): ReactElement {
text={content.empty.info} text={content.empty.info}
action={{ action={{
name: content.empty.action.name, name: content.empty.action.name,
disabled: !isAssetNetwork,
handleAction: handleShowPricingForm handleAction: handleShowPricingForm
}} }}
/> />

View File

@ -2,6 +2,13 @@
div.filterList { div.filterList {
white-space: normal; white-space: normal;
margin-bottom: 0; margin-bottom: 0;
display: flex;
flex-direction: row;
align-items: baseline;
}
.separator {
width: calc(var(--spacer) / 2);
} }
.filter { .filter {

View File

@ -1,7 +1,11 @@
import React, { ReactElement, useState } from 'react' import React, { ReactElement, useState } from 'react'
import { useNavigate } from '@reach/router' import { useNavigate } from '@reach/router'
import classNames from 'classnames/bind' import classNames from 'classnames/bind'
import { addExistingParamsToUrl, FilterByTypeOptions } from './utils' import {
addExistingParamsToUrl,
FilterByAccessOptions,
FilterByTypeOptions
} from './utils'
import Button from '../../atoms/Button' import Button from '../../atoms/Button'
import styles from './Filters.module.css' import styles from './Filters.module.css'
@ -14,61 +18,123 @@ const serviceFilterItems = [
{ display: 'algorithms', value: FilterByTypeOptions.Algorithm } { display: 'algorithms', value: FilterByTypeOptions.Algorithm }
] ]
const accessFilterItems = [
{ display: 'download ', value: FilterByAccessOptions.Download },
{ display: 'compute ', value: FilterByAccessOptions.Compute }
]
export default function Filters({ export default function Filters({
serviceType, serviceType,
accessType,
setServiceType, setServiceType,
setAccessType,
isSearch, isSearch,
className className
}: { }: {
serviceType: string serviceType: string
accessType: string
setServiceType: React.Dispatch<React.SetStateAction<string>> setServiceType: React.Dispatch<React.SetStateAction<string>>
isSearch: boolean isSearch: boolean
setAccessType: React.Dispatch<React.SetStateAction<string>>
className?: string className?: string
}): ReactElement { }): ReactElement {
const navigate = useNavigate() const navigate = useNavigate()
const [serviceSelections, setServiceSelections] = useState<string[]>([]) const [serviceSelections, setServiceSelections] = useState<string[]>([])
const [accessSelections, setAccessSelections] = useState<string[]>([])
async function applyFilter(filter: string, filterType: string) {
let urlLocation = ''
if (filterType.localeCompare('accessType') === 0) {
urlLocation = await addExistingParamsToUrl(location, ['accessType'])
} else {
urlLocation = await addExistingParamsToUrl(location, ['serviceType'])
}
async function applyServiceFilter(filterBy: string) { async function applyServiceFilter(filterBy: string) {
setServiceType(filterBy) setServiceType(filterBy)
if (filter && location.search.indexOf(filterType) === -1) {
filterType === 'accessType'
? (urlLocation = `${urlLocation}&accessType=${filter}`)
: (urlLocation = `${urlLocation}&serviceType=${filter}`)
}
if (isSearch) { if (isSearch) {
let urlLocation = await addExistingParamsToUrl(location, ['serviceType']) let urlLocation = await addExistingParamsToUrl(location, [
'serviceType'
])
if (filterBy && location.search.indexOf('&serviceType') === -1) { if (filterBy && location.search.indexOf('&serviceType') === -1) {
urlLocation = `${urlLocation}&serviceType=${filterBy}` urlLocation = `${urlLocation}&serviceType=${filterBy}`
} }
filterType === 'accessType'
? setAccessType(filter)
: setServiceType(filter)
navigate(urlLocation) navigate(urlLocation)
} }
} }
async function handleSelectedFilter(isSelected: boolean, value: string) { async function handleSelectedFilter(isSelected: boolean, value: string) {
if (
value === FilterByAccessOptions.Download ||
value === FilterByAccessOptions.Compute
) {
if (isSelected) {
if (accessSelections.length > 1) {
// both selected -> select the other one
const otherValue = accessFilterItems.find(
(p) => p.value !== value
).value
await applyFilter(otherValue, 'accessType')
setAccessSelections([otherValue])
} else {
// only the current one selected -> deselect it
await applyFilter(undefined, 'accessType')
setAccessSelections([])
}
} else {
if (accessSelections.length) {
// one already selected -> both selected
await applyFilter(undefined, 'accessType')
setAccessSelections(accessFilterItems.map((p) => p.value))
} else {
// none selected -> select
await applyFilter(value, 'accessType')
setAccessSelections([value])
}
}
} else {
if (isSelected) { if (isSelected) {
if (serviceSelections.length > 1) { if (serviceSelections.length > 1) {
const otherValue = serviceFilterItems.find( const otherValue = serviceFilterItems.find(
(p) => p.value !== value (p) => p.value !== value
).value ).value
await applyServiceFilter(otherValue) await applyFilter(otherValue, 'serviceType')
setServiceSelections([otherValue]) setServiceSelections([otherValue])
} else { } else {
await applyServiceFilter(undefined) await applyFilter(undefined, 'serviceType')
if (serviceSelections.includes(value)) { setServiceSelections([])
serviceSelections.pop()
}
} }
} else { } else {
if (serviceSelections.length) { if (serviceSelections.length) {
await applyServiceFilter(undefined) await applyFilter(undefined, 'serviceType')
setServiceSelections(serviceFilterItems.map((p) => p.value)) setServiceSelections(serviceFilterItems.map((p) => p.value))
} else { } else {
await applyServiceFilter(value) await applyFilter(value, 'serviceType')
setServiceSelections([value]) setServiceSelections([value])
} }
} }
} }
}
async function applyClearFilter(isSearch: boolean) { async function applyClearFilter(isSearch: boolean) {
setServiceSelections([]) setServiceSelections([])
setAccessSelections([])
setServiceType(undefined) setServiceType(undefined)
setAccessType(undefined)
if (isSearch) { if (isSearch) {
let urlLocation = await addExistingParamsToUrl(location, ['serviceType']) let urlLocation = await addExistingParamsToUrl(location, [
'serviceType'
])
urlLocation = `${urlLocation}` urlLocation = `${urlLocation}`
navigate(urlLocation) navigate(urlLocation)
} }
@ -103,8 +169,31 @@ export default function Filters({
</Button> </Button>
) )
})} })}
<div className={styles.separator} />
{accessFilterItems.map((e, index) => {
const isAccessSelected =
e.value === accessType || accessSelections.includes(e.value)
const selectFilter = cx({
[styles.selected]: isAccessSelected,
[styles.filter]: true
})
return (
<Button
size="small"
style="text"
key={index}
className={selectFilter}
onClick={async () => {
handleSelectedFilter(isAccessSelected, e.value)
}}
>
{e.display}
</Button>
)
})}
{clearFilters.map((e, index) => { {clearFilters.map((e, index) => {
const showClear = serviceSelections.length > 0 const showClear =
accessSelections.length > 0 || serviceSelections.length > 0
return ( return (
<Button <Button
size="small" size="small"
@ -122,3 +211,4 @@ export default function Filters({
</div> </div>
) )
} }
}

View File

@ -21,11 +21,13 @@ export default function SearchPage({
}): ReactElement { }): ReactElement {
const { appConfig } = useSiteMetadata() const { appConfig } = useSiteMetadata()
const parsed = queryString.parse(location.search) const parsed = queryString.parse(location.search)
const { text, owner, tags, page, sort, sortOrder, serviceType } = parsed const { text, owner, tags, page, sort, sortOrder, serviceType, accessType } =
parsed
const { chainIds } = useUserPreferences() const { chainIds } = useUserPreferences()
const [queryResult, setQueryResult] = useState<QueryResult>() const [queryResult, setQueryResult] = useState<QueryResult>()
const [loading, setLoading] = useState<boolean>() const [loading, setLoading] = useState<boolean>()
const [service, setServiceType] = useState<string>(serviceType as string) const [service, setServiceType] = useState<string>(serviceType as string)
const [access, setAccessType] = useState<string>(accessType 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
@ -53,6 +55,7 @@ export default function SearchPage({
sort, sort,
page, page,
serviceType, serviceType,
accessType,
sortOrder, sortOrder,
appConfig.metadataCacheUri, appConfig.metadataCacheUri,
chainIds chainIds
@ -74,7 +77,9 @@ export default function SearchPage({
<div className={styles.row}> <div className={styles.row}>
<Filters <Filters
serviceType={service} serviceType={service}
accessType={access}
setServiceType={setServiceType} setServiceType={setServiceType}
setAccessType={setAccessType}
isSearch isSearch
/> />
<Sort <Sort

View File

@ -1,5 +1,5 @@
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache' import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import { MetadataCache, Logger } from '@oceanprotocol/lib' import { Logger } from '@oceanprotocol/lib'
import { import {
queryMetadata, queryMetadata,
transformChainIdsListToQuery transformChainIdsListToQuery
@ -33,6 +33,13 @@ export const FilterByTypeOptions = {
type FilterByTypeOptions = type FilterByTypeOptions =
typeof FilterByTypeOptions[keyof typeof FilterByTypeOptions] typeof FilterByTypeOptions[keyof typeof FilterByTypeOptions]
export const FilterByAccessOptions = {
Download: 'access',
Compute: 'compute'
}
type FilterByAccessOptions =
typeof FilterByAccessOptions[keyof typeof FilterByAccessOptions]
function getSortType(sortParam: string): string { function getSortType(sortParam: string): string {
const sortTerm = const sortTerm =
sortParam === SortTermOptions.Created sortParam === SortTermOptions.Created
@ -51,7 +58,8 @@ export function getSearchQuery(
offset?: string, offset?: string,
sort?: string, sort?: string,
sortOrder?: string, sortOrder?: string,
serviceType?: string serviceType?: string,
accessType?: string
): any { ): any {
const sortTerm = getSortType(sort) const sortTerm = getSortType(sort)
const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1 const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1
@ -139,6 +147,12 @@ export function getSearchQuery(
: `${serviceType}` : `${serviceType}`
} }
}, },
{
match: {
'service.type':
accessType === undefined ? 'access OR compute' : `${accessType}`
}
},
{ {
query_string: { query_string: {
query: `${transformChainIdsListToQuery(chainIds)}` query: `${transformChainIdsListToQuery(chainIds)}`
@ -169,6 +183,7 @@ export async function getResults(
sort?: string sort?: string
sortOrder?: string sortOrder?: string
serviceType?: string serviceType?: string
accessType?: string
}, },
metadataCacheUri: string, metadataCacheUri: string,
chainIds: number[] chainIds: number[]
@ -182,7 +197,8 @@ export async function getResults(
offset, offset,
sort, sort,
sortOrder, sortOrder,
serviceType serviceType,
accessType
} = params } = params
const searchQuery = getSearchQuery( const searchQuery = getSearchQuery(
@ -195,7 +211,8 @@ export async function getResults(
offset, offset,
sort, sort,
sortOrder, sortOrder,
serviceType serviceType,
accessType
) )
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
// const queryResult = await metadataCache.queryMetadata(searchQuery) // const queryResult = await metadataCache.queryMetadata(searchQuery)

View File

@ -131,7 +131,7 @@ const AssetPoolPriceQuery = gql`
datatokenAddress datatokenAddress
datatokenReserve datatokenReserve
oceanReserve oceanReserve
tokens { tokens(where: { isDatatoken: false }) {
symbol symbol
} }
} }