Skip to content

Commit

Permalink
Highlight matching part in token names in search results
Browse files Browse the repository at this point in the history
  • Loading branch information
csillag committed Jul 2, 2023
1 parent 5ac72ad commit 543f81f
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/app/components/Search/search-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const searchParamLoader = async ({ request, params }: LoaderFunctionArgs)
Object.entries(validateAndNormalize).map(([key, fn]) => [key, fn(searchTerm)]),
) as { [Key in keyof typeof validateAndNormalize]: string | undefined }
return {
searchTerm,
...normalized,
// TODO: remove conversion when API supports querying by EVM address
// TODO: without async conversion, this won't need to even be a loader
Expand Down
23 changes: 20 additions & 3 deletions src/app/components/Tokens/TokenDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import { DashboardLink } from '../../pages/ParatimeDashboardPage/DashboardLink'
import { DelayedContractVerificationInfo } from '../Account/ContractVerificationInfo'
import Box from '@mui/material/Box'
import { COLORS } from '../../../styles/theme/colors'
import { HighlightedText } from '../HighlightedText'

export const TokenDetails: FC<{
isLoading?: boolean
token: EvmToken | undefined
showLayer?: boolean
standalone?: boolean
}> = ({ isLoading, token, showLayer, standalone = false }) => {
highlightedPartOfName: string | undefined
}> = ({ isLoading, token, showLayer, standalone = false, highlightedPartOfName }) => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()

Expand All @@ -36,8 +38,23 @@ export const TokenDetails: FC<{
)}
<dt>{t('common.name')}</dt>
<dd>
<TokenLink scope={token} address={token.eth_contract_addr ?? token.contract_addr} name={token.name} />
<Box sx={{ ml: 3, fontWeight: 700, color: COLORS.grayMedium }}>({token.symbol})</Box>
<TokenLink
scope={token}
address={token.eth_contract_addr ?? token.contract_addr}
name={token.name}
highlightedPart={highlightedPartOfName}
/>
{token.symbol && (
<Box sx={{ ml: 3, fontWeight: 700, color: COLORS.grayMedium }}>
(
{highlightedPartOfName ? (
<HighlightedText text={token.symbol} pattern={highlightedPartOfName} />
) : (
token.symbol
)}
)
</Box>
)}
</dd>

<dt>{t(isMobile ? 'common.smartContract_short' : 'common.smartContract')}</dt>
Expand Down
18 changes: 12 additions & 6 deletions src/app/components/Tokens/TokenLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ import Link from '@mui/material/Link'

import { RouteUtils } from '../../utils/route-utils'
import { SearchScope } from '../../../types/searchScope'
import { HighlightedText } from '../HighlightedText'

export const TokenLink: FC<{ scope: SearchScope; address: string; name: string | undefined }> = ({
scope,
address,
name,
}) => {
export const TokenLink: FC<{
scope: SearchScope
address: string
name: string | undefined
highlightedPart?: string | undefined
}> = ({ scope, address, name, highlightedPart }) => {
return (
<Link component={RouterLink} to={RouteUtils.getTokenRoute(scope, address)}>
{name || address}
{!!name && !!highlightedPart ? (
<HighlightedText text={name} pattern={highlightedPart} />
) : (
name ?? address
)}
</Link>
)
}
11 changes: 7 additions & 4 deletions src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import { getThemesForNetworks } from '../../../styles/theme'
import { orderByLayer } from '../../../types/layers'
import { useRedirectIfSingleResult } from './useRedirectIfSingleResult'

export const GlobalSearchResultsView: FC<{ searchResults: SearchResults; tokenPrices: AllTokenPrices }> = ({
searchResults,
tokenPrices,
}) => {
export const GlobalSearchResultsView: FC<{
searchTerm: string
searchResults: SearchResults
tokenPrices: AllTokenPrices
}> = ({ searchTerm, searchResults, tokenPrices }) => {
const { t } = useTranslation()
const [othersOpen, setOthersOpen] = useState(false)
useRedirectIfSingleResult(undefined, searchResults)
Expand All @@ -41,6 +42,7 @@ export const GlobalSearchResultsView: FC<{ searchResults: SearchResults; tokenPr
<SearchResultsList
key={Network.mainnet}
title={networkNames[Network.mainnet]}
searchTerm={searchTerm}
searchResults={mainnetResults}
networkForTheme={Network.mainnet}
tokenPrices={tokenPrices}
Expand All @@ -54,6 +56,7 @@ export const GlobalSearchResultsView: FC<{ searchResults: SearchResults; tokenPr
<SearchResultsList
key={net}
title={networkNames[net]}
searchTerm={searchTerm}
searchResults={otherResults.filter(getFilterForNetwork(net))}
networkForTheme={net}
tokenPrices={tokenPrices}
Expand Down
5 changes: 4 additions & 1 deletion src/app/pages/SearchResultsPage/ScopedSearchResultsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ import { useRedirectIfSingleResult } from './useRedirectIfSingleResult'

export const ScopedSearchResultsView: FC<{
wantedScope: SearchScope
searchTerm: string
searchResults: SearchResults
tokenPrices: AllTokenPrices
}> = ({ wantedScope, searchResults, tokenPrices }) => {
}> = ({ wantedScope, searchTerm, searchResults, tokenPrices }) => {
const { t } = useTranslation()
const [othersOpen, setOthersOpen] = useState(false)
const networkNames = getNetworkNames(t)
Expand All @@ -38,6 +39,7 @@ export const ScopedSearchResultsView: FC<{
{wantedResults.length ? (
<SearchResultsList
title={getNameForScope(t, wantedScope)}
searchTerm={searchTerm}
searchResults={wantedResults}
networkForTheme={wantedScope.network}
tokenPrices={tokenPrices}
Expand All @@ -55,6 +57,7 @@ export const ScopedSearchResultsView: FC<{
key={net}
networkForTheme={net}
title={networkNames[net]}
searchTerm={searchTerm}
searchResults={otherResults.filter(getFilterForNetwork(net))}
tokenPrices={tokenPrices}
/>
Expand Down
5 changes: 3 additions & 2 deletions src/app/pages/SearchResultsPage/SearchResultsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export const SearchResultsList: FC<{
networkForTheme: Network
searchResults: SearchResults
tokenPrices: AllTokenPrices
}> = ({ title, networkForTheme, searchResults, tokenPrices }) => {
searchTerm: string
}> = ({ title, networkForTheme, searchResults, tokenPrices, searchTerm }) => {
const { t } = useTranslation()

const numberOfResults = searchResults.length
Expand Down Expand Up @@ -87,7 +88,7 @@ export const SearchResultsList: FC<{
<ResultsGroupByType
title={t('search.results.tokens.title')}
results={searchResults.filter((item): item is TokenResult => item.resultType === 'token')}
resultComponent={item => <TokenDetails token={item} showLayer />}
resultComponent={item => <TokenDetails token={item} highlightedPartOfName={searchTerm} showLayer />}
link={token => RouteUtils.getTokenRoute(token, token.eth_contract_addr ?? token.contract_addr)}
linkLabel={t('search.results.tokens.viewLink')}
/>
Expand Down
10 changes: 8 additions & 2 deletions src/app/pages/SearchResultsPage/SearchResultsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import { useScreenSize } from '../../hooks/useScreensize'

export const SearchResultsView: FC<{
wantedScope?: SearchScope
searchTerm: string
searchResults: SearchResults
isLoading: boolean
tokenPrices: AllTokenPrices
}> = ({ wantedScope, searchResults, isLoading, tokenPrices }) => {
}> = ({ wantedScope, searchTerm, searchResults, isLoading, tokenPrices }) => {
const { isMobile } = useScreenSize()
return (
<PageLayout>
Expand All @@ -28,11 +29,16 @@ export const SearchResultsView: FC<{
) : wantedScope ? (
<ScopedSearchResultsView
wantedScope={wantedScope}
searchTerm={searchTerm}
searchResults={searchResults.filter(getFilterForLayer(wantedScope.layer))}
tokenPrices={tokenPrices}
/>
) : (
<GlobalSearchResultsView searchResults={searchResults} tokenPrices={tokenPrices} />
<GlobalSearchResultsView
searchTerm={searchTerm}
searchResults={searchResults}
tokenPrices={tokenPrices}
/>
)}
</PageLayout>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('SearchResultsView', () => {
it('block should correctly link to transactions', () => {
renderWithProviders(
<SearchResultsList
searchTerm=""
searchResults={[suggestedParsedBlock, sapphireParsedBlock]}
tokenPrices={{
[Network.mainnet]: {
Expand Down Expand Up @@ -58,6 +59,7 @@ describe('SearchResultsView', () => {
it('account should correctly link to erc-20 tokens', () => {
renderWithProviders(
<SearchResultsList
searchTerm=""
searchResults={[suggestedParsedAccountResult]}
title="test search"
networkForTheme={Network.mainnet}
Expand Down
1 change: 1 addition & 0 deletions src/app/pages/SearchResultsPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const SearchResultsPage: FC = () => {
return (
<SearchResultsView
wantedScope={scope}
searchTerm={searchParams.searchTerm}
searchResults={results}
isLoading={isLoading}
tokenPrices={tokenPrices}
Expand Down
15 changes: 13 additions & 2 deletions src/app/pages/TokensOverviewPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,23 @@ export const TokensPage: FC = () => {
<TokenDetailsBox>
{tokensQuery.isLoading &&
[...Array(PAGE_SIZE).keys()].map(key => (
<TokenDetails key={key} isLoading={true} token={undefined} standalone />
<TokenDetails
key={key}
isLoading={true}
token={undefined}
highlightedPartOfName={undefined}
standalone
/>
))}

{!tokensQuery.isLoading &&
tokensQuery.data?.data.evm_tokens.map(token => (
<TokenDetails key={token.contract_addr} token={token} standalone />
<TokenDetails
key={token.contract_addr}
token={token}
standalone
highlightedPartOfName={undefined}
/>
))}
</TokenDetailsBox>
)}
Expand Down

0 comments on commit 543f81f

Please sign in to comment.