Skip to content

Commit

Permalink
feat: session persistence after refresh [27]
Browse files Browse the repository at this point in the history
  • Loading branch information
nblenke authored Mar 12, 2024
1 parent 7db180b commit 2995c3f
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 179 deletions.
16 changes: 0 additions & 16 deletions __tests__/components/dashboard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,6 @@ describe("Dashboard", () => {
const { container } = render(<Dashboard />)
expect(container.querySelector(".chakra-spinner")).toBeInTheDocument()
})
it("renders error if no data", () => {
useFetchMetas.mockReturnValue([
{
data: null,
isLoading: false,
refetch: jest.fn(),
},
0,
0,
jest.fn(),
])
render(<Dashboard />)
expect(
screen.getByText("Error fetching deployments. Is the backend online?"),
).toBeInTheDocument()
})
it("renders creact deployment button if logged in", () => {
useFetchMetas.mockReturnValue([
{
Expand Down
12 changes: 7 additions & 5 deletions __tests__/pages/dashboard.test.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
// @ts-nocheck
import "@testing-library/jest-dom"
import { render, screen } from "@testing-library/react"
import { render, screen, waitFor } from "@testing-library/react"
import Dashboard from "../../pages/dashboard"
import useWeb3AuthStore from "../../store/web3-auth"

jest.mock("../../store/web3-auth", () => jest.fn())
describe("Dashboard", () => {
it("renders login message if not connected", () => {
it("renders login message if not connected", async () => {
useWeb3AuthStore.mockReturnValue({
// provider: null,
isConnected: () => false,
})
render(<Dashboard />)
expect(
screen.getByText("Please login to view this page"),
).toBeInTheDocument()
await waitFor(() => {
expect(
screen.getByText("Please login to view this page"),
).toBeInTheDocument()
})
})
})
248 changes: 123 additions & 125 deletions components/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Box,
Button,
Center,
Flex,
Icon,
Table,
Thead,
Expand All @@ -15,7 +16,7 @@ import {
Spinner,
HStack,
Tooltip,
useTheme
useTheme,
} from "@chakra-ui/react"
import {
ArrowBackIcon,
Expand All @@ -32,9 +33,7 @@ import {
GHOSTCLOUD_URL_DOMAIN,
GHOSTCLOUD_URL_SCHEME,
} from "../config/ghostcloud-chain"
import {
GHOSTCLOUD_INFRA_LOADBALANCER_IP
} from "../config/ghostcloud-infra"
import { GHOSTCLOUD_INFRA_LOADBALANCER_IP } from "../config/ghostcloud-infra"
import useWeb3AuthStore from "../store/web3-auth"
import { truncateAddress } from "../helpers/address"
import { FaInfoCircle } from "react-icons/fa"
Expand Down Expand Up @@ -87,131 +86,130 @@ const Dashboard = () => {
}
}

if (isMetaLoading || !metas) {
return (
<Flex sx={{ height: "50vh" }} justify={"center"} align={"center"}>
<Spinner />
</Flex>
)
}

return (
<Box>
{isMetaLoading ? <Spinner /> : null}
{metas ? (
<>
<Button
onClick={() => setIsCreateModalOpen(true)}
float="right"
mb={2}
>
Create Deployment
</Button>
<CreateDeploymentModal
isOpen={isCreateModalOpen}
onClose={() => {
refetchMetas()
setIsCreateModalOpen(false)
}}
/>
<UpdateDeploymentModal
isOpen={isUpdateModalOpen}
onClose={() => setIsUpdateModalOpen(false)}
deploymentName={selectedDeploymentName}
deploymentDescription={selectedDeploymentDescription}
deploymentDomain={selectedDeploymentDomain}
/>
<RemoveDeploymentModal
isOpen={isRemoveModalOpen}
onClose={() => {
refetchMetas()
setIsRemoveModalOpen(false)
}}
deploymentName={selectedDeploymentName}
/>
<Table variant="simple">
<Thead>
<Tr>
<Th>Name</Th>
<Th>Description</Th>
<Th>Domain</Th>
<Th>URL</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{metas.meta.map((meta, index) => (
<Tr key={index}>
<Td>{meta.name}</Td>
<Td>{meta.description}</Td>
<Td>
{meta.domain && (
<>
{meta.domain}
<Tooltip label={`Set ${meta.domain} DNS A record to ${GHOSTCLOUD_INFRA_LOADBALANCER_IP} to activate custom domain.`}>
<Box as="span" ml="4px">
<Icon
as={FaInfoCircle}
boxSize={4}
color={theme.colors.gray[400]}
/>
</Box>
</Tooltip>
</>
)}
</Td>
<Td>
<Link
href={createUrl(meta.name, address) + "/index.html"}
isExternal
<Button onClick={() => setIsCreateModalOpen(true)} float="right" mb={2}>
Create Deployment
</Button>
<CreateDeploymentModal
isOpen={isCreateModalOpen}
onClose={() => {
refetchMetas()
setIsCreateModalOpen(false)
}}
/>
<UpdateDeploymentModal
isOpen={isUpdateModalOpen}
onClose={() => setIsUpdateModalOpen(false)}
deploymentName={selectedDeploymentName}
deploymentDescription={selectedDeploymentDescription}
deploymentDomain={selectedDeploymentDomain}
/>
<RemoveDeploymentModal
isOpen={isRemoveModalOpen}
onClose={() => {
refetchMetas()
setIsRemoveModalOpen(false)
}}
deploymentName={selectedDeploymentName}
/>
<Table variant="simple">
<Thead>
<Tr>
<Th>Name</Th>
<Th>Description</Th>
<Th>Domain</Th>
<Th>URL</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{metas.meta.map((meta, index) => (
<Tr key={index}>
<Td>{meta.name}</Td>
<Td>{meta.description}</Td>
<Td>
{meta.domain && (
<>
{meta.domain}
<Tooltip
label={`Set ${meta.domain} DNS A record to ${GHOSTCLOUD_INFRA_LOADBALANCER_IP} to activate custom domain.`}
>
{createUrl(meta.name, truncateAddress(address, 4))}
</Link>
</Td>
<Td>
<HStack spacing={0}>
<IconButton
onClick={() =>
handleUpdate(meta.name, meta.description, meta.domain)
}
aria-label="Update"
icon={<EditIcon />}
size="sm"
mr={2}
>
Update
</IconButton>
<IconButton
onClick={() => handleRemove(meta.name)}
aria-label="Remove"
icon={<DeleteIcon />}
size="sm"
>
Remove
</IconButton>
</HStack>
</Td>
</Tr>
))}
</Tbody>
</Table>
<Box as="span" ml="4px">
<Icon
as={FaInfoCircle}
boxSize={4}
color={theme.colors.gray[400]}
/>
</Box>
</Tooltip>
</>
)}
</Td>
<Td>
<Link
href={createUrl(meta.name, address) + "/index.html"}
isExternal
>
{createUrl(meta.name, truncateAddress(address, 4))}
</Link>
</Td>
<Td>
<HStack spacing={0}>
<IconButton
onClick={() =>
handleUpdate(meta.name, meta.description, meta.domain)
}
aria-label="Update"
icon={<EditIcon />}
size="sm"
mr={2}
>
Update
</IconButton>
<IconButton
onClick={() => handleRemove(meta.name)}
aria-label="Remove"
icon={<DeleteIcon />}
size="sm"
>
Remove
</IconButton>
</HStack>
</Td>
</Tr>
))}
</Tbody>
</Table>

{pageCount > 1 && (
<Center my={8}>
<IconButton
icon={<ArrowBackIcon />}
aria-label="Previous"
isDisabled={currentPage === 1}
onClick={() => handlePageClick("prev")}
data-testid="previous-button"
/>
<Box mx={4} data-testid="page-info">
{currentPage} / {pageCount}
</Box>
<IconButton
icon={<ArrowForwardIcon />}
aria-label="Next"
isDisabled={currentPage === pageCount}
onClick={() => handlePageClick("next")}
data-testid="next-button"
/>
</Center>
)}
</>
) : (
<div>Error fetching deployments. Is the backend online?</div>
{pageCount > 1 && (
<Center my={8}>
<IconButton
icon={<ArrowBackIcon />}
aria-label="Previous"
isDisabled={currentPage === 1}
onClick={() => handlePageClick("prev")}
data-testid="previous-button"
/>
<Box mx={4} data-testid="page-info">
{currentPage} / {pageCount}
</Box>
<IconButton
icon={<ArrowForwardIcon />}
aria-label="Next"
isDisabled={currentPage === pageCount}
onClick={() => handlePageClick("next")}
data-testid="next-button"
/>
</Center>
)}
</Box>
)
Expand Down
20 changes: 20 additions & 0 deletions components/login-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react"
import useAuthHandlers from "../hooks/useAuthHandlers"
import useOpenLoginSession from "../hooks/useOpenLoginSession"

const LoginWrapper = ({ children }: { children: React.ReactNode }) => {
const { handleLogin } = useAuthHandlers()
const [hasLoginAttempt, setHasLoginAttempt] = React.useState(false)
const hasSession = useOpenLoginSession()

React.useEffect(() => {
if (hasSession && !hasLoginAttempt) {
handleLogin({}, false)
setHasLoginAttempt(true)
}
}, [handleLogin, hasLoginAttempt, hasSession])

return <>{children}</>
}

export default LoginWrapper
2 changes: 1 addition & 1 deletion components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const Menu: React.FC<LoginProps> = () => {
<MenuItem onClick={handleLogout}>Logout</MenuItem>
</>
) : (
<MenuItem onClick={handleLogin}>Login</MenuItem>
<MenuItem onClick={ev => handleLogin(ev, true)}>Login</MenuItem>
)}
</MenuList>
</ChakraMenu>
Expand Down
7 changes: 5 additions & 2 deletions hooks/useAuthHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ export default function useAuthHandlers() {

// Handle the login to Web3Auth.
// Redirect to the dashboard if the user is already connected.
const handleLogin = async () => {
const handleLogin = async (
ev: any,
redirectToDashboard: boolean | null = null,
) => {
if (!store.isConnected()) {
const uiConfig = {
...GHOSTCLOUD_UI_CONFIG,
Expand All @@ -36,7 +39,7 @@ export default function useAuthHandlers() {
})
}
}
await router.push("/dashboard")
redirectToDashboard && (await router.push("/dashboard"))
}

// Handle the logout from Web3Auth.
Expand Down
Loading

0 comments on commit 2995c3f

Please sign in to comment.