saleor-dashboard/src/attributes/views/AttributeCreate/AttributeCreate.tsx

255 lines
7.6 KiB
TypeScript
Raw Normal View History

import { getAttributeData } from "@saleor/attributes/utils/data";
Page types (#807) * Create attribute class selector * Use ProductAttributeType to check if product is simple or with variants * Allow attribute class selection only during its creation * Update attribute type selection translations * Show only product attributes in columns picker on product list view * Cleanups in Attribute Organization component * Create Page Types list page * Create content management section in settings * Implement page types list view * Remove unused imports from page type list * Updatte page type list style * Remove legacy code from page type list component * Update PageTypeListPage component * Create Page Types details page * Fix page type attribute reordering * Implement PageType create view * Implement PageType update view * gUpdate page type details components * Fix page type update component * Update page type components stories * Update page type errors handling * Update page type details view * Create Page Types details page * Implement PageType create view * Update product attribute assignment mutations * Add page types attribute assignment mutations * Add page types attribute assignment handling * Temporarily fix page create mutation * Update page type error messages * Remove legacy storybook page type stories * Update attribute assignment dialogs stories * Update page type details error handling * Update props for page type components * Create attribute class selector * Implement page types list view * Add page type selector on page create and details views * Add attributes list to page details views * Update page types list * Use attribute errors for attributes muatations * Save attribute values on page create and update * Update messages for page view * Update page attributes fragment * Use AttributeError in AttributeBulkDelete * Update page type and its attribute selection * Handle page types deleting * Update page types deleting messages * Handle page types attribute reorder * Fix PageOrganizeContent component types * Update graphqql types * Fix page fixture * Update messages * Update test snapshots * Pass pageTypes to PageForm * Update changelog with page type addition note * Update package-lock * Update test snapshots * Fix malformed generated type * Update messages after rebase
2020-11-19 14:42:14 +00:00
import { AttributeErrorFragment } from "@saleor/fragments/types/AttributeErrorFragment";
import useListSettings from "@saleor/hooks/useListSettings";
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";
import { getStringOrPlaceholder } from "@saleor/misc";
import { ListViews, ReorderEvent } from "@saleor/types";
import { AttributeErrorCode } from "@saleor/types/globalTypes";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
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";
import {
useMetadataUpdate,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata";
import React from "react";
import { useIntl } from "react-intl";
import slugify from "slugify";
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";
import { useAttributeCreateMutation } from "../../mutations";
2019-08-09 10:17:04 +00:00
import {
attributeAddUrl,
AttributeAddUrlDialog,
2019-08-09 10:17:04 +00:00
AttributeAddUrlQueryParams,
attributeListUrl,
attributeUrl
2019-08-09 10:17:04 +00:00
} from "../../urls";
interface AttributeDetailsProps {
params: AttributeAddUrlQueryParams;
}
Page types (#807) * Create attribute class selector * Use ProductAttributeType to check if product is simple or with variants * Allow attribute class selection only during its creation * Update attribute type selection translations * Show only product attributes in columns picker on product list view * Cleanups in Attribute Organization component * Create Page Types list page * Create content management section in settings * Implement page types list view * Remove unused imports from page type list * Updatte page type list style * Remove legacy code from page type list component * Update PageTypeListPage component * Create Page Types details page * Fix page type attribute reordering * Implement PageType create view * Implement PageType update view * gUpdate page type details components * Fix page type update component * Update page type components stories * Update page type errors handling * Update page type details view * Create Page Types details page * Implement PageType create view * Update product attribute assignment mutations * Add page types attribute assignment mutations * Add page types attribute assignment handling * Temporarily fix page create mutation * Update page type error messages * Remove legacy storybook page type stories * Update attribute assignment dialogs stories * Update page type details error handling * Update props for page type components * Create attribute class selector * Implement page types list view * Add page type selector on page create and details views * Add attributes list to page details views * Update page types list * Use attribute errors for attributes muatations * Save attribute values on page create and update * Update messages for page view * Update page attributes fragment * Use AttributeError in AttributeBulkDelete * Update page type and its attribute selection * Handle page types deleting * Update page types deleting messages * Handle page types attribute reorder * Fix PageOrganizeContent component types * Update graphqql types * Fix page fixture * Update messages * Update test snapshots * Pass pageTypes to PageForm * Update changelog with page type addition note * Update package-lock * Update test snapshots * Fix malformed generated type * Update messages after rebase
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();
const intl = useIntl();
2019-08-09 10:17:04 +00:00
const [values, setValues] = React.useState<
AttributeValueEditDialogFormData[]
>([]);
Page types (#807) * Create attribute class selector * Use ProductAttributeType to check if product is simple or with variants * Allow attribute class selection only during its creation * Update attribute type selection translations * Show only product attributes in columns picker on product list view * Cleanups in Attribute Organization component * Create Page Types list page * Create content management section in settings * Implement page types list view * Remove unused imports from page type list * Updatte page type list style * Remove legacy code from page type list component * Update PageTypeListPage component * Create Page Types details page * Fix page type attribute reordering * Implement PageType create view * Implement PageType update view * gUpdate page type details components * Fix page type update component * Update page type components stories * Update page type errors handling * Update page type details view * Create Page Types details page * Implement PageType create view * Update product attribute assignment mutations * Add page types attribute assignment mutations * Add page types attribute assignment handling * Temporarily fix page create mutation * Update page type error messages * Remove legacy storybook page type stories * Update attribute assignment dialogs stories * Update page type details error handling * Update props for page type components * Create attribute class selector * Implement page types list view * Add page type selector on page create and details views * Add attributes list to page details views * Update page types list * Use attribute errors for attributes muatations * Save attribute values on page create and update * Update messages for page view * Update page attributes fragment * Use AttributeError in AttributeBulkDelete * Update page type and its attribute selection * Handle page types deleting * Update page types deleting messages * Handle page types attribute reorder * Fix PageOrganizeContent component types * Update graphqql types * Fix page fixture * Update messages * Update test snapshots * Pass pageTypes to PageForm * Update changelog with page type addition note * Update package-lock * Update test snapshots * Fix malformed generated type * Update messages after rebase
2020-11-19 14:42:14 +00:00
const [valueErrors, setValueErrors] = React.useState<
AttributeErrorFragment[]
>([]);
2019-08-09 10:17:04 +00:00
const { updateListSettings, settings } = useListSettings(
ListViews.ATTRIBUTE_VALUE_LIST
);
const {
pageInfo,
pageValues,
loadNextPage,
loadPreviousPage,
loadPage
} = useLocalPageInfo(values, settings?.rowNumber);
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));
}
}
});
const [updateMetadata] = useMetadataUpdate({});
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
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 = () => {
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 {
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) =>
setValues(
move(
values[pageInfo.startCursor + oldIndex],
values,
areValuesEqual,
pageInfo.startCursor + newIndex
)
);
2019-08-09 10:17:04 +00:00
const handleCreate = async (data: AttributePageFormData) => {
const input = getAttributeData(data, values);
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 (
<>
<AttributePage
attribute={null}
disabled={attributeCreateOpts.loading}
errors={attributeCreateOpts.data?.attributeCreate.errors || []}
onBack={() => navigate(attributeListUrl())}
onDelete={undefined}
onSubmit={handleSubmit}
onValueAdd={() => openModal("add-value")}
onValueDelete={id =>
openModal("remove-value", {
id
})
}
onValueReorder={handleValueReorder}
onValueUpdate={id =>
openModal("edit-value", {
id
})
}
saveButtonBarState={attributeCreateOpts.status}
values={{
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
pageInfo: {
__typename: "PageInfo" as "PageInfo",
endCursor: "",
hasNextPage: false,
hasPreviousPage: false,
startCursor: ""
},
edges: pageValues.map((value, valueIndex) => ({
__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}
/>
<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)}
confirmButtonState="default"
onClose={closeModal}
onConfirm={handleValueDelete}
2019-12-06 17:11:46 +00:00
/>
<AttributeValueEditDialog
attributeValue={values[id]}
2019-12-06 17:11:46 +00:00
confirmButtonState="default"
disabled={false}
errors={valueErrors}
open={params.action === "edit-value"}
2019-12-06 17:11:46 +00:00
onClose={closeModal}
onSubmit={handleValueUpdate}
2019-12-06 17:11:46 +00:00
/>
</>
)}
</>
2019-08-09 10:17:04 +00:00
);
};
AttributeDetails.displayName = "AttributeDetails";
export default AttributeDetails;