Skip to content

Commit

Permalink
chore: add selected network to the explore path (#94)
Browse files Browse the repository at this point in the history
* add selected network to the explore path
* redirect on unknown network

---------

Co-authored-by: Neil Campbell <[email protected]>
  • Loading branch information
PatrickDinh and neilcampbell authored Jun 14, 2024
1 parent 426120c commit 57efbe9
Show file tree
Hide file tree
Showing 25 changed files with 273 additions and 214 deletions.
91 changes: 54 additions & 37 deletions src/App.routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { AssetPage, assetPageTitle } from './features/assets/pages/asset-page'
import { ApplicationPage, applicationPageTitle } from './features/applications/pages/application-page'
import { SettingsPage } from './features/settings/pages/settings-page'
import { TxPage } from './features/transactions/pages/tx-page'
import { IndexPage } from '@/index-page'
import { NetworkPage } from '@/features/network/pages/network-page'

export const routes = evalTemplates([
{
Expand All @@ -26,53 +28,72 @@ export const routes = evalTemplates([
children: [
{
template: Urls.Index,
element: <ExplorePage />,
element: <IndexPage />,
errorElement: <ErrorPage title={explorePageTitle} />,
},
{
template: Urls.Transaction.ById,
errorElement: <ErrorPage title={transactionPageTitle} />,
template: Urls.Network,
element: (
<NetworkPage>
<Outlet />
</NetworkPage>
),
children: [
{
template: Urls.Transaction.ById,
element: <TransactionPage />,
template: Urls.Network,
element: <ExplorePage />,
errorElement: <ErrorPage title={explorePageTitle} />,
},
{
template: Urls.Transaction.ById.Inner.ById,
element: <InnerTransactionPage />,
template: Urls.Network.Transaction.ById,
errorElement: <ErrorPage title={transactionPageTitle} />,
children: [
{
template: Urls.Network.Transaction.ById,
element: <TransactionPage />,
},
{
template: Urls.Network.Transaction.ById.Inner.ById,
element: <InnerTransactionPage />,
},
],
},
{
template: Urls.Network.Block.ByRound,
children: [
{
template: Urls.Network.Block.ByRound,
errorElement: <ErrorPage title={blockPageTitle} />,
element: <BlockPage />,
},
{
template: Urls.Network.Block.ByRound.Group.ById,
errorElement: <ErrorPage title={groupPageTitle} />,
element: <GroupPage />,
},
],
},
{
template: Urls.Network.Account.ByAddress,
element: <AccountPage />,
errorElement: <ErrorPage title={accountPageTitle} />,
},
{
template: Urls.Network.Asset.ById,
element: <AssetPage />,
errorElement: <ErrorPage title={assetPageTitle} />,
},
],
},
{
template: Urls.Block.ByRound,
children: [
{
template: Urls.Block.ByRound,
errorElement: <ErrorPage title={blockPageTitle} />,
element: <BlockPage />,
template: Urls.Network.Application.ById,
errorElement: <ErrorPage title={applicationPageTitle} />,
element: <ApplicationPage />,
},
{
template: Urls.Block.ByRound.Group.ById,
errorElement: <ErrorPage title={groupPageTitle} />,
element: <GroupPage />,
template: Urls.Network.Tx,
element: <TxPage />,
},
],
},
{
template: Urls.Account.ByAddress,
element: <AccountPage />,
errorElement: <ErrorPage title={accountPageTitle} />,
},
{
template: Urls.Asset.ById,
element: <AssetPage />,
errorElement: <ErrorPage title={assetPageTitle} />,
},
{
template: Urls.Application.ById,
errorElement: <ErrorPage title={applicationPageTitle} />,
element: <ApplicationPage />,
},
{
template: Urls.AppStudio,
element: <div>App Studio</div>,
Expand All @@ -81,10 +102,6 @@ export const routes = evalTemplates([
template: Urls.Settings,
element: <SettingsPage />,
},
{
template: Urls.Tx,
element: <TxPage />,
},
],
},
])
6 changes: 4 additions & 2 deletions src/features/accounts/components/account-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ellipseAddress } from '@/utils/ellipse-address'
import { fixedForwardRef } from '@/utils/fixed-forward-ref'
import { PropsWithChildren, useCallback } from 'react'
import { toast } from 'react-toastify'
import { useSelectedNetwork } from '@/features/settings/data'

type Props = PropsWithChildren<{
address: string
Expand All @@ -16,6 +17,7 @@ type Props = PropsWithChildren<{

export const AccountLink = fixedForwardRef(
({ address, short, className, children, showCopyButton, ...rest }: Props, ref?: React.LegacyRef<HTMLAnchorElement>) => {
const [selectedNetwork] = useSelectedNetwork()
const copyClipboard = useCallback(async () => {
await navigator.clipboard.writeText(address)
toast.success('Address copied to clipboard')
Expand All @@ -24,8 +26,8 @@ export const AccountLink = fixedForwardRef(
<>
<TemplatedNavLink
className={cn(!children && 'text-primary underline', className)}
urlTemplate={Urls.Account.ByAddress}
urlParams={{ address }}
urlTemplate={Urls.Network.Account.ByAddress}
urlParams={{ address, networkId: selectedNetwork }}
ref={ref}
{...rest}
>
Expand Down
6 changes: 4 additions & 2 deletions src/features/applications/components/application-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ import { TemplatedNavLink } from '@/features/routing/components/templated-nav-li
import { Urls } from '@/routes/urls'
import { PropsWithChildren } from 'react'
import { ApplicationId } from '../data/types'
import { useSelectedNetwork } from '@/features/settings/data'

type Props = PropsWithChildren<{
applicationId: ApplicationId
className?: string
}>

export function ApplicationLink({ applicationId, className, children }: Props) {
const [selectedNetwork] = useSelectedNetwork()
return (
<TemplatedNavLink
className={cn(!children && 'text-primary underline', className)}
urlTemplate={Urls.Application.ById}
urlParams={{ applicationId: applicationId.toString() }}
urlTemplate={Urls.Network.Application.ById}
urlParams={{ applicationId: applicationId.toString(), networkId: selectedNetwork }}
>
{children ? children : applicationId}
</TemplatedNavLink>
Expand Down
6 changes: 4 additions & 2 deletions src/features/assets/components/asset-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AsyncMaybeAtom } from '@/features/common/data/types'
import { RenderInlineAsyncAtom } from '@/features/common/components/render-inline-async-atom'
import { CopyButton } from '@/features/common/components/copy-button'
import { toast } from 'react-toastify'
import { useSelectedNetwork } from '@/features/settings/data'

type CommonProps = {
className?: string
Expand All @@ -33,6 +34,7 @@ type AssetLinkProps = PropsWithChildren<
>

function Link(props: AssetIdLinkProps | AssetIdAndNameLinkProps) {
const [selectedNetwork] = useSelectedNetwork()
const copyClipboard = useCallback(async () => {
await navigator.clipboard.writeText(props.assetId.toString())
toast.success('Asset ID copied to clipboard')
Expand All @@ -42,8 +44,8 @@ function Link(props: AssetIdLinkProps | AssetIdAndNameLinkProps) {
<>
<TemplatedNavLink
className={cn(!props.children && 'text-primary underline', props.className)}
urlTemplate={Urls.Asset.ById}
urlParams={{ assetId: props.assetId.toString() }}
urlTemplate={Urls.Network.Asset.ById}
urlParams={{ assetId: props.assetId.toString(), networkId: selectedNetwork }}
>
{props.children ? props.children : props.assetId}
</TemplatedNavLink>
Expand Down
7 changes: 5 additions & 2 deletions src/features/blocks/components/block-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@ import { cn } from '@/features/common/utils'
import { TemplatedNavLink } from '@/features/routing/components/templated-nav-link/templated-nav-link'
import { Urls } from '@/routes/urls'
import { PropsWithChildren } from 'react'
import { useSelectedNetwork } from '@/features/settings/data'

type Props = PropsWithChildren<{
round: number
className?: string
}>

export function BlockLink({ round, className, children }: Props) {
const [selectedNetwork] = useSelectedNetwork()

return (
<TemplatedNavLink
className={cn(!children && 'text-primary underline', className)}
urlTemplate={Urls.Block.ByRound}
urlParams={{ round: round.toString() }}
urlTemplate={Urls.Network.Block.ByRound}
urlParams={{ round: round.toString(), networkId: selectedNetwork }}
>
{children ? children : round}
</TemplatedNavLink>
Expand Down
7 changes: 3 additions & 4 deletions src/features/deep-link/hooks/use-deep-link.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useCallback, useEffect } from 'react'
import 'react-toastify/dist/ReactToastify.css'
import { listen } from '@tauri-apps/api/event'
import { useNavigate } from 'react-router-dom'
import { useSetSelectedNetwork } from '@/features/settings/data'
import { useSelectedNetwork } from '@/features/settings/data'
import { parseDeepLink } from '@/features/deep-link/parse-deep-link'
import { Urls } from '@/routes/urls'

export function useDeepLink() {
const setSelectedNetwork = useSetSelectedNetwork()
const [_, setSelectedNetwork] = useSelectedNetwork()
const navigate = useNavigate()

const handleDeepLink = useCallback(
Expand All @@ -16,7 +15,7 @@ export function useDeepLink() {
if (options) {
await setSelectedNetwork(options.networkId)
if (options.transactionId) {
navigate(Urls.Transaction.ById.build({ transactionId: options.transactionId }))
navigate(Urls.Network.Transaction.ById.build({ transactionId: options.transactionId, networkId: options.networkId }))
} else {
navigate(Urls.Index.build({}))
}
Expand Down
7 changes: 5 additions & 2 deletions src/features/groups/components/group-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Urls } from '@/routes/urls'
import { PropsWithChildren } from 'react'
import { GroupId } from '../data/types'
import { ellipseId } from '@/utils/ellipse-id'
import { useSelectedNetwork } from '@/features/settings/data'

type Props = PropsWithChildren<{
round: Round
Expand All @@ -14,11 +15,13 @@ type Props = PropsWithChildren<{
}>

export function GroupLink({ round, groupId, short = false, className, children }: Props) {
const [selectedNetwork] = useSelectedNetwork()

return (
<TemplatedNavLink
className={cn(!children && 'text-primary underline', className)}
urlTemplate={Urls.Block.ByRound.Group.ById}
urlParams={{ round: round.toString(), groupId: encodeURIComponent(groupId) }}
urlTemplate={Urls.Network.Block.ByRound.Group.ById}
urlParams={{ round: round.toString(), groupId: encodeURIComponent(groupId), networkId: selectedNetwork }}
>
{children ? children : short ? <abbr title={groupId}>{ellipseId(groupId)}</abbr> : groupId}
</TemplatedNavLink>
Expand Down
32 changes: 8 additions & 24 deletions src/features/layout/components/left-side-bar-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { TemplatedNavLink } from '../../routing/components/templated-nav-link/templated-nav-link'
import { Urls } from '../../../routes/urls'
import { Urls } from '@/routes/urls'
import { NavigationMenu, NavigationMenuItem, NavigationMenuLink, NavigationMenuList } from '@/features/common/components/navigation-menu'
import { cn } from '@/features/common/utils'
import SvgCodeBlock from '@/features/common/components/icons/code-block'
import SvgHome from '@/features/common/components/icons/home'
import { Button } from '@/features/common/components/button'
import SvgChevronLeft from '@/features/common/components/icons/chevron-left'
import { useCallback, useMemo } from 'react'
import { useCallback } from 'react'
import SvgChevronRight from '@/features/common/components/icons/chevron-right'
import SvgCog from '@/features/common/components/icons/cog'
import { useLayout } from '@/features/settings/data'
import { useLocation } from 'react-router-dom'
import { useLayout, useSelectedNetwork } from '@/features/settings/data'

type Props = {
className?: string
}

export function LeftSideBarMenu({ className }: Props) {
const [selectedNetwork] = useSelectedNetwork()

const menuItems = [
{ urlTemplate: Urls.Index, icon: <SvgHome />, text: 'Home' },
{ urlTemplate: Urls.Network, icon: <SvgHome />, text: 'Home' },
{ urlTemplate: Urls.AppStudio, icon: <SvgCodeBlock />, text: 'App Studio' },
{ urlTemplate: Urls.Settings, icon: <SvgCog />, text: 'Settings' },
]
Expand All @@ -29,21 +30,6 @@ export function LeftSideBarMenu({ className }: Props) {
[setLayout]
)

// The little hack to make the index (root) menu item active when transaction, block, account, asset, application are viewed
// This needs to be done because React router doesn't match the root URL with any sub-path
// The doc: https://reactrouter.com/en/main/components/nav-link#end
const location = useLocation()
const isIndexActive = useMemo(() => {
const forceMatchWithIndex = [
Urls.Transaction.build({}),
Urls.Block.build({}),
Urls.Account.build({}),
Urls.Asset.build({}),
Urls.Application.build({}),
]
return forceMatchWithIndex.some((path) => location.pathname.startsWith(path))
}, [location.pathname])

return (
<NavigationMenu
className={cn('bg-card transition-all duration-300 min-h-screen', className, layout.isLeftSideBarExpanded ? 'w-52' : 'w-10')}
Expand All @@ -59,10 +45,8 @@ export function LeftSideBarMenu({ className }: Props) {
<NavigationMenuLink asChild>
<TemplatedNavLink
urlTemplate={menuItem.urlTemplate}
className={cn(
'[&.active]:text-primary flex items-center p-2 gap-2 min-h-10 pl-3 whitespace-nowrap',
menuItem.urlTemplate === Urls.Index && isIndexActive ? 'active' : ''
)}
urlParams={{ networkId: selectedNetwork }}
className={cn('[&.active]:text-primary flex items-center p-2 gap-2 min-h-10 pl-3 whitespace-nowrap')}
>
<div className={cn('text-primary')}>{menuItem.icon}</div>
<div className={cn(layout.isLeftSideBarExpanded ? 'visible delay-100' : 'invisible delay-100')}>{menuItem.text}</div>
Expand Down
4 changes: 3 additions & 1 deletion src/features/layout/pages/layout-page.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@ describe('when rendering the layout page', () => {
expect(network).toBeTruthy()
const networkConfig = settingsStore.get(networkConfigAtom)
expect(networkConfig.id).toBe('mainnet')
expect(mockNavigate).toHaveBeenCalledWith(`/transaction/JC4VRVWOA7ZQX6OJX5GCAPJVAEEQB3Q4MYWJXVJC7LCNH6HW62WQ/inner/41-1`)
expect(mockNavigate).toHaveBeenCalledWith(
`/mainnet/transaction/JC4VRVWOA7ZQX6OJX5GCAPJVAEEQB3Q4MYWJXVJC7LCNH6HW62WQ/inner/41-1`
)
})
}
)
Expand Down
21 changes: 21 additions & 0 deletions src/features/network/pages/network-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useRequiredParam } from '@/features/common/hooks/use-required-param'
import { UrlParams, Urls } from '@/routes/urls'
import { networksConfigs } from '@/features/settings/data'
import { useNavigate } from 'react-router-dom'
import { useEffect } from 'react'

type Props = {
children: React.ReactNode
}
export function NetworkPage({ children }: Props) {
const { networkId } = useRequiredParam(UrlParams.NetworkId)
const navigate = useNavigate()

useEffect(() => {
if (!networksConfigs.find((c) => c.id === networkId)) {
navigate(Urls.Index.build({}))
}
}, [navigate, networkId])

return children
}
2 changes: 1 addition & 1 deletion src/features/search/components/search.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ describe('search', () => {
const results = (await component.findAllByText(label, undefined, { timeout: 1000 })).map((result) => result.parentElement)
const result = results.find((result) => result!.textContent!.includes(type))!
await user.click(result)
expect(mockNavigate).toHaveBeenCalledWith(`/${type.toLowerCase()}/${id}`)
expect(mockNavigate).toHaveBeenCalledWith(`/localnet/${type.toLowerCase()}/${id}`)
})
}
)
Expand Down
Loading

0 comments on commit 57efbe9

Please sign in to comment.