Minor improvements (#1924)
* Add basic tests * Test if qs is preserved * Preserve querystring * Improve import performance
This commit is contained in:
parent
fbf57bbbb1
commit
3e180c8d17
5 changed files with 50 additions and 31 deletions
|
@ -14,6 +14,7 @@ export interface ExitFormDialogData {
|
||||||
shouldBlockNavigation: () => boolean;
|
shouldBlockNavigation: () => boolean;
|
||||||
setIsSubmitting: (value: boolean) => void;
|
setIsSubmitting: (value: boolean) => void;
|
||||||
submit: () => SubmitPromise;
|
submit: () => SubmitPromise;
|
||||||
|
leave: () => void;
|
||||||
setIsSubmitDisabled: (value: boolean) => void;
|
setIsSubmitDisabled: (value: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ export const ExitFormDialogContext = React.createContext<ExitFormDialogData>({
|
||||||
shouldBlockNavigation: () => false,
|
shouldBlockNavigation: () => false,
|
||||||
setIsSubmitting: () => undefined,
|
setIsSubmitting: () => undefined,
|
||||||
submit: () => Promise.resolve([]),
|
submit: () => Promise.resolve([]),
|
||||||
|
leave: () => undefined,
|
||||||
setIsSubmitDisabled: () => undefined
|
setIsSubmitDisabled: () => undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -69,9 +71,9 @@ export function useExitFormDialogProvider() {
|
||||||
const isSubmitting = useRef(defaultValues.isSubmitting);
|
const isSubmitting = useRef(defaultValues.isSubmitting);
|
||||||
const formsData = useRef<FormsData>({});
|
const formsData = useRef<FormsData>({});
|
||||||
const blockNav = useRef(defaultValues.blockNav);
|
const blockNav = useRef(defaultValues.blockNav);
|
||||||
const navAction = useRef(defaultValues.navAction);
|
const navAction = useRef<typeof history.location>(defaultValues.navAction);
|
||||||
const enableExitDialog = useRef(defaultValues.enableExitDialog);
|
const enableExitDialog = useRef(defaultValues.enableExitDialog);
|
||||||
const currentPath = useRef(window.location.pathname);
|
const currentLocation = useRef(history.location);
|
||||||
|
|
||||||
const setIsSubmitting = (value: boolean) => {
|
const setIsSubmitting = (value: boolean) => {
|
||||||
setEnableExitDialog(!value);
|
setEnableExitDialog(!value);
|
||||||
|
@ -91,8 +93,8 @@ export function useExitFormDialogProvider() {
|
||||||
formsData.current = defaultValues.formsData;
|
formsData.current = defaultValues.formsData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setCurrentPath = (newPath: string) => {
|
const setCurrentLocation = (newLocation: typeof history.location) => {
|
||||||
currentPath.current = newPath;
|
currentLocation.current = newLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setFormData = (id: symbol, newData: Partial<FormData>) => {
|
const setFormData = (id: symbol, newData: Partial<FormData>) => {
|
||||||
|
@ -156,10 +158,10 @@ export function useExitFormDialogProvider() {
|
||||||
return blockNav.current;
|
return blockNav.current;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isOnlyQuerying = transition =>
|
const isOnlyQuerying = (transition: typeof history.location) =>
|
||||||
// wee need to compare to current path and not window location
|
// We need to compare to current path and not window location
|
||||||
// so it works with browser back button as well
|
// so it works with browser back button as well
|
||||||
transition.pathname === currentPath.current;
|
transition.pathname === currentLocation.current.pathname;
|
||||||
|
|
||||||
const handleNavigationBlock = () => {
|
const handleNavigationBlock = () => {
|
||||||
const unblock = history.block(transition => {
|
const unblock = history.block(transition => {
|
||||||
|
@ -179,7 +181,7 @@ export function useExitFormDialogProvider() {
|
||||||
}
|
}
|
||||||
|
|
||||||
setStateDefaultValues();
|
setStateDefaultValues();
|
||||||
setCurrentPath(transition.pathname);
|
setCurrentLocation(transition);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -192,10 +194,10 @@ export function useExitFormDialogProvider() {
|
||||||
setBlockNav(false);
|
setBlockNav(false);
|
||||||
setDefaultFormsData();
|
setDefaultFormsData();
|
||||||
|
|
||||||
setCurrentPath(navAction.current.pathname);
|
setCurrentLocation(navAction.current);
|
||||||
// because our useNavigator navigate action may be blocked
|
// because our useNavigator navigate action may be blocked
|
||||||
// by exit dialog we want to avoid using it doing this transition
|
// by exit dialog we want to avoid using it doing this transition
|
||||||
routerHistory.push(navAction.current.pathname);
|
routerHistory.push(navAction.current.pathname + navAction.current.search);
|
||||||
setStateDefaultValues();
|
setStateDefaultValues();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -250,7 +252,8 @@ export function useExitFormDialogProvider() {
|
||||||
setExitDialogSubmitRef: setSubmitRef,
|
setExitDialogSubmitRef: setSubmitRef,
|
||||||
setIsSubmitting,
|
setIsSubmitting,
|
||||||
submit: handleSubmit,
|
submit: handleSubmit,
|
||||||
setIsSubmitDisabled
|
setIsSubmitDisabled,
|
||||||
|
leave: handleLeave
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -150,4 +150,27 @@ describe("useExitFormDialog", () => {
|
||||||
expect(result.current.exit.shouldBlockNavigation()).toBe(true);
|
expect(result.current.exit.shouldBlockNavigation()).toBe(true);
|
||||||
expect(result.current.history.location.pathname).toBe(initialPath);
|
expect(result.current.history.location.pathname).toBe(initialPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("navigates to full url with querystring", async () => {
|
||||||
|
// Given
|
||||||
|
const submitFn = jest.fn(() => Promise.resolve([]));
|
||||||
|
const { result } = setup(submitFn);
|
||||||
|
const qs = "?param=value";
|
||||||
|
const targetPathWithQs = targetPath + qs;
|
||||||
|
|
||||||
|
// When
|
||||||
|
act(() => {
|
||||||
|
result.current.form.change({
|
||||||
|
target: { name: "field", value: "something" }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
act(() => {
|
||||||
|
result.current.history.push(targetPathWithQs);
|
||||||
|
result.current.exit.leave();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(result.current.history.location.pathname).toBe(targetPath);
|
||||||
|
expect(result.current.history.location.search).toBe(qs);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,14 +8,7 @@ import {
|
||||||
} from "./ExitFormDialogProvider";
|
} from "./ExitFormDialogProvider";
|
||||||
|
|
||||||
export interface UseExitFormDialogResult
|
export interface UseExitFormDialogResult
|
||||||
extends Pick<
|
extends Omit<ExitFormDialogData, "setIsDirty" | "setExitDialogSubmitRef">,
|
||||||
ExitFormDialogData,
|
|
||||||
| "setEnableExitDialog"
|
|
||||||
| "shouldBlockNavigation"
|
|
||||||
| "setIsSubmitting"
|
|
||||||
| "setIsSubmitDisabled"
|
|
||||||
| "submit"
|
|
||||||
>,
|
|
||||||
WithFormId {
|
WithFormId {
|
||||||
setIsDirty: (isDirty: boolean) => void;
|
setIsDirty: (isDirty: boolean) => void;
|
||||||
setExitDialogSubmitRef: (submitFn: SubmitFn) => void;
|
setExitDialogSubmitRef: (submitFn: SubmitFn) => void;
|
||||||
|
|
11
src/misc.ts
11
src/misc.ts
|
@ -13,7 +13,6 @@ import { IntlShape } from "react-intl";
|
||||||
|
|
||||||
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
|
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
|
||||||
import { AddressType, AddressTypeInput } from "./customers/types";
|
import { AddressType, AddressTypeInput } from "./customers/types";
|
||||||
import { AddressFragment } from "./graphql";
|
|
||||||
import {
|
import {
|
||||||
commonStatusMessages,
|
commonStatusMessages,
|
||||||
errorMessages,
|
errorMessages,
|
||||||
|
@ -397,16 +396,6 @@ export function findInEnum<TEnum extends {}>(needle: string, haystack: TEnum) {
|
||||||
throw new Error(`Key ${needle} not found in enum`);
|
throw new Error(`Key ${needle} not found in enum`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addressToAddressInput<T>(
|
|
||||||
address: T & AddressFragment
|
|
||||||
): AddressInput {
|
|
||||||
const { id, __typename, ...rest } = address;
|
|
||||||
return {
|
|
||||||
...rest,
|
|
||||||
country: findInEnum(address.country.code, CountryCode)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function findValueInEnum<TEnum extends {}>(
|
export function findValueInEnum<TEnum extends {}>(
|
||||||
needle: string,
|
needle: string,
|
||||||
haystack: TEnum
|
haystack: TEnum
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { IMoney, subtractMoney } from "@saleor/components/Money";
|
import { IMoney, subtractMoney } from "@saleor/components/Money";
|
||||||
import {
|
import {
|
||||||
|
AddressFragment,
|
||||||
AddressInput,
|
AddressInput,
|
||||||
CountryCode,
|
CountryCode,
|
||||||
FulfillmentStatus,
|
FulfillmentStatus,
|
||||||
|
@ -12,7 +13,7 @@ import {
|
||||||
WarehouseFragment
|
WarehouseFragment
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import { FormsetData } from "@saleor/hooks/useFormset";
|
import { FormsetData } from "@saleor/hooks/useFormset";
|
||||||
import { addressToAddressInput } from "@saleor/misc";
|
import { findInEnum } from "@saleor/misc";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
LineItemData,
|
LineItemData,
|
||||||
|
@ -300,6 +301,16 @@ export const isStockError = (
|
||||||
return isQuantityLargerThanAvailable || isError;
|
return isQuantityLargerThanAvailable || isError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function addressToAddressInput<T>(
|
||||||
|
address: T & AddressFragment
|
||||||
|
): AddressInput {
|
||||||
|
const { id, __typename, ...rest } = address;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
country: findInEnum(address.country.code, CountryCode)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export const getVariantSearchAddress = (
|
export const getVariantSearchAddress = (
|
||||||
order: OrderDetailsFragment
|
order: OrderDetailsFragment
|
||||||
): AddressInput => {
|
): AddressInput => {
|
||||||
|
|
Loading…
Reference in a new issue