Fix for errors on changing channel availability (#1264)
* Add array diff util * Use arrayDiff instead of diff * Update changelog
This commit is contained in:
parent
cacf3030a2
commit
79e752cdbf
11 changed files with 112 additions and 55 deletions
|
@ -72,6 +72,7 @@ All notable, unreleased changes to this project will be documented in this file.
|
|||
- Use MacawUI - #1229 by @dominik-zeglen
|
||||
- Add Metadata for Sale & Voucher - #7653 by @piotrgrundas
|
||||
- Add variant create options dialog - #1238 by @orzechdev
|
||||
- Fix for errors on changing channel availability - #1264 by @krzysztofwolski
|
||||
|
||||
# 2.11.1
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import usePaginator, {
|
|||
} from "@saleor/hooks/usePaginator";
|
||||
import { commonMessages, errorMessages } from "@saleor/intl";
|
||||
import useProductSearch from "@saleor/searches/useProductSearch";
|
||||
import { arrayDiff } from "@saleor/utils/arrays";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||
import { mapEdgesToItems } from "@saleor/utils/maps";
|
||||
|
@ -28,7 +29,6 @@ import {
|
|||
usePrivateMetadataUpdate
|
||||
} from "@saleor/utils/metadata/updateMetadata";
|
||||
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
|
||||
import { diff } from "fast-array-diff";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
|
@ -215,11 +215,14 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
|||
input
|
||||
}
|
||||
});
|
||||
const diffChannels = diff(
|
||||
collectionChannelsChoices,
|
||||
formData.channelListings,
|
||||
(a, b) => a.id === b.id
|
||||
const initialIds = collectionChannelsChoices.map(
|
||||
channel => channel.id
|
||||
);
|
||||
const modifiedIds = formData.channelListings.map(
|
||||
channel => channel.id
|
||||
);
|
||||
|
||||
const idsDiff = arrayDiff(initialIds, modifiedIds);
|
||||
|
||||
updateChannels({
|
||||
variables: {
|
||||
|
@ -230,10 +233,7 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
|||
isPublished: channel.isPublished,
|
||||
publicationDate: channel.publicationDate
|
||||
})),
|
||||
removeChannels:
|
||||
diffChannels.removed?.map(
|
||||
removedChannel => removedChannel.id
|
||||
) || []
|
||||
removeChannels: idsDiff.removed
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,7 +5,8 @@ import { DiscountTypeEnum, RequirementsPicker } from "@saleor/discounts/types";
|
|||
import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
|
||||
import { RequireOnlyOne } from "@saleor/misc";
|
||||
import { VoucherTypeEnum } from "@saleor/types/globalTypes";
|
||||
import { diff } from "fast-array-diff";
|
||||
import { arrayDiff } from "@saleor/utils/arrays";
|
||||
|
||||
export interface ChannelArgs {
|
||||
discountValue: string;
|
||||
minSpent: string;
|
||||
|
@ -96,13 +97,10 @@ export const getChannelsVariables = (
|
|||
formData: VoucherDetailsPageFormData,
|
||||
prevChannels?: ChannelVoucherData[]
|
||||
) => {
|
||||
const removeChannels = prevChannels
|
||||
? diff(
|
||||
prevChannels,
|
||||
formData.channelListings,
|
||||
(a, b) => a.id === b.id
|
||||
).removed?.map(removedChannel => removedChannel.id)
|
||||
: [];
|
||||
const initialIds = prevChannels.map(channel => channel.id);
|
||||
const modifiedIds = formData.channelListings.map(channel => channel.id);
|
||||
|
||||
const idsDiff = arrayDiff(initialIds, modifiedIds);
|
||||
|
||||
return {
|
||||
id,
|
||||
|
@ -121,7 +119,7 @@ export const getChannelsVariables = (
|
|||
? 0
|
||||
: channel.minSpent
|
||||
})) || [],
|
||||
removeChannels
|
||||
removeChannels: idsDiff.removed
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -131,13 +129,10 @@ export const getSaleChannelsVariables = (
|
|||
formData: SaleDetailsPageFormData,
|
||||
prevChannels?: ChannelSaleData[]
|
||||
) => {
|
||||
const removeChannels = prevChannels
|
||||
? diff(
|
||||
prevChannels,
|
||||
formData.channelListings,
|
||||
(a, b) => a.id === b.id
|
||||
).removed?.map(removedChannel => removedChannel.id)
|
||||
: [];
|
||||
const initialIds = prevChannels.map(channel => channel.id);
|
||||
const modifiedIds = formData.channelListings.map(channel => channel.id);
|
||||
|
||||
const idsDiff = arrayDiff(initialIds, modifiedIds);
|
||||
|
||||
return {
|
||||
id,
|
||||
|
@ -147,7 +142,7 @@ export const getSaleChannelsVariables = (
|
|||
channelId: channel.id,
|
||||
discountValue: channel.discountValue
|
||||
})) || [],
|
||||
removeChannels
|
||||
removeChannels: idsDiff.removed
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -40,13 +40,13 @@ import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPage
|
|||
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
|
||||
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
|
||||
import { FetchMoreProps, ReorderEvent } from "@saleor/types";
|
||||
import { arrayDiff } from "@saleor/utils/arrays";
|
||||
import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit";
|
||||
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
||||
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
||||
import getMetadata from "@saleor/utils/metadata/getMetadata";
|
||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||
import useRichText from "@saleor/utils/richText/useRichText";
|
||||
import { diff } from "fast-array-diff";
|
||||
import React from "react";
|
||||
|
||||
import { ProductStockFormsetData, ProductStockInput } from "../ProductStocks";
|
||||
|
@ -180,7 +180,7 @@ const getStocksData = (
|
|||
const dataStocks = stocks.map(stock => stock.id);
|
||||
const variantStocks =
|
||||
product?.variants[0]?.stocks.map(stock => stock.warehouse.id) || [];
|
||||
const stockDiff = diff(variantStocks, dataStocks);
|
||||
const stockDiff = arrayDiff(variantStocks, dataStocks);
|
||||
|
||||
return {
|
||||
addStocks: stocks.filter(stock =>
|
||||
|
|
|
@ -30,10 +30,10 @@ import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPage
|
|||
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
|
||||
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
|
||||
import { FetchMoreProps, ReorderEvent } from "@saleor/types";
|
||||
import { arrayDiff } from "@saleor/utils/arrays";
|
||||
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
||||
import getMetadata from "@saleor/utils/metadata/getMetadata";
|
||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||
import { diff } from "fast-array-diff";
|
||||
import React from "react";
|
||||
|
||||
import handleFormSubmit from "../../../utils/handlers/handleFormSubmit";
|
||||
|
@ -206,7 +206,7 @@ function useProductVariantUpdateForm(
|
|||
|
||||
const dataStocks = stocks.data.map(stock => stock.id);
|
||||
const variantStocks = variant?.stocks.map(stock => stock.warehouse.id) || [];
|
||||
const stockDiff = diff(variantStocks, dataStocks);
|
||||
const stockDiff = arrayDiff(variantStocks, dataStocks);
|
||||
|
||||
const addStocks = stocks.data.filter(stock =>
|
||||
stockDiff.added.some(addedStock => addedStock === stock.id)
|
||||
|
|
|
@ -15,7 +15,7 @@ import { SimpleProductUpdate } from "@saleor/products/types/SimpleProductUpdate"
|
|||
import { mapFormsetStockToStockInput } from "@saleor/products/utils/data";
|
||||
import { getAvailabilityVariables } from "@saleor/products/utils/handlers";
|
||||
import { ProductChannelListingAddInput } from "@saleor/types/globalTypes";
|
||||
import { diff } from "fast-array-diff";
|
||||
import { arrayDiff } from "@saleor/utils/arrays";
|
||||
import isEqual from "lodash/isEqual";
|
||||
|
||||
import { ChannelsWithVariantsData, ChannelWithVariantData } from "../types";
|
||||
|
@ -70,7 +70,7 @@ export const getChannelListingUpdateInputFromData = (
|
|||
basicChannelData: ChannelData
|
||||
) => ({
|
||||
...getChannelListingBaseInputData(basicChannelData),
|
||||
addVariants: diff(initialSelectedVariantsIds, variantsIdsToAdd).added,
|
||||
addVariants: arrayDiff(initialSelectedVariantsIds, variantsIdsToAdd).added,
|
||||
removeVariants: variantsIdsToRemove
|
||||
});
|
||||
|
||||
|
@ -164,10 +164,11 @@ export const getSimpleChannelsVariables = (
|
|||
product: ProductDetails_product
|
||||
) => {
|
||||
const productChannels = createSortedChannelsDataFromProduct(product);
|
||||
const diffChannels = diff(
|
||||
productChannels,
|
||||
data.channelListings,
|
||||
(a, b) => a.id === b.id
|
||||
const existingChannelIDs = productChannels.map(channel => channel.id);
|
||||
const modifiedChannelIDs = data.channelListings.map(channel => channel.id);
|
||||
|
||||
const removedChannelIDs = existingChannelIDs.filter(
|
||||
x => !modifiedChannelIDs.includes(x)
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -175,9 +176,7 @@ export const getSimpleChannelsVariables = (
|
|||
id: product.id,
|
||||
input: {
|
||||
updateChannels: getAvailabilityVariables(data.channelListings),
|
||||
removeChannels: diffChannels.removed?.map(
|
||||
removedChannel => removedChannel.id
|
||||
)
|
||||
removeChannels: removedChannelIDs
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
useShippingZoneDelete,
|
||||
useShippingZoneUpdate
|
||||
} from "@saleor/shipping/mutations";
|
||||
import { arrayDiff } from "@saleor/utils/arrays";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||
import { mapEdgesToItems } from "@saleor/utils/maps";
|
||||
|
@ -27,7 +28,6 @@ import {
|
|||
usePrivateMetadataUpdate
|
||||
} from "@saleor/utils/metadata/updateMetadata";
|
||||
import { useWarehouseCreate } from "@saleor/warehouses/mutations";
|
||||
import { diff } from "fast-array-diff";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
|
@ -133,12 +133,12 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
|||
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
|
||||
|
||||
const updateData = async (submitData: FormData) => {
|
||||
const warehouseDiff = diff(
|
||||
const warehouseDiff = arrayDiff(
|
||||
data.shippingZone.warehouses.map(warehouse => warehouse.id),
|
||||
submitData.warehouses
|
||||
);
|
||||
|
||||
const channelsDiff = diff(
|
||||
const channelsDiff = arrayDiff(
|
||||
data.shippingZone.channels.map(channel => channel.id),
|
||||
submitData.channels
|
||||
);
|
||||
|
|
55
src/utils/arrays/arrays.test.ts
Normal file
55
src/utils/arrays/arrays.test.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import { arrayDiff } from "./arrays";
|
||||
|
||||
const fruits = ["apple", "orange", "strawberry"];
|
||||
|
||||
const vegetables = ["potato", "onion"];
|
||||
|
||||
describe("Validate diff results", () => {
|
||||
it("Empty arrays", () => {
|
||||
const diff = arrayDiff([], []);
|
||||
expect(diff).toStrictEqual({ added: [], removed: [], common: [] });
|
||||
});
|
||||
|
||||
it("Compare array with itself", () => {
|
||||
const diff = arrayDiff(fruits, fruits);
|
||||
expect(diff).toStrictEqual({ added: [], removed: [], common: fruits });
|
||||
});
|
||||
|
||||
it("Added elements to empty", () => {
|
||||
const diff = arrayDiff([], vegetables);
|
||||
expect(diff).toStrictEqual({
|
||||
added: vegetables,
|
||||
removed: [],
|
||||
common: []
|
||||
});
|
||||
});
|
||||
|
||||
it("Added elements to populated array", () => {
|
||||
const diff = arrayDiff(fruits, [...fruits, ...vegetables]);
|
||||
expect(diff).toStrictEqual({
|
||||
added: vegetables,
|
||||
removed: [],
|
||||
common: fruits
|
||||
});
|
||||
});
|
||||
|
||||
it("Removed elements", () => {
|
||||
const diff = arrayDiff([...fruits, ...vegetables], fruits);
|
||||
expect(diff).toStrictEqual({
|
||||
added: [],
|
||||
removed: vegetables,
|
||||
common: fruits
|
||||
});
|
||||
});
|
||||
|
||||
it("Added, removed, and common elements", () => {
|
||||
const before = ["a", "b", "c", "d"];
|
||||
const after = ["b", "e", "a", "t"];
|
||||
const diff = arrayDiff(before, after);
|
||||
expect(diff).toStrictEqual({
|
||||
added: ["e", "t"],
|
||||
removed: ["c", "d"],
|
||||
common: ["a", "b"]
|
||||
});
|
||||
});
|
||||
});
|
8
src/utils/arrays/arrays.ts
Normal file
8
src/utils/arrays/arrays.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import difference from "lodash/difference";
|
||||
import intersection from "lodash/intersection";
|
||||
|
||||
export const arrayDiff = (before: string[], after: string[]) => ({
|
||||
added: difference(after, before),
|
||||
removed: difference(before, after),
|
||||
common: intersection(before, after)
|
||||
});
|
1
src/utils/arrays/index.ts
Normal file
1
src/utils/arrays/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from "./arrays";
|
|
@ -1,7 +1,7 @@
|
|||
import { MetadataFormData } from "@saleor/components/Metadata/types";
|
||||
import { MetadataErrorFragment } from "@saleor/fragments/types/MetadataErrorFragment";
|
||||
import { MetadataInput } from "@saleor/types/globalTypes";
|
||||
import { diff } from "fast-array-diff";
|
||||
import { arrayDiff } from "@saleor/utils/arrays";
|
||||
import { MutationFetchResult } from "react-apollo";
|
||||
|
||||
import {
|
||||
|
@ -40,16 +40,15 @@ function createMetadataUpdateHandler<TData extends MetadataFormData, TError>(
|
|||
|
||||
if (errors.length === 0) {
|
||||
if (data.metadata) {
|
||||
const metaDiff = diff(
|
||||
initial.metadata,
|
||||
data.metadata,
|
||||
(a, b) => a.key === b.key
|
||||
);
|
||||
const initialKeys = initial.metadata.map(m => m.key);
|
||||
const modifiedKeys = data.metadata.map(m => m.key);
|
||||
|
||||
const keyDiff = arrayDiff(initialKeys, modifiedKeys);
|
||||
|
||||
const updateMetaResult = await updateMetadata({
|
||||
id: initial.id,
|
||||
input: data.metadata,
|
||||
keysToDelete: metaDiff.removed.map(meta => meta.key)
|
||||
keysToDelete: keyDiff.removed
|
||||
});
|
||||
const updateMetaErrors = [
|
||||
...(updateMetaResult.data.deleteMetadata.errors || []),
|
||||
|
@ -62,16 +61,15 @@ function createMetadataUpdateHandler<TData extends MetadataFormData, TError>(
|
|||
}
|
||||
|
||||
if (data.privateMetadata) {
|
||||
const privateMetaDiff = diff(
|
||||
initial.privateMetadata,
|
||||
data.privateMetadata,
|
||||
(a, b) => a.key === b.key
|
||||
);
|
||||
const initialKeys = initial.privateMetadata.map(m => m.key);
|
||||
const modifiedKeys = data.privateMetadata.map(m => m.key);
|
||||
|
||||
const keyDiff = arrayDiff(initialKeys, modifiedKeys);
|
||||
|
||||
const updatePrivateMetaResult = await updatePrivateMetadata({
|
||||
id: initial.id,
|
||||
input: data.privateMetadata,
|
||||
keysToDelete: privateMetaDiff.removed.map(meta => meta.key)
|
||||
keysToDelete: keyDiff.removed
|
||||
});
|
||||
|
||||
const updatePrivateMetaErrors = [
|
||||
|
|
Loading…
Reference in a new issue