diff --git a/packages/website/src/hooks/routing/useSafeUrl.ts b/packages/website/src/hooks/routing/useSafeUrl.ts new file mode 100644 index 000000000..310a92e71 --- /dev/null +++ b/packages/website/src/hooks/routing/useSafeUrl.ts @@ -0,0 +1,24 @@ +import isInteger from 'lodash/isInteger'; +import { useRouter } from 'next/router'; +import { Address, isAddress } from 'viem'; + +export function useSafeUrl() { + const router = useRouter(); + const { query: params } = router; + const { chainId, safeAddress } = params; + + const isSafeUrl = router.pathname.includes('/deploy/[chainId]/[safeAddress]'); + + if (isSafeUrl && !isInteger(Number(chainId))) throw new Error('Invalid chainId URL param'); + + if (isSafeUrl && (typeof safeAddress !== 'string' || !isAddress(safeAddress))) { + throw new Error('Invalid safeAddress URL param'); + } + + return { + isSafeUrl, + chainId: chainId ? +chainId : null, + safeAddress: (safeAddress as Address) || null, + safeString: `${chainId}:${safeAddress}`, + }; +} diff --git a/packages/website/src/pages/deploy/[chainId]/[safeAddress]/gitops/index.tsx b/packages/website/src/pages/deploy/[chainId]/[safeAddress]/gitops/index.tsx new file mode 100644 index 000000000..e6a889113 --- /dev/null +++ b/packages/website/src/pages/deploy/[chainId]/[safeAddress]/gitops/index.tsx @@ -0,0 +1,44 @@ +import dynamic from 'next/dynamic'; +import { ReactElement } from 'react'; +import Layout from '@/pages/deploy/deployLayout'; +import { NextSeo } from 'next-seo'; +import defaultSEO from '@/constants/defaultSeo'; + +const NoSSR = dynamic( + async () => { + return import('@/features/Deploy/QueueFromGitOpsPage'); + }, + { + ssr: false, + } +); + +/*export const metadata: Metadata = { + title: 'Cannon | Queue From GitOps', + description: 'Queue From GitOps', + openGraph: { + title: 'Cannon | Queue From GitOps', + description: 'Queue From GitOps', + }, + };*/ + +export default function QueueFromGitOps() { + return ( + <> + + + + ); +} +QueueFromGitOps.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; diff --git a/packages/website/src/pages/deploy/[chainId]/[safeAddress]/queue/index.tsx b/packages/website/src/pages/deploy/[chainId]/[safeAddress]/queue/index.tsx new file mode 100644 index 000000000..91d5e5fbb --- /dev/null +++ b/packages/website/src/pages/deploy/[chainId]/[safeAddress]/queue/index.tsx @@ -0,0 +1,51 @@ +//import { QueuedTxns } from '@/features/Deploy/QueueDrawer'; +import { Box, Container, Heading, Text } from '@chakra-ui/react'; +import { ReactElement } from 'react'; +import Layout from '../../../deployLayout'; +import { QueuedTxns } from '@/features/Deploy/QueueDrawer'; +import { NextSeo } from 'next-seo'; +import defaultSEO from '@/constants/defaultSeo'; + +/*export const metadata: Metadata = { + title: 'Cannon | Queue Transactions', + description: 'Queue Transactions', + openGraph: { + title: 'Cannon | Queue Transactions', + description: 'Queue Transactions', + }, + };*/ + +const QueueTransactions = () => { + return ( + <> + + + + + Stage Transactions + + + Queue transactions from a package on the Cannon registry. + Transactions executed after being staged with this tool will not + result in a package to publish. + + + + + + ); +}; +QueueTransactions.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default QueueTransactions; diff --git a/packages/website/src/pages/deploy/[chainId]/[safeAddress]/txn/[nonce]/[sigHash]/index.tsx b/packages/website/src/pages/deploy/[chainId]/[safeAddress]/txn/[nonce]/[sigHash]/index.tsx new file mode 100644 index 000000000..a99399a3f --- /dev/null +++ b/packages/website/src/pages/deploy/[chainId]/[safeAddress]/txn/[nonce]/[sigHash]/index.tsx @@ -0,0 +1,39 @@ +import PageLoading from '@/components/PageLoading'; +import defaultSEO from '@/constants/defaultSeo'; +import { NextSeo } from 'next-seo'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/router'; +import { ReactElement } from 'react'; +import Layout from '@/pages/deploy/deployLayout'; + +const NoSSRTransactionDetailsPage = dynamic( + async () => { + return import('@/features/Deploy/TransactionDetailsPage'); + }, + { + ssr: false, + } +); + +export default function TransactionDetails() { + const router = useRouter(); + return ( + <> + + {router.isReady ? : } + + ); +} + +TransactionDetails.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; diff --git a/packages/website/src/pages/deploy/_gitops/index.tsx b/packages/website/src/pages/deploy/_gitops/index.tsx new file mode 100644 index 000000000..e6a889113 --- /dev/null +++ b/packages/website/src/pages/deploy/_gitops/index.tsx @@ -0,0 +1,44 @@ +import dynamic from 'next/dynamic'; +import { ReactElement } from 'react'; +import Layout from '@/pages/deploy/deployLayout'; +import { NextSeo } from 'next-seo'; +import defaultSEO from '@/constants/defaultSeo'; + +const NoSSR = dynamic( + async () => { + return import('@/features/Deploy/QueueFromGitOpsPage'); + }, + { + ssr: false, + } +); + +/*export const metadata: Metadata = { + title: 'Cannon | Queue From GitOps', + description: 'Queue From GitOps', + openGraph: { + title: 'Cannon | Queue From GitOps', + description: 'Queue From GitOps', + }, + };*/ + +export default function QueueFromGitOps() { + return ( + <> + + + + ); +} +QueueFromGitOps.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; diff --git a/packages/website/src/pages/deploy/_queue/index.tsx b/packages/website/src/pages/deploy/_queue/index.tsx new file mode 100644 index 000000000..4c887542d --- /dev/null +++ b/packages/website/src/pages/deploy/_queue/index.tsx @@ -0,0 +1,51 @@ +//import { QueuedTxns } from '@/features/Deploy/QueueDrawer'; +import { Box, Container, Heading, Text } from '@chakra-ui/react'; +import { ReactElement } from 'react'; +import Layout from '../deployLayout'; +import { QueuedTxns } from '@/features/Deploy/QueueDrawer'; +import { NextSeo } from 'next-seo'; +import defaultSEO from '@/constants/defaultSeo'; + +/*export const metadata: Metadata = { + title: 'Cannon | Queue Transactions', + description: 'Queue Transactions', + openGraph: { + title: 'Cannon | Queue Transactions', + description: 'Queue Transactions', + }, + };*/ + +const QueueTransactions = () => { + return ( + <> + + + + + Stage Transactions + + + Queue transactions from a package on the Cannon registry. + Transactions executed after being staged with this tool will not + result in a package to publish. + + + + + + ); +}; +QueueTransactions.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default QueueTransactions; diff --git a/packages/website/src/pages/deploy/_txn/[chainId]/[safeAddress]/[nonce]/[sigHash]/index.tsx b/packages/website/src/pages/deploy/_txn/[chainId]/[safeAddress]/[nonce]/[sigHash]/index.tsx new file mode 100644 index 000000000..18cdb7e32 --- /dev/null +++ b/packages/website/src/pages/deploy/_txn/[chainId]/[safeAddress]/[nonce]/[sigHash]/index.tsx @@ -0,0 +1,39 @@ +import PageLoading from '@/components/PageLoading'; +import defaultSEO from '@/constants/defaultSeo'; +import { NextSeo } from 'next-seo'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/router'; +import { ReactElement } from 'react'; +import Layout from '../../../../../deployLayout'; + +const NoSSRTransactionDetailsPage = dynamic( + async () => { + return import('@/features/Deploy/TransactionDetailsPage'); + }, + { + ssr: false, + } +); + +export default function TransactionDetails() { + const router = useRouter(); + return ( + <> + + {router.isReady ? : } + + ); +} + +TransactionDetails.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; diff --git a/packages/website/src/pages/deploy/deployLayout.tsx b/packages/website/src/pages/deploy/deployLayout.tsx new file mode 100644 index 000000000..bb75ab8bc --- /dev/null +++ b/packages/website/src/pages/deploy/deployLayout.tsx @@ -0,0 +1,87 @@ +'use client'; + +import dynamic from 'next/dynamic'; +import { ReactNode } from 'react'; +import { Box, Flex, useBreakpointValue } from '@chakra-ui/react'; +import { useRouter } from 'next/router'; +import { links } from '@/constants/links'; +import { NavLink } from '@/components/NavLink'; +import { SafeAddressInput } from '@/features/Deploy/SafeAddressInput'; +import ClientOnly from '@/components/ClientOnly'; +import { CustomSpinner } from '@/components/CustomSpinner'; +import { useParams } from 'next/navigation'; + +const NoSSRWithSafe = dynamic(() => import('@/features/Deploy/WithSafe'), { + ssr: false, +}); + +export default function DeployLayout({ children }: { children: ReactNode }) { + const router = useRouter(); + const params = useParams(); + const isLarge = useBreakpointValue({ base: false, lg: true }); + + const isSafeUrl = router.pathname.includes('/deploy/[chainId]/[safeAddress]'); + const isGitOpsPage = + router.pathname === '/deploy/[chainId]/[safeAddress]/gitops'; + const isQueuePage = + router.pathname === '/deploy/[chainId]/[safeAddress]/queue'; + const isTxnPage = router.pathname === '/deploy/[chainId]/[safeAddress]/txn'; + + return ( + + {params !== null ? ( + <> + {/* Header */} + + + + + + + + {isSafeUrl && ( + + + Sign{isLarge && ' Transactions'} + + + {isLarge && 'Queue '} Deployment + + + Stage{isLarge && ' Transactions'} + + + )} + + + + {/* Body */} + {children} + + ) : ( + + )} + + ); +} diff --git a/packages/website/src/pages/learn/guides/index.tsx b/packages/website/src/pages/learn/guides/index.tsx index e0095e685..0b0ebdaab 100644 --- a/packages/website/src/pages/learn/guides/index.tsx +++ b/packages/website/src/pages/learn/guides/index.tsx @@ -17,7 +17,7 @@ export default function Home() { .catch(() => { // do nothing }); - }, []); + }, [router]); return ( <>