Skip to content

Commit

Permalink
Merge pull request #478 from oasisprotocol/csillag/adjust-global-search
Browse files Browse the repository at this point in the history
Adjust global search
  • Loading branch information
csillag committed Jun 8, 2023
2 parents 01b1bce + c087368 commit ccc5f69
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 67 deletions.
10 changes: 2 additions & 8 deletions src/app/components/ParaTimePicker/LayerMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Layer } from '../../../oasis-indexer/api'
import { getLayerLabels } from '../../utils/content'
import { RouteUtils } from '../../utils/route-utils'
import { Network } from '../../../types/network'
import { orderByLayer } from '../../../types/layers'

type BaseLayerMenuItemProps = {
divider: boolean
Expand Down Expand Up @@ -88,13 +89,6 @@ type LayerMenuProps = {
setSelectedLayer: (layer: Layer) => void
}

const menuSortOrder: Record<Layer, number> = {
[Layer.consensus]: 1,
[Layer.sapphire]: 2,
[Layer.emerald]: 3,
[Layer.cipher]: 4,
}

export const LayerMenu: FC<LayerMenuProps> = ({
activeLayer,
network,
Expand All @@ -108,7 +102,7 @@ export const LayerMenu: FC<LayerMenuProps> = ({
layer,
enabled: RouteUtils.getEnabledLayersForNetwork(selectedNetwork || network).includes(layer),
}))
.sort((a, b) => menuSortOrder[a.layer] - menuSortOrder[b.layer])
.sort(orderByLayer)

return (
<MenuList>
Expand Down
63 changes: 51 additions & 12 deletions src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,73 @@
import { FC } from 'react'
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'

import { getFilterForScope, getKeyForScope, getNameForScope } from '../../../types/searchScope'
import { RouteUtils } from '../../utils/route-utils'
import { SearchResults } from './hooks'
import { NoResults } from './NoResults'
import { NoResultsOnMainnet, NoResultsWhatsoever } from './NoResults'
import { SearchResultsList } from './SearchResultsList'
import { AllTokenPrices } from '../../../coin-gecko/api'
import {
getFilterForNetwork,
getNetworkNames,
isNotMainnet,
isNotOnMainnet,
isOnMainnet,
Network,
} from '../../../types/network'
import { HideMoreResults, ShowMoreResults } from './notifications'
import { getThemesForNetworks } from '../../../styles/theme'
import { orderByLayer } from '../../../types/layers'
import { useRedirectIfSingleResult } from './useRedirectIfSingleResult'

export const GlobalSearchResultsView: FC<{ searchResults: SearchResults; tokenPrices: AllTokenPrices }> = ({
searchResults,
tokenPrices,
}) => {
const { t } = useTranslation()
const [othersOpen, setOthersOpen] = useState(false)
useRedirectIfSingleResult(undefined, searchResults)

return searchResults.length === 0 ? (
<NoResults />
) : (
const themes = getThemesForNetworks()
const networkNames = getNetworkNames(t)
const otherNetworks = RouteUtils.getEnabledNetworks().filter(isNotMainnet)
const notificationTheme = themes[Network.testnet]
const mainnetResults = searchResults.filter(isOnMainnet).sort(orderByLayer)
const otherResults = searchResults.filter(isNotOnMainnet).sort(orderByLayer)

return (
<>
{RouteUtils.getEnabledSearchScopes().map(scope => (
{!mainnetResults.length && (otherResults.length ? <NoResultsOnMainnet /> : <NoResultsWhatsoever />)}
{
<SearchResultsList
key={getKeyForScope(scope)}
title={getNameForScope(t, scope)}
searchResults={searchResults.filter(getFilterForScope(scope))}
networkForTheme={scope.network}
key={Network.mainnet}
title={networkNames[Network.mainnet]}
searchResults={mainnetResults}
networkForTheme={Network.mainnet}
tokenPrices={tokenPrices}
/>
))}
}
{otherResults.length !== 0 &&
(othersOpen ? (
<>
<HideMoreResults theme={notificationTheme} onHide={() => setOthersOpen(false)} />
{otherNetworks.map(net => (
<SearchResultsList
key={net}
title={networkNames[net]}
searchResults={otherResults.filter(getFilterForNetwork(net))}
networkForTheme={net}
tokenPrices={tokenPrices}
/>
))}
</>
) : (
<ShowMoreResults
theme={notificationTheme}
hasWantedResults={!!mainnetResults.length}
otherResultsCount={otherResults.length}
onShow={() => setOthersOpen(true)}
/>
))}
</>
)
}
26 changes: 21 additions & 5 deletions src/app/pages/SearchResultsPage/NoResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ import { SearchSuggestionsLinks } from '../../components/Search/SearchSuggestion
import { OptionalBreak } from '../../components/OptionalBreak'
import { useTheme } from '@mui/material/styles'
import { getNameForScope, SearchScope } from '../../../types/searchScope'
import { getNetworkNames, Network } from '../../../types/network'
import { Layer } from '../../../oasis-indexer/api'

export const NoResults: FC<{ scope?: SearchScope }> = ({ scope }) => {
export const NoResults: FC<{
network?: Network
layer?: Layer
}> = ({ network, layer }) => {
const { t } = useTranslation()
const theme = useTheme()
const title = !scope
? t('search.noResults.header')
: t('search.noResults.scopeHeader', { scope: getNameForScope(t, scope) })
const title = network
? t('search.noResults.scopeHeader', {
scope: layer ? getNameForScope(t, { network, layer }) : getNetworkNames(t)[network],
})
: t('search.noResults.header')

return (
<EmptyState
Expand All @@ -34,10 +41,19 @@ export const NoResults: FC<{ scope?: SearchScope }> = ({ scope }) => {
/>
</p>
<p>
<SearchSuggestionsLinks scope={scope} />
<SearchSuggestionsLinks scope={layer && network ? { network, layer } : undefined} />
</p>
</Box>
}
/>
)
}

export const NoResultsWhatsoever: FC = () => <NoResults />
export const NoResultsOnNetwork: FC<{ network: Network }> = ({ network }) => <NoResults network={network} />

export const NoResultsOnMainnet: FC = () => <NoResultsOnNetwork network={Network.mainnet} />

export const NoResultsInScope: FC<{ scope: SearchScope }> = ({ scope }) => (
<NoResults network={scope.network} layer={scope.layer} />
)
25 changes: 8 additions & 17 deletions src/app/pages/SearchResultsPage/ScopedSearchResultsView.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
getFilterForLayer,
getFilterForNetwork,
getNetworkNames,
isOnMainnet,
Network,
} from '../../../types/network'
import { getFilterForNetwork, getNetworkNames, isOnMainnet, Network } from '../../../types/network'
import {
getFilterForScope,
getNameForScope,
Expand All @@ -17,7 +11,7 @@ import { getThemesForNetworks } from '../../../styles/theme'
import { RouteUtils } from '../../utils/route-utils'
import { SearchResults } from './hooks'
import { SearchResultsList } from './SearchResultsList'
import { NoResults } from './NoResults'
import { NoResultsInScope } from './NoResults'
import { AllTokenPrices } from '../../../coin-gecko/api'
import { HideMoreResults, ShowMoreResults } from './notifications'
import { useRedirectIfSingleResult } from './useRedirectIfSingleResult'
Expand All @@ -33,26 +27,23 @@ export const ScopedSearchResultsView: FC<{
const themes = getThemesForNetworks()
const isInWantedScope = getFilterForScope(wantedScope)
const isNotInWantedScope = getInverseFilterForScope(wantedScope)
const isOnTheRightParatime = getFilterForLayer(wantedScope.layer)
const wantedResults = searchResults.filter(isInWantedScope)
const hasWantedResults = !!wantedResults.length
const otherResults = searchResults.filter(isNotInWantedScope).filter(isOnTheRightParatime)
const hasMainnetResults = otherResults.some(isOnMainnet)
const notificationTheme = themes[hasMainnetResults ? Network.mainnet : Network.testnet]
const otherResults = searchResults.filter(isNotInWantedScope)
const notificationTheme = themes[otherResults.some(isOnMainnet) ? Network.mainnet : Network.testnet]

useRedirectIfSingleResult(wantedScope, wantedResults)
useRedirectIfSingleResult(wantedScope, [...wantedResults, ...otherResults])

return (
<>
{hasWantedResults ? (
{wantedResults.length ? (
<SearchResultsList
title={getNameForScope(t, wantedScope)}
searchResults={wantedResults}
networkForTheme={wantedScope.network}
tokenPrices={tokenPrices}
/>
) : (
<NoResults scope={wantedScope} />
<NoResultsInScope scope={wantedScope} />
)}
{othersOpen ? (
<>
Expand All @@ -74,7 +65,7 @@ export const ScopedSearchResultsView: FC<{
<ShowMoreResults
theme={notificationTheme}
onShow={() => setOthersOpen(true)}
hasWantedResults={hasWantedResults}
hasWantedResults={!!wantedResults.length}
otherResultsCount={otherResults.length}
/>
)
Expand Down
3 changes: 2 additions & 1 deletion src/app/pages/SearchResultsPage/SearchResultsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SearchResults } from './hooks'
import { GlobalSearchResultsView } from './GlobalSearchResultsView'
import { ScopedSearchResultsView } from './ScopedSearchResultsView'
import { AllTokenPrices } from '../../../coin-gecko/api'
import { getFilterForLayer } from '../../../types/layers'

export const SearchResultsView: FC<{
wantedScope?: SearchScope
Expand All @@ -25,7 +26,7 @@ export const SearchResultsView: FC<{
) : wantedScope ? (
<ScopedSearchResultsView
wantedScope={wantedScope}
searchResults={searchResults}
searchResults={searchResults.filter(getFilterForLayer(wantedScope.layer))}
tokenPrices={tokenPrices}
/>
) : (
Expand Down
12 changes: 7 additions & 5 deletions src/app/pages/SearchResultsPage/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ export const useSearch = (q: SearchParams) => {
...(queries.oasisAccount.results || []),
...(queries.evmBech32Account.results || []),
].filter(isAccountNonEmpty)
const results: SearchResultItem[] = [
...blocks.map((block): BlockResult => ({ ...block, resultType: 'block' })),
...transactions.map((tx): TransactionResult => ({ ...tx, resultType: 'transaction' })),
...accounts.map((account): AccountResult => ({ ...account, resultType: 'account' })),
]
const results: SearchResultItem[] = isLoading
? []
: [
...blocks.map((block): BlockResult => ({ ...block, resultType: 'block' })),
...transactions.map((tx): TransactionResult => ({ ...tx, resultType: 'transaction' })),
...accounts.map((account): AccountResult => ({ ...account, resultType: 'account' })),
]
return {
isLoading,
results,
Expand Down
28 changes: 28 additions & 0 deletions src/types/layers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Here we need to import from the generated code, in order to break
// a cycle of imports which confuse jest
// eslint-disable-next-line no-restricted-imports
import { Layer } from '../oasis-indexer/generated/api'
import { TFunction } from 'i18next'

export const getLayerNames = (t: TFunction): Record<Layer, string> => ({
[Layer.emerald]: t('common.emerald'),
[Layer.sapphire]: t('common.sapphire'),
[Layer.cipher]: t('common.cipher'),
[Layer.consensus]: t('common.consensus'),
})

interface HasLayer {
layer: Layer
}

export const getFilterForLayer = (layer: Layer) => (item: HasLayer) => item.layer === layer

const layerOrder: Record<Layer, number> = {
[Layer.consensus]: 1,
[Layer.sapphire]: 2,
[Layer.emerald]: 3,
[Layer.cipher]: 4,
}

export const orderByLayer = (itemA: HasLayer, itemB: HasLayer): number =>
layerOrder[itemA.layer] - layerOrder[itemB.layer]
21 changes: 3 additions & 18 deletions src/types/network.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { TFunction } from 'i18next'

// Here we need to import from the generated code, in order to break
// a cycle of imports which confuse jest
// eslint-disable-next-line no-restricted-imports
import { Layer } from '../oasis-indexer/generated/api'

export type Network = (typeof Network)[keyof typeof Network]

// eslint-disable-next-line @typescript-eslint/no-redeclare
Expand All @@ -18,19 +13,6 @@ export const getNetworkNames = (t: TFunction): Record<Network, string> => ({
[Network.testnet]: t('common.testnet'),
})

export const getLayerNames = (t: TFunction): Record<Layer, string> => ({
[Layer.emerald]: t('common.emerald'),
[Layer.sapphire]: t('common.sapphire'),
[Layer.cipher]: t('common.cipher'),
[Layer.consensus]: t('common.consensus'),
})

interface HasLayer {
layer: Layer
}

export const getFilterForLayer = (layer: Layer) => (item: HasLayer) => item.layer === layer

interface HasNetwork {
network: Network
}
Expand All @@ -39,4 +21,7 @@ export const getFilterForNetwork = (network: Network) => (item: HasNetwork) => i
export const getInverseFilterForNetwork = (network: Network) => (item: HasNetwork) => item.network !== network

export const isOnMainnet = getFilterForNetwork(Network.mainnet)
export const isNotOnMainnet = getInverseFilterForNetwork(Network.mainnet)
export const isOnTestnet = getFilterForNetwork(Network.testnet)

export const isNotMainnet = (network: Network) => network !== Network.mainnet
3 changes: 2 additions & 1 deletion src/types/searchScope.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getLayerNames, getNetworkNames, Network } from './network'
import { getNetworkNames, Network } from './network'
import { getLayerNames } from './layers'
import { HasScope, Layer } from '../oasis-indexer/api'
import { TFunction } from 'i18next'

Expand Down

0 comments on commit ccc5f69

Please sign in to comment.