diff --git a/virtweb_frontend/src/dialogs/CreatedTokenDialog.tsx b/virtweb_frontend/src/dialogs/CreatedTokenDialog.tsx new file mode 100644 index 0000000..b654db9 --- /dev/null +++ b/virtweb_frontend/src/dialogs/CreatedTokenDialog.tsx @@ -0,0 +1,58 @@ +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Typography, +} from "@mui/material"; +import { useNavigate } from "react-router-dom"; +import { APITokenURL, CreatedAPIToken } from "../api/TokensApi"; +import { CopyToClipboard } from "../widgets/CopyToClipboard"; +import { InlineCode } from "../widgets/InlineCode"; + +export function CreatedTokenDialog(p: { + createdToken: CreatedAPIToken; +}): React.ReactElement { + const navigate = useNavigate(); + + const close = () => { + navigate(APITokenURL(p.createdToken.token)); + }; + return ( + + Token successfully created + + + Your token was successfully created. You need now to copy the private + key, as it will be technically impossible to recover it after closing + this dialog. + + + + + + + + + + + ); +} + +function InfoBlock( + p: React.PropsWithChildren<{ label: string; value: string }> +): React.ReactElement { + return ( +
+ {p.label} + + {p.value} + +
+ ); +} diff --git a/virtweb_frontend/src/routes/EditAPITokenRoute.tsx b/virtweb_frontend/src/routes/EditAPITokenRoute.tsx index 4f1358d..7063028 100644 --- a/virtweb_frontend/src/routes/EditAPITokenRoute.tsx +++ b/virtweb_frontend/src/routes/EditAPITokenRoute.tsx @@ -1,7 +1,13 @@ import { Button } from "@mui/material"; import React from "react"; import { useNavigate, useParams } from "react-router-dom"; -import { APIToken, APITokenURL, TokensApi } from "../api/TokensApi"; +import { + APIToken, + APITokenURL, + CreatedAPIToken, + TokensApi, +} from "../api/TokensApi"; +import { CreatedTokenDialog } from "../dialogs/CreatedTokenDialog"; import { useAlert } from "../hooks/providers/AlertDialogProvider"; import { useLoadingMessage } from "../hooks/providers/LoadingMessageProvider"; import { useSnackbar } from "../hooks/providers/SnackbarProvider"; @@ -18,6 +24,10 @@ export function CreateApiTokenRoute(): React.ReactElement { const snackbar = useSnackbar(); const navigate = useNavigate(); + const [createdToken, setCreatedToken] = React.useState< + CreatedAPIToken | undefined + >(); + const [token] = React.useState({ id: "", name: "", @@ -32,8 +42,7 @@ export function CreateApiTokenRoute(): React.ReactElement { try { const res = await TokensApi.Create(n); snackbar("The api token was successfully created!"); - // TODO : show a modal to give token information - navigate(APITokenURL(res.token)); + setCreatedToken(res); } catch (e) { console.error(e); alert(`Failed to create API token!\n${e}`); @@ -41,12 +50,16 @@ export function CreateApiTokenRoute(): React.ReactElement { }; return ( - navigate("/tokens")} - onSave={createApiToken} - /> + <> + {createdToken && } + + navigate("/tokens")} + onSave={createApiToken} + /> + ); } diff --git a/virtweb_frontend/src/widgets/InlineCode.tsx b/virtweb_frontend/src/widgets/InlineCode.tsx new file mode 100644 index 0000000..38c94c5 --- /dev/null +++ b/virtweb_frontend/src/widgets/InlineCode.tsx @@ -0,0 +1,18 @@ +export function InlineCode(p: React.PropsWithChildren): React.ReactElement { + return ( + + {p.children} + + ); +} diff --git a/virtweb_frontend/src/widgets/net/NetworkHookStatusWidget.tsx b/virtweb_frontend/src/widgets/net/NetworkHookStatusWidget.tsx index 191ca7d..b5d2237 100644 --- a/virtweb_frontend/src/widgets/net/NetworkHookStatusWidget.tsx +++ b/virtweb_frontend/src/widgets/net/NetworkHookStatusWidget.tsx @@ -3,6 +3,7 @@ import React, { PropsWithChildren } from "react"; import { NetworkHookStatus, ServerApi } from "../../api/ServerApi"; import { AsyncWidget } from "../AsyncWidget"; import { CopyToClipboard } from "../CopyToClipboard"; +import { InlineCode } from "../InlineCode"; export function NetworkHookStatusWidget(p: { hiddenIfInstalled: boolean; @@ -72,25 +73,6 @@ function NetworkHookStatusWidgetInner(p: { ); } -function InlineCode(p: PropsWithChildren): React.ReactElement { - return ( - - {p.children} - - ); -} - function CodeBlock(p: PropsWithChildren): React.ReactElement { return (