2021-01-18 15:37:38 +00:00
|
|
|
import {
|
|
|
|
AttributeInput,
|
|
|
|
AttributeInputData
|
|
|
|
} from "@saleor/components/Attributes";
|
2020-12-16 10:53:28 +00:00
|
|
|
import {
|
|
|
|
FileUpload,
|
|
|
|
FileUploadVariables
|
|
|
|
} from "@saleor/files/types/FileUpload";
|
2021-01-18 15:37:38 +00:00
|
|
|
import {
|
|
|
|
FormsetAtomicData,
|
|
|
|
FormsetChange,
|
|
|
|
FormsetData
|
|
|
|
} from "@saleor/hooks/useFormset";
|
2020-12-16 10:53:28 +00:00
|
|
|
import { PageDetails_page_attributes } from "@saleor/pages/types/PageDetails";
|
2021-05-28 09:59:25 +00:00
|
|
|
import { ProductDetails_product_attributes } from "@saleor/products/types/ProductDetails";
|
2021-06-02 19:11:30 +00:00
|
|
|
import { ProductVariantDetails_productVariant_nonSelectionAttributes } from "@saleor/products/types/ProductVariantDetails";
|
2021-01-20 16:37:36 +00:00
|
|
|
import { FetchMoreProps, ReorderEvent } from "@saleor/types";
|
2020-12-16 10:53:28 +00:00
|
|
|
import {
|
2021-01-20 16:37:36 +00:00
|
|
|
AttributeEntityTypeEnum,
|
2020-12-16 10:53:28 +00:00
|
|
|
AttributeInputTypeEnum,
|
|
|
|
AttributeValueInput
|
|
|
|
} from "@saleor/types/globalTypes";
|
2021-01-18 15:37:38 +00:00
|
|
|
import { move, toggle } from "@saleor/utils/lists";
|
2020-12-16 10:53:28 +00:00
|
|
|
import { MutationFetchResult } from "react-apollo";
|
|
|
|
|
|
|
|
import {
|
|
|
|
AttributeValueDelete,
|
|
|
|
AttributeValueDeleteVariables
|
|
|
|
} from "../types/AttributeValueDelete";
|
|
|
|
import { getFileValuesToUploadFromAttributes, isFileValueUnused } from "./data";
|
|
|
|
|
2021-01-18 15:37:38 +00:00
|
|
|
export function createAttributeChangeHandler(
|
|
|
|
changeAttributeData: FormsetChange<string[]>,
|
|
|
|
triggerChange: () => void
|
|
|
|
): FormsetChange<string> {
|
|
|
|
return (attributeId: string, value: string) => {
|
|
|
|
triggerChange();
|
|
|
|
changeAttributeData(attributeId, value === "" ? [] : [value]);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createAttributeMultiChangeHandler(
|
|
|
|
changeAttributeData: FormsetChange<string[]>,
|
|
|
|
attributes: FormsetData<AttributeInputData, string[]>,
|
|
|
|
triggerChange: () => void
|
|
|
|
): FormsetChange<string> {
|
|
|
|
return (attributeId: string, value: string) => {
|
|
|
|
const attribute = attributes.find(
|
|
|
|
attribute => attribute.id === attributeId
|
|
|
|
);
|
|
|
|
|
|
|
|
const newAttributeValues = toggle(
|
|
|
|
value,
|
|
|
|
attribute.value,
|
|
|
|
(a, b) => a === b
|
|
|
|
);
|
|
|
|
|
|
|
|
triggerChange();
|
|
|
|
changeAttributeData(attributeId, newAttributeValues);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createAttributeReferenceChangeHandler(
|
|
|
|
changeAttributeData: FormsetChange<string[]>,
|
|
|
|
triggerChange: () => void
|
|
|
|
): FormsetChange<string[]> {
|
|
|
|
return (attributeId: string, values: string[]) => {
|
|
|
|
changeAttributeData(attributeId, values);
|
|
|
|
triggerChange();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-01-20 16:37:36 +00:00
|
|
|
export function createFetchReferencesHandler(
|
|
|
|
attributes: FormsetData<AttributeInputData, string[]>,
|
|
|
|
assignReferencesAttributeId: string,
|
|
|
|
fetchReferencePages?: (data: string) => void,
|
|
|
|
fetchReferenceProducts?: (data: string) => void
|
|
|
|
) {
|
|
|
|
return (value: string) => {
|
|
|
|
const attribute = attributes?.find(
|
|
|
|
attribute => attribute.id === assignReferencesAttributeId
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!attribute) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
attribute.data.entityType === AttributeEntityTypeEnum.PAGE &&
|
|
|
|
fetchReferencePages
|
|
|
|
) {
|
|
|
|
fetchReferencePages(value);
|
|
|
|
} else if (
|
|
|
|
attribute.data.entityType === AttributeEntityTypeEnum.PRODUCT &&
|
|
|
|
fetchReferenceProducts
|
|
|
|
) {
|
|
|
|
fetchReferenceProducts(value);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createFetchMoreReferencesHandler(
|
|
|
|
attributes: FormsetData<AttributeInputData, string[]>,
|
|
|
|
assignReferencesAttributeId: string,
|
|
|
|
fetchMoreReferencePages?: FetchMoreProps,
|
|
|
|
fetchMoreReferenceProducts?: FetchMoreProps
|
|
|
|
) {
|
|
|
|
const attribute = attributes?.find(
|
|
|
|
attribute => attribute.id === assignReferencesAttributeId
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!attribute) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attribute.data.entityType === AttributeEntityTypeEnum.PAGE) {
|
|
|
|
return fetchMoreReferencePages;
|
|
|
|
} else if (attribute.data.entityType === AttributeEntityTypeEnum.PRODUCT) {
|
|
|
|
return fetchMoreReferenceProducts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-18 15:37:38 +00:00
|
|
|
export function createAttributeFileChangeHandler(
|
|
|
|
changeAttributeData: FormsetChange<string[]>,
|
|
|
|
attributesWithNewFileValue: FormsetData<FormsetData<null, File>>,
|
|
|
|
addAttributeNewFileValue: (data: FormsetAtomicData<null, File>) => void,
|
|
|
|
changeAttributeNewFileValue: FormsetChange<File>,
|
|
|
|
triggerChange: () => void
|
|
|
|
): FormsetChange<File> {
|
|
|
|
return (attributeId: string, value: File) => {
|
|
|
|
triggerChange();
|
|
|
|
|
|
|
|
const newFileValueAssigned = attributesWithNewFileValue.find(
|
|
|
|
attribute => attribute.id === attributeId
|
|
|
|
);
|
|
|
|
|
|
|
|
if (newFileValueAssigned) {
|
|
|
|
changeAttributeNewFileValue(attributeId, value);
|
|
|
|
} else {
|
|
|
|
addAttributeNewFileValue({
|
|
|
|
data: null,
|
|
|
|
id: attributeId,
|
|
|
|
label: null,
|
|
|
|
value
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
changeAttributeData(attributeId, value ? [value.name] : []);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createAttributeValueReorderHandler(
|
|
|
|
changeAttributeData: FormsetChange<string[]>,
|
|
|
|
attributes: FormsetData<AttributeInputData, string[]>,
|
|
|
|
triggerChange: () => void
|
|
|
|
): FormsetChange<ReorderEvent> {
|
|
|
|
return (attributeId: string, reorder: ReorderEvent) => {
|
|
|
|
triggerChange();
|
|
|
|
|
|
|
|
const attribute = attributes.find(
|
|
|
|
attribute => attribute.id === attributeId
|
|
|
|
);
|
|
|
|
|
|
|
|
const reorderedValues = move(
|
|
|
|
attribute.value[reorder.oldIndex],
|
|
|
|
attribute.value,
|
|
|
|
(a, b) => a === b,
|
|
|
|
reorder.newIndex
|
|
|
|
);
|
|
|
|
|
|
|
|
changeAttributeData(attributeId, reorderedValues);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-12-16 10:53:28 +00:00
|
|
|
interface AttributesArgs {
|
|
|
|
attributes: AttributeInput[];
|
|
|
|
updatedFileAttributes: AttributeValueInput[];
|
|
|
|
}
|
|
|
|
|
2021-06-19 23:13:16 +00:00
|
|
|
function getFileInput(
|
|
|
|
attribute: AttributeInput,
|
|
|
|
updatedFileAttributes: AttributeValueInput[]
|
|
|
|
) {
|
|
|
|
const updatedFileAttribute = updatedFileAttributes.find(
|
|
|
|
attributeWithNewFile => attribute.id === attributeWithNewFile.id
|
|
|
|
);
|
|
|
|
|
|
|
|
if (updatedFileAttribute) {
|
|
|
|
return {
|
|
|
|
file: updatedFileAttribute.file,
|
2021-11-08 09:41:27 +00:00
|
|
|
id: updatedFileAttribute.id,
|
|
|
|
contentType: updatedFileAttribute.contentType
|
2021-06-19 23:13:16 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
return {
|
2021-06-23 11:21:13 +00:00
|
|
|
file: attribute.data.selectedValues?.[0]?.file?.url,
|
2021-11-08 09:41:27 +00:00
|
|
|
contentType: attribute.data.selectedValues?.[0]?.file.contentType,
|
2021-06-23 11:21:13 +00:00
|
|
|
id: attribute.id
|
2021-06-19 23:13:16 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function getReferenceInput(attribute: AttributeInput) {
|
|
|
|
return {
|
|
|
|
id: attribute.id,
|
|
|
|
references: attribute.value
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function getRichTextInput(attribute: AttributeInput) {
|
|
|
|
return {
|
|
|
|
id: attribute.id,
|
|
|
|
richText: attribute.value[0]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function getBooleanInput(attribute: AttributeInput) {
|
|
|
|
return {
|
|
|
|
id: attribute.id,
|
|
|
|
boolean: JSON.parse(attribute.value[0] ?? "false")
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-07-29 12:15:14 +00:00
|
|
|
function getDateInput(attribute: AttributeInput) {
|
|
|
|
return {
|
|
|
|
id: attribute.id,
|
|
|
|
date: attribute.value[0]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function getDateTimeInput(attribute: AttributeInput) {
|
|
|
|
return {
|
|
|
|
id: attribute.id,
|
|
|
|
dateTime: attribute.value[0]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-06-19 23:13:16 +00:00
|
|
|
function getDefaultInput(attribute: AttributeInput) {
|
|
|
|
return {
|
|
|
|
id: attribute.id,
|
2021-07-01 11:20:01 +00:00
|
|
|
values: ["", undefined, null].includes(attribute.value[0])
|
|
|
|
? []
|
|
|
|
: attribute.value
|
2021-06-19 23:13:16 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-12-16 10:53:28 +00:00
|
|
|
export const prepareAttributesInput = ({
|
|
|
|
attributes,
|
|
|
|
updatedFileAttributes
|
|
|
|
}: AttributesArgs): AttributeValueInput[] =>
|
|
|
|
attributes.map(attribute => {
|
2021-06-19 23:13:16 +00:00
|
|
|
switch (attribute.data.inputType) {
|
|
|
|
case AttributeInputTypeEnum.FILE:
|
|
|
|
return getFileInput(attribute, updatedFileAttributes);
|
|
|
|
|
|
|
|
case AttributeInputTypeEnum.REFERENCE:
|
|
|
|
return getReferenceInput(attribute);
|
|
|
|
|
|
|
|
case AttributeInputTypeEnum.RICH_TEXT:
|
|
|
|
return getRichTextInput(attribute);
|
|
|
|
|
|
|
|
case AttributeInputTypeEnum.BOOLEAN:
|
|
|
|
return getBooleanInput(attribute);
|
|
|
|
|
2021-07-29 12:15:14 +00:00
|
|
|
case AttributeInputTypeEnum.DATE:
|
|
|
|
return getDateInput(attribute);
|
|
|
|
|
|
|
|
case AttributeInputTypeEnum.DATE_TIME:
|
|
|
|
return getDateTimeInput(attribute);
|
|
|
|
|
2021-06-19 23:13:16 +00:00
|
|
|
default:
|
|
|
|
return getDefaultInput(attribute);
|
2021-04-09 07:51:49 +00:00
|
|
|
}
|
2020-12-16 10:53:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
export const handleUploadMultipleFiles = async (
|
|
|
|
attributesWithNewFileValue: FormsetData<null, File>,
|
|
|
|
uploadFile: (
|
|
|
|
variables: FileUploadVariables
|
|
|
|
) => Promise<MutationFetchResult<FileUpload>>
|
|
|
|
) =>
|
|
|
|
Promise.all(
|
|
|
|
getFileValuesToUploadFromAttributes(attributesWithNewFileValue).map(
|
|
|
|
fileAttribute =>
|
|
|
|
uploadFile({
|
|
|
|
file: fileAttribute.value
|
|
|
|
})
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
export const handleDeleteMultipleAttributeValues = async (
|
|
|
|
attributesWithNewFileValue: FormsetData<null, File>,
|
2021-05-28 09:59:25 +00:00
|
|
|
attributes: Array<
|
2021-06-02 19:11:30 +00:00
|
|
|
| PageDetails_page_attributes
|
|
|
|
| ProductDetails_product_attributes
|
|
|
|
| ProductVariantDetails_productVariant_nonSelectionAttributes
|
2021-05-28 09:59:25 +00:00
|
|
|
>,
|
2020-12-16 10:53:28 +00:00
|
|
|
deleteAttributeValue: (
|
|
|
|
variables: AttributeValueDeleteVariables
|
|
|
|
) => Promise<MutationFetchResult<AttributeValueDelete>>
|
|
|
|
) =>
|
|
|
|
Promise.all(
|
|
|
|
attributes.map(existingAttribute => {
|
|
|
|
const fileValueUnused = isFileValueUnused(
|
|
|
|
attributesWithNewFileValue,
|
|
|
|
existingAttribute
|
|
|
|
);
|
|
|
|
|
|
|
|
if (fileValueUnused) {
|
|
|
|
return deleteAttributeValue({
|
|
|
|
id: existingAttribute.values[0].id
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|