feat(api-key): Add delete functionality

This commit is contained in:
Myzel394 2023-03-11 12:42:04 +01:00
parent dace44f1d9
commit 9605fafe54
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
5 changed files with 62 additions and 18 deletions

View File

@ -61,7 +61,8 @@
"deleted": "Report has been deleted!" "deleted": "Report has been deleted!"
}, },
"apiKey": { "apiKey": {
"keyCopied": "API key has been copied to your clipboard!" "keyCopied": "API key has been copied to your clipboard!",
"deleted": "API key has been deleted!"
} }
}, },
"general": { "general": {

View File

@ -31,5 +31,12 @@
"emptyState": { "emptyState": {
"title": "Welcome to your API Keys", "title": "Welcome to your API Keys",
"description": "Create an API Key to get started with the API." "description": "Create an API Key to get started with the API."
},
"actions": {
"delete": {
"label": "Delete API Key",
"description": "Are you sure you want to delete this API Key? Your existing integrations using this API Key will stop working. You can create a new API Key to replace it.",
"continueActionLabel": "Delete API Key"
}
} }
} }

View File

@ -1,6 +1,7 @@
import {client} from "~/constants/axios-client" import {client} from "~/constants/axios-client"
import {SimpleDetailResponse} from "~/server-types"
export default async function deleteApiKey(id: string): Promise<void> { export default async function deleteAPIKey(id: string): Promise<SimpleDetailResponse> {
const {data} = await client.delete(`${import.meta.env.VITE_SERVER_BASE_URL}/v1/api-key/${id}`, { const {data} = await client.delete(`${import.meta.env.VITE_SERVER_BASE_URL}/v1/api-key/${id}`, {
withCredentials: true, withCredentials: true,
}) })

View File

@ -25,6 +25,8 @@ export interface DeleteAPIButtonProps {
description?: string description?: string
successMessage?: string successMessage?: string
navigateTo?: string navigateTo?: string
children?: (onDelete: () => void) => ReactElement
onDone?: () => void
} }
export default function DeleteAPIButton({ export default function DeleteAPIButton({
@ -33,7 +35,9 @@ export default function DeleteAPIButton({
label, label,
continueLabel, continueLabel,
description, description,
navigateTo = "/aliases", navigateTo,
onDone,
children: render,
}: DeleteAPIButtonProps): ReactElement { }: DeleteAPIButtonProps): ReactElement {
const {t} = useTranslation("common") const {t} = useTranslation("common")
const {showError, showSuccess} = useErrorSuccessSnacks() const {showError, showSuccess} = useErrorSuccessSnacks()
@ -43,7 +47,12 @@ export default function DeleteAPIButton({
onError: showError, onError: showError,
onSuccess: () => { onSuccess: () => {
showSuccess(successMessage || t("messages.deletedObject")) showSuccess(successMessage || t("messages.deletedObject"))
navigate(navigateTo)
if (navigateTo) {
navigate(navigateTo)
} else if (onDone) {
onDone()
}
}, },
}) })
@ -51,15 +60,19 @@ export default function DeleteAPIButton({
return ( return (
<> <>
<Button {render ? (
variant="outlined" render(() => setShowDeleteDialog(true))
color="error" ) : (
size="small" <Button
startIcon={<MdDelete />} variant="outlined"
onClick={() => setShowDeleteDialog(true)} color="error"
> size="small"
{label} startIcon={<MdDelete />}
</Button> onClick={() => setShowDeleteDialog(true)}
>
{label}
</Button>
)}
<Dialog open={showDeleteDialog} onClose={() => setShowDeleteDialog(false)}> <Dialog open={showDeleteDialog} onClose={() => setShowDeleteDialog(false)}>
<DialogTitle>{label}</DialogTitle> <DialogTitle>{label}</DialogTitle>
<DialogContent> <DialogContent>

View File

@ -4,14 +4,21 @@ import {Alert, IconButton, ListItem, ListItemSecondaryAction, ListItemText} from
import {useTranslation} from "react-i18next" import {useTranslation} from "react-i18next"
import {MdContentCopy, MdDelete} from "react-icons/md" import {MdContentCopy, MdDelete} from "react-icons/md"
import {useCopyToClipboard} from "react-use" import {useCopyToClipboard} from "react-use"
import {ErrorSnack, SuccessSnack} from "~/components" import {DeleteButton, ErrorSnack, SuccessSnack} from "~/components"
import {deleteAPIKey} from "~/apis"
import {queryClient} from "~/constants/react-query"
export interface APIKeyListItemProps { export interface APIKeyListItemProps {
apiKey: APIKey apiKey: APIKey
queryKey: readonly string[]
privateKey?: string privateKey?: string
} }
export default function APIKeyListItem({apiKey, privateKey}: APIKeyListItemProps): ReactElement { export default function APIKeyListItem({
queryKey,
apiKey,
privateKey,
}: APIKeyListItemProps): ReactElement {
const {t} = useTranslation(["settings-api-keys", "common"]) const {t} = useTranslation(["settings-api-keys", "common"])
const [{value, error}, copy] = useCopyToClipboard() const [{value, error}, copy] = useCopyToClipboard()
@ -43,9 +50,24 @@ export default function APIKeyListItem({apiKey, privateKey}: APIKeyListItemProps
<> <>
<ListItemText primary={apiKey.label} secondary={apiKey.expiresAt.toString()} /> <ListItemText primary={apiKey.label} secondary={apiKey.expiresAt.toString()} />
<ListItemSecondaryAction> <ListItemSecondaryAction>
<IconButton edge="end"> <DeleteButton
<MdDelete /> onDelete={() => deleteAPIKey(apiKey.id)}
</IconButton> onDone={() =>
queryClient.invalidateQueries({
queryKey,
})
}
label={t("actions.delete.label")}
description={t("actions.delete.description")}
continueLabel={t("actions.delete.continueActionLabel")}
successMessage={t("messages.apiKey.deleted", {ns: "common"})}
>
{onDelete => (
<IconButton edge="end" onClick={onDelete}>
<MdDelete />
</IconButton>
)}
</DeleteButton>
</ListItemSecondaryAction> </ListItemSecondaryAction>
</> </>
</ListItem> </ListItem>