diff --git a/cypress/elements/shared/unsavedChangesDialog.js b/cypress/elements/shared/unsavedChangesDialog.js index f2f58799a..3452a3e9d 100644 --- a/cypress/elements/shared/unsavedChangesDialog.js +++ b/cypress/elements/shared/unsavedChangesDialog.js @@ -1,4 +1,4 @@ export const UNSAVED_CHANGES_DIALOG = { - leaveWithoutSavingButton: '[data-test-id="leave-without-saving"]', - saveAndContinueButton: '[data-test-id="save-and-continue"]' + keepEditingButton: '[data-test-id="keep-editing"]', + ignoreChangesButton: '[data-test-id="ignore-changes"]', }; diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index ee2982193..ec4c77ea7 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -464,10 +464,6 @@ "1div9r": { "string": "Search Attribute" }, - "1eEyJv": { - "context": "ExitFormPrompt continue editing button", - "string": "Continue editing" - }, "1gzck6": { "string": "{firstName} {lastName}" }, @@ -2164,10 +2160,6 @@ "context": "option title", "string": "Prioritize warehouses by sorting order" }, - "FWWliu": { - "context": "ExitFormPrompt title", - "string": "You have unsaved changes" - }, "FYfoiF": { "context": "section name", "string": "Allocation strategy" @@ -3094,10 +3086,6 @@ "context": "table column header", "string": "Channel threshold" }, - "MPOj0I": { - "context": "ExitFormPrompt confirm button", - "string": "Save changes" - }, "MPfyne": { "string": "Are you sure you want to send this invoice: {invoiceNumber} to the customer?" }, @@ -4086,10 +4074,6 @@ "context": "navigator placeholder", "string": "Search Customer" }, - "TtZg/K": { - "context": "ExitFormPrompt title", - "string": "Would you like to save changes?" - }, "U1eJIw": { "context": "order history message", "string": "Products were added to an order" @@ -5187,6 +5171,10 @@ "context": "ProductTypeDeleteWarningDialog single consent label", "string": "Yes, I want to delete this product type and assigned products" }, + "blZJmA": { + "context": "ExitFormPrompt ignore changes button", + "string": "Ignore changes" + }, "bp/i0x": { "context": "header", "string": "Quantity" @@ -5223,6 +5211,10 @@ "c4gbXr": { "string": "Draft order successfully finalized" }, + "c5fFin": { + "context": "ExitFormPrompt title", + "string": "Leave without saving changes?" + }, "c5pMZ8": { "string": "API error" }, @@ -7137,10 +7129,6 @@ "context": "table header column", "string": "Show gross prices in storefront" }, - "sn2awN": { - "context": "ExitFormPrompt cancel button", - "string": "Discard changes" - }, "snUby7": { "context": "header", "string": "Unnamed Webhook Details" @@ -7855,6 +7843,10 @@ "context": "delete shipping method", "string": "Are you sure you want to delete {name}?" }, + "ySqncG": { + "context": "ExitFormPrompt keep editing button", + "string": "Keep editing" + }, "ySqrUU": { "context": "button", "string": "Assign variants" diff --git a/src/components/Form/ExitFormDialog.test.tsx b/src/components/Form/ExitFormDialog.test.tsx new file mode 100644 index 000000000..3c7edc77a --- /dev/null +++ b/src/components/Form/ExitFormDialog.test.tsx @@ -0,0 +1,53 @@ +import { render } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import React from "react"; + +import ExitFormDialog from "./ExitFormDialog"; + +jest.mock("react-intl", () => ({ + useIntl: jest.fn(() => ({ + formatMessage: jest.fn(x => x.defaultMessage), + })), + defineMessages: jest.fn(x => x), +})); + +jest.mock("@saleor/macaw-ui", () => ({ + useStyles: jest.fn(() => () => ({})), + makeStyles: jest.fn(() => () => ({})), + DialogHeader: jest.fn(() => () => <>), +})); + +describe("ExitFormDialog", () => { + it("closes when ignore changes is clicked", async () => { + // Arrange + const props = { + onClose: jest.fn(), + onLeave: jest.fn(), + isOpen: true, + }; + const user = userEvent.setup(); + + // Act + const { getByTestId } = render(); + await user.click(getByTestId("ignore-changes")); + + // Assert + expect(props.onLeave).toHaveBeenCalled(); + }); + it("closes when keep editing is clicked", async () => { + // Arrange + const props = { + onClose: jest.fn(), + onLeave: jest.fn(), + isOpen: true, + }; + const user = userEvent.setup(); + + // Act + const { getByTestId } = render(); + await user.click(getByTestId("keep-editing")); + + // Assert + expect(props.onClose).toHaveBeenCalled(); + }); +}); diff --git a/src/components/Form/ExitFormDialog.tsx b/src/components/Form/ExitFormDialog.tsx index f48587b62..b309c191c 100644 --- a/src/components/Form/ExitFormDialog.tsx +++ b/src/components/Form/ExitFormDialog.tsx @@ -1,6 +1,6 @@ import { Button, Dialog, DialogContent, makeStyles } from "@material-ui/core"; import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer"; -import CardTitle from "@saleor/components/CardTitle"; +import { DialogHeader } from "@saleor/macaw-ui"; import React from "react"; import { useIntl } from "react-intl"; @@ -30,47 +30,37 @@ const useStyles = makeStyles( ); interface ExitFormDialogProps { - onSubmit: () => void; onClose: () => void; onLeave: () => void; isOpen: boolean; - isSubmitDisabled: boolean; } const ExitFormDialog: React.FC = ({ - onSubmit, onLeave, onClose, isOpen, - isSubmitDisabled, }) => { const classes = useStyles(); const intl = useIntl(); return ( - + + {intl.formatMessage(messages.unableToSaveTitle)} +
-
diff --git a/src/components/Form/ExitFormDialogProvider.tsx b/src/components/Form/ExitFormDialogProvider.tsx index c8d0ccee5..e23b1e2fb 100644 --- a/src/components/Form/ExitFormDialogProvider.tsx +++ b/src/components/Form/ExitFormDialogProvider.tsx @@ -13,7 +13,6 @@ export interface ExitFormDialogData { setEnableExitDialog: (value: boolean) => void; shouldBlockNavigation: () => boolean; setIsSubmitting: (value: boolean) => void; - submit: () => SubmitPromise; leave: () => void; setIsSubmitDisabled: (value: boolean) => void; } @@ -41,7 +40,6 @@ export const ExitFormDialogContext = React.createContext({ setExitDialogSubmitRef: () => undefined, shouldBlockNavigation: () => false, setIsSubmitting: () => undefined, - submit: () => Promise.resolve([]), leave: () => undefined, setIsSubmitDisabled: () => undefined, }); @@ -51,7 +49,6 @@ const defaultValues = { showDialog: false, blockNav: true, navAction: null, - submit: null, enableExitDialog: false, isSubmitting: false, formsData: {}, @@ -203,37 +200,6 @@ export function useExitFormDialogProvider() { setStateDefaultValues(); }; - const getDirtyFormsSubmitFn = () => - getFormsDataValuesArray() - .filter(({ isDirty }) => isDirty) - .map(({ submitFn }) => submitFn); - - const hasAnySubmitFn = () => - getFormsDataValuesArray().some(({ submitFn }) => !!submitFn); - - const handleSubmit = async () => { - if (!hasAnySubmitFn()) { - return; - } - - setShowDialog(false); - setIsSubmitting(true); - - const errors = await Promise.all( - getDirtyFormsSubmitFn().map(submitFn => submitFn()), - ); - - setIsSubmitting(false); - - const isError = errors.flat().some(errors => errors); - - if (!isError) { - continueNavigation(); - } - - setDefaultNavAction(); - }; - const handleLeave = () => { continueNavigation(); }; @@ -253,7 +219,6 @@ export function useExitFormDialogProvider() { setEnableExitDialog, setExitDialogSubmitRef: setSubmitRef, setIsSubmitting, - submit: handleSubmit, setIsSubmitDisabled, leave: handleLeave, }; @@ -261,7 +226,6 @@ export function useExitFormDialogProvider() { return { providerData, showDialog, - handleSubmit, handleLeave, handleClose, shouldBlockNav, @@ -273,11 +237,9 @@ const ExitFormDialogProvider = ({ children }) => { const { handleClose, handleLeave, - handleSubmit, providerData, showDialog, shouldBlockNav, - isSubmitDisabled, } = useExitFormDialogProvider(); useBeforeUnload(e => { @@ -293,10 +255,8 @@ const ExitFormDialogProvider = ({ children }) => { {children} diff --git a/src/components/Form/messages.ts b/src/components/Form/messages.ts index 0246e3f35..f0f674d2c 100644 --- a/src/components/Form/messages.ts +++ b/src/components/Form/messages.ts @@ -1,29 +1,19 @@ import { defineMessages } from "react-intl"; export const exitFormPromptMessages = defineMessages({ - title: { - id: "TtZg/K", - defaultMessage: "Would you like to save changes?", - description: "ExitFormPrompt title", - }, unableToSaveTitle: { - id: "FWWliu", - defaultMessage: "You have unsaved changes", + id: "c5fFin", + defaultMessage: "Leave without saving changes?", description: "ExitFormPrompt title", }, - cancelButton: { - id: "sn2awN", - defaultMessage: "Discard changes", - description: "ExitFormPrompt cancel button", + keepEditing: { + id: "ySqncG", + defaultMessage: "Keep editing", + description: "ExitFormPrompt keep editing button", }, - confirmButton: { - id: "MPOj0I", - defaultMessage: "Save changes", - description: "ExitFormPrompt confirm button", - }, - continueEditingButton: { - id: "1eEyJv", - defaultMessage: "Continue editing", - description: "ExitFormPrompt continue editing button", + ignoreChanges: { + id: "blZJmA", + defaultMessage: "Ignore changes", + description: "ExitFormPrompt ignore changes button", }, }); diff --git a/src/components/Form/useExitFormDialog.test.tsx b/src/components/Form/useExitFormDialog.test.tsx index 5ae3c7da7..fd147238a 100644 --- a/src/components/Form/useExitFormDialog.test.tsx +++ b/src/components/Form/useExitFormDialog.test.tsx @@ -86,71 +86,6 @@ describe("useExitFormDialog", () => { expect(result.current.exit.shouldBlockNavigation()).toBe(false); expect(result.current.history.location.pathname).toBe(targetPath); }); - - it("blocks navigation if an error occured", async () => { - // Given - const submitFn = jest.fn(() => - Promise.resolve([{ field: "field", code: "code" }]), - ); - const { result } = setup(submitFn); - - // When - act(() => { - result.current.form.change({ - target: { name: "field", value: "something" }, - }); - result.current.history.push(targetPath); - }); - await act(() => result.current.exit.submit()); - - // Then - expect(result.current.history.location.pathname).toBe(initialPath); - }); - - it("allows navigation if an error occured, but confirmation is not needed", async () => { - // Given - const submitFn = jest.fn(() => - Promise.resolve([{ field: "field", code: "code" }]), - ); - const { result } = setup(submitFn, false); - - // When - act(() => { - result.current.form.change({ - target: { name: "field", value: "something" }, - }); - result.current.history.push(targetPath); - }); - await act(() => result.current.exit.submit()); - - // Then - expect(result.current.history.location.pathname).toBe(targetPath); - }); - - it("blocks navigation if an error occured and user tries to leave anyway", async () => { - // Given - const submitFn = jest.fn(() => - Promise.resolve([{ field: "field", code: "code" }]), - ); - const { result } = setup(submitFn); - - // When - act(() => { - result.current.form.change({ - target: { name: "field", value: "something" }, - }); - result.current.history.push(targetPath); - }); - await act(() => result.current.exit.submit()); - act(() => { - result.current.history.push(targetPath); - }); - - // Then - expect(result.current.exit.shouldBlockNavigation()).toBe(true); - expect(result.current.history.location.pathname).toBe(initialPath); - }); - it("navigates to full url with querystring", async () => { // Given const submitFn = jest.fn(() => Promise.resolve([]));