2019-08-09 10:17:04 +00:00
|
|
|
import React from "react";
|
2019-08-16 11:47:30 +00:00
|
|
|
import { useIntl } from "react-intl";
|
2019-08-09 10:17:04 +00:00
|
|
|
import slugify from "slugify";
|
|
|
|
|
|
|
|
import useNavigator from "@saleor/hooks/useNavigator";
|
|
|
|
import useNotifier from "@saleor/hooks/useNotifier";
|
2019-12-06 17:11:46 +00:00
|
|
|
import { maybe } from "@saleor/misc";
|
2020-03-04 12:50:25 +00:00
|
|
|
import { ReorderEvent } from "@saleor/types";
|
2019-08-09 10:17:04 +00:00
|
|
|
import {
|
|
|
|
add,
|
|
|
|
isSelected,
|
|
|
|
move,
|
|
|
|
remove,
|
|
|
|
updateAtIndex
|
|
|
|
} from "@saleor/utils/lists";
|
2019-12-06 14:58:28 +00:00
|
|
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
2020-03-04 12:50:25 +00:00
|
|
|
import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
|
|
|
|
import { ProductErrorCode } from "@saleor/types/globalTypes";
|
2019-08-09 10:17:04 +00:00
|
|
|
import AttributePage from "../../components/AttributePage";
|
|
|
|
import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog";
|
|
|
|
import AttributeValueEditDialog, {
|
|
|
|
AttributeValueEditDialogFormData
|
|
|
|
} from "../../components/AttributeValueEditDialog";
|
|
|
|
import { AttributeCreateMutation } from "../../mutations";
|
|
|
|
import { AttributeCreate } from "../../types/AttributeCreate";
|
|
|
|
import {
|
|
|
|
attributeAddUrl,
|
|
|
|
AttributeAddUrlQueryParams,
|
|
|
|
attributeListUrl,
|
2019-12-06 14:58:28 +00:00
|
|
|
attributeUrl,
|
|
|
|
AttributeAddUrlDialog
|
2019-08-09 10:17:04 +00:00
|
|
|
} from "../../urls";
|
|
|
|
|
|
|
|
interface AttributeDetailsProps {
|
|
|
|
params: AttributeAddUrlQueryParams;
|
|
|
|
}
|
|
|
|
|
2020-03-04 12:50:25 +00:00
|
|
|
const attributeValueAlreadyExistsError: ProductErrorFragment = {
|
|
|
|
__typename: "ProductError",
|
|
|
|
code: ProductErrorCode.ALREADY_EXISTS,
|
|
|
|
field: "name"
|
|
|
|
};
|
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
function areValuesEqual(
|
|
|
|
a: AttributeValueEditDialogFormData,
|
|
|
|
b: AttributeValueEditDialogFormData
|
|
|
|
) {
|
|
|
|
return a.name === b.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|
|
|
const navigate = useNavigator();
|
|
|
|
const notify = useNotifier();
|
2019-08-16 11:47:30 +00:00
|
|
|
const intl = useIntl();
|
2019-08-09 10:17:04 +00:00
|
|
|
|
|
|
|
const [values, setValues] = React.useState<
|
|
|
|
AttributeValueEditDialogFormData[]
|
|
|
|
>([]);
|
2020-03-04 12:50:25 +00:00
|
|
|
const [valueErrors, setValueErrors] = React.useState<ProductErrorFragment[]>(
|
|
|
|
[]
|
|
|
|
);
|
2019-08-09 10:17:04 +00:00
|
|
|
|
|
|
|
const id = params.id ? parseInt(params.id, 0) : undefined;
|
|
|
|
|
2019-12-06 14:58:28 +00:00
|
|
|
const [openModal, closeModal] = createDialogActionHandlers<
|
|
|
|
AttributeAddUrlDialog,
|
|
|
|
AttributeAddUrlQueryParams
|
|
|
|
>(navigate, attributeAddUrl, params);
|
2019-08-09 10:17:04 +00:00
|
|
|
|
2020-03-04 12:50:25 +00:00
|
|
|
React.useEffect(() => setValueErrors([]), [params.action]);
|
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
const handleValueDelete = () => {
|
|
|
|
setValues(remove(values[params.id], values, areValuesEqual));
|
|
|
|
closeModal();
|
|
|
|
};
|
|
|
|
const handleCreate = (data: AttributeCreate) => {
|
|
|
|
if (data.attributeCreate.errors.length === 0) {
|
2019-08-16 11:47:30 +00:00
|
|
|
notify({
|
|
|
|
text: intl.formatMessage({
|
2019-08-22 16:19:16 +00:00
|
|
|
defaultMessage: "Successfully created attribute"
|
2019-08-16 11:47:30 +00:00
|
|
|
})
|
|
|
|
});
|
2019-08-09 10:17:04 +00:00
|
|
|
navigate(attributeUrl(data.attributeCreate.attribute.id));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const handleValueUpdate = (input: AttributeValueEditDialogFormData) => {
|
|
|
|
if (isSelected(input, values, areValuesEqual)) {
|
2020-03-04 12:50:25 +00:00
|
|
|
setValueErrors([attributeValueAlreadyExistsError]);
|
2019-08-09 10:17:04 +00:00
|
|
|
} else {
|
|
|
|
setValues(updateAtIndex(input, values, id));
|
|
|
|
closeModal();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const handleValueCreate = (input: AttributeValueEditDialogFormData) => {
|
|
|
|
if (isSelected(input, values, areValuesEqual)) {
|
2020-03-04 12:50:25 +00:00
|
|
|
setValueErrors([attributeValueAlreadyExistsError]);
|
2019-08-09 10:17:04 +00:00
|
|
|
} else {
|
|
|
|
setValues(add(input, values));
|
|
|
|
closeModal();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const handleValueReorder = ({ newIndex, oldIndex }: ReorderEvent) =>
|
|
|
|
setValues(move(values[oldIndex], values, areValuesEqual, newIndex));
|
|
|
|
|
|
|
|
return (
|
|
|
|
<AttributeCreateMutation onCompleted={handleCreate}>
|
2019-12-06 17:11:46 +00:00
|
|
|
{(attributeCreate, attributeCreateOpts) => (
|
|
|
|
<>
|
|
|
|
<AttributePage
|
|
|
|
attribute={null}
|
|
|
|
disabled={false}
|
2020-03-04 12:50:25 +00:00
|
|
|
errors={attributeCreateOpts.data?.attributeCreate.errors || []}
|
2019-12-06 17:11:46 +00:00
|
|
|
onBack={() => navigate(attributeListUrl())}
|
|
|
|
onDelete={undefined}
|
|
|
|
onSubmit={input =>
|
|
|
|
attributeCreate({
|
|
|
|
variables: {
|
|
|
|
input: {
|
|
|
|
...input,
|
|
|
|
storefrontSearchPosition: parseInt(
|
|
|
|
input.storefrontSearchPosition,
|
|
|
|
0
|
|
|
|
),
|
|
|
|
values: values.map(value => ({
|
|
|
|
name: value.name
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
onValueAdd={() => openModal("add-value")}
|
2019-12-06 14:58:28 +00:00
|
|
|
onValueDelete={id =>
|
|
|
|
openModal("remove-value", {
|
|
|
|
id
|
|
|
|
})
|
|
|
|
}
|
2019-12-06 17:11:46 +00:00
|
|
|
onValueReorder={handleValueReorder}
|
2019-12-06 14:58:28 +00:00
|
|
|
onValueUpdate={id =>
|
|
|
|
openModal("edit-value", {
|
|
|
|
id
|
|
|
|
})
|
|
|
|
}
|
2019-12-06 17:17:44 +00:00
|
|
|
saveButtonBarState={attributeCreateOpts.status}
|
2019-12-06 17:11:46 +00:00
|
|
|
values={values.map((value, valueIndex) => ({
|
|
|
|
__typename: "AttributeValue" as "AttributeValue",
|
|
|
|
id: valueIndex.toString(),
|
|
|
|
slug: slugify(value.name).toLowerCase(),
|
|
|
|
sortOrder: valueIndex,
|
|
|
|
type: null,
|
|
|
|
value: null,
|
|
|
|
...value
|
|
|
|
}))}
|
|
|
|
/>
|
|
|
|
<AttributeValueEditDialog
|
|
|
|
attributeValue={null}
|
|
|
|
confirmButtonState="default"
|
|
|
|
disabled={false}
|
|
|
|
errors={valueErrors}
|
|
|
|
open={params.action === "add-value"}
|
|
|
|
onClose={closeModal}
|
|
|
|
onSubmit={handleValueCreate}
|
|
|
|
/>
|
|
|
|
{values.length > 0 && (
|
|
|
|
<>
|
|
|
|
<AttributeValueDeleteDialog
|
|
|
|
attributeName={undefined}
|
|
|
|
open={params.action === "remove-value"}
|
|
|
|
name={maybe(() => values[id].name, "...")}
|
|
|
|
confirmButtonState="default"
|
|
|
|
onClose={closeModal}
|
|
|
|
onConfirm={handleValueDelete}
|
|
|
|
/>
|
|
|
|
<AttributeValueEditDialog
|
|
|
|
attributeValue={maybe(() => values[params.id])}
|
|
|
|
confirmButtonState="default"
|
|
|
|
disabled={false}
|
|
|
|
errors={valueErrors}
|
|
|
|
open={params.action === "edit-value"}
|
|
|
|
onClose={closeModal}
|
|
|
|
onSubmit={handleValueUpdate}
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)}
|
2019-08-09 10:17:04 +00:00
|
|
|
</AttributeCreateMutation>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
AttributeDetails.displayName = "AttributeDetails";
|
|
|
|
|
|
|
|
export default AttributeDetails;
|