- Notifications
You must be signed in to change notification settings - Fork928
feat: have user type name of thing to delete for extra safety#4080
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
614fc86
0dc2717
cf53085
d52354a
a8a78f0
b8a6c53
ce02bed
06e6e65
2a85c53
0ac54d7
c787fbb
b629274
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { screen } from "@testing-library/react" | ||
import userEvent from "@testing-library/user-event" | ||
import i18next from "i18next" | ||
import { render } from "testHelpers/renderHelpers" | ||
import { DeleteDialog } from "./DeleteDialog" | ||
describe("DeleteDialog", () => { | ||
it("disables confirm button when the text field is empty", () => { | ||
render( | ||
<DeleteDialog | ||
isOpen | ||
onConfirm={jest.fn()} | ||
onCancel={jest.fn()} | ||
entity="template" | ||
name="MyTemplate" | ||
/>, | ||
) | ||
const confirmButton = screen.getByRole("button", { name: "Delete" }) | ||
expect(confirmButton).toBeDisabled() | ||
}) | ||
it("disables confirm button when the text field is filled incorrectly", async () => { | ||
const { t } = i18next | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. ❤️ | ||
render( | ||
<DeleteDialog | ||
isOpen | ||
onConfirm={jest.fn()} | ||
onCancel={jest.fn()} | ||
entity="template" | ||
name="MyTemplate" | ||
/>, | ||
) | ||
const labelText = t("deleteDialog.confirmLabel", { ns: "common", entity: "template" }) | ||
const textField = screen.getByLabelText(labelText) | ||
await userEvent.type(textField, "MyTemplateWrong") | ||
const confirmButton = screen.getByRole("button", { name: "Delete" }) | ||
expect(confirmButton).toBeDisabled() | ||
}) | ||
it("enables confirm button when the text field is filled correctly", async () => { | ||
const { t } = i18next | ||
render( | ||
<DeleteDialog | ||
isOpen | ||
onConfirm={jest.fn()} | ||
onCancel={jest.fn()} | ||
entity="template" | ||
name="MyTemplate" | ||
/>, | ||
) | ||
const labelText = t("deleteDialog.confirmLabel", { ns: "common", entity: "template" }) | ||
const textField = screen.getByLabelText(labelText) | ||
await userEvent.type(textField, "MyTemplate") | ||
const confirmButton = screen.getByRole("button", { name: "Delete" }) | ||
expect(confirmButton).not.toBeDisabled() | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,80 @@ | ||
import FormHelperText from "@material-ui/core/FormHelperText" | ||
import makeStyles from "@material-ui/core/styles/makeStyles" | ||
import TextField from "@material-ui/core/TextField" | ||
import Typography from "@material-ui/core/Typography" | ||
import { Maybe } from "components/Conditionals/Maybe" | ||
import { Stack } from "components/Stack/Stack" | ||
import React, { ChangeEvent, useState } from "react" | ||
import { useTranslation } from "react-i18next" | ||
import { ConfirmDialog } from "../ConfirmDialog/ConfirmDialog" | ||
export interface DeleteDialogProps { | ||
isOpen: boolean | ||
onConfirm: () => void | ||
onCancel: () => void | ||
entity: string | ||
name: string | ||
info?: string | ||
confirmLoading?: boolean | ||
} | ||
export const DeleteDialog: React.FC<React.PropsWithChildren<DeleteDialogProps>> = ({ | ||
isOpen, | ||
onCancel, | ||
onConfirm, | ||
entity, | ||
info, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. What kind of info is this? A description? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Yeah, it's intended to help the user identify the entity to delete, so they don't delete the wrong one by accident.@bpmct suggested this on the basis of an article about making the wrong repo private and thus losing all their github stars. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. | ||
name, | ||
confirmLoading, | ||
}) => { | ||
const styles = useStyles() | ||
const { t } = useTranslation("common") | ||
const [nameValue, setNameValue] = useState("") | ||
const confirmed = name === nameValue | ||
const handleChange = (event: ChangeEvent<HTMLInputElement>) => { | ||
setNameValue(event.target.value) | ||
} | ||
const content = ( | ||
<> | ||
<Typography>{t("deleteDialog.intro", { entity })}</Typography> | ||
<Maybe condition={info !== undefined}> | ||
<Typography className={styles.warning}>{info}</Typography> | ||
</Maybe> | ||
<Typography>{t("deleteDialog.confirm", { entity })}</Typography> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I love how we're not passing whole strings in so that the language will stay consistent. | ||
<Stack spacing={1}> | ||
<TextField | ||
name="confirmation" | ||
id="confirmation" | ||
placeholder={name} | ||
value={nameValue} | ||
onChange={handleChange} | ||
label={t("deleteDialog.confirmLabel", { entity })} | ||
/> | ||
<Maybe condition={nameValue.length > 0 && !confirmed}> | ||
<FormHelperText error>{t("deleteDialog.incorrectName", { entity })}</FormHelperText> | ||
</Maybe> | ||
</Stack> | ||
</> | ||
) | ||
return ( | ||
<ConfirmDialog | ||
type="delete" | ||
hideCancel={false} | ||
open={isOpen} | ||
title={t("deleteDialog.title", { entity })} | ||
onConfirm={onConfirm} | ||
onClose={onCancel} | ||
description={content} | ||
confirmLoading={confirmLoading} | ||
disabled={!confirmed} | ||
/> | ||
) | ||
} | ||
const useStyles = makeStyles((theme) => ({ | ||
warning: { | ||
color: theme.palette.warning.light, | ||
}, | ||
})) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,3 @@ | ||
{ | ||
"deleteSuccess": "Template successfully deleted." | ||
} |
Uh oh!
There was an error while loading.Please reload this page.