Merge pull request #779 from mirumee/fix/multiple-value-attribute-1399
Fix multiple value dropdown
This commit is contained in:
commit
fb2957e2f5
3 changed files with 127 additions and 31 deletions
|
@ -170,13 +170,15 @@ const MultiAutocompleteSelectFieldComponent: React.FC<MultiAutocompleteSelectFie
|
||||||
/>
|
/>
|
||||||
{isOpen && (!!inputValue || !!choices.length) && (
|
{isOpen && (!!inputValue || !!choices.length) && (
|
||||||
<MultiAutocompleteSelectFieldContent
|
<MultiAutocompleteSelectFieldContent
|
||||||
add={{
|
add={
|
||||||
...add,
|
add && {
|
||||||
onClick: () => {
|
...add,
|
||||||
add.onClick();
|
onClick: () => {
|
||||||
closeMenu();
|
add.onClick();
|
||||||
|
closeMenu();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
choices={choices.filter(
|
choices={choices.filter(
|
||||||
choice => !value.includes(choice.value)
|
choice => !value.includes(choice.value)
|
||||||
)}
|
)}
|
||||||
|
|
111
src/products/utils/handlers.test.ts
Normal file
111
src/products/utils/handlers.test.ts
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
import { FormsetData } from "@saleor/hooks/useFormset";
|
||||||
|
import { AttributeInputTypeEnum } from "@saleor/types/globalTypes";
|
||||||
|
|
||||||
|
import { ProductAttributeInputData } from "../components/ProductAttributes";
|
||||||
|
import { createAttributeMultiChangeHandler } from "./handlers";
|
||||||
|
|
||||||
|
const attributes: FormsetData<ProductAttributeInputData, string[]> = [
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
inputType: AttributeInputTypeEnum.DROPDOWN,
|
||||||
|
isRequired: false,
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
__typename: "AttributeValue",
|
||||||
|
id: "attrv-1",
|
||||||
|
name: "Attribute 1 Value 1",
|
||||||
|
slug: "attr-1-v-1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
id: "attr-1",
|
||||||
|
label: "Attribute 1",
|
||||||
|
value: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
inputType: AttributeInputTypeEnum.MULTISELECT,
|
||||||
|
isRequired: false,
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
__typename: "AttributeValue",
|
||||||
|
id: "attrv-2",
|
||||||
|
name: "Attribute 2 Value 1",
|
||||||
|
slug: "attr-2-v-1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "AttributeValue",
|
||||||
|
id: "attrv-3",
|
||||||
|
name: "Attribute 2 Value 2",
|
||||||
|
slug: "attr-2-v-2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "AttributeValue",
|
||||||
|
id: "attrv-4",
|
||||||
|
name: "Attribute 2 Value 3",
|
||||||
|
slug: "attr-2-v-3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
id: "attr-2",
|
||||||
|
label: "Attribute 2",
|
||||||
|
value: ["attr-2-v-3"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
describe("Multiple select", () => {
|
||||||
|
it("is able to select value", () => {
|
||||||
|
const change = jest.fn();
|
||||||
|
const trigger = jest.fn();
|
||||||
|
const handler = createAttributeMultiChangeHandler(
|
||||||
|
change,
|
||||||
|
attributes,
|
||||||
|
trigger
|
||||||
|
);
|
||||||
|
|
||||||
|
handler("attr-2", "attr-2-v-1");
|
||||||
|
|
||||||
|
expect(change).toHaveBeenCalledTimes(1);
|
||||||
|
expect(change.mock.calls[0][0]).toBe("attr-2");
|
||||||
|
expect(change.mock.calls[0][1]).toHaveLength(2);
|
||||||
|
expect(change.mock.calls[0][1][0]).toBe("attr-2-v-3");
|
||||||
|
expect(change.mock.calls[0][1][1]).toBe("attr-2-v-1");
|
||||||
|
expect(trigger).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is able to deselect value", () => {
|
||||||
|
const change = jest.fn();
|
||||||
|
const trigger = jest.fn();
|
||||||
|
const handler = createAttributeMultiChangeHandler(
|
||||||
|
change,
|
||||||
|
attributes,
|
||||||
|
trigger
|
||||||
|
);
|
||||||
|
|
||||||
|
handler("attr-2", "attr-2-v-3");
|
||||||
|
|
||||||
|
expect(change).toHaveBeenCalledTimes(1);
|
||||||
|
expect(change.mock.calls[0][0]).toBe("attr-2");
|
||||||
|
expect(change.mock.calls[0][1]).toHaveLength(0);
|
||||||
|
expect(trigger).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is able to add custom value", () => {
|
||||||
|
const change = jest.fn();
|
||||||
|
const trigger = jest.fn();
|
||||||
|
const handler = createAttributeMultiChangeHandler(
|
||||||
|
change,
|
||||||
|
attributes,
|
||||||
|
trigger
|
||||||
|
);
|
||||||
|
|
||||||
|
handler("attr-2", "A Value");
|
||||||
|
|
||||||
|
expect(change).toHaveBeenCalledTimes(1);
|
||||||
|
expect(change.mock.calls[0][0]).toBe("attr-2");
|
||||||
|
expect(change.mock.calls[0][1]).toHaveLength(2);
|
||||||
|
expect(change.mock.calls[0][1][0]).toBe("attr-2-v-3");
|
||||||
|
expect(change.mock.calls[0][1][1]).toBe("A Value");
|
||||||
|
expect(trigger).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,4 +1,3 @@
|
||||||
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
|
|
||||||
import { FormChange } from "@saleor/hooks/useForm";
|
import { FormChange } from "@saleor/hooks/useForm";
|
||||||
import { FormsetChange, FormsetData } from "@saleor/hooks/useFormset";
|
import { FormsetChange, FormsetData } from "@saleor/hooks/useFormset";
|
||||||
import { toggle } from "@saleor/utils/lists";
|
import { toggle } from "@saleor/utils/lists";
|
||||||
|
@ -18,38 +17,22 @@ export function createAttributeChangeHandler(
|
||||||
|
|
||||||
export function createAttributeMultiChangeHandler(
|
export function createAttributeMultiChangeHandler(
|
||||||
changeAttributeData: FormsetChange<string[]>,
|
changeAttributeData: FormsetChange<string[]>,
|
||||||
attributes: FormsetData<ProductAttributeInputData>,
|
attributes: FormsetData<ProductAttributeInputData, string[]>,
|
||||||
triggerChange: () => void
|
triggerChange: () => void
|
||||||
): FormsetChange {
|
): FormsetChange {
|
||||||
return (attributeId: string, value: string) => {
|
return (attributeId: string, value: string) => {
|
||||||
const attributeValue = attributes
|
const attribute = attributes.find(
|
||||||
.find(attribute => attribute.id === attributeId)
|
attribute => attribute.id === attributeId
|
||||||
.data.values.find(attributeValue => attributeValue.slug === value);
|
);
|
||||||
|
|
||||||
const valueChoice = {
|
|
||||||
label: attributeValue ? attributeValue.name : value,
|
|
||||||
value
|
|
||||||
};
|
|
||||||
|
|
||||||
const itemIndex = attributes.findIndex(item => item.id === attributeId);
|
|
||||||
const attributeValues: MultiAutocompleteChoiceType[] = attributes[
|
|
||||||
itemIndex
|
|
||||||
].data.values.map(value => ({
|
|
||||||
label: value.name,
|
|
||||||
value: value.id
|
|
||||||
}));
|
|
||||||
|
|
||||||
const newAttributeValues = toggle(
|
const newAttributeValues = toggle(
|
||||||
valueChoice,
|
value,
|
||||||
attributeValues,
|
attribute.value,
|
||||||
(a, b) => a.value === b.value
|
(a, b) => a === b
|
||||||
);
|
);
|
||||||
|
|
||||||
triggerChange();
|
triggerChange();
|
||||||
changeAttributeData(
|
changeAttributeData(attributeId, newAttributeValues);
|
||||||
attributeId,
|
|
||||||
newAttributeValues.map(({ value }) => value)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue