Remove isDevelopment
flag and cleanup a code in Form component (#2912)
This commit is contained in:
parent
1c0076a0db
commit
c60f6f870c
14 changed files with 243 additions and 245 deletions
|
@ -1,36 +1,9 @@
|
||||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
import React from "react";
|
||||||
import { isInDevelopment } from "@saleor/misc";
|
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
|
||||||
import { useHistory } from "react-router";
|
|
||||||
import useRouter from "use-react-router";
|
|
||||||
|
|
||||||
import ExitFormDialog from "./ExitFormDialog";
|
import ExitFormDialog from "./ExitFormDialog";
|
||||||
|
import { ExitFormDialogData } from "./types";
|
||||||
import useBeforeUnload from "./useBeforeUnload";
|
import useBeforeUnload from "./useBeforeUnload";
|
||||||
|
import { useExitFormDialogProvider } from "./useExitFormDialogProvider";
|
||||||
export interface ExitFormDialogData {
|
|
||||||
setIsDirty: (id: symbol, isDirty: boolean) => void;
|
|
||||||
setExitDialogSubmitRef: (id: symbol, submitFn: SubmitFn) => void;
|
|
||||||
setEnableExitDialog: (value: boolean) => void;
|
|
||||||
shouldBlockNavigation: () => boolean;
|
|
||||||
setIsSubmitting: (value: boolean) => void;
|
|
||||||
leave: () => void;
|
|
||||||
setIsSubmitDisabled: (value: boolean) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SubmitFn = (dataOrEvent?: any) => SubmitPromise<any[]>;
|
|
||||||
|
|
||||||
export type FormId = symbol;
|
|
||||||
|
|
||||||
type FormsData = Record<FormId, FormData>;
|
|
||||||
|
|
||||||
export interface WithFormId {
|
|
||||||
formId: FormId;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FormData {
|
|
||||||
isDirty: boolean;
|
|
||||||
submitFn: SubmitFn | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not use this context directly in components
|
// Do not use this context directly in components
|
||||||
// use useExitFormDialog hook instead
|
// use useExitFormDialog hook instead
|
||||||
|
@ -44,195 +17,6 @@ export const ExitFormDialogContext = React.createContext<ExitFormDialogData>({
|
||||||
setIsSubmitDisabled: () => undefined,
|
setIsSubmitDisabled: () => undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultValues = {
|
|
||||||
isDirty: false,
|
|
||||||
showDialog: false,
|
|
||||||
blockNav: true,
|
|
||||||
navAction: null,
|
|
||||||
enableExitDialog: false,
|
|
||||||
isSubmitting: false,
|
|
||||||
formsData: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useExitFormDialogProvider() {
|
|
||||||
const history = useHistory();
|
|
||||||
const { history: routerHistory } = useRouter();
|
|
||||||
|
|
||||||
const [showDialog, setShowDialog] = useState(defaultValues.showDialog);
|
|
||||||
const isSubmitDisabled = useRef(false);
|
|
||||||
|
|
||||||
const setIsSubmitDisabled = (status: boolean) => {
|
|
||||||
isSubmitDisabled.current = status;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isSubmitting = useRef(defaultValues.isSubmitting);
|
|
||||||
const formsData = useRef<FormsData>({});
|
|
||||||
const blockNav = useRef(defaultValues.blockNav);
|
|
||||||
const navAction = useRef<typeof history.location>(defaultValues.navAction);
|
|
||||||
const enableExitDialog = useRef(defaultValues.enableExitDialog);
|
|
||||||
const currentLocation = useRef(history.location);
|
|
||||||
|
|
||||||
const setIsSubmitting = (value: boolean) => {
|
|
||||||
setEnableExitDialog(!value);
|
|
||||||
isSubmitting.current = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setEnableExitDialog = (value: boolean) => {
|
|
||||||
// dialog should never be toggled to enabled during form submission
|
|
||||||
if (isSubmitting.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enableExitDialog.current = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setDefaultFormsData = () => {
|
|
||||||
formsData.current = defaultValues.formsData;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setCurrentLocation = (newLocation: typeof history.location) => {
|
|
||||||
currentLocation.current = newLocation;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setFormData = (id: symbol, newData: Partial<FormData>) => {
|
|
||||||
const updatedFormData = { ...formsData.current[id], ...newData };
|
|
||||||
|
|
||||||
formsData.current = {
|
|
||||||
...formsData.current,
|
|
||||||
[id]: updatedFormData,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set either on generic form load or on every custom form data change
|
|
||||||
// but doesn't cause re-renders
|
|
||||||
const setSubmitRef = <T extends () => SubmitPromise<any[]>>(
|
|
||||||
id: symbol,
|
|
||||||
submitFn: T,
|
|
||||||
) => {
|
|
||||||
setFormData(id, { submitFn });
|
|
||||||
};
|
|
||||||
|
|
||||||
const setIsDirty = (id: symbol, value: boolean) => {
|
|
||||||
// in case of race conitions between forms and transitions
|
|
||||||
if (!formsData.current[id]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFormData(id, { isDirty: value });
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
setEnableExitDialog(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setBlockNav = (value: boolean) => (blockNav.current = value);
|
|
||||||
|
|
||||||
const setDefaultNavAction = () =>
|
|
||||||
(navAction.current = defaultValues.navAction);
|
|
||||||
|
|
||||||
const setStateDefaultValues = () => {
|
|
||||||
setIsSubmitting(defaultValues.isSubmitting);
|
|
||||||
setDefaultFormsData();
|
|
||||||
setShowDialog(defaultValues.showDialog);
|
|
||||||
setBlockNav(defaultValues.blockNav);
|
|
||||||
setEnableExitDialog(defaultValues.enableExitDialog);
|
|
||||||
setDefaultNavAction();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getFormsDataValuesArray = () =>
|
|
||||||
Object.getOwnPropertySymbols(formsData.current).map(
|
|
||||||
key => formsData.current[key],
|
|
||||||
);
|
|
||||||
|
|
||||||
const hasAnyFormsDirty = () =>
|
|
||||||
getFormsDataValuesArray().some(({ isDirty }) => isDirty);
|
|
||||||
|
|
||||||
const shouldBlockNav = () => {
|
|
||||||
if (!enableExitDialog.current || !hasAnyFormsDirty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return blockNav.current;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isOnlyQuerying = (transition: typeof history.location) =>
|
|
||||||
// We need to compare to current path and not window location
|
|
||||||
// so it works with browser back button as well
|
|
||||||
transition.pathname === currentLocation.current.pathname;
|
|
||||||
|
|
||||||
const handleNavigationBlock = () => {
|
|
||||||
const unblock = history.block(transition => {
|
|
||||||
// needs to be done before the shouldBlockNav condition
|
|
||||||
// so it doesnt trigger setting default values
|
|
||||||
if (isOnlyQuerying(transition)) {
|
|
||||||
// ransition type requires this function to return either
|
|
||||||
// false | void | string where string opens up the browser prompt
|
|
||||||
// hence we return null
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldBlockNav()) {
|
|
||||||
navAction.current = transition;
|
|
||||||
setShowDialog(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setStateDefaultValues();
|
|
||||||
setCurrentLocation(transition);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
return unblock;
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(handleNavigationBlock, []);
|
|
||||||
|
|
||||||
const continueNavigation = () => {
|
|
||||||
setBlockNav(false);
|
|
||||||
setDefaultFormsData();
|
|
||||||
|
|
||||||
setCurrentLocation(navAction.current);
|
|
||||||
// because our useNavigator navigate action may be blocked
|
|
||||||
// by exit dialog we want to avoid using it doing this transition
|
|
||||||
if (navAction.current !== null) {
|
|
||||||
routerHistory.push(navAction.current.pathname + navAction.current.search);
|
|
||||||
}
|
|
||||||
setStateDefaultValues();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleLeave = () => {
|
|
||||||
continueNavigation();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setDefaultNavAction();
|
|
||||||
setShowDialog(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Used to prevent race conditions from places such as
|
|
||||||
// create pages with navigation on mutation completed
|
|
||||||
const shouldBlockNavigation = () => !!navAction.current;
|
|
||||||
|
|
||||||
const providerData: ExitFormDialogData = {
|
|
||||||
setIsDirty,
|
|
||||||
shouldBlockNavigation,
|
|
||||||
setEnableExitDialog,
|
|
||||||
setExitDialogSubmitRef: setSubmitRef,
|
|
||||||
setIsSubmitting,
|
|
||||||
setIsSubmitDisabled,
|
|
||||||
leave: handleLeave,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
providerData,
|
|
||||||
showDialog,
|
|
||||||
handleLeave,
|
|
||||||
handleClose,
|
|
||||||
shouldBlockNav,
|
|
||||||
isSubmitDisabled,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const ExitFormDialogProvider = ({ children }) => {
|
const ExitFormDialogProvider = ({ children }) => {
|
||||||
const {
|
const {
|
||||||
handleClose,
|
handleClose,
|
||||||
|
@ -245,7 +29,7 @@ const ExitFormDialogProvider = ({ children }) => {
|
||||||
useBeforeUnload(e => {
|
useBeforeUnload(e => {
|
||||||
// If form is dirty and user does a refresh,
|
// If form is dirty and user does a refresh,
|
||||||
// the browser will ask about unsaved changes
|
// the browser will ask about unsaved changes
|
||||||
if (shouldBlockNav() && !isInDevelopment) {
|
if (shouldBlockNav()) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.returnValue = "";
|
e.returnValue = "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import useForm, { SubmitPromise, UseFormResult } from "@saleor/hooks/useForm";
|
import useForm, { SubmitPromise, UseFormResult } from "@saleor/hooks/useForm";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { FormId } from "./ExitFormDialogProvider";
|
import { FormId } from "./types";
|
||||||
|
|
||||||
export type CheckIfSaveIsDisabledFnType<T> = (data: T) => boolean;
|
export type CheckIfSaveIsDisabledFnType<T> = (data: T) => boolean;
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
export * from "./Form";
|
export * from "./Form";
|
||||||
export { default } from "./Form";
|
export { default } from "./Form";
|
||||||
|
export * from "./types";
|
||||||
|
export * from "./useExitFormDialog";
|
||||||
|
|
27
src/components/Form/types.ts
Normal file
27
src/components/Form/types.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export type SubmitFn = (event?: React.FormEvent) => SubmitPromise;
|
||||||
|
|
||||||
|
export type FormId = symbol;
|
||||||
|
|
||||||
|
export type FormsData = Record<FormId, FormData>;
|
||||||
|
|
||||||
|
export interface WithFormId {
|
||||||
|
formId: FormId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExitFormDialogData {
|
||||||
|
setIsDirty: (id: symbol, isDirty: boolean) => void;
|
||||||
|
setExitDialogSubmitRef: (id: symbol, submitFn: SubmitFn) => void;
|
||||||
|
setEnableExitDialog: (value: boolean) => void;
|
||||||
|
shouldBlockNavigation: () => boolean;
|
||||||
|
setIsSubmitting: (value: boolean) => void;
|
||||||
|
leave: () => void;
|
||||||
|
setIsSubmitDisabled: (value: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FormData {
|
||||||
|
isDirty: boolean;
|
||||||
|
submitFn: SubmitFn | null;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
const useBeforeUnload = fn => {
|
const useBeforeUnload = (fn: (event: BeforeUnloadEvent) => void) => {
|
||||||
const cb = useRef(fn);
|
const cb = useRef(fn);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -8,7 +8,7 @@ const useBeforeUnload = fn => {
|
||||||
}, [fn]);
|
}, [fn]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onBeforeUnload = (...args) => cb.current?.(...args);
|
const onBeforeUnload = (event: BeforeUnloadEvent) => cb.current?.(event);
|
||||||
|
|
||||||
window.addEventListener("beforeunload", onBeforeUnload);
|
window.addEventListener("beforeunload", onBeforeUnload);
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,9 @@ import React from "react";
|
||||||
import { useHistory } from "react-router";
|
import { useHistory } from "react-router";
|
||||||
import { MemoryRouter } from "react-router-dom";
|
import { MemoryRouter } from "react-router-dom";
|
||||||
|
|
||||||
import {
|
import { ExitFormDialogContext } from "./ExitFormDialogProvider";
|
||||||
ExitFormDialogContext,
|
|
||||||
useExitFormDialogProvider,
|
|
||||||
} from "./ExitFormDialogProvider";
|
|
||||||
import { useExitFormDialog } from "./useExitFormDialog";
|
import { useExitFormDialog } from "./useExitFormDialog";
|
||||||
|
import { useExitFormDialogProvider } from "./useExitFormDialogProvider";
|
||||||
|
|
||||||
jest.mock("../../hooks/useNotifier", () => undefined);
|
jest.mock("../../hooks/useNotifier", () => undefined);
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import React, { useContext, useRef } from "react";
|
import React, { useContext, useRef } from "react";
|
||||||
|
|
||||||
import {
|
import { ExitFormDialogContext } from "./ExitFormDialogProvider";
|
||||||
ExitFormDialogContext,
|
import { ExitFormDialogData, SubmitFn, WithFormId } from "./types";
|
||||||
ExitFormDialogData,
|
|
||||||
SubmitFn,
|
|
||||||
WithFormId,
|
|
||||||
} from "./ExitFormDialogProvider";
|
|
||||||
|
|
||||||
export interface UseExitFormDialogResult
|
export interface UseExitFormDialogResult
|
||||||
extends Omit<ExitFormDialogData, "setIsDirty" | "setExitDialogSubmitRef">,
|
extends Omit<ExitFormDialogData, "setIsDirty" | "setExitDialogSubmitRef">,
|
||||||
|
|
196
src/components/Form/useExitFormDialogProvider.tsx
Normal file
196
src/components/Form/useExitFormDialogProvider.tsx
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { useHistory } from "react-router";
|
||||||
|
import useRouter from "use-react-router";
|
||||||
|
|
||||||
|
import { ExitFormDialogData, FormData, FormsData } from "./types";
|
||||||
|
|
||||||
|
const defaultValues = {
|
||||||
|
isDirty: false,
|
||||||
|
showDialog: false,
|
||||||
|
blockNav: true,
|
||||||
|
navAction: null,
|
||||||
|
enableExitDialog: false,
|
||||||
|
isSubmitting: false,
|
||||||
|
formsData: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useExitFormDialogProvider() {
|
||||||
|
const history = useHistory();
|
||||||
|
const { history: routerHistory } = useRouter();
|
||||||
|
|
||||||
|
const [showDialog, setShowDialog] = useState(defaultValues.showDialog);
|
||||||
|
const isSubmitDisabled = useRef(false);
|
||||||
|
|
||||||
|
const setIsSubmitDisabled = (status: boolean) => {
|
||||||
|
isSubmitDisabled.current = status;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isSubmitting = useRef(defaultValues.isSubmitting);
|
||||||
|
const formsData = useRef<FormsData>({});
|
||||||
|
const blockNav = useRef(defaultValues.blockNav);
|
||||||
|
const navAction = useRef<typeof history.location>(defaultValues.navAction);
|
||||||
|
const enableExitDialog = useRef(defaultValues.enableExitDialog);
|
||||||
|
const currentLocation = useRef(history.location);
|
||||||
|
|
||||||
|
const setIsSubmitting = (value: boolean) => {
|
||||||
|
setEnableExitDialog(!value);
|
||||||
|
isSubmitting.current = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setEnableExitDialog = (value: boolean) => {
|
||||||
|
// dialog should never be toggled to enabled during form submission
|
||||||
|
if (isSubmitting.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
enableExitDialog.current = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setDefaultFormsData = () => {
|
||||||
|
formsData.current = defaultValues.formsData;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setCurrentLocation = (newLocation: typeof history.location) => {
|
||||||
|
currentLocation.current = newLocation;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setFormData = (id: symbol, newData: Partial<FormData>) => {
|
||||||
|
const updatedFormData = { ...formsData.current[id], ...newData };
|
||||||
|
|
||||||
|
formsData.current = {
|
||||||
|
...formsData.current,
|
||||||
|
[id]: updatedFormData,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set either on generic form load or on every custom form data change
|
||||||
|
// but doesn't cause re-renders
|
||||||
|
const setSubmitRef = <T extends () => SubmitPromise<any[]>>(
|
||||||
|
id: symbol,
|
||||||
|
submitFn: T,
|
||||||
|
) => {
|
||||||
|
setFormData(id, { submitFn });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setIsDirty = (id: symbol, value: boolean) => {
|
||||||
|
// in case of race conitions between forms and transitions
|
||||||
|
if (!formsData.current[id]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFormData(id, { isDirty: value });
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
setEnableExitDialog(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setBlockNav = (value: boolean) => (blockNav.current = value);
|
||||||
|
|
||||||
|
const setDefaultNavAction = () =>
|
||||||
|
(navAction.current = defaultValues.navAction);
|
||||||
|
|
||||||
|
const setStateDefaultValues = () => {
|
||||||
|
setIsSubmitting(defaultValues.isSubmitting);
|
||||||
|
setDefaultFormsData();
|
||||||
|
setShowDialog(defaultValues.showDialog);
|
||||||
|
setBlockNav(defaultValues.blockNav);
|
||||||
|
setEnableExitDialog(defaultValues.enableExitDialog);
|
||||||
|
setDefaultNavAction();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFormsDataValuesArray = () =>
|
||||||
|
Object.getOwnPropertySymbols(formsData.current).map(
|
||||||
|
key => formsData.current[key],
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasAnyFormsDirty = () =>
|
||||||
|
getFormsDataValuesArray().some(({ isDirty }) => isDirty);
|
||||||
|
|
||||||
|
const shouldBlockNav = () => {
|
||||||
|
if (!enableExitDialog.current || !hasAnyFormsDirty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockNav.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isOnlyQuerying = (transition: typeof history.location) =>
|
||||||
|
// We need to compare to current path and not window location
|
||||||
|
// so it works with browser back button as well
|
||||||
|
transition.pathname === currentLocation.current.pathname;
|
||||||
|
|
||||||
|
const handleNavigationBlock = () => {
|
||||||
|
// This callback blocks only navigation between internal dashboard pages
|
||||||
|
// https://github.com/remix-run/history/blob/main/docs/blocking-transitions.md#caveats
|
||||||
|
const unblock = history.block(transition => {
|
||||||
|
// needs to be done before the shouldBlockNav condition
|
||||||
|
// so it doesn't trigger setting default values
|
||||||
|
if (isOnlyQuerying(transition)) {
|
||||||
|
// transition type requires this function to return either
|
||||||
|
// false | void | string where string opens up the browser prompt
|
||||||
|
// hence we return null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (shouldBlockNav()) {
|
||||||
|
navAction.current = transition;
|
||||||
|
setShowDialog(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStateDefaultValues();
|
||||||
|
setCurrentLocation(transition);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return unblock;
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(handleNavigationBlock, []);
|
||||||
|
|
||||||
|
const continueNavigation = () => {
|
||||||
|
setBlockNav(false);
|
||||||
|
setDefaultFormsData();
|
||||||
|
|
||||||
|
setCurrentLocation(navAction.current);
|
||||||
|
// because our useNavigator navigate action may be blocked
|
||||||
|
// by exit dialog we want to avoid using it doing this transition
|
||||||
|
if (navAction.current !== null) {
|
||||||
|
routerHistory.push(navAction.current.pathname + navAction.current.search);
|
||||||
|
}
|
||||||
|
setStateDefaultValues();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLeave = () => {
|
||||||
|
continueNavigation();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setDefaultNavAction();
|
||||||
|
setShowDialog(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to prevent race conditions from places such as
|
||||||
|
// create pages with navigation on mutation completed
|
||||||
|
const shouldBlockNavigation = () => !!navAction.current;
|
||||||
|
|
||||||
|
const providerData: ExitFormDialogData = {
|
||||||
|
setIsDirty,
|
||||||
|
shouldBlockNavigation,
|
||||||
|
setEnableExitDialog,
|
||||||
|
setExitDialogSubmitRef: setSubmitRef,
|
||||||
|
setIsSubmitting,
|
||||||
|
setIsSubmitDisabled,
|
||||||
|
leave: handleLeave,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
providerData,
|
||||||
|
showDialog,
|
||||||
|
handleLeave,
|
||||||
|
handleClose,
|
||||||
|
shouldBlockNav,
|
||||||
|
isSubmitDisabled,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
import { ChannelsAction } from "@saleor/channels/urls";
|
import { ChannelsAction } from "@saleor/channels/urls";
|
||||||
import { Channel } from "@saleor/channels/utils";
|
import { Channel } from "@saleor/channels/utils";
|
||||||
import { WithFormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
import { useExitFormDialog, WithFormId } from "@saleor/components/Form";
|
||||||
import { useExitFormDialog } from "@saleor/components/Form/useExitFormDialog";
|
|
||||||
import useListActions from "@saleor/hooks/useListActions";
|
import useListActions from "@saleor/hooks/useListActions";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { CheckIfSaveIsDisabledFnType } from "@saleor/components/Form";
|
|
||||||
import { FormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
|
||||||
import {
|
import {
|
||||||
|
CheckIfSaveIsDisabledFnType,
|
||||||
|
FormId,
|
||||||
useExitFormDialog,
|
useExitFormDialog,
|
||||||
UseExitFormDialogResult,
|
UseExitFormDialogResult,
|
||||||
} from "@saleor/components/Form/useExitFormDialog";
|
} from "@saleor/components/Form";
|
||||||
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
||||||
import { toggle } from "@saleor/utils/lists";
|
import { toggle } from "@saleor/utils/lists";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { FormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
import { FormId, useExitFormDialog } from "@saleor/components/Form";
|
||||||
import { useExitFormDialog } from "@saleor/components/Form/useExitFormDialog";
|
|
||||||
import { MessageContext } from "@saleor/components/messages";
|
import { MessageContext } from "@saleor/components/messages";
|
||||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
|
|
|
@ -536,9 +536,6 @@ export const combinedMultiAutocompleteChoices = (
|
||||||
choices: MultiAutocompleteChoiceType[],
|
choices: MultiAutocompleteChoiceType[],
|
||||||
) => uniqBy([...selected, ...choices], "value");
|
) => uniqBy([...selected, ...choices], "value");
|
||||||
|
|
||||||
export const isInDevelopment =
|
|
||||||
!process.env.NODE_ENV || process.env.NODE_ENV === "development";
|
|
||||||
|
|
||||||
export type WithOptional<T, K extends keyof T> = Omit<T, K> &
|
export type WithOptional<T, K extends keyof T> = Omit<T, K> &
|
||||||
Partial<Pick<T, K>>;
|
Partial<Pick<T, K>>;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Backlink } from "@saleor/components/Backlink";
|
||||||
import CardSpacer from "@saleor/components/CardSpacer";
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
import ChannelsAvailabilityCard from "@saleor/components/ChannelsAvailabilityCard";
|
import ChannelsAvailabilityCard from "@saleor/components/ChannelsAvailabilityCard";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
import { WithFormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
import { WithFormId } from "@saleor/components/Form";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import Savebar from "@saleor/components/Savebar";
|
import Savebar from "@saleor/components/Savebar";
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Backlink } from "@saleor/components/Backlink";
|
||||||
import CardSpacer from "@saleor/components/CardSpacer";
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
import ChannelsAvailabilityCard from "@saleor/components/ChannelsAvailabilityCard";
|
import ChannelsAvailabilityCard from "@saleor/components/ChannelsAvailabilityCard";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
import { WithFormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
import { WithFormId } from "@saleor/components/Form";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
import Metadata from "@saleor/components/Metadata/Metadata";
|
import Metadata from "@saleor/components/Metadata/Metadata";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
|
Loading…
Reference in a new issue