Merge pull request #779 from mirumee/fix/multiple-value-attribute-1399

Fix multiple value dropdown
This commit is contained in:
Marcin Gębala 2020-10-20 08:24:49 +02:00 committed by GitHub
commit fb2957e2f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 31 deletions

View file

@ -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)
)} )}

View 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);
});
});

View file

@ -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)
);
}; };
} }