diff --git a/public/locales/en-US/settings-api-keys.json b/public/locales/en-US/settings-api-keys.json new file mode 100644 index 0000000..fe1a5d7 --- /dev/null +++ b/public/locales/en-US/settings-api-keys.json @@ -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." + } +} diff --git a/public/locales/en-US/settings.json b/public/locales/en-US/settings.json index 3f70247..756d4aa 100644 --- a/public/locales/en-US/settings.json +++ b/public/locales/en-US/settings.json @@ -3,6 +3,6 @@ "actions": { "enable2fa": "Two-Factor-Authentication", "aliasPreferences": "Alias Preferences", - "apiKeys": "Edit API Keys" + "apiKeys": "Manage API Keys" } } diff --git a/src/App.tsx b/src/App.tsx index c54ecea..c58c86c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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: , }, + { + path: "/settings/api-keys", + element: , + }, { path: "/reports", loader: getServerSettings, diff --git a/src/route-widgets/SettingsAPIKeysRoute/APIKeyListItem.tsx b/src/route-widgets/SettingsAPIKeysRoute/APIKeyListItem.tsx new file mode 100644 index 0000000..93e9783 --- /dev/null +++ b/src/route-widgets/SettingsAPIKeysRoute/APIKeyListItem.tsx @@ -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 ( + + + + + + + + + ) +} diff --git a/src/route-widgets/SettingsAPIKeysRoute/EmptyStateScreen.tsx b/src/route-widgets/SettingsAPIKeysRoute/EmptyStateScreen.tsx new file mode 100644 index 0000000..196144b --- /dev/null +++ b/src/route-widgets/SettingsAPIKeysRoute/EmptyStateScreen.tsx @@ -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 ( + + + + + {t("emptyState.title")} + + + + + + + {t("emptyState.description")} + + + + ) +} diff --git a/src/routes/SettingsAPIKeysRoute.tsx b/src/routes/SettingsAPIKeysRoute.tsx new file mode 100644 index 0000000..82d9ab8 --- /dev/null +++ b/src/routes/SettingsAPIKeysRoute.tsx @@ -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, AxiosError>(["get_api_keys"], () => + getAPIKeys(), + ) + + return ( + + {t("create.label")} + + } + > + , AxiosError> query={query}> + {({items: apiKeys}) => + apiKeys.length > 0 ? ( + + {apiKeys.map(apiKey => ( + + ))} + + ) : ( + + ) + } + + + ) +} diff --git a/src/server-types.ts b/src/server-types.ts index 62642c7..6046098 100644 --- a/src/server-types.ts +++ b/src/server-types.ts @@ -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