Use category search hook
This commit is contained in:
parent
0a7f65727a
commit
e67727af03
11 changed files with 835 additions and 871 deletions
|
@ -19,7 +19,7 @@ import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
||||||
import useSearchQuery from "@saleor/hooks/useSearchQuery";
|
import useSearchQuery from "@saleor/hooks/useSearchQuery";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
import { SearchCategories_search_edges_node } from "../../containers/SearchCategories/types/SearchCategories";
|
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
|
||||||
import Checkbox from "../Checkbox";
|
import Checkbox from "../Checkbox";
|
||||||
|
|
||||||
export interface FormData {
|
export interface FormData {
|
||||||
|
|
|
@ -16,10 +16,10 @@ import usePaginator, {
|
||||||
} from "@saleor/hooks/usePaginator";
|
} from "@saleor/hooks/usePaginator";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
import { commonMessages, sectionNames } from "@saleor/intl";
|
import { commonMessages, sectionNames } from "@saleor/intl";
|
||||||
|
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import { categoryUrl } from "../../categories/urls";
|
import { categoryUrl } from "../../categories/urls";
|
||||||
import { collectionUrl } from "../../collections/urls";
|
import { collectionUrl } from "../../collections/urls";
|
||||||
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config";
|
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config";
|
||||||
import SearchCategories from "../../containers/SearchCategories";
|
|
||||||
import SearchCollections from "../../containers/SearchCollections";
|
import SearchCollections from "../../containers/SearchCollections";
|
||||||
import SearchProducts from "../../containers/SearchProducts";
|
import SearchProducts from "../../containers/SearchProducts";
|
||||||
import { decimal, getMutationState, joinDateTime, maybe } from "../../misc";
|
import { decimal, getMutationState, joinDateTime, maybe } from "../../misc";
|
||||||
|
@ -66,6 +66,12 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
|
||||||
params.ids
|
params.ids
|
||||||
);
|
);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const {
|
||||||
|
search: searchCategories,
|
||||||
|
result: searchCategoriesOpts
|
||||||
|
} = useCategorySearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
});
|
||||||
|
|
||||||
const paginationState = createPaginationState(PAGINATE_BY, params);
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
const changeTab = (tab: SaleDetailsPageTab) => {
|
const changeTab = (tab: SaleDetailsPageTab) => {
|
||||||
|
@ -377,43 +383,33 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SearchProducts>
|
</SearchProducts>
|
||||||
<SearchCategories
|
<AssignCategoriesDialog
|
||||||
variables={DEFAULT_INITIAL_SEARCH_DATA}
|
categories={maybe(() =>
|
||||||
>
|
searchCategoriesOpts.data.search.edges
|
||||||
{({
|
.map(edge => edge.node)
|
||||||
search: searchCategories,
|
.filter(
|
||||||
result: searchCategoriesOpts
|
suggestedCategory => suggestedCategory.id
|
||||||
}) => (
|
)
|
||||||
<AssignCategoriesDialog
|
|
||||||
categories={maybe(() =>
|
|
||||||
searchCategoriesOpts.data.search.edges
|
|
||||||
.map(edge => edge.node)
|
|
||||||
.filter(
|
|
||||||
suggestedCategory =>
|
|
||||||
suggestedCategory.id
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
confirmButtonState={assignTransitionState}
|
|
||||||
open={params.action === "assign-category"}
|
|
||||||
onFetch={searchCategories}
|
|
||||||
loading={searchCategoriesOpts.loading}
|
|
||||||
onClose={closeModal}
|
|
||||||
onSubmit={categories =>
|
|
||||||
saleCataloguesAdd({
|
|
||||||
variables: {
|
|
||||||
...paginationState,
|
|
||||||
id,
|
|
||||||
input: {
|
|
||||||
categories: categories.map(
|
|
||||||
product => product.id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</SearchCategories>
|
confirmButtonState={assignTransitionState}
|
||||||
|
open={params.action === "assign-category"}
|
||||||
|
onFetch={searchCategories}
|
||||||
|
loading={searchCategoriesOpts.loading}
|
||||||
|
onClose={closeModal}
|
||||||
|
onSubmit={categories =>
|
||||||
|
saleCataloguesAdd({
|
||||||
|
variables: {
|
||||||
|
...paginationState,
|
||||||
|
id,
|
||||||
|
input: {
|
||||||
|
categories: categories.map(
|
||||||
|
product => product.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
<SearchCollections
|
<SearchCollections
|
||||||
variables={DEFAULT_INITIAL_SEARCH_DATA}
|
variables={DEFAULT_INITIAL_SEARCH_DATA}
|
||||||
>
|
>
|
||||||
|
|
|
@ -16,10 +16,10 @@ import usePaginator, {
|
||||||
} from "@saleor/hooks/usePaginator";
|
} from "@saleor/hooks/usePaginator";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
import { commonMessages, sectionNames } from "@saleor/intl";
|
import { commonMessages, sectionNames } from "@saleor/intl";
|
||||||
|
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import { categoryUrl } from "../../categories/urls";
|
import { categoryUrl } from "../../categories/urls";
|
||||||
import { collectionUrl } from "../../collections/urls";
|
import { collectionUrl } from "../../collections/urls";
|
||||||
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config";
|
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config";
|
||||||
import SearchCategories from "../../containers/SearchCategories";
|
|
||||||
import SearchCollections from "../../containers/SearchCollections";
|
import SearchCollections from "../../containers/SearchCollections";
|
||||||
import SearchProducts from "../../containers/SearchProducts";
|
import SearchProducts from "../../containers/SearchProducts";
|
||||||
import { decimal, getMutationState, joinDateTime, maybe } from "../../misc";
|
import { decimal, getMutationState, joinDateTime, maybe } from "../../misc";
|
||||||
|
@ -68,6 +68,12 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
|
||||||
params.ids
|
params.ids
|
||||||
);
|
);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const {
|
||||||
|
search: searchCategories,
|
||||||
|
result: searchCategoriesOpts
|
||||||
|
} = useCategorySearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
});
|
||||||
|
|
||||||
const paginationState = createPaginationState(PAGINATE_BY, params);
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
const changeTab = (tab: VoucherDetailsPageTab) => {
|
const changeTab = (tab: VoucherDetailsPageTab) => {
|
||||||
|
@ -420,43 +426,33 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
|
||||||
toggle={toggle}
|
toggle={toggle}
|
||||||
toggleAll={toggleAll}
|
toggleAll={toggleAll}
|
||||||
/>
|
/>
|
||||||
<SearchCategories
|
<AssignCategoriesDialog
|
||||||
variables={DEFAULT_INITIAL_SEARCH_DATA}
|
categories={maybe(() =>
|
||||||
>
|
searchCategoriesOpts.data.search.edges
|
||||||
{({
|
.map(edge => edge.node)
|
||||||
search: searchCategories,
|
.filter(
|
||||||
result: searchCategoriesOpts
|
suggestedCategory => suggestedCategory.id
|
||||||
}) => (
|
)
|
||||||
<AssignCategoriesDialog
|
|
||||||
categories={maybe(() =>
|
|
||||||
searchCategoriesOpts.data.search.edges
|
|
||||||
.map(edge => edge.node)
|
|
||||||
.filter(
|
|
||||||
suggestedCategory =>
|
|
||||||
suggestedCategory.id
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
confirmButtonState={assignTransitionState}
|
|
||||||
open={params.action === "assign-category"}
|
|
||||||
onFetch={searchCategories}
|
|
||||||
loading={searchCategoriesOpts.loading}
|
|
||||||
onClose={closeModal}
|
|
||||||
onSubmit={categories =>
|
|
||||||
voucherCataloguesAdd({
|
|
||||||
variables: {
|
|
||||||
...paginationState,
|
|
||||||
id,
|
|
||||||
input: {
|
|
||||||
categories: categories.map(
|
|
||||||
product => product.id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</SearchCategories>
|
confirmButtonState={assignTransitionState}
|
||||||
|
open={params.action === "assign-category"}
|
||||||
|
onFetch={searchCategories}
|
||||||
|
loading={searchCategoriesOpts.loading}
|
||||||
|
onClose={closeModal}
|
||||||
|
onSubmit={categories =>
|
||||||
|
voucherCataloguesAdd({
|
||||||
|
variables: {
|
||||||
|
...paginationState,
|
||||||
|
id,
|
||||||
|
input: {
|
||||||
|
categories: categories.map(
|
||||||
|
product => product.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
<SearchCollections
|
<SearchCollections
|
||||||
variables={DEFAULT_INITIAL_SEARCH_DATA}
|
variables={DEFAULT_INITIAL_SEARCH_DATA}
|
||||||
>
|
>
|
||||||
|
|
|
@ -14,13 +14,13 @@ import ConfirmButton, {
|
||||||
ConfirmButtonTransitionState
|
ConfirmButtonTransitionState
|
||||||
} from "@saleor/components/ConfirmButton";
|
} from "@saleor/components/ConfirmButton";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import { SearchCategories_search_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories";
|
|
||||||
import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections";
|
import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections";
|
||||||
import { SearchPages_search_edges_node } from "@saleor/containers/SearchPages/types/SearchPages";
|
import { SearchPages_search_edges_node } from "@saleor/containers/SearchPages/types/SearchPages";
|
||||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||||
import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
|
import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
import { buttonMessages, sectionNames } from "@saleor/intl";
|
import { buttonMessages, sectionNames } from "@saleor/intl";
|
||||||
|
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
|
||||||
import { UserError } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
import { getErrors, getFieldError } from "@saleor/utils/errors";
|
import { getErrors, getFieldError } from "@saleor/utils/errors";
|
||||||
import { getMenuItemByValue, IMenu } from "@saleor/utils/menu";
|
import { getMenuItemByValue, IMenu } from "@saleor/utils/menu";
|
||||||
|
|
|
@ -5,10 +5,10 @@ import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import ActionDialog from "@saleor/components/ActionDialog";
|
import ActionDialog from "@saleor/components/ActionDialog";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import { categoryUrl } from "../../../categories/urls";
|
import { categoryUrl } from "../../../categories/urls";
|
||||||
import { collectionUrl } from "../../../collections/urls";
|
import { collectionUrl } from "../../../collections/urls";
|
||||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config";
|
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config";
|
||||||
import SearchCategories from "../../../containers/SearchCategories";
|
|
||||||
import SearchCollections from "../../../containers/SearchCollections";
|
import SearchCollections from "../../../containers/SearchCollections";
|
||||||
import SearchPages from "../../../containers/SearchPages";
|
import SearchPages from "../../../containers/SearchPages";
|
||||||
import { getMutationState, maybe } from "../../../misc";
|
import { getMutationState, maybe } from "../../../misc";
|
||||||
|
@ -59,6 +59,9 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const categorySearch = useCategorySearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
});
|
||||||
|
|
||||||
const closeModal = () =>
|
const closeModal = () =>
|
||||||
navigate(
|
navigate(
|
||||||
|
@ -97,324 +100,304 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
|
||||||
return (
|
return (
|
||||||
<SearchPages variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
<SearchPages variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
||||||
{pageSearch => (
|
{pageSearch => (
|
||||||
<SearchCategories variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
||||||
{categorySearch => (
|
{collectionSearch => (
|
||||||
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
<MenuDetailsQuery displayLoader variables={{ id }}>
|
||||||
{collectionSearch => (
|
{({ data, loading, refetch }) => {
|
||||||
<MenuDetailsQuery displayLoader variables={{ id }}>
|
const handleQueryChange = (query: string) => {
|
||||||
{({ data, loading, refetch }) => {
|
categorySearch.search(query);
|
||||||
const handleQueryChange = (query: string) => {
|
collectionSearch.search(query);
|
||||||
categorySearch.search(query);
|
pageSearch.search(query);
|
||||||
collectionSearch.search(query);
|
};
|
||||||
pageSearch.search(query);
|
|
||||||
};
|
|
||||||
|
|
||||||
const categories = maybe(
|
const categories = maybe(
|
||||||
() =>
|
() =>
|
||||||
categorySearch.result.data.search.edges.map(
|
categorySearch.result.data.search.edges.map(
|
||||||
edge => edge.node
|
edge => edge.node
|
||||||
),
|
),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const collections = maybe(
|
const collections = maybe(
|
||||||
() =>
|
() =>
|
||||||
collectionSearch.result.data.search.edges.map(
|
collectionSearch.result.data.search.edges.map(
|
||||||
edge => edge.node
|
edge => edge.node
|
||||||
),
|
),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const pages = maybe(
|
const pages = maybe(
|
||||||
() =>
|
() =>
|
||||||
pageSearch.result.data.search.edges.map(
|
pageSearch.result.data.search.edges.map(edge => edge.node),
|
||||||
edge => edge.node
|
[]
|
||||||
),
|
);
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuDeleteMutation
|
<MenuDeleteMutation
|
||||||
|
onCompleted={data =>
|
||||||
|
handleDelete(data, navigate, notify, intl)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{(menuDelete, menuDeleteOpts) => (
|
||||||
|
<MenuUpdateMutation
|
||||||
onCompleted={data =>
|
onCompleted={data =>
|
||||||
handleDelete(data, navigate, notify, intl)
|
handleUpdate(data, notify, refetch, intl)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{(menuDelete, menuDeleteOpts) => (
|
{(menuUpdate, menuUpdateOpts) => {
|
||||||
<MenuUpdateMutation
|
const deleteState = getMutationState(
|
||||||
onCompleted={data =>
|
menuDeleteOpts.called,
|
||||||
handleUpdate(data, notify, refetch, intl)
|
menuDeleteOpts.loading,
|
||||||
}
|
maybe(() => menuDeleteOpts.data.menuDelete.errors)
|
||||||
>
|
);
|
||||||
{(menuUpdate, menuUpdateOpts) => {
|
|
||||||
const deleteState = getMutationState(
|
|
||||||
menuDeleteOpts.called,
|
|
||||||
menuDeleteOpts.loading,
|
|
||||||
maybe(
|
|
||||||
() => menuDeleteOpts.data.menuDelete.errors
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateState = getMutationState(
|
const updateState = getMutationState(
|
||||||
menuUpdateOpts.called,
|
menuUpdateOpts.called,
|
||||||
menuUpdateOpts.loading,
|
menuUpdateOpts.loading,
|
||||||
maybe(
|
maybe(() => menuUpdateOpts.data.menuUpdate.errors),
|
||||||
() => menuUpdateOpts.data.menuUpdate.errors
|
maybe(() => menuUpdateOpts.data.menuItemMove.errors)
|
||||||
),
|
);
|
||||||
maybe(
|
|
||||||
() => menuUpdateOpts.data.menuItemMove.errors
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// This is a workaround to let know <MenuDetailsPage />
|
// This is a workaround to let know <MenuDetailsPage />
|
||||||
// that it should clean operation stack if mutations
|
// that it should clean operation stack if mutations
|
||||||
// were successful
|
// were successful
|
||||||
const handleSubmit = async (
|
const handleSubmit = async (
|
||||||
data: MenuDetailsSubmitData
|
data: MenuDetailsSubmitData
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const result = await menuUpdate({
|
const result = await menuUpdate({
|
||||||
variables: {
|
variables: {
|
||||||
id,
|
id,
|
||||||
moves: getMoves(data),
|
moves: getMoves(data),
|
||||||
name: data.name,
|
name: data.name,
|
||||||
removeIds: getRemoveIds(data)
|
removeIds: getRemoveIds(data)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result) {
|
if (result) {
|
||||||
if (
|
if (
|
||||||
result.data.menuItemBulkDelete.errors
|
result.data.menuItemBulkDelete.errors.length >
|
||||||
.length > 0 ||
|
0 ||
|
||||||
result.data.menuItemMove.errors.length >
|
result.data.menuItemMove.errors.length > 0 ||
|
||||||
0 ||
|
result.data.menuUpdate.errors.length > 0
|
||||||
result.data.menuUpdate.errors.length > 0
|
) {
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuDetailsPage
|
<MenuDetailsPage
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
menu={maybe(() => data.menu)}
|
menu={maybe(() => data.menu)}
|
||||||
onBack={() => navigate(menuListUrl())}
|
onBack={() => navigate(menuListUrl())}
|
||||||
onDelete={() =>
|
onDelete={() =>
|
||||||
navigate(
|
navigate(
|
||||||
menuUrl(id, {
|
menuUrl(id, {
|
||||||
action: "remove"
|
action: "remove"
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onItemAdd={() =>
|
||||||
|
navigate(
|
||||||
|
menuUrl(id, {
|
||||||
|
action: "add-item"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onItemClick={handleItemClick}
|
||||||
|
onItemEdit={itemId =>
|
||||||
|
navigate(
|
||||||
|
menuUrl(id, {
|
||||||
|
action: "edit-item",
|
||||||
|
id: itemId
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
saveButtonState={updateState}
|
||||||
|
/>
|
||||||
|
<ActionDialog
|
||||||
|
open={params.action === "remove"}
|
||||||
|
onClose={closeModal}
|
||||||
|
confirmButtonState={deleteState}
|
||||||
|
onConfirm={() =>
|
||||||
|
menuDelete({ variables: { id } })
|
||||||
|
}
|
||||||
|
variant="delete"
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Delete Menu",
|
||||||
|
description: "dialog header",
|
||||||
|
id: "menuDetailsDeleteMenuHeader"
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<DialogContentText>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Are you sure you want to delete menu {menuName}?"
|
||||||
|
id="menuDetailsDeleteMenuContent"
|
||||||
|
values={{
|
||||||
|
menuName: (
|
||||||
|
<strong>
|
||||||
|
{maybe(() => data.menu.name, "...")}
|
||||||
|
</strong>
|
||||||
)
|
)
|
||||||
}
|
}}
|
||||||
onItemAdd={() =>
|
|
||||||
navigate(
|
|
||||||
menuUrl(id, {
|
|
||||||
action: "add-item"
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onItemClick={handleItemClick}
|
|
||||||
onItemEdit={itemId =>
|
|
||||||
navigate(
|
|
||||||
menuUrl(id, {
|
|
||||||
action: "edit-item",
|
|
||||||
id: itemId
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
saveButtonState={updateState}
|
|
||||||
/>
|
/>
|
||||||
<ActionDialog
|
</DialogContentText>
|
||||||
open={params.action === "remove"}
|
</ActionDialog>
|
||||||
onClose={closeModal}
|
|
||||||
confirmButtonState={deleteState}
|
|
||||||
onConfirm={() =>
|
|
||||||
menuDelete({ variables: { id } })
|
|
||||||
}
|
|
||||||
variant="delete"
|
|
||||||
title={intl.formatMessage({
|
|
||||||
defaultMessage: "Delete Menu",
|
|
||||||
description: "dialog header",
|
|
||||||
id: "menuDetailsDeleteMenuHeader"
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<DialogContentText>
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Are you sure you want to delete menu {menuName}?"
|
|
||||||
id="menuDetailsDeleteMenuContent"
|
|
||||||
values={{
|
|
||||||
menuName: (
|
|
||||||
<strong>
|
|
||||||
{maybe(
|
|
||||||
() => data.menu.name,
|
|
||||||
"..."
|
|
||||||
)}
|
|
||||||
</strong>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContentText>
|
|
||||||
</ActionDialog>
|
|
||||||
|
|
||||||
<MenuItemCreateMutation
|
<MenuItemCreateMutation
|
||||||
onCompleted={data =>
|
onCompleted={data =>
|
||||||
handleItemCreate(
|
handleItemCreate(
|
||||||
data,
|
data,
|
||||||
notify,
|
notify,
|
||||||
closeModal,
|
closeModal,
|
||||||
intl
|
intl
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{(menuItemCreate, menuItemCreateOpts) => {
|
{(menuItemCreate, menuItemCreateOpts) => {
|
||||||
const handleSubmit = (
|
const handleSubmit = (
|
||||||
data: MenuItemDialogFormData
|
data: MenuItemDialogFormData
|
||||||
) => {
|
) => {
|
||||||
const variables: MenuItemCreateVariables = {
|
const variables: MenuItemCreateVariables = {
|
||||||
input: getMenuItemCreateInputData(
|
input: getMenuItemCreateInputData(
|
||||||
id,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
menuItemCreate({ variables });
|
|
||||||
};
|
|
||||||
|
|
||||||
const formTransitionState = getMutationState(
|
|
||||||
menuItemCreateOpts.called,
|
|
||||||
menuItemCreateOpts.loading,
|
|
||||||
maybe(
|
|
||||||
() =>
|
|
||||||
menuItemCreateOpts.data
|
|
||||||
.menuItemCreate.errors
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MenuItemDialog
|
|
||||||
open={params.action === "add-item"}
|
|
||||||
categories={categories}
|
|
||||||
collections={collections}
|
|
||||||
errors={maybe(
|
|
||||||
() =>
|
|
||||||
menuItemCreateOpts.data
|
|
||||||
.menuItemCreate.errors,
|
|
||||||
[]
|
|
||||||
)}
|
|
||||||
pages={pages}
|
|
||||||
loading={
|
|
||||||
categorySearch.result.loading ||
|
|
||||||
collectionSearch.result.loading
|
|
||||||
}
|
|
||||||
confirmButtonState={
|
|
||||||
formTransitionState
|
|
||||||
}
|
|
||||||
disabled={menuItemCreateOpts.loading}
|
|
||||||
onClose={closeModal}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
onQueryChange={handleQueryChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</MenuItemCreateMutation>
|
|
||||||
<MenuItemUpdateMutation
|
|
||||||
onCompleted={data =>
|
|
||||||
handleItemUpdate(
|
|
||||||
data,
|
|
||||||
id,
|
id,
|
||||||
navigate,
|
data
|
||||||
notify,
|
|
||||||
intl
|
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
>
|
|
||||||
{(menuItemUpdate, menuItemUpdateOpts) => {
|
|
||||||
const handleSubmit = (
|
|
||||||
data: MenuItemDialogFormData
|
|
||||||
) => {
|
|
||||||
const variables: MenuItemUpdateVariables = {
|
|
||||||
id: params.id,
|
|
||||||
input: getMenuItemInputData(data)
|
|
||||||
};
|
|
||||||
|
|
||||||
menuItemUpdate({ variables });
|
menuItemCreate({ variables });
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuItem = maybe(() =>
|
const formTransitionState = getMutationState(
|
||||||
getNode(
|
menuItemCreateOpts.called,
|
||||||
data.menu.items,
|
menuItemCreateOpts.loading,
|
||||||
findNode(data.menu.items, params.id)
|
maybe(
|
||||||
)
|
() =>
|
||||||
);
|
menuItemCreateOpts.data.menuItemCreate
|
||||||
|
.errors
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const formTransitionState = getMutationState(
|
return (
|
||||||
menuItemUpdateOpts.called,
|
<MenuItemDialog
|
||||||
menuItemUpdateOpts.loading,
|
open={params.action === "add-item"}
|
||||||
maybe(
|
categories={categories}
|
||||||
() =>
|
collections={collections}
|
||||||
menuItemUpdateOpts.data
|
errors={maybe(
|
||||||
.menuItemUpdate.errors
|
() =>
|
||||||
)
|
menuItemCreateOpts.data.menuItemCreate
|
||||||
);
|
.errors,
|
||||||
|
[]
|
||||||
|
)}
|
||||||
|
pages={pages}
|
||||||
|
loading={
|
||||||
|
categorySearch.result.loading ||
|
||||||
|
collectionSearch.result.loading
|
||||||
|
}
|
||||||
|
confirmButtonState={formTransitionState}
|
||||||
|
disabled={menuItemCreateOpts.loading}
|
||||||
|
onClose={closeModal}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
onQueryChange={handleQueryChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</MenuItemCreateMutation>
|
||||||
|
<MenuItemUpdateMutation
|
||||||
|
onCompleted={data =>
|
||||||
|
handleItemUpdate(
|
||||||
|
data,
|
||||||
|
id,
|
||||||
|
navigate,
|
||||||
|
notify,
|
||||||
|
intl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{(menuItemUpdate, menuItemUpdateOpts) => {
|
||||||
|
const handleSubmit = (
|
||||||
|
data: MenuItemDialogFormData
|
||||||
|
) => {
|
||||||
|
const variables: MenuItemUpdateVariables = {
|
||||||
|
id: params.id,
|
||||||
|
input: getMenuItemInputData(data)
|
||||||
|
};
|
||||||
|
|
||||||
const initialFormData: MenuItemDialogFormData = {
|
menuItemUpdate({ variables });
|
||||||
id: maybe(() => getItemId(menuItem)),
|
};
|
||||||
name: maybe(() => menuItem.name, "..."),
|
|
||||||
type: maybe<MenuItemType>(
|
|
||||||
() => getItemType(menuItem),
|
|
||||||
"category"
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
const menuItem = maybe(() =>
|
||||||
<MenuItemDialog
|
getNode(
|
||||||
open={params.action === "edit-item"}
|
data.menu.items,
|
||||||
categories={categories}
|
findNode(data.menu.items, params.id)
|
||||||
collections={collections}
|
)
|
||||||
errors={maybe(
|
);
|
||||||
() =>
|
|
||||||
menuItemUpdateOpts.data
|
const formTransitionState = getMutationState(
|
||||||
.menuItemUpdate.errors,
|
menuItemUpdateOpts.called,
|
||||||
[]
|
menuItemUpdateOpts.loading,
|
||||||
)}
|
maybe(
|
||||||
pages={pages}
|
() =>
|
||||||
initial={initialFormData}
|
menuItemUpdateOpts.data.menuItemUpdate
|
||||||
initialDisplayValue={getInitialDisplayValue(
|
.errors
|
||||||
menuItem
|
)
|
||||||
)}
|
);
|
||||||
loading={
|
|
||||||
categorySearch.result.loading ||
|
const initialFormData: MenuItemDialogFormData = {
|
||||||
collectionSearch.result.loading
|
id: maybe(() => getItemId(menuItem)),
|
||||||
}
|
name: maybe(() => menuItem.name, "..."),
|
||||||
confirmButtonState={
|
type: maybe<MenuItemType>(
|
||||||
formTransitionState
|
() => getItemType(menuItem),
|
||||||
}
|
"category"
|
||||||
disabled={menuItemUpdateOpts.loading}
|
)
|
||||||
onClose={closeModal}
|
};
|
||||||
onSubmit={handleSubmit}
|
|
||||||
onQueryChange={handleQueryChange}
|
return (
|
||||||
/>
|
<MenuItemDialog
|
||||||
);
|
open={params.action === "edit-item"}
|
||||||
}}
|
categories={categories}
|
||||||
</MenuItemUpdateMutation>
|
collections={collections}
|
||||||
</>
|
errors={maybe(
|
||||||
);
|
() =>
|
||||||
}}
|
menuItemUpdateOpts.data.menuItemUpdate
|
||||||
</MenuUpdateMutation>
|
.errors,
|
||||||
)}
|
[]
|
||||||
</MenuDeleteMutation>
|
)}
|
||||||
);
|
pages={pages}
|
||||||
}}
|
initial={initialFormData}
|
||||||
</MenuDetailsQuery>
|
initialDisplayValue={getInitialDisplayValue(
|
||||||
)}
|
menuItem
|
||||||
</SearchCollections>
|
)}
|
||||||
|
loading={
|
||||||
|
categorySearch.result.loading ||
|
||||||
|
collectionSearch.result.loading
|
||||||
|
}
|
||||||
|
confirmButtonState={formTransitionState}
|
||||||
|
disabled={menuItemUpdateOpts.loading}
|
||||||
|
onClose={closeModal}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
onQueryChange={handleQueryChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</MenuItemUpdateMutation>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</MenuUpdateMutation>
|
||||||
|
)}
|
||||||
|
</MenuDeleteMutation>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</MenuDetailsQuery>
|
||||||
)}
|
)}
|
||||||
</SearchCategories>
|
</SearchCollections>
|
||||||
)}
|
)}
|
||||||
</SearchPages>
|
</SearchPages>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,7 +13,6 @@ import PageHeader from "@saleor/components/PageHeader";
|
||||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
import SeoForm from "@saleor/components/SeoForm";
|
import SeoForm from "@saleor/components/SeoForm";
|
||||||
import VisibilityCard from "@saleor/components/VisibilityCard";
|
import VisibilityCard from "@saleor/components/VisibilityCard";
|
||||||
import { SearchCategories_search_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories";
|
|
||||||
import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections";
|
import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections";
|
||||||
import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes";
|
import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes";
|
||||||
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
||||||
|
@ -25,6 +24,7 @@ import {
|
||||||
ProductAttributeValueChoices,
|
ProductAttributeValueChoices,
|
||||||
ProductType
|
ProductType
|
||||||
} from "@saleor/products/utils/data";
|
} from "@saleor/products/utils/data";
|
||||||
|
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
|
||||||
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
||||||
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
||||||
import { FetchMoreProps, UserError } from "../../../types";
|
import { FetchMoreProps, UserError } from "../../../types";
|
||||||
|
|
|
@ -12,13 +12,13 @@ import PageHeader from "@saleor/components/PageHeader";
|
||||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
import SeoForm from "@saleor/components/SeoForm";
|
import SeoForm from "@saleor/components/SeoForm";
|
||||||
import VisibilityCard from "@saleor/components/VisibilityCard";
|
import VisibilityCard from "@saleor/components/VisibilityCard";
|
||||||
import { SearchCategories_search_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories";
|
|
||||||
import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections";
|
import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections";
|
||||||
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
||||||
import useFormset from "@saleor/hooks/useFormset";
|
import useFormset from "@saleor/hooks/useFormset";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { maybe } from "@saleor/misc";
|
import { maybe } from "@saleor/misc";
|
||||||
|
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
|
||||||
import { FetchMoreProps, ListActions, UserError } from "@saleor/types";
|
import { FetchMoreProps, ListActions, UserError } from "@saleor/types";
|
||||||
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
||||||
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
||||||
|
|
|
@ -6,8 +6,8 @@ import SearchProductTypes from "@saleor/containers/SearchProductTypes";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
|
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config";
|
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config";
|
||||||
import SearchCategories from "../../containers/SearchCategories";
|
|
||||||
import SearchCollections from "../../containers/SearchCollections";
|
import SearchCollections from "../../containers/SearchCollections";
|
||||||
import { decimal, getMutationState, maybe } from "../../misc";
|
import { decimal, getMutationState, maybe } from "../../misc";
|
||||||
import ProductCreatePage, {
|
import ProductCreatePage, {
|
||||||
|
@ -26,174 +26,171 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = () => {
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
const shop = useShop();
|
const shop = useShop();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const {
|
||||||
|
loadMore: loadMoreCategories,
|
||||||
|
search: searchCategory,
|
||||||
|
result: searchCategoryOpts
|
||||||
|
} = useCategorySearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
});
|
||||||
|
|
||||||
const handleBack = () => navigate(productListUrl());
|
const handleBack = () => navigate(productListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SearchCategories variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
||||||
{({
|
{({
|
||||||
loadMore: loadMoreCategories,
|
loadMore: loadMoreCollections,
|
||||||
search: searchCategory,
|
search: searchCollection,
|
||||||
result: searchCategoryOpts
|
result: searchCollectionOpts
|
||||||
}) => (
|
}) => (
|
||||||
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
<SearchProductTypes variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
||||||
{({
|
{({
|
||||||
loadMore: loadMoreCollections,
|
loadMore: loadMoreProductTypes,
|
||||||
search: searchCollection,
|
search: searchProductTypes,
|
||||||
result: searchCollectionOpts
|
result: searchProductTypesOpts
|
||||||
}) => (
|
}) => {
|
||||||
<SearchProductTypes variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
const handleSuccess = (data: ProductCreate) => {
|
||||||
{({
|
if (data.productCreate.errors.length === 0) {
|
||||||
loadMore: loadMoreProductTypes,
|
notify({
|
||||||
search: searchProductTypes,
|
text: intl.formatMessage({
|
||||||
result: searchProductTypesOpts
|
defaultMessage: "Product created"
|
||||||
}) => {
|
})
|
||||||
const handleSuccess = (data: ProductCreate) => {
|
});
|
||||||
if (data.productCreate.errors.length === 0) {
|
navigate(productUrl(data.productCreate.product.id));
|
||||||
notify({
|
} else {
|
||||||
text: intl.formatMessage({
|
const attributeError = data.productCreate.errors.find(
|
||||||
defaultMessage: "Product created"
|
err => err.field === "attributes"
|
||||||
})
|
|
||||||
});
|
|
||||||
navigate(productUrl(data.productCreate.product.id));
|
|
||||||
} else {
|
|
||||||
const attributeError = data.productCreate.errors.find(
|
|
||||||
err => err.field === "attributes"
|
|
||||||
);
|
|
||||||
if (!!attributeError) {
|
|
||||||
notify({ text: attributeError.message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TypedProductCreateMutation onCompleted={handleSuccess}>
|
|
||||||
{(
|
|
||||||
productCreate,
|
|
||||||
{
|
|
||||||
called: productCreateCalled,
|
|
||||||
data: productCreateData,
|
|
||||||
loading: productCreateDataLoading
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
const handleSubmit = (
|
|
||||||
formData: ProductCreatePageSubmitData
|
|
||||||
) => {
|
|
||||||
productCreate({
|
|
||||||
variables: {
|
|
||||||
attributes: formData.attributes.map(attribute => ({
|
|
||||||
id: attribute.id,
|
|
||||||
values: attribute.value
|
|
||||||
})),
|
|
||||||
basePrice: decimal(formData.basePrice),
|
|
||||||
category: formData.category,
|
|
||||||
chargeTaxes: formData.chargeTaxes,
|
|
||||||
collections: formData.collections,
|
|
||||||
descriptionJson: JSON.stringify(
|
|
||||||
formData.description
|
|
||||||
),
|
|
||||||
isPublished: formData.isPublished,
|
|
||||||
name: formData.name,
|
|
||||||
productType: formData.productType,
|
|
||||||
publicationDate:
|
|
||||||
formData.publicationDate !== ""
|
|
||||||
? formData.publicationDate
|
|
||||||
: null,
|
|
||||||
seo: {
|
|
||||||
description: formData.seoDescription,
|
|
||||||
title: formData.seoTitle
|
|
||||||
},
|
|
||||||
sku: formData.sku,
|
|
||||||
stockQuantity:
|
|
||||||
formData.stockQuantity !== null
|
|
||||||
? formData.stockQuantity
|
|
||||||
: 0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const formTransitionState = getMutationState(
|
|
||||||
productCreateCalled,
|
|
||||||
productCreateDataLoading,
|
|
||||||
maybe(() => productCreateData.productCreate.errors)
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<WindowTitle
|
|
||||||
title={intl.formatMessage({
|
|
||||||
defaultMessage: "Create Product",
|
|
||||||
description: "window title"
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<ProductCreatePage
|
|
||||||
currency={maybe(() => shop.defaultCurrency)}
|
|
||||||
categories={maybe(
|
|
||||||
() => searchCategoryOpts.data.search.edges,
|
|
||||||
[]
|
|
||||||
).map(edge => edge.node)}
|
|
||||||
collections={maybe(
|
|
||||||
() => searchCollectionOpts.data.search.edges,
|
|
||||||
[]
|
|
||||||
).map(edge => edge.node)}
|
|
||||||
disabled={productCreateDataLoading}
|
|
||||||
errors={maybe(
|
|
||||||
() => productCreateData.productCreate.errors,
|
|
||||||
[]
|
|
||||||
)}
|
|
||||||
fetchCategories={searchCategory}
|
|
||||||
fetchCollections={searchCollection}
|
|
||||||
fetchProductTypes={searchProductTypes}
|
|
||||||
header={intl.formatMessage({
|
|
||||||
defaultMessage: "New Product",
|
|
||||||
description: "page header"
|
|
||||||
})}
|
|
||||||
productTypes={maybe(() =>
|
|
||||||
searchProductTypesOpts.data.search.edges.map(
|
|
||||||
edge => edge.node
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
onBack={handleBack}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
saveButtonBarState={formTransitionState}
|
|
||||||
fetchMoreCategories={{
|
|
||||||
hasMore: maybe(
|
|
||||||
() =>
|
|
||||||
searchCategoryOpts.data.search.pageInfo
|
|
||||||
.hasNextPage
|
|
||||||
),
|
|
||||||
loading: searchCategoryOpts.loading,
|
|
||||||
onFetchMore: loadMoreCategories
|
|
||||||
}}
|
|
||||||
fetchMoreCollections={{
|
|
||||||
hasMore: maybe(
|
|
||||||
() =>
|
|
||||||
searchCollectionOpts.data.search.pageInfo
|
|
||||||
.hasNextPage
|
|
||||||
),
|
|
||||||
loading: searchCollectionOpts.loading,
|
|
||||||
onFetchMore: loadMoreCollections
|
|
||||||
}}
|
|
||||||
fetchMoreProductTypes={{
|
|
||||||
hasMore: maybe(
|
|
||||||
() =>
|
|
||||||
searchProductTypesOpts.data.search.pageInfo
|
|
||||||
.hasNextPage
|
|
||||||
),
|
|
||||||
loading: searchProductTypesOpts.loading,
|
|
||||||
onFetchMore: loadMoreProductTypes
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</TypedProductCreateMutation>
|
|
||||||
);
|
);
|
||||||
}}
|
if (!!attributeError) {
|
||||||
</SearchProductTypes>
|
notify({ text: attributeError.message });
|
||||||
)}
|
}
|
||||||
</SearchCollections>
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TypedProductCreateMutation onCompleted={handleSuccess}>
|
||||||
|
{(
|
||||||
|
productCreate,
|
||||||
|
{
|
||||||
|
called: productCreateCalled,
|
||||||
|
data: productCreateData,
|
||||||
|
loading: productCreateDataLoading
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const handleSubmit = (
|
||||||
|
formData: ProductCreatePageSubmitData
|
||||||
|
) => {
|
||||||
|
productCreate({
|
||||||
|
variables: {
|
||||||
|
attributes: formData.attributes.map(attribute => ({
|
||||||
|
id: attribute.id,
|
||||||
|
values: attribute.value
|
||||||
|
})),
|
||||||
|
basePrice: decimal(formData.basePrice),
|
||||||
|
category: formData.category,
|
||||||
|
chargeTaxes: formData.chargeTaxes,
|
||||||
|
collections: formData.collections,
|
||||||
|
descriptionJson: JSON.stringify(formData.description),
|
||||||
|
isPublished: formData.isPublished,
|
||||||
|
name: formData.name,
|
||||||
|
productType: formData.productType,
|
||||||
|
publicationDate:
|
||||||
|
formData.publicationDate !== ""
|
||||||
|
? formData.publicationDate
|
||||||
|
: null,
|
||||||
|
seo: {
|
||||||
|
description: formData.seoDescription,
|
||||||
|
title: formData.seoTitle
|
||||||
|
},
|
||||||
|
sku: formData.sku,
|
||||||
|
stockQuantity:
|
||||||
|
formData.stockQuantity !== null
|
||||||
|
? formData.stockQuantity
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const formTransitionState = getMutationState(
|
||||||
|
productCreateCalled,
|
||||||
|
productCreateDataLoading,
|
||||||
|
maybe(() => productCreateData.productCreate.errors)
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<WindowTitle
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Create Product",
|
||||||
|
description: "window title"
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<ProductCreatePage
|
||||||
|
currency={maybe(() => shop.defaultCurrency)}
|
||||||
|
categories={maybe(
|
||||||
|
() => searchCategoryOpts.data.search.edges,
|
||||||
|
[]
|
||||||
|
).map(edge => edge.node)}
|
||||||
|
collections={maybe(
|
||||||
|
() => searchCollectionOpts.data.search.edges,
|
||||||
|
[]
|
||||||
|
).map(edge => edge.node)}
|
||||||
|
disabled={productCreateDataLoading}
|
||||||
|
errors={maybe(
|
||||||
|
() => productCreateData.productCreate.errors,
|
||||||
|
[]
|
||||||
|
)}
|
||||||
|
fetchCategories={searchCategory}
|
||||||
|
fetchCollections={searchCollection}
|
||||||
|
fetchProductTypes={searchProductTypes}
|
||||||
|
header={intl.formatMessage({
|
||||||
|
defaultMessage: "New Product",
|
||||||
|
description: "page header"
|
||||||
|
})}
|
||||||
|
productTypes={maybe(() =>
|
||||||
|
searchProductTypesOpts.data.search.edges.map(
|
||||||
|
edge => edge.node
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
onBack={handleBack}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
saveButtonBarState={formTransitionState}
|
||||||
|
fetchMoreCategories={{
|
||||||
|
hasMore: maybe(
|
||||||
|
() =>
|
||||||
|
searchCategoryOpts.data.search.pageInfo
|
||||||
|
.hasNextPage
|
||||||
|
),
|
||||||
|
loading: searchCategoryOpts.loading,
|
||||||
|
onFetchMore: loadMoreCategories
|
||||||
|
}}
|
||||||
|
fetchMoreCollections={{
|
||||||
|
hasMore: maybe(
|
||||||
|
() =>
|
||||||
|
searchCollectionOpts.data.search.pageInfo
|
||||||
|
.hasNextPage
|
||||||
|
),
|
||||||
|
loading: searchCollectionOpts.loading,
|
||||||
|
onFetchMore: loadMoreCollections
|
||||||
|
}}
|
||||||
|
fetchMoreProductTypes={{
|
||||||
|
hasMore: maybe(
|
||||||
|
() =>
|
||||||
|
searchProductTypesOpts.data.search.pageInfo
|
||||||
|
.hasNextPage
|
||||||
|
),
|
||||||
|
loading: searchProductTypesOpts.loading,
|
||||||
|
onFetchMore: loadMoreProductTypes
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</TypedProductCreateMutation>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</SearchProductTypes>
|
||||||
)}
|
)}
|
||||||
</SearchCategories>
|
</SearchCollections>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ProductUpdate;
|
export default ProductUpdate;
|
||||||
|
|
|
@ -14,8 +14,8 @@ import useShop from "@saleor/hooks/useShop";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import ProductVariantCreateDialog from "@saleor/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog";
|
import ProductVariantCreateDialog from "@saleor/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog";
|
||||||
import { ProductVariantBulkCreate } from "@saleor/products/types/ProductVariantBulkCreate";
|
import { ProductVariantBulkCreate } from "@saleor/products/types/ProductVariantBulkCreate";
|
||||||
|
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config";
|
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config";
|
||||||
import SearchCategories from "../../../containers/SearchCategories";
|
|
||||||
import SearchCollections from "../../../containers/SearchCollections";
|
import SearchCollections from "../../../containers/SearchCollections";
|
||||||
import { getMutationState, maybe } from "../../../misc";
|
import { getMutationState, maybe } from "../../../misc";
|
||||||
import ProductUpdatePage from "../../components/ProductUpdatePage";
|
import ProductUpdatePage from "../../components/ProductUpdatePage";
|
||||||
|
@ -55,6 +55,13 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
);
|
);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const shop = useShop();
|
const shop = useShop();
|
||||||
|
const {
|
||||||
|
loadMore: loadMoreCategories,
|
||||||
|
search: searchCategories,
|
||||||
|
result: searchCategoriesOpts
|
||||||
|
} = useCategorySearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
});
|
||||||
|
|
||||||
const openModal = (action: ProductUrlDialog) =>
|
const openModal = (action: ProductUrlDialog) =>
|
||||||
navigate(
|
navigate(
|
||||||
|
@ -64,356 +71,341 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SearchCategories variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
||||||
{({
|
{({
|
||||||
loadMore: loadMoreCategories,
|
loadMore: loadMoreCollections,
|
||||||
search: searchCategories,
|
search: searchCollections,
|
||||||
result: searchCategoriesOpts
|
result: searchCollectionsOpts
|
||||||
}) => (
|
}) => (
|
||||||
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
|
<TypedProductDetailsQuery
|
||||||
{({
|
displayLoader
|
||||||
loadMore: loadMoreCollections,
|
require={["product"]}
|
||||||
search: searchCollections,
|
variables={{ id }}
|
||||||
result: searchCollectionsOpts
|
>
|
||||||
}) => (
|
{({ data, loading, refetch }) => {
|
||||||
<TypedProductDetailsQuery
|
const handleDelete = () => {
|
||||||
displayLoader
|
notify({
|
||||||
require={["product"]}
|
text: intl.formatMessage({
|
||||||
variables={{ id }}
|
defaultMessage: "Product removed"
|
||||||
>
|
})
|
||||||
{({ data, loading, refetch }) => {
|
});
|
||||||
const handleDelete = () => {
|
navigate(productListUrl());
|
||||||
notify({
|
};
|
||||||
text: intl.formatMessage({
|
const handleUpdate = (data: ProductUpdateMutationResult) => {
|
||||||
defaultMessage: "Product removed"
|
if (data.productUpdate.errors.length === 0) {
|
||||||
})
|
notify({
|
||||||
});
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
navigate(productListUrl());
|
});
|
||||||
};
|
} else {
|
||||||
const handleUpdate = (data: ProductUpdateMutationResult) => {
|
const attributeError = data.productUpdate.errors.find(
|
||||||
if (data.productUpdate.errors.length === 0) {
|
err => err.field === "attributes"
|
||||||
notify({
|
);
|
||||||
text: intl.formatMessage(commonMessages.savedChanges)
|
if (!!attributeError) {
|
||||||
});
|
notify({ text: attributeError.message });
|
||||||
} else {
|
}
|
||||||
const attributeError = data.productUpdate.errors.find(
|
}
|
||||||
err => err.field === "attributes"
|
};
|
||||||
);
|
|
||||||
if (!!attributeError) {
|
|
||||||
notify({ text: attributeError.message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleImageCreate = (data: ProductImageCreate) => {
|
const handleImageCreate = (data: ProductImageCreate) => {
|
||||||
const imageError = data.productImageCreate.errors.find(
|
const imageError = data.productImageCreate.errors.find(
|
||||||
error =>
|
error =>
|
||||||
error.field ===
|
error.field === ("image" as keyof ProductImageCreateVariables)
|
||||||
("image" as keyof ProductImageCreateVariables)
|
);
|
||||||
|
if (imageError) {
|
||||||
|
notify({
|
||||||
|
text: imageError.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleImageDeleteSuccess = () =>
|
||||||
|
notify({
|
||||||
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
|
});
|
||||||
|
const handleVariantAdd = () => navigate(productVariantAddUrl(id));
|
||||||
|
|
||||||
|
const handleBulkProductVariantCreate = (
|
||||||
|
data: ProductVariantBulkCreate
|
||||||
|
) => {
|
||||||
|
if (data.productVariantBulkCreate.errors.length === 0) {
|
||||||
|
navigate(productUrl(id), true);
|
||||||
|
refetch();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBulkProductVariantDelete = (
|
||||||
|
data: ProductVariantBulkDelete
|
||||||
|
) => {
|
||||||
|
if (data.productVariantBulkDelete.errors.length === 0) {
|
||||||
|
navigate(productUrl(id), true);
|
||||||
|
reset();
|
||||||
|
refetch();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVariantCreatorOpen = () =>
|
||||||
|
navigate(
|
||||||
|
productUrl(id, {
|
||||||
|
...params,
|
||||||
|
action: "create-variants"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const product = data ? data.product : undefined;
|
||||||
|
return (
|
||||||
|
<ProductUpdateOperations
|
||||||
|
product={product}
|
||||||
|
onBulkProductVariantCreate={handleBulkProductVariantCreate}
|
||||||
|
onBulkProductVariantDelete={handleBulkProductVariantDelete}
|
||||||
|
onDelete={handleDelete}
|
||||||
|
onImageCreate={handleImageCreate}
|
||||||
|
onImageDelete={handleImageDeleteSuccess}
|
||||||
|
onUpdate={handleUpdate}
|
||||||
|
>
|
||||||
|
{({
|
||||||
|
bulkProductVariantCreate,
|
||||||
|
bulkProductVariantDelete,
|
||||||
|
createProductImage,
|
||||||
|
deleteProduct,
|
||||||
|
deleteProductImage,
|
||||||
|
reorderProductImages,
|
||||||
|
updateProduct,
|
||||||
|
updateSimpleProduct
|
||||||
|
}) => {
|
||||||
|
const handleImageDelete = (id: string) => () =>
|
||||||
|
deleteProductImage.mutate({ id });
|
||||||
|
const handleImageEdit = (imageId: string) => () =>
|
||||||
|
navigate(productImageUrl(id, imageId));
|
||||||
|
const handleSubmit = createUpdateHandler(
|
||||||
|
product,
|
||||||
|
updateProduct.mutate,
|
||||||
|
updateSimpleProduct.mutate
|
||||||
);
|
);
|
||||||
if (imageError) {
|
const handleImageUpload = createImageUploadHandler(
|
||||||
notify({
|
id,
|
||||||
text: imageError.message
|
createProductImage.mutate
|
||||||
});
|
);
|
||||||
}
|
const handleImageReorder = createImageReorderHandler(
|
||||||
};
|
product,
|
||||||
const handleImageDeleteSuccess = () =>
|
reorderProductImages.mutate
|
||||||
notify({
|
|
||||||
text: intl.formatMessage(commonMessages.savedChanges)
|
|
||||||
});
|
|
||||||
const handleVariantAdd = () =>
|
|
||||||
navigate(productVariantAddUrl(id));
|
|
||||||
|
|
||||||
const handleBulkProductVariantCreate = (
|
|
||||||
data: ProductVariantBulkCreate
|
|
||||||
) => {
|
|
||||||
if (data.productVariantBulkCreate.errors.length === 0) {
|
|
||||||
navigate(productUrl(id), true);
|
|
||||||
refetch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBulkProductVariantDelete = (
|
|
||||||
data: ProductVariantBulkDelete
|
|
||||||
) => {
|
|
||||||
if (data.productVariantBulkDelete.errors.length === 0) {
|
|
||||||
navigate(productUrl(id), true);
|
|
||||||
reset();
|
|
||||||
refetch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleVariantCreatorOpen = () =>
|
|
||||||
navigate(
|
|
||||||
productUrl(id, {
|
|
||||||
...params,
|
|
||||||
action: "create-variants"
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const product = data ? data.product : undefined;
|
const disableFormSave =
|
||||||
return (
|
createProductImage.opts.loading ||
|
||||||
<ProductUpdateOperations
|
deleteProduct.opts.loading ||
|
||||||
product={product}
|
reorderProductImages.opts.loading ||
|
||||||
onBulkProductVariantCreate={handleBulkProductVariantCreate}
|
updateProduct.opts.loading ||
|
||||||
onBulkProductVariantDelete={handleBulkProductVariantDelete}
|
loading;
|
||||||
onDelete={handleDelete}
|
const formTransitionState = getMutationState(
|
||||||
onImageCreate={handleImageCreate}
|
updateProduct.opts.called ||
|
||||||
onImageDelete={handleImageDeleteSuccess}
|
updateSimpleProduct.opts.called,
|
||||||
onUpdate={handleUpdate}
|
updateProduct.opts.loading ||
|
||||||
>
|
updateSimpleProduct.opts.loading,
|
||||||
{({
|
maybe(() => updateProduct.opts.data.productUpdate.errors),
|
||||||
bulkProductVariantCreate,
|
maybe(
|
||||||
bulkProductVariantDelete,
|
() => updateSimpleProduct.opts.data.productUpdate.errors
|
||||||
createProductImage,
|
),
|
||||||
deleteProduct,
|
maybe(
|
||||||
deleteProductImage,
|
() =>
|
||||||
reorderProductImages,
|
updateSimpleProduct.opts.data.productVariantUpdate
|
||||||
updateProduct,
|
.errors
|
||||||
updateSimpleProduct
|
)
|
||||||
}) => {
|
);
|
||||||
const handleImageDelete = (id: string) => () =>
|
const deleteTransitionState = getMutationState(
|
||||||
deleteProductImage.mutate({ id });
|
deleteProduct.opts.called,
|
||||||
const handleImageEdit = (imageId: string) => () =>
|
deleteProduct.opts.loading,
|
||||||
navigate(productImageUrl(id, imageId));
|
maybe(() => deleteProduct.opts.data.productDelete.errors)
|
||||||
const handleSubmit = createUpdateHandler(
|
);
|
||||||
product,
|
|
||||||
updateProduct.mutate,
|
|
||||||
updateSimpleProduct.mutate
|
|
||||||
);
|
|
||||||
const handleImageUpload = createImageUploadHandler(
|
|
||||||
id,
|
|
||||||
createProductImage.mutate
|
|
||||||
);
|
|
||||||
const handleImageReorder = createImageReorderHandler(
|
|
||||||
product,
|
|
||||||
reorderProductImages.mutate
|
|
||||||
);
|
|
||||||
|
|
||||||
const disableFormSave =
|
const bulkProductVariantDeleteTransitionState = getMutationState(
|
||||||
createProductImage.opts.loading ||
|
bulkProductVariantDelete.opts.called,
|
||||||
deleteProduct.opts.loading ||
|
bulkProductVariantDelete.opts.loading,
|
||||||
reorderProductImages.opts.loading ||
|
maybe(
|
||||||
updateProduct.opts.loading ||
|
() =>
|
||||||
loading;
|
bulkProductVariantDelete.opts.data
|
||||||
const formTransitionState = getMutationState(
|
.productVariantBulkDelete.errors
|
||||||
updateProduct.opts.called ||
|
)
|
||||||
updateSimpleProduct.opts.called,
|
);
|
||||||
updateProduct.opts.loading ||
|
|
||||||
updateSimpleProduct.opts.loading,
|
|
||||||
maybe(
|
|
||||||
() => updateProduct.opts.data.productUpdate.errors
|
|
||||||
),
|
|
||||||
maybe(
|
|
||||||
() =>
|
|
||||||
updateSimpleProduct.opts.data.productUpdate.errors
|
|
||||||
),
|
|
||||||
maybe(
|
|
||||||
() =>
|
|
||||||
updateSimpleProduct.opts.data.productVariantUpdate
|
|
||||||
.errors
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const deleteTransitionState = getMutationState(
|
|
||||||
deleteProduct.opts.called,
|
|
||||||
deleteProduct.opts.loading,
|
|
||||||
maybe(
|
|
||||||
() => deleteProduct.opts.data.productDelete.errors
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const bulkProductVariantDeleteTransitionState = getMutationState(
|
const categories = maybe(
|
||||||
bulkProductVariantDelete.opts.called,
|
() => searchCategoriesOpts.data.search.edges,
|
||||||
bulkProductVariantDelete.opts.loading,
|
[]
|
||||||
maybe(
|
).map(edge => edge.node);
|
||||||
() =>
|
const collections = maybe(
|
||||||
bulkProductVariantDelete.opts.data
|
() => searchCollectionsOpts.data.search.edges,
|
||||||
.productVariantBulkDelete.errors
|
[]
|
||||||
)
|
).map(edge => edge.node);
|
||||||
);
|
const errors = maybe(
|
||||||
|
() => updateProduct.opts.data.productUpdate.errors,
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const categories = maybe(
|
return (
|
||||||
() => searchCategoriesOpts.data.search.edges,
|
<>
|
||||||
[]
|
<WindowTitle title={maybe(() => data.product.name)} />
|
||||||
).map(edge => edge.node);
|
<ProductUpdatePage
|
||||||
const collections = maybe(
|
categories={categories}
|
||||||
() => searchCollectionsOpts.data.search.edges,
|
collections={collections}
|
||||||
[]
|
disabled={disableFormSave}
|
||||||
).map(edge => edge.node);
|
errors={errors}
|
||||||
const errors = maybe(
|
fetchCategories={searchCategories}
|
||||||
() => updateProduct.opts.data.productUpdate.errors,
|
fetchCollections={searchCollections}
|
||||||
[]
|
saveButtonBarState={formTransitionState}
|
||||||
);
|
images={maybe(() => data.product.images)}
|
||||||
|
header={maybe(() => product.name)}
|
||||||
return (
|
placeholderImage={placeholderImg}
|
||||||
<>
|
product={product}
|
||||||
<WindowTitle title={maybe(() => data.product.name)} />
|
variants={maybe(() => product.variants)}
|
||||||
<ProductUpdatePage
|
onBack={() => {
|
||||||
categories={categories}
|
navigate(productListUrl());
|
||||||
collections={collections}
|
}}
|
||||||
disabled={disableFormSave}
|
onDelete={() => openModal("remove")}
|
||||||
errors={errors}
|
onProductShow={() => {
|
||||||
fetchCategories={searchCategories}
|
if (product) {
|
||||||
fetchCollections={searchCollections}
|
window.open(product.url);
|
||||||
saveButtonBarState={formTransitionState}
|
}
|
||||||
images={maybe(() => data.product.images)}
|
}}
|
||||||
header={maybe(() => product.name)}
|
onImageReorder={handleImageReorder}
|
||||||
placeholderImage={placeholderImg}
|
onSubmit={handleSubmit}
|
||||||
product={product}
|
onVariantAdd={handleVariantAdd}
|
||||||
variants={maybe(() => product.variants)}
|
onVariantsAdd={handleVariantCreatorOpen}
|
||||||
onBack={() => {
|
onVariantShow={variantId => () =>
|
||||||
navigate(productListUrl());
|
navigate(
|
||||||
}}
|
productVariantEditUrl(product.id, variantId)
|
||||||
onDelete={() => openModal("remove")}
|
)}
|
||||||
onProductShow={() => {
|
onImageUpload={handleImageUpload}
|
||||||
if (product) {
|
onImageEdit={handleImageEdit}
|
||||||
window.open(product.url);
|
onImageDelete={handleImageDelete}
|
||||||
}
|
toolbar={
|
||||||
}}
|
<IconButton
|
||||||
onImageReorder={handleImageReorder}
|
color="primary"
|
||||||
onSubmit={handleSubmit}
|
onClick={() =>
|
||||||
onVariantAdd={handleVariantAdd}
|
|
||||||
onVariantsAdd={handleVariantCreatorOpen}
|
|
||||||
onVariantShow={variantId => () =>
|
|
||||||
navigate(
|
|
||||||
productVariantEditUrl(product.id, variantId)
|
|
||||||
)}
|
|
||||||
onImageUpload={handleImageUpload}
|
|
||||||
onImageEdit={handleImageEdit}
|
|
||||||
onImageDelete={handleImageDelete}
|
|
||||||
toolbar={
|
|
||||||
<IconButton
|
|
||||||
color="primary"
|
|
||||||
onClick={() =>
|
|
||||||
navigate(
|
|
||||||
productUrl(id, {
|
|
||||||
action: "remove-variants",
|
|
||||||
ids: listElements
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<DeleteIcon />
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
isChecked={isSelected}
|
|
||||||
selected={listElements.length}
|
|
||||||
toggle={toggle}
|
|
||||||
toggleAll={toggleAll}
|
|
||||||
fetchMoreCategories={{
|
|
||||||
hasMore: maybe(
|
|
||||||
() =>
|
|
||||||
searchCategoriesOpts.data.search.pageInfo
|
|
||||||
.hasNextPage
|
|
||||||
),
|
|
||||||
loading: searchCategoriesOpts.loading,
|
|
||||||
onFetchMore: loadMoreCategories
|
|
||||||
}}
|
|
||||||
fetchMoreCollections={{
|
|
||||||
hasMore: maybe(
|
|
||||||
() =>
|
|
||||||
searchCollectionsOpts.data.search.pageInfo
|
|
||||||
.hasNextPage
|
|
||||||
),
|
|
||||||
loading: searchCollectionsOpts.loading,
|
|
||||||
onFetchMore: loadMoreCollections
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ActionDialog
|
|
||||||
open={params.action === "remove"}
|
|
||||||
onClose={() => navigate(productUrl(id), true)}
|
|
||||||
confirmButtonState={deleteTransitionState}
|
|
||||||
onConfirm={() => deleteProduct.mutate({ id })}
|
|
||||||
variant="delete"
|
|
||||||
title={intl.formatMessage({
|
|
||||||
defaultMessage: "Delete Product",
|
|
||||||
description: "dialog header"
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<DialogContentText>
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Are you sure you want to delete {name}?"
|
|
||||||
description="delete product"
|
|
||||||
values={{
|
|
||||||
name: product ? product.name : undefined
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContentText>
|
|
||||||
</ActionDialog>
|
|
||||||
<ActionDialog
|
|
||||||
open={params.action === "remove-variants"}
|
|
||||||
onClose={() => navigate(productUrl(id), true)}
|
|
||||||
confirmButtonState={
|
|
||||||
bulkProductVariantDeleteTransitionState
|
|
||||||
}
|
|
||||||
onConfirm={() =>
|
|
||||||
bulkProductVariantDelete.mutate({
|
|
||||||
ids: params.ids
|
|
||||||
})
|
|
||||||
}
|
|
||||||
variant="delete"
|
|
||||||
title={intl.formatMessage({
|
|
||||||
defaultMessage: "Delete Product Variants",
|
|
||||||
description: "dialog header"
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<DialogContentText>
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Are you sure you want to delete {counter,plural,one{this variant} other{{displayQuantity} variants}}?"
|
|
||||||
description="dialog content"
|
|
||||||
values={{
|
|
||||||
counter: maybe(() => params.ids.length),
|
|
||||||
displayQuantity: (
|
|
||||||
<strong>
|
|
||||||
{maybe(() => params.ids.length)}
|
|
||||||
</strong>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContentText>
|
|
||||||
</ActionDialog>
|
|
||||||
<ProductVariantCreateDialog
|
|
||||||
defaultPrice={maybe(() =>
|
|
||||||
data.product.basePrice.amount.toFixed(2)
|
|
||||||
)}
|
|
||||||
errors={maybe(
|
|
||||||
() =>
|
|
||||||
bulkProductVariantCreate.opts.data
|
|
||||||
.productVariantBulkCreate.bulkProductErrors,
|
|
||||||
[]
|
|
||||||
)}
|
|
||||||
open={params.action === "create-variants"}
|
|
||||||
attributes={maybe(
|
|
||||||
() => data.product.productType.variantAttributes,
|
|
||||||
[]
|
|
||||||
)}
|
|
||||||
currencySymbol={maybe(() => shop.defaultCurrency)}
|
|
||||||
onClose={() =>
|
|
||||||
navigate(
|
navigate(
|
||||||
productUrl(id, {
|
productUrl(id, {
|
||||||
...params,
|
action: "remove-variants",
|
||||||
action: undefined
|
ids: listElements
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onSubmit={inputs =>
|
>
|
||||||
bulkProductVariantCreate.mutate({
|
<DeleteIcon />
|
||||||
id,
|
</IconButton>
|
||||||
inputs
|
}
|
||||||
})
|
isChecked={isSelected}
|
||||||
}
|
selected={listElements.length}
|
||||||
|
toggle={toggle}
|
||||||
|
toggleAll={toggleAll}
|
||||||
|
fetchMoreCategories={{
|
||||||
|
hasMore: maybe(
|
||||||
|
() =>
|
||||||
|
searchCategoriesOpts.data.search.pageInfo
|
||||||
|
.hasNextPage
|
||||||
|
),
|
||||||
|
loading: searchCategoriesOpts.loading,
|
||||||
|
onFetchMore: loadMoreCategories
|
||||||
|
}}
|
||||||
|
fetchMoreCollections={{
|
||||||
|
hasMore: maybe(
|
||||||
|
() =>
|
||||||
|
searchCollectionsOpts.data.search.pageInfo
|
||||||
|
.hasNextPage
|
||||||
|
),
|
||||||
|
loading: searchCollectionsOpts.loading,
|
||||||
|
onFetchMore: loadMoreCollections
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ActionDialog
|
||||||
|
open={params.action === "remove"}
|
||||||
|
onClose={() => navigate(productUrl(id), true)}
|
||||||
|
confirmButtonState={deleteTransitionState}
|
||||||
|
onConfirm={() => deleteProduct.mutate({ id })}
|
||||||
|
variant="delete"
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Delete Product",
|
||||||
|
description: "dialog header"
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<DialogContentText>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Are you sure you want to delete {name}?"
|
||||||
|
description="delete product"
|
||||||
|
values={{
|
||||||
|
name: product ? product.name : undefined
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</DialogContentText>
|
||||||
);
|
</ActionDialog>
|
||||||
}}
|
<ActionDialog
|
||||||
</ProductUpdateOperations>
|
open={params.action === "remove-variants"}
|
||||||
);
|
onClose={() => navigate(productUrl(id), true)}
|
||||||
}}
|
confirmButtonState={
|
||||||
</TypedProductDetailsQuery>
|
bulkProductVariantDeleteTransitionState
|
||||||
)}
|
}
|
||||||
</SearchCollections>
|
onConfirm={() =>
|
||||||
|
bulkProductVariantDelete.mutate({
|
||||||
|
ids: params.ids
|
||||||
|
})
|
||||||
|
}
|
||||||
|
variant="delete"
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Delete Product Variants",
|
||||||
|
description: "dialog header"
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<DialogContentText>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Are you sure you want to delete {counter,plural,one{this variant} other{{displayQuantity} variants}}?"
|
||||||
|
description="dialog content"
|
||||||
|
values={{
|
||||||
|
counter: maybe(() => params.ids.length),
|
||||||
|
displayQuantity: (
|
||||||
|
<strong>
|
||||||
|
{maybe(() => params.ids.length)}
|
||||||
|
</strong>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DialogContentText>
|
||||||
|
</ActionDialog>
|
||||||
|
<ProductVariantCreateDialog
|
||||||
|
defaultPrice={maybe(() =>
|
||||||
|
data.product.basePrice.amount.toFixed(2)
|
||||||
|
)}
|
||||||
|
errors={maybe(
|
||||||
|
() =>
|
||||||
|
bulkProductVariantCreate.opts.data
|
||||||
|
.productVariantBulkCreate.bulkProductErrors,
|
||||||
|
[]
|
||||||
|
)}
|
||||||
|
open={params.action === "create-variants"}
|
||||||
|
attributes={maybe(
|
||||||
|
() => data.product.productType.variantAttributes,
|
||||||
|
[]
|
||||||
|
)}
|
||||||
|
currencySymbol={maybe(() => shop.defaultCurrency)}
|
||||||
|
onClose={() =>
|
||||||
|
navigate(
|
||||||
|
productUrl(id, {
|
||||||
|
...params,
|
||||||
|
action: undefined
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onSubmit={inputs =>
|
||||||
|
bulkProductVariantCreate.mutate({
|
||||||
|
id,
|
||||||
|
inputs
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</ProductUpdateOperations>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</TypedProductDetailsQuery>
|
||||||
)}
|
)}
|
||||||
</SearchCategories>
|
</SearchCollections>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ProductUpdate;
|
export default ProductUpdate;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch";
|
||||||
import { pageInfoFragment } from "@saleor/queries";
|
import { pageInfoFragment } from "@saleor/queries";
|
||||||
import TopLevelSearch from "../TopLevelSearch";
|
|
||||||
import {
|
import {
|
||||||
SearchCategories,
|
SearchCategories,
|
||||||
SearchCategoriesVariables
|
SearchCategoriesVariables
|
||||||
|
@ -24,6 +24,6 @@ export const searchCategories = gql`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default TopLevelSearch<SearchCategories, SearchCategoriesVariables>(
|
export default makeTopLevelSearch<SearchCategories, SearchCategoriesVariables>(
|
||||||
searchCategories
|
searchCategories
|
||||||
);
|
);
|
Loading…
Reference in a new issue