Skip to content

Commit 5b07f1e

Browse files
authored
feat(tokens): improve delete confirmation dialog (#6651)
1 parent db40c29 commit 5b07f1e

File tree

6 files changed

+88
-39
lines changed

6 files changed

+88
-39
lines changed

site/src/i18n/en/tokensPage.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"addToken": "Add token",
77
"deleteToken": {
88
"delete": "Delete Token",
9-
"deleteCaption": "Are you sure you want to delete this token?<br/><br/><4>{{tokenId}}</4>",
9+
"deleteCaption": "Are you sure you want to permanently delete token <strong><4>{{tokenName}}</4></strong>?",
1010
"deleteSuccess": "Token has been deleted",
1111
"deleteFailure": "Failed to delete token"
1212
}

site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Stack } from "components/Stack/Stack"
99
import Button from "@material-ui/core/Button"
1010
import { Link as RouterLink } from "react-router-dom"
1111
import AddIcon from "@material-ui/icons/AddOutlined"
12+
import { APIKeyWithOwner } from "api/typesGenerated"
1213

1314
export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
1415
const styles = useStyles()
@@ -30,9 +31,9 @@ export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
3031
</Stack>
3132
)
3233

33-
const [tokenIdToDelete, setTokenIdToDelete] = useState<string | undefined>(
34-
undefined,
35-
)
34+
const [tokenToDelete, setTokenToDelete] = useState<
35+
APIKeyWithOwner | undefined
36+
>(undefined)
3637

3738
const {
3839
data: tokens,
@@ -60,15 +61,15 @@ export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
6061
isLoading={isFetching}
6162
hasLoaded={isFetched}
6263
getTokensError={getTokensError}
63-
onDelete={(id) => {
64-
setTokenIdToDelete(id)
64+
onDelete={(token) => {
65+
setTokenToDelete(token)
6566
}}
6667
/>
6768
</Section>
6869
<ConfirmDeleteDialog
6970
queryKey={queryKey}
70-
tokenId={tokenIdToDelete}
71-
setTokenId={setTokenIdToDelete}
71+
token={tokenToDelete}
72+
setToken={setTokenToDelete}
7273
/>
7374
</>
7475
)

site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface TokensPageViewProps {
2828
getTokensError?: Error | unknown
2929
isLoading: boolean
3030
hasLoaded: boolean
31-
onDelete: (id: string) => void
31+
onDelete: (token: APIKeyWithOwner) => void
3232
deleteTokenError?: Error | unknown
3333
}
3434

@@ -114,7 +114,7 @@ export const TokensPageView: FC<
114114
<span style={{ color: theme.palette.text.secondary }}>
115115
<IconButton
116116
onClick={() => {
117-
onDelete(token.id)
117+
onDelete(token)
118118
}}
119119
size="medium"
120120
aria-label={t("tokenActions.deleteToken.delete")}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Story } from "@storybook/react"
2+
import { MockToken } from "testHelpers/entities"
3+
import {
4+
ConfirmDeleteDialog,
5+
ConfirmDeleteDialogProps,
6+
} from "./ConfirmDeleteDialog"
7+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
8+
9+
const queryClient = new QueryClient({
10+
defaultOptions: {
11+
queries: {
12+
retry: false,
13+
cacheTime: 0,
14+
refetchOnWindowFocus: false,
15+
},
16+
},
17+
})
18+
19+
export default {
20+
title: "components/ConfirmDeleteDialog",
21+
component: ConfirmDeleteDialog,
22+
}
23+
24+
const Template: Story<ConfirmDeleteDialogProps> = (
25+
args: ConfirmDeleteDialogProps,
26+
) => (
27+
<QueryClientProvider client={queryClient}>
28+
<ConfirmDeleteDialog {...args} />
29+
</QueryClientProvider>
30+
)
31+
32+
export const DeleteDialog = Template.bind({})
33+
DeleteDialog.args = {
34+
queryKey: ["tokens"],
35+
token: MockToken,
36+
setToken: () => {
37+
return null
38+
},
39+
}

site/src/pages/UserSettingsPage/TokensPage/components/ConfirmDeleteDialog.tsx

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,28 @@ import { useTranslation, Trans } from "react-i18next"
44
import { useDeleteToken } from "../hooks"
55
import { displaySuccess, displayError } from "components/GlobalSnackbar/utils"
66
import { getErrorMessage } from "api/errors"
7+
import { APIKeyWithOwner } from "api/typesGenerated"
78

8-
export const ConfirmDeleteDialog: FC<{
9+
export interface ConfirmDeleteDialogProps {
910
queryKey: (string | boolean)[]
10-
tokenId: string | undefined
11-
setTokenId: (arg: string | undefined) => void
12-
}> = ({ queryKey, tokenId, setTokenId }) => {
13-
const { t } = useTranslation("tokensPage")
11+
token: APIKeyWithOwner | undefined
12+
setToken: (arg: APIKeyWithOwner | undefined) => void
13+
}
1414

15+
export const ConfirmDeleteDialog: FC<ConfirmDeleteDialogProps> = ({
16+
queryKey,
17+
token,
18+
setToken,
19+
}) => {
20+
const { t } = useTranslation("tokensPage")
21+
const tokenName = token?.token_name
1522
const description = (
1623
<Trans
1724
t={t}
1825
i18nKey="tokenActions.deleteToken.deleteCaption"
19-
values={{ tokenId }}
26+
values={{ tokenName }}
2027
>
21-
Are you sure you want to delete this token?
22-
<br />
23-
<br />
24-
{{ tokenId }}
28+
Are you sure you want to permanently delete token {{ tokenName }}?
2529
</Trans>
2630
)
2731

@@ -30,7 +34,7 @@ export const ConfirmDeleteDialog: FC<{
3034

3135
const onDeleteSuccess = () => {
3236
displaySuccess(t("tokenActions.deleteToken.deleteSuccess"))
33-
setTokenId(undefined)
37+
setToken(undefined)
3438
}
3539

3640
const onDeleteError = (error: unknown) => {
@@ -39,26 +43,27 @@ export const ConfirmDeleteDialog: FC<{
3943
t("tokenActions.deleteToken.deleteFailure"),
4044
)
4145
displayError(message)
42-
setTokenId(undefined)
46+
setToken(undefined)
4347
}
4448

4549
return (
4650
<ConfirmDialog
51+
type="delete"
4752
title={t("tokenActions.deleteToken.delete")}
4853
description={description}
49-
open={Boolean(tokenId) || isDeleting}
54+
open={Boolean(token) || isDeleting}
5055
confirmLoading={isDeleting}
5156
onConfirm={() => {
52-
if (!tokenId) {
57+
if (!token) {
5358
return
5459
}
55-
deleteToken(tokenId, {
60+
deleteToken(token.id, {
5661
onError: onDeleteError,
5762
onSuccess: onDeleteSuccess,
5863
})
5964
}}
6065
onClose={() => {
61-
setTokenId(undefined)
66+
setToken(undefined)
6267
}}
6368
/>
6469
)

site/src/testHelpers/entities.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,22 @@ export const MockAPIKey: TypesGen.GenerateAPIKeyResponse = {
3737
key: "my-api-key",
3838
}
3939

40-
export const MockTokens: TypesGen.APIKey[] = [
41-
{
42-
id: "tBoVE3dqLl",
43-
user_id: "f9ee61d8-1d84-4410-ab6e-c1ec1a641e0b",
44-
last_used: "0001-01-01T00:00:00Z",
45-
expires_at: "2023-01-15T20:10:45.637438Z",
46-
created_at: "2022-12-16T20:10:45.637452Z",
47-
updated_at: "2022-12-16T20:10:45.637452Z",
48-
login_type: "token",
49-
scope: "all",
50-
lifetime_seconds: 2592000,
51-
token_name: "token-one",
52-
},
40+
export const MockToken: TypesGen.APIKeyWithOwner = {
41+
id: "tBoVE3dqLl",
42+
user_id: "f9ee61d8-1d84-4410-ab6e-c1ec1a641e0b",
43+
last_used: "0001-01-01T00:00:00Z",
44+
expires_at: "2023-01-15T20:10:45.637438Z",
45+
created_at: "2022-12-16T20:10:45.637452Z",
46+
updated_at: "2022-12-16T20:10:45.637452Z",
47+
login_type: "token",
48+
scope: "all",
49+
lifetime_seconds: 2592000,
50+
token_name: "token-one",
51+
username: "admin",
52+
}
53+
54+
export const MockTokens: TypesGen.APIKeyWithOwner[] = [
55+
MockToken,
5356
{
5457
id: "tBoVE3dqLl",
5558
user_id: "f9ee61d8-1d84-4410-ab6e-c1ec1a641e0b",
@@ -61,6 +64,7 @@ export const MockTokens: TypesGen.APIKey[] = [
6164
scope: "all",
6265
lifetime_seconds: 2592000,
6366
token_name: "token-two",
67+
username: "admin",
6468
},
6569
]
6670

0 commit comments

Comments
 (0)