Skip to content

Commit

Permalink
feat: add UI components to support admin apikey interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
0xjei committed Mar 28, 2024
1 parent fb852d3 commit 011f7b9
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 1 deletion.
1 change: 1 addition & 0 deletions apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"dependencies": {
"@bandada/credentials": "2.1.1",
"@bandada/utils": "2.1.1",
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/react": "^2.5.1",
"@chakra-ui/styled-system": "^2.0.0",
"@chakra-ui/theme-tools": "^2.0.16",
Expand Down
188 changes: 188 additions & 0 deletions apps/dashboard/src/components/api-key.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { useEffect, useState } from "react"
import {
Box,
Flex,
Switch,
useClipboard,
useToast,
IconButton,
Tooltip,
Text
} from "@chakra-ui/react"
import { ViewIcon, CopyIcon, RepeatIcon, CheckIcon } from "@chakra-ui/icons"
import { ApiKeyActions } from "@bandada/utils"
import { Admin } from "../types"
import { getAdmin, updateApiKey } from "../api/bandadaAPI"

export default function ApiKeyComponent({
adminId
}: {
adminId: string
}): JSX.Element {
const [admin, setAdmin] = useState<Admin>()
const [apiKey, setApiKey] = useState("")
const [isEnabled, setIsEnabled] = useState(false)
const [isCopied, setIsCopied] = useState(false)
const { onCopy } = useClipboard(apiKey)
const toast = useToast()

useEffect(() => {
getAdmin(adminId).then((admin) => {
if (admin) {
setAdmin(admin)
setApiKey(!admin.apiKey ? "" : admin.apiKey)
setIsEnabled(admin.apiEnabled)
}
})
})

useEffect(() => {
if (isCopied) {
const timer = setTimeout(() => {
setIsCopied(false)
}, 2000)
return () => clearTimeout(timer)
}
}, [isCopied])

const showToast = (
title: string,
description: string,
status: "info" | "warning" | "success" | "error",
duration = 2000,
position: "top" | "bottom" = "top"
) => {
toast({
title,
description,
status,
duration,
isClosable: true,
position
})
}

const handleCopy = () => {
onCopy()
setIsCopied(true)
}

const handleRefresh = async () => {
if (admin) {
const newApiKey = await updateApiKey(
admin.id,
ApiKeyActions.Generate
)
if (!newApiKey) {
showToast(
"Something went wrong",
"API Key has not been refreshed",
"error"
)
} else {
showToast(
"API Key refresh",
"Successfully refreshed",
"success"
)
setApiKey(newApiKey)
}
}
}

const showApiKey = () => {
if (admin && admin.apiKey) {
showToast(
"API Key",
`Your API key is: ${admin.apiKey}`,
"info",
2500,
"top"
)
}
}

const toggleIsEnabled = async () => {
if (admin) {
let toastTitle = ""
let toastDescription = ""
let action = ApiKeyActions.Enable

if (!admin.apiKey) {
await updateApiKey(admin.id, ApiKeyActions.Generate)
toastTitle = "API Key Generated"
toastDescription = "A new API key has been generated."
} else {
action = isEnabled
? ApiKeyActions.Disable
: ApiKeyActions.Enable
await updateApiKey(admin.id, action)
toastTitle =
action === ApiKeyActions.Enable
? "API Key Enabled"
: "API Key Disabled"
toastDescription =
action === ApiKeyActions.Enable
? "API key has been enabled."
: "API key has been disabled."
}

showToast(toastTitle, toastDescription, "success")
setIsEnabled((prevState) => !prevState)
}
}

return (
<Flex
align="center"
justify="space-between"
p={4}
borderRadius="md"
minWidth="300px"
height="48px"
>
<Flex align="center" flexGrow={1} justify="center">
<Box>
<Text
fontWeight="bold"
colorScheme="primary"
color={isEnabled ? "balticSea.900" : "balticSea.400"}
>
API Key
</Text>
</Box>
<Switch
isChecked={isEnabled}
onChange={toggleIsEnabled}
mx={4}
/>

{isEnabled && (
<Flex align="center">
<Tooltip label="Show API Key">
<IconButton
icon={<ViewIcon />}
onClick={showApiKey}
aria-label="View API Key"
/>
</Tooltip>
<IconButton
icon={isCopied ? <CheckIcon /> : <CopyIcon />}
onClick={handleCopy}
ml={2}
aria-label="Copy API Key"
isDisabled={!isEnabled}
/>
<IconButton
icon={<RepeatIcon />}
onClick={handleRefresh}
ml={2}
aria-label="Refresh API Key"
isDisabled={!isEnabled}
/>
</Flex>
)}
</Flex>
</Flex>
)
}
3 changes: 3 additions & 0 deletions apps/dashboard/src/pages/groups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import GroupCard from "../components/group-card"
import { AuthContext } from "../context/auth-context"
import { Group } from "../types"
import GoerliGroupCard from "../components/goerli-group"
import ApiKeyComponent from "../components/api-key"

export default function GroupsPage(): JSX.Element {
const { admin } = useContext(AuthContext)
Expand Down Expand Up @@ -115,6 +116,8 @@ export default function GroupsPage(): JSX.Element {
</Button>
</HStack>

<ApiKeyComponent adminId={admin?.id!} />

<Button
variant="solid"
colorScheme="primary"
Expand Down
4 changes: 3 additions & 1 deletion apps/dashboard/src/types/Admin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export type Admin = {
address: string
id: string
address: string
apiKey: string | null
apiEnabled: boolean
}

export default Admin
25 changes: 25 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2685,6 +2685,30 @@ __metadata:
languageName: node
linkType: hard

"@chakra-ui/icon@npm:3.2.0":
version: 3.2.0
resolution: "@chakra-ui/icon@npm:3.2.0"
dependencies:
"@chakra-ui/shared-utils": "npm:2.0.5"
peerDependencies:
"@chakra-ui/system": ">=2.0.0"
react: ">=18"
checksum: 10/b63eec1cb00b3f92ab64927fef96b60563ae32ae5df4a29edfe8cda4ba1c5aeb980c608b5a12e2376eaeb117a12362a45dd5e974b87ef72937dd897de7dc272f
languageName: node
linkType: hard

"@chakra-ui/icons@npm:^2.1.1":
version: 2.1.1
resolution: "@chakra-ui/icons@npm:2.1.1"
dependencies:
"@chakra-ui/icon": "npm:3.2.0"
peerDependencies:
"@chakra-ui/system": ">=2.0.0"
react: ">=18"
checksum: 10/30c8644e1e80a1d24ce5fa081673da726a2b26e7dc62fa90f318f478efdd4537ef31db4bf4f6d5afc76ad6d815fdb6a1b6a394a353fc4ba99af28cf9116a6186
languageName: node
linkType: hard

"@chakra-ui/image@npm:2.0.15":
version: 2.0.15
resolution: "@chakra-ui/image@npm:2.0.15"
Expand Down Expand Up @@ -13923,6 +13947,7 @@ __metadata:
dependencies:
"@bandada/credentials": "npm:2.1.1"
"@bandada/utils": "npm:2.1.1"
"@chakra-ui/icons": "npm:^2.1.1"
"@chakra-ui/react": "npm:^2.5.1"
"@chakra-ui/styled-system": "npm:^2.0.0"
"@chakra-ui/theme-tools": "npm:^2.0.16"
Expand Down

0 comments on commit 011f7b9

Please sign in to comment.