Skip to content
This repository was archived by the owner on Feb 2, 2024. It is now read-only.

Commit

Permalink
fix: deep link graph views (#563)
Browse files Browse the repository at this point in the history
* fix: do not overwrite query string on TransactionTableWidget

* chore: add utils fn useUpdateQueryString

* refactor: use useUpdateQueryString rather than directly replacing history.search

* refactor: add TAB_QUERY_PARAM_KEY const
  • Loading branch information
alfetopito authored Jul 25, 2023
1 parent 4fd2219 commit 2b707e1
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 44 deletions.
21 changes: 11 additions & 10 deletions src/apps/explorer/components/TransactionsTableWidget/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import React, { useState, useEffect, useCallback } from 'react'
import React, { useCallback, useEffect, useState } from 'react'
import { faListUl, faProjectDiagram } from '@fortawesome/free-solid-svg-icons'
import { useHistory } from 'react-router-dom'

import { useQuery } from 'hooks/useQuery'
import { useQuery, useUpdateQueryString } from 'hooks/useQuery'
import { BlockchainNetwork, TransactionsTableContext } from './context/TransactionsTableContext'
import { useGetTxOrders, useTxOrderExplorerLink } from 'hooks/useGetOrders'
import RedirectToSearch from 'components/RedirectToSearch'
import { RedirectToNetwork, useNetworkId } from 'state/network'
import { Order } from 'api/operator'
import { TransactionsTableWithData } from 'apps/explorer/components/TransactionsTableWidget/TransactionsTableWithData'
import { TabItemInterface, TabIcon } from 'components/common/Tabs/Tabs'
import { TabIcon, TabItemInterface } from 'components/common/Tabs/Tabs'
import ExplorerTabs from '../common/ExplorerTabs/ExplorerTabs'
import { TitleAddress, FlexContainer, Title } from 'apps/explorer/pages/styled'
import { FlexContainer, Title, TitleAddress } from 'apps/explorer/pages/styled'
import { BlockExplorerLink } from 'components/common/BlockExplorerLink'
import { ConnectionStatus } from 'components/ConnectionStatus'
import { Notification } from 'components/Notification'
import { TransactionBatchGraph } from 'apps/explorer/components/TransanctionBatchGraph'
import CowLoading from 'components/common/CowLoading'
import { TAB_QUERY_PARAM_KEY } from 'apps/explorer/const'

interface Props {
txHash: string
Expand All @@ -33,7 +33,7 @@ const DEFAULT_TAB = TabView[1]

function useQueryViewParams(): { tab: string } {
const query = useQuery()
return { tab: query.get('tab')?.toUpperCase() || DEFAULT_TAB } // if URL param empty will be used DEFAULT
return { tab: query.get(TAB_QUERY_PARAM_KEY)?.toUpperCase() || DEFAULT_TAB } // if URL param empty will be used DEFAULT
}

const tabItems = (orders: Order[] | undefined, networkId: BlockchainNetwork, txHash: string): TabItemInterface[] => {
Expand Down Expand Up @@ -61,7 +61,7 @@ export const TransactionsTableWidget: React.FC<Props> = ({ txHash }) => {
const isZeroOrders = !!(orders && orders.length === 0)
const notGpv2ExplorerData = useTxOrderExplorerLink(txHash, isZeroOrders)

const history = useHistory()
const updateQueryString = useUpdateQueryString()

// Avoid redirecting until another network is searched again
useEffect(() => {
Expand All @@ -81,9 +81,10 @@ export const TransactionsTableWidget: React.FC<Props> = ({ txHash }) => {
setTabViewSelected(TabView[newTabViewName])
}, [])

useEffect(() => {
history.replace({ search: `?tab=${TabView[tabViewSelected].toLowerCase()}` })
}, [history, tabViewSelected])
useEffect(
() => updateQueryString(TAB_QUERY_PARAM_KEY, TabView[tabViewSelected].toLowerCase()),
[tabViewSelected, updateQueryString],
)

if (errorTxPresentInNetworkId && networkId != errorTxPresentInNetworkId) {
return <RedirectToNetwork networkId={errorTxPresentInNetworkId} />
Expand Down
18 changes: 4 additions & 14 deletions src/apps/explorer/components/TransanctionBatchGraph/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ import {
PopperInstance,
ViewType,
} from 'apps/explorer/components/TransanctionBatchGraph/types'
import { useQuery } from 'hooks/useQuery'
import { useHistory } from 'react-router-dom'
import { useQuery, useUpdateQueryString } from 'hooks/useQuery'
import { Order } from 'api/operator'
import { useTransactionData } from 'hooks/useTransactionData'
import {
Expand Down Expand Up @@ -205,18 +204,9 @@ function useQueryViewParams(): { visualization: string } {
}

function useUpdateVisQuery(): (vis: string) => void {
const query = useQuery()
const history = useHistory()

// TODO: this is causing one extra re-render as the query is being updated when history is updated
// TODO: make it not depend on query
return useCallback(
(vis: string) => {
query.set(VISUALIZATION_PARAM_NAME, vis)
history.replace({ search: query.toString() })
},
[history, query],
)
const updateQueryString = useUpdateQueryString()

return useCallback((vis: string) => updateQueryString(VISUALIZATION_PARAM_NAME, vis), [updateQueryString])
}

export function useTxBatchData(
Expand Down
2 changes: 2 additions & 0 deletions src/apps/explorer/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ export const SPECIAL_ADDRESSES = {
'0xa03be496e67ec29bc62f01a428683d7f9c204930': 'Solver Rewards Safe',
'0xca771eda0c70aa7d053ab1b25004559b918fe662': 'CoW DAO',
}

export const TAB_QUERY_PARAM_KEY = 'tab'
18 changes: 9 additions & 9 deletions src/apps/explorer/pages/AppData/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { useCallback, useState, useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import React, { useCallback, useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { faCode, faListUl } from '@fortawesome/free-solid-svg-icons'
import { useQuery } from 'hooks/useQuery'
import { useQuery, useUpdateQueryString } from 'hooks/useQuery'
import EncodePage from './EncodePage'
import DecodePage from './DecodePage'
import TabIcon from 'components/common/Tabs/TabIcon'
Expand All @@ -12,7 +11,7 @@ import { ContentCard as Content, Title } from 'apps/explorer/pages/styled'
import { FormProps } from './config'

import { StyledExplorerTabs, Wrapper } from './styled'
import { APP_TITLE } from 'apps/explorer/const'
import { APP_TITLE, TAB_QUERY_PARAM_KEY } from 'apps/explorer/const'

export enum TabView {
ENCODE = 1,
Expand All @@ -28,7 +27,7 @@ const DEFAULT_TAB = TabView[1]

function useQueryViewParams(): { tab: string } {
const query = useQuery()
return { tab: query.get('tab')?.toUpperCase() || DEFAULT_TAB } // if URL param empty will be used DEFAULT
return { tab: query.get(TAB_QUERY_PARAM_KEY)?.toUpperCase() || DEFAULT_TAB } // if URL param empty will be used DEFAULT
}

const tabItems = (
Expand All @@ -51,23 +50,24 @@ const tabItems = (
}

const AppDataPage: React.FC = () => {
const history = useHistory()
const { tab } = useQueryViewParams()
const [tabData, setTabData] = useState<TabData>({
encode: { formData: {}, options: {} },
decode: { formData: {}, options: {} },
})
const [tabViewSelected, setTabViewSelected] = useState<TabView>(TabView[tab] || TabView[DEFAULT_TAB]) // use DEFAULT when URL param is outside the enum
const updateQueryString = useUpdateQueryString()

const onChangeTab = useCallback((tabId: number) => {
const newTabViewName = TabView[tabId]
if (!newTabViewName) return
setTabViewSelected(TabView[newTabViewName])
}, [])

useEffect(() => {
history.replace({ search: `?tab=${TabView[tabViewSelected].toLowerCase()}` })
}, [history, tabViewSelected])
useEffect(
() => updateQueryString(TAB_QUERY_PARAM_KEY, TabView[tabViewSelected].toLowerCase()),
[tabViewSelected, updateQueryString],
)

return (
<Wrapper>
Expand Down
5 changes: 3 additions & 2 deletions src/components/orders/DetailsTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { GasFeeDisplay } from 'components/orders/GasFeeDisplay'
import { sendEvent } from 'components/analytics'
import { LinkWithPrefixNetwork } from 'components/common/LinkWithPrefixNetwork'
import DecodeAppData from 'components/AppData/DecodeAppData'
import { TAB_QUERY_PARAM_KEY } from 'apps/explorer/const'

const Table = styled(SimpleTable)`
> tbody > tr {
Expand Down Expand Up @@ -261,7 +262,7 @@ export function DetailsTable(props: Props): JSX.Element | null {
onCopy={(): void => onCopy('settlementTx')}
contentsToDisplay={<LinkWithPrefixNetwork to={`/tx/${txHash}`}>{txHash}</LinkWithPrefixNetwork>}
/>
<LinkButton to={`/tx/${txHash}/?tab=graph`}>
<LinkButton to={`/tx/${txHash}/?${TAB_QUERY_PARAM_KEY}=graph`}>
<FontAwesomeIcon icon={faProjectDiagram} />
View batch graph
</LinkButton>
Expand Down Expand Up @@ -358,7 +359,7 @@ export function DetailsTable(props: Props): JSX.Element | null {
<Wrapper>
<FilledProgress order={order} />
{showFillsButton && (
<LinkButton onClickOptional={viewFills} to={`/orders/${uid}/?tab=fills`}>
<LinkButton onClickOptional={viewFills} to={`/orders/${uid}/?${TAB_QUERY_PARAM_KEY}=fills`}>
<FontAwesomeIcon icon={faFill} />
View fills
</LinkButton>
Expand Down
15 changes: 8 additions & 7 deletions src/components/orders/OrderDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useCallback, useEffect, useState } from 'react'
import { useHistory } from 'react-router-dom'
import styled from 'styled-components'

import { Order, Trade } from 'api/operator'
Expand All @@ -8,7 +7,7 @@ import { Errors } from 'types'
import { formatPercentage } from 'utils'
import { FillsTableContext } from './context/FillsTableContext'
import { media } from 'theme/styles/media'
import { useQuery } from 'hooks/useQuery'
import { useQuery, useUpdateQueryString } from 'hooks/useQuery'
import { DetailsTable } from 'components/orders/DetailsTable'
import { RowWithCopyButton } from 'components/common/RowWithCopyButton'
import RedirectToSearch from 'components/RedirectToSearch'
Expand All @@ -22,6 +21,7 @@ import { useTable } from 'apps/explorer/components/TokensTableWidget/useTable'
import ExplorerTabs from 'apps/explorer/components/common/ExplorerTabs/ExplorerTabs'

import { FillsTableWithData } from './FillsTableWithData'
import { TAB_QUERY_PARAM_KEY } from 'apps/explorer/const'

const TitleUid = styled(RowWithCopyButton)`
color: ${({ theme }): string => theme.grey};
Expand Down Expand Up @@ -74,7 +74,7 @@ const DEFAULT_TAB = TabView[1]

function useQueryViewParams(): { tab: string } {
const query = useQuery()
return { tab: query.get('tab')?.toUpperCase() || DEFAULT_TAB } // if URL param empty will be used DEFAULT
return { tab: query.get(TAB_QUERY_PARAM_KEY)?.toUpperCase() || DEFAULT_TAB } // if URL param empty will be used DEFAULT
}

const tabItems = (
Expand Down Expand Up @@ -166,7 +166,7 @@ export const OrderDetails: React.FC<Props> = (props) => {
const invertPrice = useCallback((): void => setIsPriceInverted((prev) => !prev), [])

const [redirectTo, setRedirectTo] = useState(false)
const history = useHistory()
const updateQueryString = useUpdateQueryString()

tableState['hasNextPage'] = tableState.pageOffset + tableState.pageSize < trades.length
tableState['totalResults'] = trades.length
Expand Down Expand Up @@ -195,9 +195,10 @@ export const OrderDetails: React.FC<Props> = (props) => {
setTabViewSelected(TabView[newTabViewName])
}, [])

useEffect(() => {
history.replace({ search: `?tab=${TabView[tabViewSelected].toLowerCase()}` })
}, [history, tabViewSelected])
useEffect(
() => updateQueryString(TAB_QUERY_PARAM_KEY, TabView[tabViewSelected].toLowerCase()),
[tabViewSelected, updateQueryString],
)

if (redirectTo) {
return <RedirectToSearch from="orders" />
Expand Down
18 changes: 16 additions & 2 deletions src/hooks/useQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useLocation } from 'react-router'
import { useMemo } from 'react'
import { sanitizeInput, checkDateOrValidBatchTime } from 'utils'
import { useCallback, useMemo } from 'react'
import { checkDateOrValidBatchTime, sanitizeInput } from 'utils'
import { useHistory } from 'react-router-dom'

export function useQuery(): URLSearchParams {
const { search } = useLocation()
Expand Down Expand Up @@ -32,3 +33,16 @@ export function useQueryTradeParams(): {
validUntil: checkDateOrValidBatchTime(query.get('expires')),
}
}

export function useUpdateQueryString(): (key: string, value: string) => void {
const query = useQuery()
const history = useHistory()

return useCallback(
(key: string, value: string) => {
query.set(key, value)
history.replace({ search: query.toString() })
},
[history, query],
)
}

0 comments on commit 2b707e1

Please sign in to comment.