From c152dcf78b459d87c1e448d7cab77b3c6e515251 Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Thu, 15 Feb 2024 12:25:38 +0100 Subject: [PATCH 1/2] Rename some constant to better reflect functionality (We can select consensus, too, not just paratimes, so the correct term is Layer, not ParaTime.) --- src/app/components/LayerPicker/index.tsx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/app/components/LayerPicker/index.tsx b/src/app/components/LayerPicker/index.tsx index 102d183b1..4b461100e 100644 --- a/src/app/components/LayerPicker/index.tsx +++ b/src/app/components/LayerPicker/index.tsx @@ -77,8 +77,8 @@ type LayerPickerContentProps = Omit enum LayerPickerTabletStep { Network, - ParaTime, - ParaTimeDetails, + Layer, + LayerDetails, } const LayerPickerContent: FC = ({ isOutOfDate, onClose, onConfirm }) => { @@ -87,7 +87,7 @@ const LayerPickerContent: FC = ({ isOutOfDate, onClose, const { network, layer } = useRequiredScopeParam() const [selectedLayer, setSelectedLayer] = useState(layer) const [selectedNetwork, setSelectedNetwork] = useState(network) - const [tabletStep, setTabletStep] = useState(LayerPickerTabletStep.ParaTimeDetails) + const [tabletStep, setTabletStep] = useState(LayerPickerTabletStep.LayerDetails) const selectNetwork = (newNetwork: Network) => { const enabledLayers = RouteUtils.getAllLayersForNetwork(newNetwork).enabled const targetLayer = enabledLayers.includes(selectedLayer) ? selectedLayer : enabledLayers[0] @@ -104,7 +104,7 @@ const LayerPickerContent: FC = ({ isOutOfDate, onClose, {isTablet && (
- {tabletStep === LayerPickerTabletStep.ParaTime && ( + {tabletStep === LayerPickerTabletStep.Layer && ( } @@ -115,12 +115,12 @@ const LayerPickerContent: FC = ({ isOutOfDate, onClose, {t('layerPicker.viewNetworks')} )} - {tabletStep === LayerPickerTabletStep.ParaTimeDetails && ( + {tabletStep === LayerPickerTabletStep.LayerDetails && ( } onClick={() => { - setTabletStep(LayerPickerTabletStep.ParaTime) + setTabletStep(LayerPickerTabletStep.Layer) }} > {t('layerPicker.viewLayers')} @@ -140,12 +140,12 @@ const LayerPickerContent: FC = ({ isOutOfDate, onClose, selectedNetwork={selectedNetwork} setSelectedNetwork={network => { selectNetwork(network) - setTabletStep(LayerPickerTabletStep.ParaTime) + setTabletStep(LayerPickerTabletStep.Layer) }} /> )} - {(!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.ParaTime)) && ( + {(!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.Layer)) && ( = ({ isOutOfDate, onClose, selectedNetwork={selectedNetwork} setSelectedLayer={layer => { setSelectedLayer(layer) - setTabletStep(LayerPickerTabletStep.ParaTimeDetails) + setTabletStep(LayerPickerTabletStep.LayerDetails) }} /> )} - {(!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.ParaTimeDetails)) && ( + {(!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.LayerDetails)) && ( Date: Fri, 9 Feb 2024 15:31:03 +0100 Subject: [PATCH 2/2] Support limiting scope to one network or layer It's now possible to specify a given network or layer in the .env file, and when given, the scope of the whole explorer will be limited to that specific network, or even a specific layer within that network. No data external to the required scope will be shown. The network (and the layer) will not be part of the URLs. You can specify network, or layer, or both. --- .changelog/1242.feature.md | 1 + .env | 2 + .env.production | 2 + src/app/components/LayerPicker/LayerMenu.tsx | 5 +- src/app/components/LayerPicker/index.tsx | 109 ++++++++++-------- src/app/components/PageLayout/Header.tsx | 4 +- .../components/PageLayout/NetworkButton.tsx | 15 ++- .../components/PageLayout/NetworkSelector.tsx | 4 +- src/app/components/ThemeByNetwork/index.tsx | 7 +- src/app/hooks/useSearchQueryNetworkParam.ts | 4 +- .../HomePage/Graph/ParaTimeSelector/index.tsx | 3 +- .../GlobalSearchResultsView.tsx | 19 ++- src/app/pages/SearchResultsPage/hooks.ts | 10 +- src/app/utils/route-utils.ts | 82 +++++++++++-- src/global.d.ts | 2 + src/routes.tsx | 41 +++++-- 16 files changed, 222 insertions(+), 88 deletions(-) create mode 100644 .changelog/1242.feature.md diff --git a/.changelog/1242.feature.md b/.changelog/1242.feature.md new file mode 100644 index 000000000..d8b6cc7a2 --- /dev/null +++ b/.changelog/1242.feature.md @@ -0,0 +1 @@ +Support limiting scope to one network or layer diff --git a/.env b/.env index 4c551766e..57ada427b 100644 --- a/.env +++ b/.env @@ -23,3 +23,5 @@ REACT_APP_SOCIAL_REDDIT=https://www.reddit.com/r/oasisnetwork/ REACT_APP_PRODUCTION_URLS=https://explorer.oasis.io, https://explorer.prd.oasis.io REACT_APP_STAGING_URLS=https://explorer.stg.oasis.io REACT_APP_SHOW_BUILD_BANNERS=true +# REACT_APP_FIXED_NETWORK=testnet +# REACT_APP_FIXED_LAYER=sapphire diff --git a/.env.production b/.env.production index f40ed0524..99b926670 100644 --- a/.env.production +++ b/.env.production @@ -18,3 +18,5 @@ REACT_APP_SOCIAL_REDDIT=https://www.reddit.com/r/oasisnetwork/ REACT_APP_PRODUCTION_URLS=https://explorer.oasis.io, https://explorer.prd.oasis.io REACT_APP_STAGING_URLS=https://explorer.stg.oasis.io REACT_APP_SHOW_BUILD_BANNERS=true +# REACT_APP_FIXED_NETWORK=testnet +# REACT_APP_FIXED_LAYER=sapphire diff --git a/src/app/components/LayerPicker/LayerMenu.tsx b/src/app/components/LayerPicker/LayerMenu.tsx index ec0dca885..710ffd24b 100644 --- a/src/app/components/LayerPicker/LayerMenu.tsx +++ b/src/app/components/LayerPicker/LayerMenu.tsx @@ -13,6 +13,7 @@ import { RouteUtils } from '../../utils/route-utils' import { Network } from '../../../types/network' import { isLayerHidden, orderByLayer } from '../../../types/layers' import { useScreenSize } from '../../hooks/useScreensize' +import { useScopeParam } from '../../hooks/useScopeParam' type BaseLayerMenuItemProps = { divider: boolean @@ -107,9 +108,11 @@ export const LayerMenu: FC = ({ selectedNetwork, setSelectedLayer, }) => { + const currentScope = useScopeParam() const [hoveredLayer, setHoveredLayer] = useState() const options = Object.values(Layer) - .filter(layer => !isLayerHidden(layer)) + // Don't show hidden layers, unless we are already viewing them. + .filter(layer => !isLayerHidden(layer) || layer === currentScope?.layer) .map(layer => ({ layer, enabled: RouteUtils.getAllLayersForNetwork(selectedNetwork || network).enabled.includes(layer), diff --git a/src/app/components/LayerPicker/index.tsx b/src/app/components/LayerPicker/index.tsx index 4b461100e..f642af262 100644 --- a/src/app/components/LayerPicker/index.tsx +++ b/src/app/components/LayerPicker/index.tsx @@ -13,7 +13,7 @@ import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { NetworkMenu } from './NetworkMenu' import { LayerMenu } from './LayerMenu' import { LayerDetails } from './LayerDetails' -import { RouteUtils } from '../../utils/route-utils' +import { scopeFreedom, RouteUtils } from '../../utils/route-utils' import { styled } from '@mui/material/styles' import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft' import { useScreenSize } from '../../hooks/useScreensize' @@ -104,28 +104,33 @@ const LayerPickerContent: FC = ({ isOutOfDate, onClose, {isTablet && (
- {tabletStep === LayerPickerTabletStep.Layer && ( - } - onClick={() => { - setTabletStep(LayerPickerTabletStep.Network) - }} - > - {t('layerPicker.viewNetworks')} - - )} - {tabletStep === LayerPickerTabletStep.LayerDetails && ( - } - onClick={() => { - setTabletStep(LayerPickerTabletStep.Layer) - }} - > - {t('layerPicker.viewLayers')} - - )} + { + // Do we need a "back to networks" button ? + ((scopeFreedom === 'network-layer' && tabletStep === LayerPickerTabletStep.Layer) || // Stepping back from layers + (scopeFreedom === 'network' && tabletStep === LayerPickerTabletStep.LayerDetails)) && ( // Stepping back from details, skipping layers + } + onClick={() => { + setTabletStep(LayerPickerTabletStep.Network) + }} + > + {t('layerPicker.viewNetworks')} + + ) + } + {scopeFreedom !== 'network' && + tabletStep === LayerPickerTabletStep.LayerDetails && ( // Stepping back from details, going to layers + } + onClick={() => { + setTabletStep(LayerPickerTabletStep.Layer) + }} + > + {t('layerPicker.viewLayers')} + + )}
@@ -133,32 +138,38 @@ const LayerPickerContent: FC = ({ isOutOfDate, onClose, - {(!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.Network)) && ( - - { - selectNetwork(network) - setTabletStep(LayerPickerTabletStep.Layer) - }} - /> - - )} - {(!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.Layer)) && ( - - { - setSelectedLayer(layer) - setTabletStep(LayerPickerTabletStep.LayerDetails) - }} - /> - - )} + {scopeFreedom !== 'layer' && + (!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.Network)) && ( + + { + selectNetwork(network) + setTabletStep( + scopeFreedom === 'network' // Are we fixed to a specific layer, selecting only network? + ? LayerPickerTabletStep.LayerDetails // If so, skip layer selection, go straight to layer details. + : LayerPickerTabletStep.Layer, // Otherwise, go to layer selection. + ) + }} + /> + + )} + {scopeFreedom !== 'network' && + (!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.Layer)) && ( + + { + setSelectedLayer(layer) + setTabletStep(LayerPickerTabletStep.LayerDetails) + }} + /> + + )} {(!isTablet || (isTablet && tabletStep === LayerPickerTabletStep.LayerDetails)) && ( { const theme = useTheme() const { isMobile } = useScreenSize() const scope = useScopeParam() + const withScopeSelector = !!scope && isScopeSelectorNeeded(scope) const scrollTrigger = useScrollTrigger({ disableHysteresis: true, threshold: 0, @@ -49,7 +51,7 @@ export const Header: FC = () => { showText={!scrollTrigger && !isMobile} /> - {scope && ( + {withScopeSelector && ( <> diff --git a/src/app/components/PageLayout/NetworkButton.tsx b/src/app/components/PageLayout/NetworkButton.tsx index 79dc63829..e35405416 100644 --- a/src/app/components/PageLayout/NetworkButton.tsx +++ b/src/app/components/PageLayout/NetworkButton.tsx @@ -5,10 +5,12 @@ import Button, { buttonClasses } from '@mui/material/Button' import EditIcon from '@mui/icons-material/Edit' import { styled } from '@mui/material/styles' import { COLORS } from '../../../styles/theme/colors' -import { Network } from '../../../types/network' +import { getNetworkNames, Network } from '../../../types/network' import { Layer } from '../../../oasis-nexus/api' import { getLayerLabels, getNetworkIcons } from '../../utils/content' import { LayerStatus } from '../LayerStatus' +import { fixedLayer } from '../../utils/route-utils' +import { TFunction } from 'i18next' export const StyledNetworkButton = styled(Button)(({ theme }) => ({ alignItems: 'center', @@ -75,9 +77,13 @@ type NetworkButtonProps = { onClick: () => void } +const getNetworkButtonLabel = (t: TFunction, network: Network, layer: Layer) => + fixedLayer // If we are fixed to a layer, + ? getNetworkNames(t)[network] // let's show the name of the network, + : getLayerLabels(t)[layer] // otherwise, the name of the layer. + export const NetworkButton: FC = ({ isOutOfDate, layer, network, onClick }) => { const { t } = useTranslation() - const labels = getLayerLabels(t) const icons = getNetworkIcons() return ( @@ -90,7 +96,7 @@ export const NetworkButton: FC = ({ isOutOfDate, layer, netw onClick={onClick} > - {labels[layer]} + {getNetworkButtonLabel(t, network, layer)} @@ -115,11 +121,10 @@ export const StyledMobileNetworkButton = styled(Button)(({ theme }) => ({ export const MobileNetworkButton: FC = ({ isOutOfDate, layer, network, onClick }) => { const { t } = useTranslation() - const labels = getLayerLabels(t) return ( - {labels[layer]} + {getNetworkButtonLabel(t, network, layer)} ) diff --git a/src/app/components/PageLayout/NetworkSelector.tsx b/src/app/components/PageLayout/NetworkSelector.tsx index de8c428ab..14a33a57a 100644 --- a/src/app/components/PageLayout/NetworkSelector.tsx +++ b/src/app/components/PageLayout/NetworkSelector.tsx @@ -10,7 +10,7 @@ import { COLORS } from '../../../styles/theme/colors' import { Network, getNetworkNames } from '../../../types/network' import { Layer } from '../../../oasis-nexus/api' import { LayerPicker } from './../LayerPicker' -import { RouteUtils } from '../../utils/route-utils' +import { fixedLayer, RouteUtils } from '../../utils/route-utils' import { useConsensusFreshness, useRuntimeFreshness } from '../OfflineBanner/hook' export const StyledBox = styled(Box)(({ theme }) => ({ @@ -84,7 +84,7 @@ const NetworkSelectorView: FC = ({ isOutOfDate, layer, {!isMobile && ( )} - {!isTablet && network !== Network.mainnet && ( + {!fixedLayer && !isTablet && network !== Network.mainnet && ( = ({ network, @@ -14,6 +15,8 @@ export const ThemeByNetwork: FC<{ network: Network; children: React.ReactNode }> ) -export const withDefaultTheme = (node: ReactNode) => ( - {node} +export const withDefaultTheme = (node: ReactNode, alwaysMainnet = false) => ( + + {node} + ) diff --git a/src/app/hooks/useSearchQueryNetworkParam.ts b/src/app/hooks/useSearchQueryNetworkParam.ts index ffa28e358..2e698856c 100644 --- a/src/app/hooks/useSearchQueryNetworkParam.ts +++ b/src/app/hooks/useSearchQueryNetworkParam.ts @@ -1,6 +1,6 @@ import { useSearchParams } from 'react-router-dom' import { Network } from '../../types/network' -import { RouteUtils } from '../utils/route-utils' +import { fixedNetwork, RouteUtils } from '../utils/route-utils' import { AppErrors } from '../../types/errors' /** @@ -12,7 +12,7 @@ export const useSearchQueryNetworkParam = (): { setNetwork: (network: Network) => void } => { const [searchParams, setSearchParams] = useSearchParams() - const networkQueryParam = searchParams.get('network') ?? Network.mainnet + const networkQueryParam = fixedNetwork ?? searchParams.get('network') ?? Network.mainnet if (!RouteUtils.getEnabledNetworks().includes(networkQueryParam as any)) { throw AppErrors.InvalidUrl } diff --git a/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx b/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx index 3e1daaed8..7edb48278 100644 --- a/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx +++ b/src/app/pages/HomePage/Graph/ParaTimeSelector/index.tsx @@ -24,6 +24,7 @@ import { useSearchQueryNetworkParam } from '../../../../hooks/useSearchQueryNetw import { storage } from '../../../../utils/storage' import { StorageKeys } from '../../../../../types/storage' import { GraphTooltipMobile } from '../GraphTooltipMobile' +import { fixedNetwork } from '../../../../utils/route-utils' interface ParaTimeSelectorBaseProps { disabled: boolean @@ -284,7 +285,7 @@ const ParaTimeSelectorCmp: FC = ({ )} - {step === ParaTimeSelectorStep.Explore && ( + {!fixedNetwork && step === ParaTimeSelectorStep.Explore && ( setNetwork(network ?? Network.mainnet)} /> )} diff --git a/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx b/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx index 223480793..defe110fe 100644 --- a/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx +++ b/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx @@ -1,7 +1,7 @@ import { FC, useState } from 'react' import { useTranslation } from 'react-i18next' -import { RouteUtils } from '../../utils/route-utils' +import { fixedNetwork, RouteUtils } from '../../utils/route-utils' import { SearchResults } from './hooks' import { NoResultsOnMainnet, NoResultsWhatsoever } from './NoResults' import { SearchResultsList } from './SearchResultsList' @@ -30,6 +30,23 @@ export const GlobalSearchResultsView: FC<{ const themes = getThemesForNetworks() const networkNames = getNetworkNames(t) + + if (fixedNetwork) { + return ( + <> + {!searchResults.length && } + + + ) + } + const otherNetworks = RouteUtils.getEnabledNetworks().filter(isNotMainnet) const notificationTheme = themes[Network.testnet] const mainnetResults = searchResults.filter(isOnMainnet).sort(orderByLayer) diff --git a/src/app/pages/SearchResultsPage/hooks.ts b/src/app/pages/SearchResultsPage/hooks.ts index d02c4dcbd..6da6903d9 100644 --- a/src/app/pages/SearchResultsPage/hooks.ts +++ b/src/app/pages/SearchResultsPage/hooks.ts @@ -174,12 +174,10 @@ export function useRuntimeTokenConditionally( export function useNetworkProposalsConditionally( nameFragment: string | undefined, ): ConditionalResults { - const queries = RouteUtils.getEnabledNetworks() - .filter(network => RouteUtils.getAllLayersForNetwork(network).enabled.includes(Layer.consensus)) - .map(network => - // eslint-disable-next-line react-hooks/rules-of-hooks - useGetConsensusProposalsByName(network, nameFragment), - ) + const queries = RouteUtils.getEnabledNetworksForLayer(Layer.consensus).map(network => + // eslint-disable-next-line react-hooks/rules-of-hooks + useGetConsensusProposalsByName(network, nameFragment), + ) return { isLoading: queries.some(query => query.isInitialLoading), results: queries diff --git a/src/app/utils/route-utils.ts b/src/app/utils/route-utils.ts index 921d90870..9908604e2 100644 --- a/src/app/utils/route-utils.ts +++ b/src/app/utils/route-utils.ts @@ -7,6 +7,24 @@ import { Network } from '../../types/network' import { SearchScope } from '../../types/searchScope' import { isStableDeploy } from '../../config' import { getSearchTermFromRequest } from '../components/Search/search-utils' +import { isLayerHidden } from '../../types/layers' + +export const fixedNetwork = process.env.REACT_APP_FIXED_NETWORK as Network | undefined +export const fixedLayer = process.env.REACT_APP_FIXED_LAYER as Layer | undefined + +export type ScopeFreedom = + | 'network' // We can select only the network + | 'layer' // We can select only the layer + | 'network-layer' // We can select both network and layer + | 'none' // We can't select anything, everything is fixed + +export const scopeFreedom: ScopeFreedom = fixedNetwork + ? fixedLayer + ? 'none' + : 'layer' + : fixedLayer + ? 'network' + : 'network-layer' export type SpecifiedPerEnabledLayer = { [N in keyof (typeof RouteUtils)['ENABLED_LAYERS_FOR_NETWORK']]: { @@ -101,7 +119,7 @@ export abstract class RouteUtils { static getSearchRoute = (scope: SearchScope | undefined, searchTerm: string) => { return scope - ? `/${scope.network}/${scope.layer}/search?q=${encodeURIComponent(searchTerm)}` + ? `/${encodeURIComponent(scope.network)}/${encodeURIComponent(scope.layer)}/search?q=${encodeURIComponent(searchTerm)}` : `/search?q=${encodeURIComponent(searchTerm)}` } @@ -130,9 +148,13 @@ export abstract class RouteUtils { const enabled: Layer[] = [] const disabled: Layer[] = [] - Object.values(Layer).forEach(layer => - RouteUtils.ENABLED_LAYERS_FOR_NETWORK[network][layer] ? enabled.push(layer) : disabled.push(layer), - ) + Object.values(Layer).forEach(layer => { + if ((!fixedLayer || layer === fixedLayer) && RouteUtils.ENABLED_LAYERS_FOR_NETWORK[network][layer]) { + enabled.push(layer) + } else { + disabled.push(layer) + } + }) return { enabled, @@ -140,6 +162,12 @@ export abstract class RouteUtils { } } + static getVisibleLayersForNetwork(network: Network, currentScope: SearchScope | undefined): Layer[] { + return this.getAllLayersForNetwork(network).enabled.filter( + layer => !isLayerHidden(layer) || layer === currentScope?.layer, + ) + } + static getProposalsRoute = (network: Network) => { return `/${encodeURIComponent(network)}/consensus/proposal` } @@ -154,16 +182,32 @@ export abstract class RouteUtils { ) } + /** + * Get the list of enabled networks. + * + * If this Explorer is fixed to a specific network, the only that network will be returned. + * Furthermore, if this Explorer is fixed to a specific layer, only networks that support that layer are returned. + */ static getEnabledNetworks(): Network[] { - return Object.values(Network).filter(network => { - return RouteUtils.getAllLayersForNetwork(network).enabled.length > 0 - }) + const networks = fixedNetwork + ? [fixedNetwork] + : Object.values(Network).filter(network => { + return this.getAllLayersForNetwork(network).enabled.length > 0 + }) + return fixedLayer + ? networks.filter(network => { + return this.getAllLayersForNetwork(network).enabled.includes(fixedLayer) + }) + : networks } - static getEnabledSearchScopes(): SearchScope[] { - return RouteUtils.getEnabledNetworks().flatMap(network => - RouteUtils.getAllLayersForNetwork(network).enabled.map(layer => ({ network, layer })), - ) + static getEnabledNetworksForLayer(layer: Layer | undefined): Network[] { + const networks = this.getEnabledNetworks() + return layer + ? networks.filter(network => { + return this.getAllLayersForNetwork(network).enabled.includes(layer) + }) + : networks } } @@ -276,3 +320,19 @@ export const proposalIdParamLoader = async ({ params, request }: LoaderFunctionA searchTerm: getSearchTermFromRequest(request), } } + +/** + * Is it possible to change the scope, given the current configuration? + */ +export const isScopeSelectorNeeded = (sourceScope: SearchScope) => { + switch (scopeFreedom) { + case 'network': + return RouteUtils.getEnabledNetworks().length > 1 + case 'layer': + return RouteUtils.getVisibleLayersForNetwork(fixedNetwork!, sourceScope).length > 1 + case 'network-layer': + return RouteUtils.getEnabledScopes().length > 1 + case 'none': + return false + } +} diff --git a/src/global.d.ts b/src/global.d.ts index dc359c103..eb2123075 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -23,6 +23,8 @@ declare global { REACT_APP_SOCIAL_HOME?: string REACT_APP_PRODUCTION_URLS: string REACT_APP_STAGING_URLS?: string + REACT_APP_FIXED_NETWORK?: string + REACT_APP_FIXED_LAYER?: string } } } diff --git a/src/routes.tsx b/src/routes.tsx index a289e816b..8021b6bb4 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -1,4 +1,4 @@ -import { Outlet, RouteObject, ScrollRestoration } from 'react-router-dom' +import { Outlet, RouteObject, ScrollRestoration, useNavigate } from 'react-router-dom' import { HomePage } from './app/pages/HomePage' import { RuntimeBlocksPage } from './app/pages/RuntimeBlocksPage' import { RuntimeTransactionsPage } from './app/pages/RuntimeTransactionsPage' @@ -16,6 +16,9 @@ import { transactionParamLoader, assertEnabledScope, proposalIdParamLoader, + fixedNetwork, + fixedLayer, + RouteUtils, } from './app/utils/route-utils' import { searchParamLoader } from './app/components/Search/search-utils' import { RoutingErrorPage } from './app/pages/RoutingErrorPage' @@ -43,6 +46,7 @@ import { ConsensusBlocksPage } from './app/pages/ConsensusBlocksPage' import { ConsensusAccountsPage } from './app/pages/ConsensusAccountsPage' import { ConsensusTransactionsPage } from './app/pages/ConsensusTransactionsPage' import { ConsensusAccountDetailsPage } from './app/pages/ConsensusAccountDetailsPage' +import { FC, useEffect } from 'react' const NetworkSpecificPart = () => ( @@ -50,6 +54,25 @@ const NetworkSpecificPart = () => ( ) +/** + * In case of being restricted to a specific layer, jump to a dashboard + * + * This should be rendered on the landing page, since we don't want the opening graph. + */ +const RedirectToDashboard: FC = () => { + const navigate = useNavigate() + + useEffect(() => + navigate( + RouteUtils.getDashboardRoute({ + network: fixedNetwork ?? RouteUtils.getEnabledNetworksForLayer(fixedLayer!)[0]!, + layer: fixedLayer!, + }), + ), + ) + return null +} + export const routes: RouteObject[] = [ { errorElement: , @@ -62,13 +85,17 @@ export const routes: RouteObject[] = [ children: [ { path: '/', - element: withDefaultTheme(), - }, - { - path: '/search', // Global search - element: withDefaultTheme(), - loader: searchParamLoader, + element: fixedLayer ? : withDefaultTheme(, true), }, + ...(!!fixedNetwork && !!fixedLayer + ? [] + : [ + { + path: '/search', // Global search + element: withDefaultTheme(), + loader: searchParamLoader, + }, + ]), { path: '/:_network/consensus', element: ,