mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-18 23:45:26 +02:00
feat(api-keys): Add API overview
This commit is contained in:
parent
7cd798a343
commit
eeb6ba4892
10
public/locales/en-US/settings-api-keys.json
Normal file
10
public/locales/en-US/settings-api-keys.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": "Manage your API Keys",
|
||||
"create": {
|
||||
"label": "Create a new API Key"
|
||||
},
|
||||
"emptyState": {
|
||||
"title": "Welcome to your API Keys",
|
||||
"description": "Create an API Key to get started with the API."
|
||||
}
|
||||
}
|
@ -3,6 +3,6 @@
|
||||
"actions": {
|
||||
"enable2fa": "Two-Factor-Authentication",
|
||||
"aliasPreferences": "Alias Preferences",
|
||||
"apiKeys": "Edit API Keys"
|
||||
"apiKeys": "Manage API Keys"
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import ReservedAliasDetailRoute from "~/routes/ReservedAliasDetailRoute"
|
||||
import ReservedAliasesRoute from "~/routes/ReservedAliasesRoute"
|
||||
import RootRoute from "~/routes/Root"
|
||||
import Settings2FARoute from "~/routes/Settings2FARoute"
|
||||
import SettingsAPIKeysRoute from "~/routes/SettingsAPIKeysRoute"
|
||||
import SettingsAliasPreferencesRoute from "~/routes/SettingsAliasPreferencesRoute"
|
||||
import SettingsRoute from "~/routes/SettingsRoute"
|
||||
import SignupRoute from "~/routes/SignupRoute"
|
||||
@ -105,6 +106,10 @@ const router = createBrowserRouter([
|
||||
path: "/settings/2fa",
|
||||
element: <Settings2FARoute />,
|
||||
},
|
||||
{
|
||||
path: "/settings/api-keys",
|
||||
element: <SettingsAPIKeysRoute />,
|
||||
},
|
||||
{
|
||||
path: "/reports",
|
||||
loader: getServerSettings,
|
||||
|
24
src/route-widgets/SettingsAPIKeysRoute/APIKeyListItem.tsx
Normal file
24
src/route-widgets/SettingsAPIKeysRoute/APIKeyListItem.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import {ReactElement} from "react"
|
||||
import {APIKey} from "~/server-types"
|
||||
import {IconButton, ListItem, ListItemSecondaryAction, ListItemText} from "@mui/material"
|
||||
import {useTranslation} from "react-i18next"
|
||||
import {MdDelete} from "react-icons/md"
|
||||
|
||||
export interface APIKeyListItemProps {
|
||||
apiKey: APIKey
|
||||
}
|
||||
|
||||
export default function APIKeyListItem({apiKey}: APIKeyListItemProps): ReactElement {
|
||||
const {t} = useTranslation("settings-api-keys")
|
||||
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemText primary={apiKey.label} secondary={apiKey.expiresAt.toString()} />
|
||||
<ListItemSecondaryAction>
|
||||
<IconButton edge="end">
|
||||
<MdDelete />
|
||||
</IconButton>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
)
|
||||
}
|
35
src/route-widgets/SettingsAPIKeysRoute/EmptyStateScreen.tsx
Normal file
35
src/route-widgets/SettingsAPIKeysRoute/EmptyStateScreen.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import {ReactElement} from "react"
|
||||
import {useTranslation} from "react-i18next"
|
||||
|
||||
import {Container, Grid, Typography} from "@mui/material"
|
||||
import {MdVpnKey} from "react-icons/md"
|
||||
|
||||
export default function EmptyStateScreen(): ReactElement {
|
||||
const {t} = useTranslation("settings-api-keys")
|
||||
|
||||
return (
|
||||
<Container maxWidth="xs">
|
||||
<Grid
|
||||
container
|
||||
spacing={4}
|
||||
direction="column"
|
||||
alignItems="center"
|
||||
maxWidth="80%"
|
||||
alignSelf="center"
|
||||
marginX="auto"
|
||||
>
|
||||
<Grid item>
|
||||
<Typography variant="h6" component="h2">
|
||||
{t("emptyState.title")}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<MdVpnKey size={40} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="body1">{t("emptyState.description")}</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
)
|
||||
}
|
48
src/routes/SettingsAPIKeysRoute.tsx
Normal file
48
src/routes/SettingsAPIKeysRoute.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import {ReactElement} from "react"
|
||||
import {useTranslation} from "react-i18next"
|
||||
import {useQuery} from "@tanstack/react-query"
|
||||
import {APIKey, PaginationResult} from "~/server-types"
|
||||
import {AxiosError} from "axios"
|
||||
import {getAPIKeys} from "~/apis"
|
||||
import {QueryResult, SimplePage} from "~/components"
|
||||
import {Button, List} from "@mui/material"
|
||||
import {Link} from "react-router-dom"
|
||||
import APIKeyListItem from "~/route-widgets/SettingsAPIKeysRoute/APIKeyListItem"
|
||||
import EmptyStateScreen from "~/route-widgets/SettingsAPIKeysRoute/EmptyStateScreen"
|
||||
|
||||
export default function SettingsAPIKeysRoute(): ReactElement {
|
||||
const {t} = useTranslation("settings-api-keys")
|
||||
const query = useQuery<PaginationResult<APIKey>, AxiosError>(["get_api_keys"], () =>
|
||||
getAPIKeys(),
|
||||
)
|
||||
|
||||
return (
|
||||
<SimplePage
|
||||
title={t("title")}
|
||||
actions={
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
component={Link}
|
||||
to="/settings/api-keys/new"
|
||||
>
|
||||
{t("create.label")}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<QueryResult<PaginationResult<APIKey>, AxiosError> query={query}>
|
||||
{({items: apiKeys}) =>
|
||||
apiKeys.length > 0 ? (
|
||||
<List>
|
||||
{apiKeys.map(apiKey => (
|
||||
<APIKeyListItem apiKey={apiKey} key={apiKey.id} />
|
||||
))}
|
||||
</List>
|
||||
) : (
|
||||
<EmptyStateScreen />
|
||||
)
|
||||
}
|
||||
</QueryResult>
|
||||
</SimplePage>
|
||||
)
|
||||
}
|
@ -141,6 +141,13 @@ export interface AliasList {
|
||||
type: AliasType
|
||||
}
|
||||
|
||||
export interface APIKey {
|
||||
id: string
|
||||
label: string
|
||||
expiresAt: Date
|
||||
scopes: string[]
|
||||
}
|
||||
|
||||
export interface Report {
|
||||
id: string
|
||||
encryptedContent: string
|
||||
|
Loading…
x
Reference in New Issue
Block a user