2021-01-12 11:11:15 +00:00
|
|
|
import { getAttributeData } from "@saleor/attributes/utils/data";
|
2020-11-19 14:42:14 +00:00
|
|
|
import { AttributeErrorFragment } from "@saleor/fragments/types/AttributeErrorFragment";
|
2021-05-24 11:01:18 +00:00
|
|
|
import useListSettings from "@saleor/hooks/useListSettings";
|
2021-05-28 09:59:25 +00:00
|
|
|
import useLocalPageInfo, { getMaxPage } from "@saleor/hooks/useLocalPageInfo";
|
2019-08-09 10:17:04 +00:00
|
|
|
import useNavigator from "@saleor/hooks/useNavigator";
|
|
|
|
import useNotifier from "@saleor/hooks/useNotifier";
|
2020-08-28 12:45:11 +00:00
|
|
|
import { getStringOrPlaceholder } from "@saleor/misc";
|
2021-05-24 11:01:18 +00:00
|
|
|
import { ListViews, ReorderEvent } from "@saleor/types";
|
2021-01-12 11:11:15 +00:00
|
|
|
import { AttributeErrorCode } from "@saleor/types/globalTypes";
|
2020-05-14 09:30:32 +00:00
|
|
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
2020-09-01 14:16:50 +00:00
|
|
|
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
|
2019-08-09 10:17:04 +00:00
|
|
|
import {
|
|
|
|
add,
|
|
|
|
isSelected,
|
|
|
|
move,
|
|
|
|
remove,
|
|
|
|
updateAtIndex
|
|
|
|
} from "@saleor/utils/lists";
|
2020-09-01 14:16:50 +00:00
|
|
|
import {
|
|
|
|
useMetadataUpdate,
|
|
|
|
usePrivateMetadataUpdate
|
|
|
|
} from "@saleor/utils/metadata/updateMetadata";
|
2020-05-14 09:30:32 +00:00
|
|
|
import React from "react";
|
|
|
|
import { useIntl } from "react-intl";
|
|
|
|
import slugify from "slugify";
|
|
|
|
|
2020-09-01 14:16:50 +00:00
|
|
|
import AttributePage, {
|
|
|
|
AttributePageFormData
|
|
|
|
} from "../../components/AttributePage";
|
2019-08-09 10:17:04 +00:00
|
|
|
import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog";
|
|
|
|
import AttributeValueEditDialog, {
|
|
|
|
AttributeValueEditDialogFormData
|
|
|
|
} from "../../components/AttributeValueEditDialog";
|
2020-08-28 12:45:11 +00:00
|
|
|
import { useAttributeCreateMutation } from "../../mutations";
|
2019-08-09 10:17:04 +00:00
|
|
|
import {
|
|
|
|
attributeAddUrl,
|
2020-05-14 09:30:32 +00:00
|
|
|
AttributeAddUrlDialog,
|
2019-08-09 10:17:04 +00:00
|
|
|
AttributeAddUrlQueryParams,
|
|
|
|
attributeListUrl,
|
2020-05-14 09:30:32 +00:00
|
|
|
attributeUrl
|
2019-08-09 10:17:04 +00:00
|
|
|
} from "../../urls";
|
|
|
|
|
|
|
|
interface AttributeDetailsProps {
|
|
|
|
params: AttributeAddUrlQueryParams;
|
|
|
|
}
|
|
|
|
|
2020-11-19 14:42:14 +00:00
|
|
|
const attributeValueAlreadyExistsError: AttributeErrorFragment = {
|
|
|
|
__typename: "AttributeError",
|
|
|
|
code: AttributeErrorCode.ALREADY_EXISTS,
|
2020-03-24 14:05:26 +00:00
|
|
|
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-11-19 14:42:14 +00:00
|
|
|
const [valueErrors, setValueErrors] = React.useState<
|
|
|
|
AttributeErrorFragment[]
|
|
|
|
>([]);
|
2019-08-09 10:17:04 +00:00
|
|
|
|
2021-05-24 11:01:18 +00:00
|
|
|
const { updateListSettings, settings } = useListSettings(
|
|
|
|
ListViews.ATTRIBUTE_VALUE_LIST
|
|
|
|
);
|
2021-05-28 09:59:25 +00:00
|
|
|
|
|
|
|
const {
|
|
|
|
pageInfo,
|
|
|
|
pageValues,
|
|
|
|
loadNextPage,
|
|
|
|
loadPreviousPage,
|
|
|
|
loadPage
|
|
|
|
} = useLocalPageInfo(values, settings?.rowNumber);
|
2021-05-24 11:01:18 +00:00
|
|
|
|
2020-08-28 12:45:11 +00:00
|
|
|
const [attributeCreate, attributeCreateOpts] = useAttributeCreateMutation({
|
|
|
|
onCompleted: data => {
|
|
|
|
if (data.attributeCreate.errors.length === 0) {
|
|
|
|
notify({
|
|
|
|
status: "success",
|
|
|
|
text: intl.formatMessage({
|
|
|
|
defaultMessage: "Successfully created attribute"
|
|
|
|
})
|
|
|
|
});
|
|
|
|
navigate(attributeUrl(data.attributeCreate.attribute.id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2020-09-01 14:16:50 +00:00
|
|
|
const [updateMetadata] = useMetadataUpdate({});
|
|
|
|
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
|
2020-08-28 12:45:11 +00:00
|
|
|
|
2021-05-28 09:59:25 +00:00
|
|
|
const id = params.id
|
|
|
|
? parseInt(params.id, 0) + pageInfo.startCursor
|
|
|
|
: undefined;
|
2019-08-09 10:17:04 +00:00
|
|
|
|
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-24 14:05:26 +00:00
|
|
|
React.useEffect(() => setValueErrors([]), [params.action]);
|
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
const handleValueDelete = () => {
|
2021-05-28 09:59:25 +00:00
|
|
|
const newValues = remove(values[id], values, areValuesEqual);
|
|
|
|
setValues(newValues);
|
2019-08-09 10:17:04 +00:00
|
|
|
closeModal();
|
|
|
|
};
|
|
|
|
const handleValueUpdate = (input: AttributeValueEditDialogFormData) => {
|
|
|
|
if (isSelected(input, values, areValuesEqual)) {
|
2020-03-24 14:05:26 +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-24 14:05:26 +00:00
|
|
|
setValueErrors([attributeValueAlreadyExistsError]);
|
2019-08-09 10:17:04 +00:00
|
|
|
} else {
|
2021-05-28 09:59:25 +00:00
|
|
|
const newValues = add(input, values);
|
|
|
|
setValues(newValues);
|
|
|
|
const addedToNotVisibleLastPage =
|
|
|
|
newValues.length - pageInfo.startCursor > settings.rowNumber;
|
|
|
|
if (addedToNotVisibleLastPage) {
|
|
|
|
const maxPage = getMaxPage(newValues.length, settings.rowNumber);
|
|
|
|
loadPage(maxPage);
|
|
|
|
}
|
2019-08-09 10:17:04 +00:00
|
|
|
closeModal();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const handleValueReorder = ({ newIndex, oldIndex }: ReorderEvent) =>
|
2021-05-28 09:59:25 +00:00
|
|
|
setValues(
|
|
|
|
move(
|
|
|
|
values[pageInfo.startCursor + oldIndex],
|
|
|
|
values,
|
|
|
|
areValuesEqual,
|
|
|
|
pageInfo.startCursor + newIndex
|
|
|
|
)
|
|
|
|
);
|
2019-08-09 10:17:04 +00:00
|
|
|
|
2020-09-01 14:16:50 +00:00
|
|
|
const handleCreate = async (data: AttributePageFormData) => {
|
2021-01-12 11:11:15 +00:00
|
|
|
const input = getAttributeData(data, values);
|
2020-09-01 14:16:50 +00:00
|
|
|
|
|
|
|
const result = await attributeCreate({
|
|
|
|
variables: {
|
|
|
|
input
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return result.data.attributeCreate?.attribute?.id || null;
|
|
|
|
};
|
|
|
|
const handleSubmit = createMetadataCreateHandler(
|
|
|
|
handleCreate,
|
|
|
|
updateMetadata,
|
|
|
|
updatePrivateMetadata
|
|
|
|
);
|
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
return (
|
2020-08-28 12:45:11 +00:00
|
|
|
<>
|
|
|
|
<AttributePage
|
|
|
|
attribute={null}
|
|
|
|
disabled={attributeCreateOpts.loading}
|
|
|
|
errors={attributeCreateOpts.data?.attributeCreate.errors || []}
|
|
|
|
onBack={() => navigate(attributeListUrl())}
|
|
|
|
onDelete={undefined}
|
2020-09-01 14:16:50 +00:00
|
|
|
onSubmit={handleSubmit}
|
2020-08-28 12:45:11 +00:00
|
|
|
onValueAdd={() => openModal("add-value")}
|
|
|
|
onValueDelete={id =>
|
|
|
|
openModal("remove-value", {
|
|
|
|
id
|
|
|
|
})
|
|
|
|
}
|
|
|
|
onValueReorder={handleValueReorder}
|
|
|
|
onValueUpdate={id =>
|
|
|
|
openModal("edit-value", {
|
|
|
|
id
|
|
|
|
})
|
|
|
|
}
|
|
|
|
saveButtonBarState={attributeCreateOpts.status}
|
2021-05-24 11:01:18 +00:00
|
|
|
values={{
|
|
|
|
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
|
|
|
|
pageInfo: {
|
|
|
|
__typename: "PageInfo" as "PageInfo",
|
|
|
|
endCursor: "",
|
|
|
|
hasNextPage: false,
|
|
|
|
hasPreviousPage: false,
|
|
|
|
startCursor: ""
|
|
|
|
},
|
2021-05-28 09:59:25 +00:00
|
|
|
edges: pageValues.map((value, valueIndex) => ({
|
2021-05-24 11:01:18 +00:00
|
|
|
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
|
|
|
cursor: "1",
|
|
|
|
node: {
|
|
|
|
__typename: "AttributeValue" as "AttributeValue",
|
|
|
|
file: null,
|
|
|
|
id: valueIndex.toString(),
|
|
|
|
reference: null,
|
|
|
|
slug: slugify(value.name).toLowerCase(),
|
|
|
|
sortOrder: valueIndex,
|
|
|
|
value: null,
|
|
|
|
richText: null,
|
|
|
|
...value
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
}}
|
|
|
|
settings={settings}
|
|
|
|
onUpdateListSettings={updateListSettings}
|
|
|
|
pageInfo={pageInfo}
|
|
|
|
onNextPage={loadNextPage}
|
|
|
|
onPreviousPage={loadPreviousPage}
|
2020-08-28 12:45:11 +00:00
|
|
|
/>
|
|
|
|
<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"}
|
2020-09-02 09:42:22 +00:00
|
|
|
name={getStringOrPlaceholder(values[id]?.name)}
|
2020-08-28 12:45:11 +00:00
|
|
|
confirmButtonState="default"
|
|
|
|
onClose={closeModal}
|
|
|
|
onConfirm={handleValueDelete}
|
2019-12-06 17:11:46 +00:00
|
|
|
/>
|
|
|
|
<AttributeValueEditDialog
|
2021-05-28 09:59:25 +00:00
|
|
|
attributeValue={values[id]}
|
2019-12-06 17:11:46 +00:00
|
|
|
confirmButtonState="default"
|
|
|
|
disabled={false}
|
|
|
|
errors={valueErrors}
|
2020-08-28 12:45:11 +00:00
|
|
|
open={params.action === "edit-value"}
|
2019-12-06 17:11:46 +00:00
|
|
|
onClose={closeModal}
|
2020-08-28 12:45:11 +00:00
|
|
|
onSubmit={handleValueUpdate}
|
2019-12-06 17:11:46 +00:00
|
|
|
/>
|
|
|
|
</>
|
|
|
|
)}
|
2020-08-28 12:45:11 +00:00
|
|
|
</>
|
2019-08-09 10:17:04 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
AttributeDetails.displayName = "AttributeDetails";
|
|
|
|
|
|
|
|
export default AttributeDetails;
|