diff --git a/site/src/i18n/en/tokensPage.json b/site/src/i18n/en/tokensPage.json index 4a2eaa2fe5ce2..d1bd9c4ca083a 100644 --- a/site/src/i18n/en/tokensPage.json +++ b/site/src/i18n/en/tokensPage.json @@ -6,7 +6,7 @@ "addToken": "Add token", "deleteToken": { "delete": "Delete Token", - "deleteCaption": "Are you sure you want to delete this token?

<4>{{tokenId}}", + "deleteCaption": "Are you sure you want to permanently delete token <4>{{tokenName}}?", "deleteSuccess": "Token has been deleted", "deleteFailure": "Failed to delete token" } diff --git a/site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx b/site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx index d1d0c2e61648f..af4d569824b29 100644 --- a/site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx +++ b/site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx @@ -9,6 +9,7 @@ import { Stack } from "components/Stack/Stack" import Button from "@material-ui/core/Button" import { Link as RouterLink } from "react-router-dom" import AddIcon from "@material-ui/icons/AddOutlined" +import { APIKeyWithOwner } from "api/typesGenerated" export const TokensPage: FC> = () => { const styles = useStyles() @@ -30,9 +31,9 @@ export const TokensPage: FC> = () => { ) - const [tokenIdToDelete, setTokenIdToDelete] = useState( - undefined, - ) + const [tokenToDelete, setTokenToDelete] = useState< + APIKeyWithOwner | undefined + >(undefined) const { data: tokens, @@ -60,15 +61,15 @@ export const TokensPage: FC> = () => { isLoading={isFetching} hasLoaded={isFetched} getTokensError={getTokensError} - onDelete={(id) => { - setTokenIdToDelete(id) + onDelete={(token) => { + setTokenToDelete(token) }} /> ) diff --git a/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx b/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx index f62c70f6e6a23..71d9449371327 100644 --- a/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx +++ b/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx @@ -28,7 +28,7 @@ export interface TokensPageViewProps { getTokensError?: Error | unknown isLoading: boolean hasLoaded: boolean - onDelete: (id: string) => void + onDelete: (token: APIKeyWithOwner) => void deleteTokenError?: Error | unknown } @@ -114,7 +114,7 @@ export const TokensPageView: FC< { - onDelete(token.id) + onDelete(token) }} size="medium" aria-label={t("tokenActions.deleteToken.delete")} diff --git a/site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.stories.tsx b/site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.stories.tsx new file mode 100644 index 0000000000000..6f254680dc167 --- /dev/null +++ b/site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.stories.tsx @@ -0,0 +1,39 @@ +import { Story } from "@storybook/react" +import { MockToken } from "testHelpers/entities" +import { + ConfirmDeleteDialog, + ConfirmDeleteDialogProps, +} from "./ConfirmDeleteDialog" +import { QueryClient, QueryClientProvider } from "@tanstack/react-query" + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + cacheTime: 0, + refetchOnWindowFocus: false, + }, + }, +}) + +export default { + title: "components/ConfirmDeleteDialog", + component: ConfirmDeleteDialog, +} + +const Template: Story = ( + args: ConfirmDeleteDialogProps, +) => ( + + + +) + +export const DeleteDialog = Template.bind({}) +DeleteDialog.args = { + queryKey: ["tokens"], + token: MockToken, + setToken: () => { + return null + }, +} diff --git a/site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.tsx b/site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.tsx index 166836c31668e..90d2477843be5 100644 --- a/site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.tsx +++ b/site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.tsx @@ -4,24 +4,28 @@ import { useTranslation, Trans } from "react-i18next" import { useDeleteToken } from "../hooks" import { displaySuccess, displayError } from "components/GlobalSnackbar/utils" import { getErrorMessage } from "api/errors" +import { APIKeyWithOwner } from "api/typesGenerated" -export const ConfirmDeleteDialog: FC<{ +export interface ConfirmDeleteDialogProps { queryKey: (string | boolean)[] - tokenId: string | undefined - setTokenId: (arg: string | undefined) => void -}> = ({ queryKey, tokenId, setTokenId }) => { - const { t } = useTranslation("tokensPage") + token: APIKeyWithOwner | undefined + setToken: (arg: APIKeyWithOwner | undefined) => void +} +export const ConfirmDeleteDialog: FC = ({ + queryKey, + token, + setToken, +}) => { + const { t } = useTranslation("tokensPage") + const tokenName = token?.token_name const description = ( - Are you sure you want to delete this token? -
-
- {{ tokenId }} + Are you sure you want to permanently delete token {{ tokenName }}?
) @@ -30,7 +34,7 @@ export const ConfirmDeleteDialog: FC<{ const onDeleteSuccess = () => { displaySuccess(t("tokenActions.deleteToken.deleteSuccess")) - setTokenId(undefined) + setToken(undefined) } const onDeleteError = (error: unknown) => { @@ -39,26 +43,27 @@ export const ConfirmDeleteDialog: FC<{ t("tokenActions.deleteToken.deleteFailure"), ) displayError(message) - setTokenId(undefined) + setToken(undefined) } return ( { - if (!tokenId) { + if (!token) { return } - deleteToken(tokenId, { + deleteToken(token.id, { onError: onDeleteError, onSuccess: onDeleteSuccess, }) }} onClose={() => { - setTokenId(undefined) + setToken(undefined) }} /> ) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 01a2ab60cc090..478e841ddd29b 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -37,19 +37,22 @@ export const MockAPIKey: TypesGen.GenerateAPIKeyResponse = { key: "my-api-key", } -export const MockTokens: TypesGen.APIKey[] = [ - { - id: "tBoVE3dqLl", - user_id: "f9ee61d8-1d84-4410-ab6e-c1ec1a641e0b", - last_used: "0001-01-01T00:00:00Z", - expires_at: "2023-01-15T20:10:45.637438Z", - created_at: "2022-12-16T20:10:45.637452Z", - updated_at: "2022-12-16T20:10:45.637452Z", - login_type: "token", - scope: "all", - lifetime_seconds: 2592000, - token_name: "token-one", - }, +export const MockToken: TypesGen.APIKeyWithOwner = { + id: "tBoVE3dqLl", + user_id: "f9ee61d8-1d84-4410-ab6e-c1ec1a641e0b", + last_used: "0001-01-01T00:00:00Z", + expires_at: "2023-01-15T20:10:45.637438Z", + created_at: "2022-12-16T20:10:45.637452Z", + updated_at: "2022-12-16T20:10:45.637452Z", + login_type: "token", + scope: "all", + lifetime_seconds: 2592000, + token_name: "token-one", + username: "admin", +} + +export const MockTokens: TypesGen.APIKeyWithOwner[] = [ + MockToken, { id: "tBoVE3dqLl", user_id: "f9ee61d8-1d84-4410-ab6e-c1ec1a641e0b", @@ -61,6 +64,7 @@ export const MockTokens: TypesGen.APIKey[] = [ scope: "all", lifetime_seconds: 2592000, token_name: "token-two", + username: "admin", }, ]