From 654453d91418ca7b65f0f04509f9233467b9cace Mon Sep 17 00:00:00 2001 From: Travis Vachon Date: Tue, 28 Nov 2023 09:43:00 -0800 Subject: [PATCH] feat: add logout page (#42) use the now-fixed react-keyring package to implement a logout page. we can now add logout links to various places that send users to this page. --- package.json | 2 +- pnpm-lock.yaml | 12 ++-- src/app/layout.tsx | 6 +- src/app/logout/page.tsx | 19 ++++++ src/app/page.tsx | 12 +++- src/app/space/layout.tsx | 9 +-- src/components/SidebarLayout.tsx | 109 ++++++++++++++++--------------- src/components/W3API.tsx | 13 ++-- 8 files changed, 110 insertions(+), 72 deletions(-) create mode 100644 src/app/logout/page.tsx diff --git a/package.json b/package.json index 3ed7183..002d63d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@ucanto/core": "^9.0.0", "@ucanto/interface": "^9.0.0", "@ucanto/transport": "^9.0.0", - "@w3ui/react-keyring": "^6.2.0", + "@w3ui/react-keyring": "^6.2.1", "@w3ui/react-uploader": "^5.2.0", "@w3ui/react-uploads-list": "^4.2.0", "@web3-storage/access": "^16.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e275262..e4b72f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,8 +30,8 @@ dependencies: specifier: ^9.0.0 version: 9.0.0 '@w3ui/react-keyring': - specifier: ^6.2.0 - version: 6.2.0(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0) + specifier: ^6.2.1 + version: 6.2.1(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0) '@w3ui/react-uploader': specifier: ^5.2.0 version: 5.2.0(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0) @@ -1269,8 +1269,8 @@ packages: '@web3-storage/did-mailto': 2.0.2 dev: false - /@w3ui/react-keyring@6.2.0(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-vSM1dv7lCTMBhFB+1Z1HZiHcuGscgz6P0n+CkrrOQgoBsmFn/v+6fOnfeZ4MUHGdkLYx0FFibXiA+DX2W07jEA==} + /@w3ui/react-keyring@6.2.1(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ORXxtepWjQ7nHW5DE0pmMA9ulMCmU1+7LSMZtW31CF5AfnE2ceSzG8XYZFQCZS3HAvekwGw/0ccN0zTCjvPWxQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: @@ -1288,7 +1288,7 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@w3ui/react-keyring': 6.2.0(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0) + '@w3ui/react-keyring': 6.2.1(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0) '@w3ui/uploader-core': 6.1.0 '@web3-storage/capabilities': 11.1.0 ariakit-react-utils: 0.17.0-next.27(@types/react@18.2.32)(react@18.2.0) @@ -1304,7 +1304,7 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@w3ui/react-keyring': 6.2.0(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0) + '@w3ui/react-keyring': 6.2.1(@types/react@18.2.32)(react-dom@18.2.0)(react@18.2.0) '@w3ui/uploads-list-core': 4.1.0 '@web3-storage/capabilities': 11.1.0 ariakit-react-utils: 0.17.0-next.27(@types/react@18.2.32)(react@18.2.0) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 55341ad..d56ad61 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,6 @@ -import SidebarLayout from '@/components/SidebarLayout' import './globals.css' import type { Metadata } from 'next' +import { W3APIProvider } from '@/components/W3API' export const metadata: Metadata = { title: 'w3up console', @@ -15,9 +15,9 @@ export default function RootLayout ({ return ( - + {children} - + ) diff --git a/src/app/logout/page.tsx b/src/app/logout/page.tsx new file mode 100644 index 0000000..36a17e6 --- /dev/null +++ b/src/app/logout/page.tsx @@ -0,0 +1,19 @@ +'use client' +import { useKeyring } from "@w3ui/react-keyring" +import { useRouter } from "next/navigation" +import { useEffect } from "react" + +export default function LogoutPage () { + const [, { unloadAgent }] = useKeyring() + const router = useRouter() + useEffect(function () { + if (unloadAgent) { + async function logOutAndRedirect () { + await unloadAgent() + router.push('/') + } + logOutAndRedirect() + } + }, []) + return <> +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 0440a86..fde6ca8 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,8 +5,18 @@ import { DidIcon } from '@/components/DidIcon' import Link from 'next/link' import { SpacesNav } from './space/layout' import { H2 } from '@/components/Text' +import SidebarLayout from '@/components/SidebarLayout' +import { ReactNode } from 'react' -export default function SpacePage (): JSX.Element { +export default function HomePage () { + return ( + + + + ) +} + +function SpacePage (): ReactNode { const [{ spaces }] = useKeyring() if (spaces.length === 0) { diff --git a/src/app/space/layout.tsx b/src/app/space/layout.tsx index aed8e69..5d94324 100644 --- a/src/app/space/layout.tsx +++ b/src/app/space/layout.tsx @@ -1,6 +1,7 @@ -import { PropsWithChildren } from 'react' +import { PropsWithChildren, ReactNode } from 'react' import { Nav, NavLink } from '@/components/Nav' import { UsageBar } from '@/components/UsageBar' +import SidebarLayout from '@/components/SidebarLayout' export const runtime = 'edge' @@ -10,11 +11,11 @@ interface LayoutProps extends PropsWithChildren { } } -export default function Layout ({children}: LayoutProps): JSX.Element { +export default function Layout ({children}: LayoutProps): ReactNode { return ( - <> + {children} - + ) } diff --git a/src/components/SidebarLayout.tsx b/src/components/SidebarLayout.tsx index 1e8488d..62c98c6 100644 --- a/src/components/SidebarLayout.tsx +++ b/src/components/SidebarLayout.tsx @@ -4,14 +4,14 @@ import { Logo } from '../brand' import { Fragment, useState } from 'react' import { Dialog, Transition } from '@headlessui/react' import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline' -import { Authenticator, useKeyring, Space } from '@w3ui/react-keyring' +import { useKeyring, Space } from '@w3ui/react-keyring' import { AuthenticationEnsurer } from '../components/Authenticator' import { SpaceEnsurer } from '../components/SpaceEnsurer' import { MaybePlanGate } from './PlanGate' -import { W3APIProvider } from '@/components/W3API' import { SpaceFinder } from './SpaceFinder' import { usePathname, useRouter } from 'next/navigation' import { H2 } from './Text' +import Link from 'next/link' const navLinks = [ { name: 'Terms', href: 'https://web3.storage/docs/terms' }, @@ -23,6 +23,8 @@ interface SidebarComponentProps { sidebar?: React.ReactNode } +const footerLinkClasses = 'text-xs block text-center mt-2 px-1' + function Sidebar ({ sidebar =
}: SidebarComponentProps): JSX.Element { const [{space, spaces}] = useKeyring() const router = useRouter() @@ -44,8 +46,11 @@ function Sidebar ({ sidebar =
}: SidebarComponentProps): JSX.Element
{navLinks.map((link, i) => ( - {link.name} + {link.name} ))} + + Log Out +
@@ -61,61 +66,59 @@ export default function SidebarLayout ({ children }: LayoutComponentProps): JSX. const [sidebarOpen, setSidebarOpen] = useState(false) return ( - - - - - -
- {/* dialog sidebar for narrow browsers */} - - setSidebarOpen(false)} as='div' className='relative z-50'> +
+ + + +
+ {/* dialog sidebar for narrow browsers */} + + setSidebarOpen(false)} as='div' className='relative z-50'> + + - - {/* static sidebar for wide browsers */} -
- -
-
- {/* top nav bar for narrow browsers, mainly to have a place to put the hamburger */} -
- setSidebarOpen(true)} /> -
-
- {children} -
+
+
+ {/* static sidebar for wide browsers */} +
+ +
+
+ {/* top nav bar for narrow browsers, mainly to have a place to put the hamburger */} +
+ setSidebarOpen(true)} /> +
+
+ {children} +
- - - - - +
+
+
+
+ ) } diff --git a/src/components/W3API.tsx b/src/components/W3API.tsx index cf5eb3d..e2e3d6a 100644 --- a/src/components/W3API.tsx +++ b/src/components/W3API.tsx @@ -1,4 +1,6 @@ -import { useMemo } from 'react' +'use client' + +import { ReactNode, useMemo } from 'react' import { useUploader, UploaderContextValue, @@ -10,6 +12,7 @@ import { UploadsListProvider } from '@w3ui/react-uploads-list' import { + Authenticator, useKeyring, KeyringContextValue, KeyringProvider @@ -23,19 +26,21 @@ export interface W3APIContextValue { } export interface W3APIProviderProps { - children: JSX.Element | JSX.Element[] + children: ReactNode uploadsListPageSize?: number } export function W3APIProvider ({ children, uploadsListPageSize -}: W3APIProviderProps): JSX.Element { +}: W3APIProviderProps): ReactNode { return ( - <>{children} + + {children} +