2022-03-09 08:56:55 +00:00
|
|
|
import {
|
|
|
|
AttributeErrorCode,
|
|
|
|
AttributeErrorFragment,
|
|
|
|
useAttributeCreateMutation,
|
|
|
|
useUpdateMetadataMutation,
|
2022-06-21 09:36:55 +00:00
|
|
|
useUpdatePrivateMetadataMutation,
|
2023-01-16 09:45:12 +00:00
|
|
|
} from "@dashboard/graphql";
|
|
|
|
import useListSettings from "@dashboard/hooks/useListSettings";
|
|
|
|
import useLocalPageInfo, {
|
|
|
|
getMaxPage,
|
|
|
|
} from "@dashboard/hooks/useLocalPageInfo";
|
|
|
|
import useNavigator from "@dashboard/hooks/useNavigator";
|
|
|
|
import useNotifier from "@dashboard/hooks/useNotifier";
|
|
|
|
import { getMutationErrors, getStringOrPlaceholder } from "@dashboard/misc";
|
|
|
|
import { ListViews, ReorderEvent } from "@dashboard/types";
|
|
|
|
import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers";
|
|
|
|
import createMetadataCreateHandler from "@dashboard/utils/handlers/metadataCreateHandler";
|
2019-08-09 10:17:04 +00:00
|
|
|
import {
|
|
|
|
add,
|
|
|
|
isSelected,
|
|
|
|
move,
|
|
|
|
remove,
|
2022-06-21 09:36:55 +00:00
|
|
|
updateAtIndex,
|
2023-01-16 09:45:12 +00:00
|
|
|
} from "@dashboard/utils/lists";
|
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, {
|
2022-06-21 09:36:55 +00:00
|
|
|
AttributePageFormData,
|
2020-09-01 14:16:50 +00:00
|
|
|
} from "../../components/AttributePage";
|
2019-08-09 10:17:04 +00:00
|
|
|
import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog";
|
2021-09-21 13:16:21 +00:00
|
|
|
import AttributeValueEditDialog from "../../components/AttributeValueEditDialog";
|
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,
|
2022-06-21 09:36:55 +00:00
|
|
|
attributeUrl,
|
2019-08-09 10:17:04 +00:00
|
|
|
} from "../../urls";
|
2021-09-21 13:16:21 +00:00
|
|
|
import {
|
|
|
|
AttributeValueEditDialogFormData,
|
2022-06-21 09:36:55 +00:00
|
|
|
getAttributeData,
|
2021-09-21 13:16:21 +00:00
|
|
|
} from "../../utils/data";
|
2019-08-09 10:17:04 +00:00
|
|
|
|
|
|
|
interface AttributeDetailsProps {
|
|
|
|
params: AttributeAddUrlQueryParams;
|
|
|
|
}
|
|
|
|
|
2020-11-19 14:42:14 +00:00
|
|
|
const attributeValueAlreadyExistsError: AttributeErrorFragment = {
|
|
|
|
__typename: "AttributeError",
|
|
|
|
code: AttributeErrorCode.ALREADY_EXISTS,
|
2022-03-04 10:52:58 +00:00
|
|
|
field: "name",
|
2022-06-21 09:36:55 +00:00
|
|
|
message: "",
|
2020-03-24 14:05:26 +00:00
|
|
|
};
|
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
function areValuesEqual(
|
|
|
|
a: AttributeValueEditDialogFormData,
|
2022-06-21 09:36:55 +00:00
|
|
|
b: AttributeValueEditDialogFormData,
|
2019-08-09 10:17:04 +00:00
|
|
|
) {
|
|
|
|
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(
|
2022-06-21 09:36:55 +00:00
|
|
|
ListViews.ATTRIBUTE_VALUE_LIST,
|
2021-05-24 11:01:18 +00:00
|
|
|
);
|
2021-05-28 09:59:25 +00:00
|
|
|
|
|
|
|
const {
|
|
|
|
pageInfo,
|
|
|
|
pageValues,
|
|
|
|
loadNextPage,
|
|
|
|
loadPreviousPage,
|
2022-06-21 09:36:55 +00:00
|
|
|
loadPage,
|
2021-05-28 09:59:25 +00:00
|
|
|
} = 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({
|
2022-05-05 07:54:28 +00:00
|
|
|
id: "jTifz+",
|
2022-06-21 09:36:55 +00:00
|
|
|
defaultMessage: "Successfully created attribute",
|
|
|
|
}),
|
2020-08-28 12:45:11 +00:00
|
|
|
});
|
|
|
|
navigate(attributeUrl(data.attributeCreate.attribute.id));
|
|
|
|
}
|
2022-06-21 09:36:55 +00:00
|
|
|
},
|
2020-08-28 12:45:11 +00:00
|
|
|
});
|
2022-03-09 08:56:55 +00:00
|
|
|
const [updateMetadata] = useUpdateMetadataMutation({});
|
|
|
|
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
2020-08-28 12:45:11 +00:00
|
|
|
|
2021-05-28 09:59:25 +00:00
|
|
|
const id = params.id
|
2022-05-05 07:54:28 +00:00
|
|
|
? parseInt(params.id, 10) + pageInfo.startCursor
|
2021-05-28 09:59:25 +00:00
|
|
|
: 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();
|
|
|
|
};
|
2021-09-21 13:16:21 +00:00
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
};
|
2021-09-21 13:16:21 +00:00
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
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);
|
2021-09-21 13:16:21 +00:00
|
|
|
|
2021-05-28 09:59:25 +00:00
|
|
|
const addedToNotVisibleLastPage =
|
|
|
|
newValues.length - pageInfo.startCursor > settings.rowNumber;
|
2021-09-21 13:16:21 +00:00
|
|
|
|
2021-05-28 09:59:25 +00:00
|
|
|
if (addedToNotVisibleLastPage) {
|
|
|
|
const maxPage = getMaxPage(newValues.length, settings.rowNumber);
|
|
|
|
loadPage(maxPage);
|
|
|
|
}
|
2021-09-21 13:16:21 +00:00
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
closeModal();
|
|
|
|
}
|
|
|
|
};
|
2021-09-21 13:16:21 +00:00
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
const handleValueReorder = ({ newIndex, oldIndex }: ReorderEvent) =>
|
2021-05-28 09:59:25 +00:00
|
|
|
setValues(
|
|
|
|
move(
|
|
|
|
values[pageInfo.startCursor + oldIndex],
|
|
|
|
values,
|
|
|
|
areValuesEqual,
|
2022-06-21 09:36:55 +00:00
|
|
|
pageInfo.startCursor + newIndex,
|
|
|
|
),
|
2021-05-28 09:59:25 +00:00
|
|
|
);
|
2019-08-09 10:17:04 +00:00
|
|
|
|
2020-09-01 14:16:50 +00:00
|
|
|
const handleCreate = async (data: AttributePageFormData) => {
|
|
|
|
const result = await attributeCreate({
|
|
|
|
variables: {
|
2022-06-21 09:36:55 +00:00
|
|
|
input: getAttributeData(data, values),
|
|
|
|
},
|
2020-09-01 14:16:50 +00:00
|
|
|
});
|
|
|
|
|
2022-02-01 09:58:06 +00:00
|
|
|
return {
|
|
|
|
id: result.data.attributeCreate?.attribute?.id || null,
|
2022-06-21 09:36:55 +00:00
|
|
|
errors: getMutationErrors(result),
|
2022-02-01 09:58:06 +00:00
|
|
|
};
|
2020-09-01 14:16:50 +00:00
|
|
|
};
|
2022-02-01 09:58:06 +00:00
|
|
|
|
2020-09-01 14:16:50 +00:00
|
|
|
const handleSubmit = createMetadataCreateHandler(
|
|
|
|
handleCreate,
|
|
|
|
updateMetadata,
|
2022-06-21 09:36:55 +00:00
|
|
|
updatePrivateMetadata,
|
2020-09-01 14:16:50 +00:00
|
|
|
);
|
|
|
|
|
2019-08-09 10:17:04 +00:00
|
|
|
return (
|
2021-09-21 13:16:21 +00:00
|
|
|
<AttributePage
|
|
|
|
attribute={null}
|
|
|
|
disabled={attributeCreateOpts.loading}
|
|
|
|
errors={attributeCreateOpts.data?.attributeCreate.errors || []}
|
|
|
|
onDelete={undefined}
|
|
|
|
onSubmit={handleSubmit}
|
|
|
|
onValueAdd={() => openModal("add-value")}
|
|
|
|
onValueDelete={id =>
|
|
|
|
openModal("remove-value", {
|
2022-06-21 09:36:55 +00:00
|
|
|
id,
|
2021-09-21 13:16:21 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
onValueReorder={handleValueReorder}
|
|
|
|
onValueUpdate={id =>
|
|
|
|
openModal("edit-value", {
|
2022-06-21 09:36:55 +00:00
|
|
|
id,
|
2021-09-21 13:16:21 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
saveButtonBarState={attributeCreateOpts.status}
|
|
|
|
values={{
|
|
|
|
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
|
|
|
|
pageInfo: {
|
|
|
|
__typename: "PageInfo" as "PageInfo",
|
|
|
|
endCursor: "",
|
|
|
|
hasNextPage: false,
|
|
|
|
hasPreviousPage: false,
|
2022-06-21 09:36:55 +00:00
|
|
|
startCursor: "",
|
2021-09-21 13:16:21 +00:00
|
|
|
},
|
|
|
|
edges: pageValues.map((value, valueIndex) => ({
|
|
|
|
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
|
|
|
cursor: "1",
|
|
|
|
node: {
|
|
|
|
__typename: "AttributeValue" as "AttributeValue",
|
|
|
|
file: value?.fileUrl
|
|
|
|
? {
|
|
|
|
url: value.fileUrl,
|
|
|
|
contentType: value.contentType,
|
2022-06-21 09:36:55 +00:00
|
|
|
__typename: "File",
|
2021-09-21 13:16:21 +00:00
|
|
|
}
|
|
|
|
: null,
|
|
|
|
id: valueIndex.toString(),
|
|
|
|
reference: null,
|
|
|
|
slug: slugify(value.name).toLowerCase(),
|
|
|
|
sortOrder: valueIndex,
|
|
|
|
value: null,
|
2022-07-19 14:16:43 +00:00
|
|
|
plainText: null,
|
2021-09-21 13:16:21 +00:00
|
|
|
richText: null,
|
|
|
|
boolean: null,
|
|
|
|
date: null,
|
|
|
|
dateTime: null,
|
2022-06-21 09:36:55 +00:00
|
|
|
...value,
|
|
|
|
},
|
|
|
|
})),
|
2021-09-21 13:16:21 +00:00
|
|
|
}}
|
|
|
|
settings={settings}
|
|
|
|
onUpdateListSettings={updateListSettings}
|
|
|
|
pageInfo={pageInfo}
|
|
|
|
onNextPage={loadNextPage}
|
|
|
|
onPreviousPage={loadPreviousPage}
|
|
|
|
>
|
|
|
|
{data => (
|
2020-08-28 12:45:11 +00:00
|
|
|
<>
|
2019-12-06 17:11:46 +00:00
|
|
|
<AttributeValueEditDialog
|
2021-09-21 13:16:21 +00:00
|
|
|
attributeValue={null}
|
2019-12-06 17:11:46 +00:00
|
|
|
confirmButtonState="default"
|
|
|
|
disabled={false}
|
|
|
|
errors={valueErrors}
|
2021-09-21 13:16:21 +00:00
|
|
|
open={params.action === "add-value"}
|
2019-12-06 17:11:46 +00:00
|
|
|
onClose={closeModal}
|
2021-09-21 13:16:21 +00:00
|
|
|
onSubmit={handleValueCreate}
|
|
|
|
inputType={data.inputType}
|
2019-12-06 17:11:46 +00:00
|
|
|
/>
|
2021-09-21 13:16:21 +00:00
|
|
|
{values.length > 0 && (
|
|
|
|
<>
|
|
|
|
<AttributeValueDeleteDialog
|
|
|
|
attributeName={undefined}
|
|
|
|
open={params.action === "remove-value"}
|
|
|
|
name={getStringOrPlaceholder(values[id]?.name)}
|
|
|
|
confirmButtonState="default"
|
|
|
|
onClose={closeModal}
|
|
|
|
onConfirm={handleValueDelete}
|
|
|
|
/>
|
|
|
|
<AttributeValueEditDialog
|
|
|
|
inputType={data.inputType}
|
|
|
|
attributeValue={values[id]}
|
|
|
|
confirmButtonState="default"
|
|
|
|
disabled={false}
|
|
|
|
errors={valueErrors}
|
|
|
|
open={params.action === "edit-value"}
|
|
|
|
onClose={closeModal}
|
|
|
|
onSubmit={handleValueUpdate}
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
)}
|
2019-12-06 17:11:46 +00:00
|
|
|
</>
|
|
|
|
)}
|
2021-09-21 13:16:21 +00:00
|
|
|
</AttributePage>
|
2019-08-09 10:17:04 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
AttributeDetails.displayName = "AttributeDetails";
|
|
|
|
|
|
|
|
export default AttributeDetails;
|