From e67727af037c22693cd2774584922022b05176cd Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Tue, 19 Nov 2019 16:47:12 +0100 Subject: [PATCH] Use category search hook --- .../AssignCategoryDialog.tsx | 2 +- src/discounts/views/SaleDetails.tsx | 70 +- src/discounts/views/VoucherDetails.tsx | 70 +- .../MenuItemDialog/MenuItemDialog.tsx | 2 +- src/navigation/views/MenuDetails/index.tsx | 575 ++++++++------- .../ProductCreatePage/ProductCreatePage.tsx | 2 +- .../ProductUpdatePage/ProductUpdatePage.tsx | 2 +- src/products/views/ProductCreate.tsx | 317 +++++---- .../views/ProductUpdate/ProductUpdate.tsx | 662 +++++++++--------- .../types/SearchCategories.ts | 0 .../useCategorySearch.ts} | 4 +- 11 files changed, 835 insertions(+), 871 deletions(-) rename src/{containers/SearchCategories => searches}/types/SearchCategories.ts (100%) rename src/{containers/SearchCategories/index.tsx => searches/useCategorySearch.ts} (78%) diff --git a/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx b/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx index cecd2b136..169c0ead7 100644 --- a/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx +++ b/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx @@ -19,7 +19,7 @@ import FormSpacer from "@saleor/components/FormSpacer"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import useSearchQuery from "@saleor/hooks/useSearchQuery"; 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"; export interface FormData { diff --git a/src/discounts/views/SaleDetails.tsx b/src/discounts/views/SaleDetails.tsx index 987c2557d..272dadc3c 100644 --- a/src/discounts/views/SaleDetails.tsx +++ b/src/discounts/views/SaleDetails.tsx @@ -16,10 +16,10 @@ import usePaginator, { } from "@saleor/hooks/usePaginator"; import useShop from "@saleor/hooks/useShop"; import { commonMessages, sectionNames } from "@saleor/intl"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; import { categoryUrl } from "../../categories/urls"; import { collectionUrl } from "../../collections/urls"; import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; -import SearchCategories from "../../containers/SearchCategories"; import SearchCollections from "../../containers/SearchCollections"; import SearchProducts from "../../containers/SearchProducts"; import { decimal, getMutationState, joinDateTime, maybe } from "../../misc"; @@ -66,6 +66,12 @@ export const SaleDetails: React.FC = ({ id, params }) => { params.ids ); const intl = useIntl(); + const { + search: searchCategories, + result: searchCategoriesOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const paginationState = createPaginationState(PAGINATE_BY, params); const changeTab = (tab: SaleDetailsPageTab) => { @@ -377,43 +383,33 @@ export const SaleDetails: React.FC = ({ id, params }) => { /> )} - - {({ - search: searchCategories, - result: searchCategoriesOpts - }) => ( - - 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 - ) - } - } - }) - } - /> + + 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 + ) + } + } + }) + } + /> diff --git a/src/discounts/views/VoucherDetails.tsx b/src/discounts/views/VoucherDetails.tsx index 2ade5b3f9..9a6cb144a 100644 --- a/src/discounts/views/VoucherDetails.tsx +++ b/src/discounts/views/VoucherDetails.tsx @@ -16,10 +16,10 @@ import usePaginator, { } from "@saleor/hooks/usePaginator"; import useShop from "@saleor/hooks/useShop"; import { commonMessages, sectionNames } from "@saleor/intl"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; import { categoryUrl } from "../../categories/urls"; import { collectionUrl } from "../../collections/urls"; import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; -import SearchCategories from "../../containers/SearchCategories"; import SearchCollections from "../../containers/SearchCollections"; import SearchProducts from "../../containers/SearchProducts"; import { decimal, getMutationState, joinDateTime, maybe } from "../../misc"; @@ -68,6 +68,12 @@ export const VoucherDetails: React.FC = ({ params.ids ); const intl = useIntl(); + const { + search: searchCategories, + result: searchCategoriesOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const paginationState = createPaginationState(PAGINATE_BY, params); const changeTab = (tab: VoucherDetailsPageTab) => { @@ -420,43 +426,33 @@ export const VoucherDetails: React.FC = ({ toggle={toggle} toggleAll={toggleAll} /> - - {({ - search: searchCategories, - result: searchCategoriesOpts - }) => ( - - 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 - ) - } - } - }) - } - /> + + 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 + ) + } + } + }) + } + /> diff --git a/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx index 30f2c9945..6dac3b907 100644 --- a/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx +++ b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx @@ -14,13 +14,13 @@ import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; 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 { SearchPages_search_edges_node } from "@saleor/containers/SearchPages/types/SearchPages"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { buttonMessages, sectionNames } from "@saleor/intl"; +import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; import { UserError } from "@saleor/types"; import { getErrors, getFieldError } from "@saleor/utils/errors"; import { getMenuItemByValue, IMenu } from "@saleor/utils/menu"; diff --git a/src/navigation/views/MenuDetails/index.tsx b/src/navigation/views/MenuDetails/index.tsx index eb4f5b801..60e53e06d 100644 --- a/src/navigation/views/MenuDetails/index.tsx +++ b/src/navigation/views/MenuDetails/index.tsx @@ -5,10 +5,10 @@ import { FormattedMessage, useIntl } from "react-intl"; import ActionDialog from "@saleor/components/ActionDialog"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; import { categoryUrl } from "../../../categories/urls"; import { collectionUrl } from "../../../collections/urls"; import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; -import SearchCategories from "../../../containers/SearchCategories"; import SearchCollections from "../../../containers/SearchCollections"; import SearchPages from "../../../containers/SearchPages"; import { getMutationState, maybe } from "../../../misc"; @@ -59,6 +59,9 @@ const MenuDetails: React.FC = ({ id, params }) => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); + const categorySearch = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const closeModal = () => navigate( @@ -97,324 +100,304 @@ const MenuDetails: React.FC = ({ id, params }) => { return ( {pageSearch => ( - - {categorySearch => ( - - {collectionSearch => ( - - {({ data, loading, refetch }) => { - const handleQueryChange = (query: string) => { - categorySearch.search(query); - collectionSearch.search(query); - pageSearch.search(query); - }; + + {collectionSearch => ( + + {({ data, loading, refetch }) => { + const handleQueryChange = (query: string) => { + categorySearch.search(query); + collectionSearch.search(query); + pageSearch.search(query); + }; - const categories = maybe( - () => - categorySearch.result.data.search.edges.map( - edge => edge.node - ), - [] - ); + const categories = maybe( + () => + categorySearch.result.data.search.edges.map( + edge => edge.node + ), + [] + ); - const collections = maybe( - () => - collectionSearch.result.data.search.edges.map( - edge => edge.node - ), - [] - ); + const collections = maybe( + () => + collectionSearch.result.data.search.edges.map( + edge => edge.node + ), + [] + ); - const pages = maybe( - () => - pageSearch.result.data.search.edges.map( - edge => edge.node - ), - [] - ); + const pages = maybe( + () => + pageSearch.result.data.search.edges.map(edge => edge.node), + [] + ); - return ( - + handleDelete(data, navigate, notify, intl) + } + > + {(menuDelete, menuDeleteOpts) => ( + - handleDelete(data, navigate, notify, intl) + handleUpdate(data, notify, refetch, intl) } > - {(menuDelete, menuDeleteOpts) => ( - - handleUpdate(data, notify, refetch, intl) - } - > - {(menuUpdate, menuUpdateOpts) => { - const deleteState = getMutationState( - menuDeleteOpts.called, - menuDeleteOpts.loading, - maybe( - () => menuDeleteOpts.data.menuDelete.errors - ) - ); + {(menuUpdate, menuUpdateOpts) => { + const deleteState = getMutationState( + menuDeleteOpts.called, + menuDeleteOpts.loading, + maybe(() => menuDeleteOpts.data.menuDelete.errors) + ); - const updateState = getMutationState( - menuUpdateOpts.called, - menuUpdateOpts.loading, - maybe( - () => menuUpdateOpts.data.menuUpdate.errors - ), - maybe( - () => menuUpdateOpts.data.menuItemMove.errors - ) - ); + const updateState = getMutationState( + menuUpdateOpts.called, + menuUpdateOpts.loading, + maybe(() => menuUpdateOpts.data.menuUpdate.errors), + maybe(() => menuUpdateOpts.data.menuItemMove.errors) + ); - // This is a workaround to let know - // that it should clean operation stack if mutations - // were successful - const handleSubmit = async ( - data: MenuDetailsSubmitData - ) => { - try { - const result = await menuUpdate({ - variables: { - id, - moves: getMoves(data), - name: data.name, - removeIds: getRemoveIds(data) - } - }); - if (result) { - if ( - result.data.menuItemBulkDelete.errors - .length > 0 || - result.data.menuItemMove.errors.length > - 0 || - result.data.menuUpdate.errors.length > 0 - ) { - return false; - } - } - return true; - } catch { + // This is a workaround to let know + // that it should clean operation stack if mutations + // were successful + const handleSubmit = async ( + data: MenuDetailsSubmitData + ) => { + try { + const result = await menuUpdate({ + variables: { + id, + moves: getMoves(data), + name: data.name, + removeIds: getRemoveIds(data) + } + }); + if (result) { + if ( + result.data.menuItemBulkDelete.errors.length > + 0 || + result.data.menuItemMove.errors.length > 0 || + result.data.menuUpdate.errors.length > 0 + ) { return false; } - }; + } + return true; + } catch { + return false; + } + }; - return ( - <> - data.menu)} - onBack={() => navigate(menuListUrl())} - onDelete={() => - navigate( - menuUrl(id, { - action: "remove" - }) + return ( + <> + data.menu)} + onBack={() => navigate(menuListUrl())} + onDelete={() => + navigate( + menuUrl(id, { + 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} + /> + + menuDelete({ variables: { id } }) + } + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Menu", + description: "dialog header", + id: "menuDetailsDeleteMenuHeader" + })} + > + + + {maybe(() => data.menu.name, "...")} + ) - } - onItemAdd={() => - navigate( - menuUrl(id, { - action: "add-item" - }) - ) - } - onItemClick={handleItemClick} - onItemEdit={itemId => - navigate( - menuUrl(id, { - action: "edit-item", - id: itemId - }) - ) - } - onSubmit={handleSubmit} - saveButtonState={updateState} + }} /> - - menuDelete({ variables: { id } }) - } - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Menu", - description: "dialog header", - id: "menuDetailsDeleteMenuHeader" - })} - > - - - {maybe( - () => data.menu.name, - "..." - )} - - ) - }} - /> - - + + - - handleItemCreate( - data, - notify, - closeModal, - intl - ) - } - > - {(menuItemCreate, menuItemCreateOpts) => { - const handleSubmit = ( - data: MenuItemDialogFormData - ) => { - const variables: MenuItemCreateVariables = { - input: getMenuItemCreateInputData( - id, - data - ) - }; - - menuItemCreate({ variables }); - }; - - const formTransitionState = getMutationState( - menuItemCreateOpts.called, - menuItemCreateOpts.loading, - maybe( - () => - menuItemCreateOpts.data - .menuItemCreate.errors - ) - ); - - return ( - - menuItemCreateOpts.data - .menuItemCreate.errors, - [] - )} - pages={pages} - loading={ - categorySearch.result.loading || - collectionSearch.result.loading - } - confirmButtonState={ - formTransitionState - } - disabled={menuItemCreateOpts.loading} - onClose={closeModal} - onSubmit={handleSubmit} - onQueryChange={handleQueryChange} - /> - ); - }} - - - handleItemUpdate( - data, + + handleItemCreate( + data, + notify, + closeModal, + intl + ) + } + > + {(menuItemCreate, menuItemCreateOpts) => { + const handleSubmit = ( + data: MenuItemDialogFormData + ) => { + const variables: MenuItemCreateVariables = { + input: getMenuItemCreateInputData( id, - navigate, - notify, - intl + data ) - } - > - {(menuItemUpdate, menuItemUpdateOpts) => { - const handleSubmit = ( - data: MenuItemDialogFormData - ) => { - const variables: MenuItemUpdateVariables = { - id: params.id, - input: getMenuItemInputData(data) - }; + }; - menuItemUpdate({ variables }); - }; + menuItemCreate({ variables }); + }; - const menuItem = maybe(() => - getNode( - data.menu.items, - findNode(data.menu.items, params.id) - ) - ); + const formTransitionState = getMutationState( + menuItemCreateOpts.called, + menuItemCreateOpts.loading, + maybe( + () => + menuItemCreateOpts.data.menuItemCreate + .errors + ) + ); - const formTransitionState = getMutationState( - menuItemUpdateOpts.called, - menuItemUpdateOpts.loading, - maybe( - () => - menuItemUpdateOpts.data - .menuItemUpdate.errors - ) - ); + return ( + + menuItemCreateOpts.data.menuItemCreate + .errors, + [] + )} + pages={pages} + loading={ + categorySearch.result.loading || + collectionSearch.result.loading + } + confirmButtonState={formTransitionState} + disabled={menuItemCreateOpts.loading} + onClose={closeModal} + onSubmit={handleSubmit} + onQueryChange={handleQueryChange} + /> + ); + }} + + + handleItemUpdate( + data, + id, + navigate, + notify, + intl + ) + } + > + {(menuItemUpdate, menuItemUpdateOpts) => { + const handleSubmit = ( + data: MenuItemDialogFormData + ) => { + const variables: MenuItemUpdateVariables = { + id: params.id, + input: getMenuItemInputData(data) + }; - const initialFormData: MenuItemDialogFormData = { - id: maybe(() => getItemId(menuItem)), - name: maybe(() => menuItem.name, "..."), - type: maybe( - () => getItemType(menuItem), - "category" - ) - }; + menuItemUpdate({ variables }); + }; - return ( - - menuItemUpdateOpts.data - .menuItemUpdate.errors, - [] - )} - pages={pages} - initial={initialFormData} - initialDisplayValue={getInitialDisplayValue( - menuItem - )} - loading={ - categorySearch.result.loading || - collectionSearch.result.loading - } - confirmButtonState={ - formTransitionState - } - disabled={menuItemUpdateOpts.loading} - onClose={closeModal} - onSubmit={handleSubmit} - onQueryChange={handleQueryChange} - /> - ); - }} - - - ); - }} - - )} - - ); - }} - - )} - + const menuItem = maybe(() => + getNode( + data.menu.items, + findNode(data.menu.items, params.id) + ) + ); + + const formTransitionState = getMutationState( + menuItemUpdateOpts.called, + menuItemUpdateOpts.loading, + maybe( + () => + menuItemUpdateOpts.data.menuItemUpdate + .errors + ) + ); + + const initialFormData: MenuItemDialogFormData = { + id: maybe(() => getItemId(menuItem)), + name: maybe(() => menuItem.name, "..."), + type: maybe( + () => getItemType(menuItem), + "category" + ) + }; + + return ( + + menuItemUpdateOpts.data.menuItemUpdate + .errors, + [] + )} + pages={pages} + initial={initialFormData} + initialDisplayValue={getInitialDisplayValue( + menuItem + )} + loading={ + categorySearch.result.loading || + collectionSearch.result.loading + } + confirmButtonState={formTransitionState} + disabled={menuItemUpdateOpts.loading} + onClose={closeModal} + onSubmit={handleSubmit} + onQueryChange={handleQueryChange} + /> + ); + }} + + + ); + }} + + )} + + ); + }} + )} - + )} ); diff --git a/src/products/components/ProductCreatePage/ProductCreatePage.tsx b/src/products/components/ProductCreatePage/ProductCreatePage.tsx index 15bb0ca8b..5d74fb815 100644 --- a/src/products/components/ProductCreatePage/ProductCreatePage.tsx +++ b/src/products/components/ProductCreatePage/ProductCreatePage.tsx @@ -13,7 +13,6 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; 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 { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; @@ -25,6 +24,7 @@ import { ProductAttributeValueChoices, ProductType } from "@saleor/products/utils/data"; +import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import { FetchMoreProps, UserError } from "../../../types"; diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx index 0859c6d4a..57dd2ee01 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -12,13 +12,13 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; 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 useDateLocalize from "@saleor/hooks/useDateLocalize"; import useFormset from "@saleor/hooks/useFormset"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; +import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; import { FetchMoreProps, ListActions, UserError } from "@saleor/types"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; diff --git a/src/products/views/ProductCreate.tsx b/src/products/views/ProductCreate.tsx index fded16046..8c20a480c 100644 --- a/src/products/views/ProductCreate.tsx +++ b/src/products/views/ProductCreate.tsx @@ -6,8 +6,8 @@ import SearchProductTypes from "@saleor/containers/SearchProductTypes"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config"; -import SearchCategories from "../../containers/SearchCategories"; import SearchCollections from "../../containers/SearchCollections"; import { decimal, getMutationState, maybe } from "../../misc"; import ProductCreatePage, { @@ -26,174 +26,171 @@ export const ProductUpdate: React.FC = () => { const notify = useNotifier(); const shop = useShop(); const intl = useIntl(); + const { + loadMore: loadMoreCategories, + search: searchCategory, + result: searchCategoryOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const handleBack = () => navigate(productListUrl()); return ( - + {({ - loadMore: loadMoreCategories, - search: searchCategory, - result: searchCategoryOpts + loadMore: loadMoreCollections, + search: searchCollection, + result: searchCollectionOpts }) => ( - + {({ - loadMore: loadMoreCollections, - search: searchCollection, - result: searchCollectionOpts - }) => ( - - {({ - loadMore: loadMoreProductTypes, - search: searchProductTypes, - result: searchProductTypesOpts - }) => { - const handleSuccess = (data: ProductCreate) => { - if (data.productCreate.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Product created" - }) - }); - navigate(productUrl(data.productCreate.product.id)); - } else { - const attributeError = data.productCreate.errors.find( - err => err.field === "attributes" - ); - if (!!attributeError) { - notify({ text: attributeError.message }); - } - } - }; - - return ( - - {( - 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 ( - <> - - 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 - }} - /> - - ); - }} - + loadMore: loadMoreProductTypes, + search: searchProductTypes, + result: searchProductTypesOpts + }) => { + const handleSuccess = (data: ProductCreate) => { + if (data.productCreate.errors.length === 0) { + notify({ + text: intl.formatMessage({ + defaultMessage: "Product created" + }) + }); + navigate(productUrl(data.productCreate.product.id)); + } else { + const attributeError = data.productCreate.errors.find( + err => err.field === "attributes" ); - }} - - )} - + if (!!attributeError) { + notify({ text: attributeError.message }); + } + } + }; + + return ( + + {( + 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 ( + <> + + 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 + }} + /> + + ); + }} + + ); + }} + )} - + ); }; export default ProductUpdate; diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index 33ed7c1a2..a4357c3b9 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -14,8 +14,8 @@ import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import ProductVariantCreateDialog from "@saleor/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog"; import { ProductVariantBulkCreate } from "@saleor/products/types/ProductVariantBulkCreate"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; -import SearchCategories from "../../../containers/SearchCategories"; import SearchCollections from "../../../containers/SearchCollections"; import { getMutationState, maybe } from "../../../misc"; import ProductUpdatePage from "../../components/ProductUpdatePage"; @@ -55,6 +55,13 @@ export const ProductUpdate: React.FC = ({ id, params }) => { ); const intl = useIntl(); const shop = useShop(); + const { + loadMore: loadMoreCategories, + search: searchCategories, + result: searchCategoriesOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const openModal = (action: ProductUrlDialog) => navigate( @@ -64,356 +71,341 @@ export const ProductUpdate: React.FC = ({ id, params }) => { ); return ( - + {({ - loadMore: loadMoreCategories, - search: searchCategories, - result: searchCategoriesOpts + loadMore: loadMoreCollections, + search: searchCollections, + result: searchCollectionsOpts }) => ( - - {({ - loadMore: loadMoreCollections, - search: searchCollections, - result: searchCollectionsOpts - }) => ( - - {({ data, loading, refetch }) => { - const handleDelete = () => { - notify({ - text: intl.formatMessage({ - defaultMessage: "Product removed" - }) - }); - navigate(productListUrl()); - }; - const handleUpdate = (data: ProductUpdateMutationResult) => { - if (data.productUpdate.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - } else { - const attributeError = data.productUpdate.errors.find( - err => err.field === "attributes" - ); - if (!!attributeError) { - notify({ text: attributeError.message }); - } - } - }; + + {({ data, loading, refetch }) => { + const handleDelete = () => { + notify({ + text: intl.formatMessage({ + defaultMessage: "Product removed" + }) + }); + navigate(productListUrl()); + }; + const handleUpdate = (data: ProductUpdateMutationResult) => { + if (data.productUpdate.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + } else { + const attributeError = data.productUpdate.errors.find( + err => err.field === "attributes" + ); + if (!!attributeError) { + notify({ text: attributeError.message }); + } + } + }; - const handleImageCreate = (data: ProductImageCreate) => { - const imageError = data.productImageCreate.errors.find( - error => - error.field === - ("image" as keyof ProductImageCreateVariables) + const handleImageCreate = (data: ProductImageCreate) => { + const imageError = data.productImageCreate.errors.find( + error => + error.field === ("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 ( + + {({ + 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) { - 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 handleImageUpload = createImageUploadHandler( + id, + createProductImage.mutate + ); + const handleImageReorder = createImageReorderHandler( + product, + reorderProductImages.mutate ); - const product = data ? data.product : undefined; - return ( - - {({ - 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 - ); - const handleImageUpload = createImageUploadHandler( - id, - createProductImage.mutate - ); - const handleImageReorder = createImageReorderHandler( - product, - reorderProductImages.mutate - ); + const disableFormSave = + createProductImage.opts.loading || + deleteProduct.opts.loading || + reorderProductImages.opts.loading || + updateProduct.opts.loading || + loading; + const formTransitionState = getMutationState( + 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 disableFormSave = - createProductImage.opts.loading || - deleteProduct.opts.loading || - reorderProductImages.opts.loading || - updateProduct.opts.loading || - loading; - const formTransitionState = getMutationState( - 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( + bulkProductVariantDelete.opts.called, + bulkProductVariantDelete.opts.loading, + maybe( + () => + bulkProductVariantDelete.opts.data + .productVariantBulkDelete.errors + ) + ); - const bulkProductVariantDeleteTransitionState = getMutationState( - bulkProductVariantDelete.opts.called, - bulkProductVariantDelete.opts.loading, - maybe( - () => - bulkProductVariantDelete.opts.data - .productVariantBulkDelete.errors - ) - ); + const categories = maybe( + () => searchCategoriesOpts.data.search.edges, + [] + ).map(edge => edge.node); + const collections = maybe( + () => searchCollectionsOpts.data.search.edges, + [] + ).map(edge => edge.node); + const errors = maybe( + () => updateProduct.opts.data.productUpdate.errors, + [] + ); - const categories = maybe( - () => searchCategoriesOpts.data.search.edges, - [] - ).map(edge => edge.node); - const collections = maybe( - () => searchCollectionsOpts.data.search.edges, - [] - ).map(edge => edge.node); - const errors = maybe( - () => updateProduct.opts.data.productUpdate.errors, - [] - ); - - return ( - <> - data.product.name)} /> - data.product.images)} - header={maybe(() => product.name)} - placeholderImage={placeholderImg} - product={product} - variants={maybe(() => product.variants)} - onBack={() => { - navigate(productListUrl()); - }} - onDelete={() => openModal("remove")} - onProductShow={() => { - if (product) { - window.open(product.url); - } - }} - onImageReorder={handleImageReorder} - onSubmit={handleSubmit} - onVariantAdd={handleVariantAdd} - onVariantsAdd={handleVariantCreatorOpen} - onVariantShow={variantId => () => - navigate( - productVariantEditUrl(product.id, variantId) - )} - onImageUpload={handleImageUpload} - onImageEdit={handleImageEdit} - onImageDelete={handleImageDelete} - toolbar={ - - navigate( - productUrl(id, { - action: "remove-variants", - ids: listElements - }) - ) - } - > - - - } - 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 - }} - /> - navigate(productUrl(id), true)} - confirmButtonState={deleteTransitionState} - onConfirm={() => deleteProduct.mutate({ id })} - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Product", - description: "dialog header" - })} - > - - - - - navigate(productUrl(id), true)} - confirmButtonState={ - bulkProductVariantDeleteTransitionState - } - onConfirm={() => - bulkProductVariantDelete.mutate({ - ids: params.ids - }) - } - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Product Variants", - description: "dialog header" - })} - > - - params.ids.length), - displayQuantity: ( - - {maybe(() => params.ids.length)} - - ) - }} - /> - - - - 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={() => + return ( + <> + data.product.name)} /> + data.product.images)} + header={maybe(() => product.name)} + placeholderImage={placeholderImg} + product={product} + variants={maybe(() => product.variants)} + onBack={() => { + navigate(productListUrl()); + }} + onDelete={() => openModal("remove")} + onProductShow={() => { + if (product) { + window.open(product.url); + } + }} + onImageReorder={handleImageReorder} + onSubmit={handleSubmit} + onVariantAdd={handleVariantAdd} + onVariantsAdd={handleVariantCreatorOpen} + onVariantShow={variantId => () => + navigate( + productVariantEditUrl(product.id, variantId) + )} + onImageUpload={handleImageUpload} + onImageEdit={handleImageEdit} + onImageDelete={handleImageDelete} + toolbar={ + navigate( productUrl(id, { - ...params, - action: undefined + action: "remove-variants", + ids: listElements }) ) } - onSubmit={inputs => - bulkProductVariantCreate.mutate({ - id, - 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 + }} + /> + navigate(productUrl(id), true)} + confirmButtonState={deleteTransitionState} + onConfirm={() => deleteProduct.mutate({ id })} + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Product", + description: "dialog header" + })} + > + + - - ); - }} - - ); - }} - - )} - + + + navigate(productUrl(id), true)} + confirmButtonState={ + bulkProductVariantDeleteTransitionState + } + onConfirm={() => + bulkProductVariantDelete.mutate({ + ids: params.ids + }) + } + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Product Variants", + description: "dialog header" + })} + > + + params.ids.length), + displayQuantity: ( + + {maybe(() => params.ids.length)} + + ) + }} + /> + + + + 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 + }) + } + /> + + ); + }} + + ); + }} + )} - + ); }; export default ProductUpdate; diff --git a/src/containers/SearchCategories/types/SearchCategories.ts b/src/searches/types/SearchCategories.ts similarity index 100% rename from src/containers/SearchCategories/types/SearchCategories.ts rename to src/searches/types/SearchCategories.ts diff --git a/src/containers/SearchCategories/index.tsx b/src/searches/useCategorySearch.ts similarity index 78% rename from src/containers/SearchCategories/index.tsx rename to src/searches/useCategorySearch.ts index cdaebb8b1..2958bbf77 100644 --- a/src/containers/SearchCategories/index.tsx +++ b/src/searches/useCategorySearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchCategories, SearchCategoriesVariables @@ -24,6 +24,6 @@ export const searchCategories = gql` } `; -export default TopLevelSearch( +export default makeTopLevelSearch( searchCategories );