Merge pull request #262 from mirumee/ref/hook-searches

Use searches as hooks instead of components
This commit is contained in:
Marcin Gębala 2019-11-21 16:10:22 +01:00 committed by GitHub
commit 29bd1a43a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 1812 additions and 1990 deletions

View file

@ -12,6 +12,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Use Apollo Hooks - #254 by @dominik-zeglen - Use Apollo Hooks - #254 by @dominik-zeglen
- Fix disappearing products description - #259 by @dominik-zeglen - Fix disappearing products description - #259 by @dominik-zeglen
- Improve mobile appearance - #240 by @benekex2 and @dominik-zeglen - Improve mobile appearance - #240 by @benekex2 and @dominik-zeglen
- Use searches as hooks instead of components - #262 by @dominik-zeglen
## 2.0.0 ## 2.0.0

View file

@ -6,6 +6,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import ActionDialog from "@saleor/components/ActionDialog"; import ActionDialog from "@saleor/components/ActionDialog";
import AssignProductDialog from "@saleor/components/AssignProductDialog"; import AssignProductDialog from "@saleor/components/AssignProductDialog";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "@saleor/config";
import useBulkActions from "@saleor/hooks/useBulkActions"; import useBulkActions from "@saleor/hooks/useBulkActions";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
@ -13,8 +14,7 @@ import usePaginator, {
createPaginationState createPaginationState
} from "@saleor/hooks/usePaginator"; } from "@saleor/hooks/usePaginator";
import { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; import useProductSearch from "@saleor/searches/useProductSearch";
import SearchProducts from "../../containers/SearchProducts";
import { getMutationState, maybe } from "../../misc"; import { getMutationState, maybe } from "../../misc";
import { productUrl } from "../../products/urls"; import { productUrl } from "../../products/urls";
import { CollectionInput } from "../../types/globalTypes"; import { CollectionInput } from "../../types/globalTypes";
@ -50,6 +50,9 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
); );
const paginate = usePaginator(); const paginate = usePaginator();
const intl = useIntl(); const intl = useIntl();
const { search, result } = useProductSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const closeModal = () => const closeModal = () =>
navigate( navigate(
@ -284,8 +287,6 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
toggle={toggle} toggle={toggle}
toggleAll={toggleAll} toggleAll={toggleAll}
/> />
<SearchProducts variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({ search, result }) => (
<AssignProductDialog <AssignProductDialog
confirmButtonState={assignTransitionState} confirmButtonState={assignTransitionState}
open={params.action === "assign"} open={params.action === "assign"}
@ -305,8 +306,6 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
.filter(suggestedProduct => suggestedProduct.id) .filter(suggestedProduct => suggestedProduct.id)
)} )}
/> />
)}
</SearchProducts>
<ActionDialog <ActionDialog
confirmButtonState={removeTransitionState} confirmButtonState={removeTransitionState}
onClose={closeModal} onClose={closeModal}

View file

@ -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 {

View file

@ -15,7 +15,7 @@ import { FormattedMessage, useIntl } from "react-intl";
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 { SearchCollections_search_edges_node } from "../../containers/SearchCollections/types/SearchCollections"; import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
import Checkbox from "../Checkbox"; import Checkbox from "../Checkbox";
import ConfirmButton, { import ConfirmButton, {
ConfirmButtonTransitionState ConfirmButtonTransitionState

View file

@ -21,7 +21,7 @@ import TableCellAvatar from "@saleor/components/TableCellAvatar";
import useSearchQuery from "@saleor/hooks/useSearchQuery"; import useSearchQuery from "@saleor/hooks/useSearchQuery";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { SearchProducts_search_edges_node } from "../../containers/SearchProducts/types/SearchProducts"; import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import Checkbox from "../Checkbox"; import Checkbox from "../Checkbox";
export interface FormData { export interface FormData {

View file

@ -1,10 +1,10 @@
import { SearchQueryVariables } from "./containers/BaseSearch"; import { SearchVariables } from "./hooks/makeSearch";
import { ListSettings, ListViews } from "./types"; import { ListSettings, ListViews } from "./types";
export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/"; export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/";
export const API_URI = process.env.API_URI || "/graphql/"; export const API_URI = process.env.API_URI || "/graphql/";
export const DEFAULT_INITIAL_SEARCH_DATA: SearchQueryVariables = { export const DEFAULT_INITIAL_SEARCH_DATA: SearchVariables = {
after: null, after: null,
first: 20, first: 20,
query: "" query: ""

View file

@ -1,77 +0,0 @@
import { DocumentNode } from "graphql";
import React from "react";
import Debounce from "../components/Debounce";
import { TypedQuery, TypedQueryResult } from "../queries";
export interface SearchQueryVariables {
after?: string;
first: number;
query: string;
}
interface BaseSearchProps<
TQuery,
TQueryVariables extends SearchQueryVariables
> {
children: (props: {
loadMore: () => void;
search: (query: string) => void;
result: TypedQueryResult<TQuery, TQueryVariables>;
}) => React.ReactElement<any>;
variables: TQueryVariables;
}
function BaseSearch<TQuery, TQueryVariables extends SearchQueryVariables>(
query: DocumentNode,
loadMoreFn: (result: TypedQueryResult<TQuery, TQueryVariables>) => void
) {
const Query = TypedQuery<TQuery, TQueryVariables>(query);
class BaseSearchComponent extends React.Component<
BaseSearchProps<TQuery, TQueryVariables>,
SearchQueryVariables
> {
state: SearchQueryVariables = {
first: this.props.variables.first,
query: this.props.variables.query
};
search = (query: string) => {
if (query === undefined) {
this.setState({ query: "" });
} else {
this.setState({ query });
}
};
render() {
const { children, variables } = this.props;
return (
<Debounce debounceFn={this.search} time={200}>
{search => (
<Query
displayLoader={true}
variables={{
...variables,
query: this.state.query
}}
>
{result =>
children({
loadMore: () => loadMoreFn(result),
result,
search
})
}
</Query>
)}
</Debounce>
);
}
}
return BaseSearchComponent;
}
export default BaseSearch;

View file

@ -8,6 +8,7 @@ import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog";
import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog"; import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog";
import AssignProductDialog from "@saleor/components/AssignProductDialog"; import AssignProductDialog from "@saleor/components/AssignProductDialog";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "@saleor/config";
import useBulkActions from "@saleor/hooks/useBulkActions"; import useBulkActions from "@saleor/hooks/useBulkActions";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
@ -16,12 +17,11 @@ 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 useCollectionSearch from "@saleor/searches/useCollectionSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
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 SearchCategories from "../../containers/SearchCategories";
import SearchCollections from "../../containers/SearchCollections";
import SearchProducts from "../../containers/SearchProducts";
import { decimal, getMutationState, joinDateTime, maybe } from "../../misc"; import { decimal, getMutationState, joinDateTime, maybe } from "../../misc";
import { productUrl } from "../../products/urls"; import { productUrl } from "../../products/urls";
import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes"; import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes";
@ -66,6 +66,24 @@ 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 {
search: searchCollections,
result: searchCollectionsOpts
} = useCollectionSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const {
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
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) => {
@ -341,13 +359,6 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
toggle={toggle} toggle={toggle}
toggleAll={toggleAll} toggleAll={toggleAll}
/> />
<SearchProducts
variables={DEFAULT_INITIAL_SEARCH_DATA}
>
{({
search: searchProducts,
result: searchProductsOpts
}) => (
<AssignProductDialog <AssignProductDialog
confirmButtonState={assignTransitionState} confirmButtonState={assignTransitionState}
open={params.action === "assign-product"} open={params.action === "assign-product"}
@ -375,22 +386,12 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
) )
)} )}
/> />
)}
</SearchProducts>
<SearchCategories
variables={DEFAULT_INITIAL_SEARCH_DATA}
>
{({
search: searchCategories,
result: searchCategoriesOpts
}) => (
<AssignCategoriesDialog <AssignCategoriesDialog
categories={maybe(() => categories={maybe(() =>
searchCategoriesOpts.data.search.edges searchCategoriesOpts.data.search.edges
.map(edge => edge.node) .map(edge => edge.node)
.filter( .filter(
suggestedCategory => suggestedCategory => suggestedCategory.id
suggestedCategory.id
) )
)} )}
confirmButtonState={assignTransitionState} confirmButtonState={assignTransitionState}
@ -412,22 +413,12 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
}) })
} }
/> />
)}
</SearchCategories>
<SearchCollections
variables={DEFAULT_INITIAL_SEARCH_DATA}
>
{({
search: searchCollections,
result: searchCollectionsOpts
}) => (
<AssignCollectionDialog <AssignCollectionDialog
collections={maybe(() => collections={maybe(() =>
searchCollectionsOpts.data.search.edges searchCollectionsOpts.data.search.edges
.map(edge => edge.node) .map(edge => edge.node)
.filter( .filter(
suggestedCategory => suggestedCategory => suggestedCategory.id
suggestedCategory.id
) )
)} )}
confirmButtonState={assignTransitionState} confirmButtonState={assignTransitionState}
@ -449,8 +440,6 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
}) })
} }
/> />
)}
</SearchCollections>
<ActionDialog <ActionDialog
open={ open={
params.action === "unassign-category" && params.action === "unassign-category" &&

View file

@ -8,6 +8,7 @@ import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog";
import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog"; import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog";
import AssignProductDialog from "@saleor/components/AssignProductDialog"; import AssignProductDialog from "@saleor/components/AssignProductDialog";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "@saleor/config";
import useBulkActions from "@saleor/hooks/useBulkActions"; import useBulkActions from "@saleor/hooks/useBulkActions";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
@ -16,12 +17,11 @@ 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 useCollectionSearch from "@saleor/searches/useCollectionSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
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 SearchCategories from "../../containers/SearchCategories";
import SearchCollections from "../../containers/SearchCollections";
import SearchProducts from "../../containers/SearchProducts";
import { decimal, getMutationState, joinDateTime, maybe } from "../../misc"; import { decimal, getMutationState, joinDateTime, maybe } from "../../misc";
import { productUrl } from "../../products/urls"; import { productUrl } from "../../products/urls";
import { import {
@ -68,6 +68,24 @@ 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 {
search: searchCollections,
result: searchCollectionsOpts
} = useCollectionSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const {
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
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,20 +438,12 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
toggle={toggle} toggle={toggle}
toggleAll={toggleAll} toggleAll={toggleAll}
/> />
<SearchCategories
variables={DEFAULT_INITIAL_SEARCH_DATA}
>
{({
search: searchCategories,
result: searchCategoriesOpts
}) => (
<AssignCategoriesDialog <AssignCategoriesDialog
categories={maybe(() => categories={maybe(() =>
searchCategoriesOpts.data.search.edges searchCategoriesOpts.data.search.edges
.map(edge => edge.node) .map(edge => edge.node)
.filter( .filter(
suggestedCategory => suggestedCategory => suggestedCategory.id
suggestedCategory.id
) )
)} )}
confirmButtonState={assignTransitionState} confirmButtonState={assignTransitionState}
@ -455,22 +465,12 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
}) })
} }
/> />
)}
</SearchCategories>
<SearchCollections
variables={DEFAULT_INITIAL_SEARCH_DATA}
>
{({
search: searchCollections,
result: searchCollectionsOpts
}) => (
<AssignCollectionDialog <AssignCollectionDialog
collections={maybe(() => collections={maybe(() =>
searchCollectionsOpts.data.search.edges searchCollectionsOpts.data.search.edges
.map(edge => edge.node) .map(edge => edge.node)
.filter( .filter(
suggestedCategory => suggestedCategory => suggestedCategory.id
suggestedCategory.id
) )
)} )}
confirmButtonState={assignTransitionState} confirmButtonState={assignTransitionState}
@ -492,8 +492,6 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
}) })
} }
/> />
)}
</SearchCollections>
<DiscountCountrySelectDialog <DiscountCountrySelectDialog
confirmButtonState={formTransitionState} confirmButtonState={formTransitionState}
countries={maybe(() => shop.countries, [])} countries={maybe(() => shop.countries, [])}
@ -517,13 +515,6 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
[] []
)} )}
/> />
<SearchProducts
variables={DEFAULT_INITIAL_SEARCH_DATA}
>
{({
search: searchProducts,
result: searchProductsOpts
}) => (
<AssignProductDialog <AssignProductDialog
confirmButtonState={assignTransitionState} confirmButtonState={assignTransitionState}
open={params.action === "assign-product"} open={params.action === "assign-product"}
@ -551,8 +542,6 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
) )
)} )}
/> />
)}
</SearchProducts>
<ActionDialog <ActionDialog
open={ open={
params.action === "unassign-category" && params.action === "unassign-category" &&

View file

@ -16,7 +16,7 @@ export interface LoadMore<TData, TVariables> {
) => Promise<ApolloQueryResult<TData>>; ) => Promise<ApolloQueryResult<TData>>;
} }
type UseQuery<TData, TVariables> = QueryResult<TData, TVariables> & export type UseQueryResult<TData, TVariables> = QueryResult<TData, TVariables> &
LoadMore<TData, TVariables>; LoadMore<TData, TVariables>;
type UseQueryOpts<TData, TVariables> = Partial<{ type UseQueryOpts<TData, TVariables> = Partial<{
displayLoader: boolean; displayLoader: boolean;
@ -26,17 +26,17 @@ type UseQueryOpts<TData, TVariables> = Partial<{
}>; }>;
type UseQueryHook<TData, TVariables> = ( type UseQueryHook<TData, TVariables> = (
opts: UseQueryOpts<TData, TVariables> opts: UseQueryOpts<TData, TVariables>
) => UseQuery<TData, TVariables>; ) => UseQueryResult<TData, TVariables>;
function makeQuery<TData, TVariables>( function makeQuery<TData, TVariables>(
query: DocumentNode query: DocumentNode
): UseQueryHook<TData, TVariables> { ): UseQueryHook<TData, TVariables> {
function useQuery<TData, TVariables>({ function useQuery({
displayLoader, displayLoader,
require, require,
skip, skip,
variables variables
}: UseQueryOpts<TData, TVariables>): UseQuery<TData, TVariables> { }: UseQueryOpts<TData, TVariables>): UseQueryResult<TData, TVariables> {
const notify = useNotifier(); const notify = useNotifier();
const intl = useIntl(); const intl = useIntl();
const [, dispatchAppState] = useAppState(); const [, dispatchAppState] = useAppState();

57
src/hooks/makeSearch.ts Normal file
View file

@ -0,0 +1,57 @@
import { DocumentNode } from "graphql";
import { useState } from "react";
import { QueryResult } from "react-apollo";
import makeQuery, { UseQueryResult } from "./makeQuery";
import useDebounce from "./useDebounce";
export interface SearchVariables {
after?: string;
first: number;
query: string;
}
export interface UseSearchResult<TData, TVariables extends SearchVariables> {
loadMore: () => void;
result: QueryResult<TData, TVariables>;
search: (query: string) => void;
}
export type UseSearchOpts<TVariables extends SearchVariables> = Partial<{
skip: boolean;
variables: TVariables;
}>;
export type UseSearchHook<TData, TVariables extends SearchVariables> = (
opts: UseSearchOpts<TVariables>
) => UseSearchResult<TData, TVariables>;
function makeSearch<TData, TVariables extends SearchVariables>(
query: DocumentNode,
loadMoreFn: (result: UseQueryResult<TData, TVariables>) => void
): UseSearchHook<TData, TVariables> {
const useSearchQuery = makeQuery<TData, TVariables>(query);
function useSearch(
opts: UseSearchOpts<TVariables>
): UseSearchResult<TData, TVariables> {
const [searchQuery, setSearchQuery] = useState("");
const debouncedSearch = useDebounce(setSearchQuery);
const result = useSearchQuery({
...opts,
displayLoader: true,
variables: {
...opts.variables,
query: searchQuery
}
});
return {
loadMore: () => loadMoreFn(result),
result,
search: debouncedSearch
};
}
return useSearch;
}
export default makeSearch;

View file

@ -1,9 +1,9 @@
import { DocumentNode } from "graphql"; import { DocumentNode } from "graphql";
import { PageInfoFragment } from "@saleor/types/PageInfoFragment"; import { PageInfoFragment } from "@saleor/types/PageInfoFragment";
import BaseSearch, { SearchQueryVariables } from "./BaseSearch"; import makeSearch, { SearchVariables, UseSearchHook } from "./makeSearch";
export interface SearchQuery { export interface SearchData {
search: { search: {
edges: Array<{ edges: Array<{
node: any; node: any;
@ -12,11 +12,11 @@ export interface SearchQuery {
}; };
} }
function TopLevelSearch< function makeTopLevelSearch<
TQuery extends SearchQuery, TData extends SearchData,
TQueryVariables extends SearchQueryVariables TVariables extends SearchVariables
>(query: DocumentNode) { >(query: DocumentNode): UseSearchHook<TData, TVariables> {
return BaseSearch<TQuery, TQueryVariables>(query, result => { return makeSearch<TData, TVariables>(query, result => {
if (result.data.search.pageInfo.hasNextPage) { if (result.data.search.pageInfo.hasNextPage) {
result.loadMore( result.loadMore(
(prev, next) => { (prev, next) => {
@ -44,4 +44,4 @@ function TopLevelSearch<
}); });
} }
export default TopLevelSearch; export default makeTopLevelSearch;

19
src/hooks/useDebounce.ts Normal file
View file

@ -0,0 +1,19 @@
import { useEffect, useRef } from "react";
export type UseDebounceFn<T> = (...args: T[]) => void;
function useDebounce<T>(
debounceFn: UseDebounceFn<T>,
time = 200
): UseDebounceFn<T> {
const timer = useRef(null);
useEffect(() => () => clearTimeout(timer.current));
return (...args: T[]) => {
if (timer.current) {
clearTimeout(timer.current);
}
timer.current = setTimeout(() => debounceFn(...args), time);
};
}
export default useDebounce;

View file

@ -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 { 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 { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
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";

View file

@ -3,14 +3,14 @@ import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import ActionDialog from "@saleor/components/ActionDialog"; import ActionDialog from "@saleor/components/ActionDialog";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
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 useCollectionSearch from "@saleor/searches/useCollectionSearch";
import usePageSearch from "@saleor/searches/usePageSearch";
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 SearchCategories from "../../../containers/SearchCategories";
import SearchCollections from "../../../containers/SearchCollections";
import SearchPages from "../../../containers/SearchPages";
import { getMutationState, maybe } from "../../../misc"; import { getMutationState, maybe } from "../../../misc";
import { pageUrl } from "../../../pages/urls"; import { pageUrl } from "../../../pages/urls";
import MenuDetailsPage, { import MenuDetailsPage, {
@ -59,6 +59,15 @@ 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 collectionSearch = useCollectionSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const pageSearch = usePageSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const closeModal = () => const closeModal = () =>
navigate( navigate(
@ -95,12 +104,6 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
}; };
return ( return (
<SearchPages variables={DEFAULT_INITIAL_SEARCH_DATA}>
{pageSearch => (
<SearchCategories variables={DEFAULT_INITIAL_SEARCH_DATA}>
{categorySearch => (
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
{collectionSearch => (
<MenuDetailsQuery displayLoader variables={{ id }}> <MenuDetailsQuery displayLoader variables={{ id }}>
{({ data, loading, refetch }) => { {({ data, loading, refetch }) => {
const handleQueryChange = (query: string) => { const handleQueryChange = (query: string) => {
@ -110,67 +113,47 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
}; };
const categories = maybe( const categories = maybe(
() => () => categorySearch.result.data.search.edges.map(edge => edge.node),
categorySearch.result.data.search.edges.map(
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(edge => edge.node),
pageSearch.result.data.search.edges.map(
edge => edge.node
),
[] []
); );
return ( return (
<MenuDeleteMutation <MenuDeleteMutation
onCompleted={data => onCompleted={data => handleDelete(data, navigate, notify, intl)}
handleDelete(data, navigate, notify, intl)
}
> >
{(menuDelete, menuDeleteOpts) => ( {(menuDelete, menuDeleteOpts) => (
<MenuUpdateMutation <MenuUpdateMutation
onCompleted={data => onCompleted={data => handleUpdate(data, notify, refetch, intl)}
handleUpdate(data, notify, refetch, intl)
}
> >
{(menuUpdate, menuUpdateOpts) => { {(menuUpdate, menuUpdateOpts) => {
const deleteState = getMutationState( const deleteState = getMutationState(
menuDeleteOpts.called, menuDeleteOpts.called,
menuDeleteOpts.loading, menuDeleteOpts.loading,
maybe( maybe(() => menuDeleteOpts.data.menuDelete.errors)
() => 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: {
@ -182,10 +165,8 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
}); });
if (result) { if (result) {
if ( if (
result.data.menuItemBulkDelete.errors result.data.menuItemBulkDelete.errors.length > 0 ||
.length > 0 || result.data.menuItemMove.errors.length > 0 ||
result.data.menuItemMove.errors.length >
0 ||
result.data.menuUpdate.errors.length > 0 result.data.menuUpdate.errors.length > 0
) { ) {
return false; return false;
@ -233,9 +214,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
open={params.action === "remove"} open={params.action === "remove"}
onClose={closeModal} onClose={closeModal}
confirmButtonState={deleteState} confirmButtonState={deleteState}
onConfirm={() => onConfirm={() => menuDelete({ variables: { id } })}
menuDelete({ variables: { id } })
}
variant="delete" variant="delete"
title={intl.formatMessage({ title={intl.formatMessage({
defaultMessage: "Delete Menu", defaultMessage: "Delete Menu",
@ -250,10 +229,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
values={{ values={{
menuName: ( menuName: (
<strong> <strong>
{maybe( {maybe(() => data.menu.name, "...")}
() => data.menu.name,
"..."
)}
</strong> </strong>
) )
}} }}
@ -263,12 +239,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
<MenuItemCreateMutation <MenuItemCreateMutation
onCompleted={data => onCompleted={data =>
handleItemCreate( handleItemCreate(data, notify, closeModal, intl)
data,
notify,
closeModal,
intl
)
} }
> >
{(menuItemCreate, menuItemCreateOpts) => { {(menuItemCreate, menuItemCreateOpts) => {
@ -276,10 +247,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
data: MenuItemDialogFormData data: MenuItemDialogFormData
) => { ) => {
const variables: MenuItemCreateVariables = { const variables: MenuItemCreateVariables = {
input: getMenuItemCreateInputData( input: getMenuItemCreateInputData(id, data)
id,
data
)
}; };
menuItemCreate({ variables }); menuItemCreate({ variables });
@ -290,8 +258,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
menuItemCreateOpts.loading, menuItemCreateOpts.loading,
maybe( maybe(
() => () =>
menuItemCreateOpts.data menuItemCreateOpts.data.menuItemCreate.errors
.menuItemCreate.errors
) )
); );
@ -302,8 +269,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
collections={collections} collections={collections}
errors={maybe( errors={maybe(
() => () =>
menuItemCreateOpts.data menuItemCreateOpts.data.menuItemCreate.errors,
.menuItemCreate.errors,
[] []
)} )}
pages={pages} pages={pages}
@ -311,9 +277,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
categorySearch.result.loading || categorySearch.result.loading ||
collectionSearch.result.loading collectionSearch.result.loading
} }
confirmButtonState={ confirmButtonState={formTransitionState}
formTransitionState
}
disabled={menuItemCreateOpts.loading} disabled={menuItemCreateOpts.loading}
onClose={closeModal} onClose={closeModal}
onSubmit={handleSubmit} onSubmit={handleSubmit}
@ -324,13 +288,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
</MenuItemCreateMutation> </MenuItemCreateMutation>
<MenuItemUpdateMutation <MenuItemUpdateMutation
onCompleted={data => onCompleted={data =>
handleItemUpdate( handleItemUpdate(data, id, navigate, notify, intl)
data,
id,
navigate,
notify,
intl
)
} }
> >
{(menuItemUpdate, menuItemUpdateOpts) => { {(menuItemUpdate, menuItemUpdateOpts) => {
@ -357,8 +315,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
menuItemUpdateOpts.loading, menuItemUpdateOpts.loading,
maybe( maybe(
() => () =>
menuItemUpdateOpts.data menuItemUpdateOpts.data.menuItemUpdate.errors
.menuItemUpdate.errors
) )
); );
@ -378,8 +335,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
collections={collections} collections={collections}
errors={maybe( errors={maybe(
() => () =>
menuItemUpdateOpts.data menuItemUpdateOpts.data.menuItemUpdate.errors,
.menuItemUpdate.errors,
[] []
)} )}
pages={pages} pages={pages}
@ -391,9 +347,7 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
categorySearch.result.loading || categorySearch.result.loading ||
collectionSearch.result.loading collectionSearch.result.loading
} }
confirmButtonState={ confirmButtonState={formTransitionState}
formTransitionState
}
disabled={menuItemUpdateOpts.loading} disabled={menuItemUpdateOpts.loading}
onClose={closeModal} onClose={closeModal}
onSubmit={handleSubmit} onSubmit={handleSubmit}
@ -411,12 +365,6 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
); );
}} }}
</MenuDetailsQuery> </MenuDetailsQuery>
)}
</SearchCollections>
)}
</SearchCategories>
)}
</SearchPages>
); );
}; };
MenuDetails.displayName = "MenuDetails"; MenuDetails.displayName = "MenuDetails";

View file

@ -16,10 +16,10 @@ import SingleAutocompleteSelectField from "@saleor/components/SingleAutocomplete
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers";
import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; import { FetchMoreProps, UserPermissionProps } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes"; import { PermissionEnum } from "@saleor/types/globalTypes";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import { SearchCustomers_search_edges_node } from "../../../containers/SearchCustomers/types/SearchCustomers";
import { customerUrl } from "../../../customers/urls"; import { customerUrl } from "../../../customers/urls";
import { createHref, maybe } from "../../../misc"; import { createHref, maybe } from "../../../misc";
import { OrderDetails_order } from "../../types/OrderDetails"; import { OrderDetails_order } from "../../types/OrderDetails";

View file

@ -13,8 +13,8 @@ import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers";
import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; import { FetchMoreProps, UserPermissionProps } from "@saleor/types";
import { SearchCustomers_search_edges_node } from "../../../containers/SearchCustomers/types/SearchCustomers";
import { maybe } from "../../../misc"; import { maybe } from "../../../misc";
import { DraftOrderInput } from "../../../types/globalTypes"; import { DraftOrderInput } from "../../../types/globalTypes";
import { OrderDetails_order } from "../../types/OrderDetails"; import { OrderDetails_order } from "../../types/OrderDetails";

View file

@ -1,5 +1,5 @@
import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers";
import { MessageDescriptor } from "react-intl"; import { MessageDescriptor } from "react-intl";
import { SearchCustomers_search_edges_node } from "../containers/SearchCustomers/types/SearchCustomers";
import { transformOrderStatus, transformPaymentStatus } from "../misc"; import { transformOrderStatus, transformPaymentStatus } from "../misc";
import { import {
FulfillmentStatus, FulfillmentStatus,

View file

@ -1,6 +1,6 @@
import gql from "graphql-tag"; import gql from "graphql-tag";
import TopLevelSearch from "../containers/TopLevelSearch"; import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch";
import { TypedQuery } from "../queries"; import { TypedQuery } from "../queries";
import { OrderDetails, OrderDetailsVariables } from "./types/OrderDetails"; import { OrderDetails, OrderDetailsVariables } from "./types/OrderDetails";
import { import {
@ -314,7 +314,7 @@ export const searchOrderVariant = gql`
} }
} }
`; `;
export const SearchOrderVariant = TopLevelSearch< export const useOrderVariantSearch = makeTopLevelSearch<
SearchOrderVariantType, SearchOrderVariantType,
SearchOrderVariantVariables SearchOrderVariantVariables
>(searchOrderVariant); >(searchOrderVariant);

View file

@ -1,10 +1,10 @@
import React from "react"; import React from "react";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useUser from "@saleor/hooks/useUser"; import useUser from "@saleor/hooks/useUser";
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; import useCustomerSearch from "@saleor/searches/useCustomerSearch";
import SearchCustomers from "../../../containers/SearchCustomers";
import { customerUrl } from "../../../customers/urls"; import { customerUrl } from "../../../customers/urls";
import { getMutationState, maybe, transformAddressToForm } from "../../../misc"; import { getMutationState, maybe, transformAddressToForm } from "../../../misc";
import { productUrl } from "../../../products/urls"; import { productUrl } from "../../../products/urls";
@ -26,7 +26,7 @@ import OrderPaymentVoidDialog from "../../components/OrderPaymentVoidDialog";
import OrderProductAddDialog from "../../components/OrderProductAddDialog"; import OrderProductAddDialog from "../../components/OrderProductAddDialog";
import OrderShippingMethodEditDialog from "../../components/OrderShippingMethodEditDialog"; import OrderShippingMethodEditDialog from "../../components/OrderShippingMethodEditDialog";
import OrderOperations from "../../containers/OrderOperations"; import OrderOperations from "../../containers/OrderOperations";
import { SearchOrderVariant, TypedOrderDetailsQuery } from "../../queries"; import { TypedOrderDetailsQuery, useOrderVariantSearch } from "../../queries";
import { OrderDetails_order } from "../../types/OrderDetails"; import { OrderDetails_order } from "../../types/OrderDetails";
import { import {
orderListUrl, orderListUrl,
@ -74,6 +74,20 @@ interface OrderDetailsProps {
export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => { export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
const navigate = useNavigator(); const navigate = useNavigator();
const { user } = useUser(); const { user } = useUser();
const {
loadMore: loadMoreCustomers,
search: searchUsers,
result: users
} = useCustomerSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const {
loadMore,
search: variantSearch,
result: variantSearchOpts
} = useOrderVariantSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
return ( return (
<TypedOrderDetailsQuery <TypedOrderDetailsQuery
@ -91,12 +105,6 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
}) })
); );
return ( return (
<SearchCustomers variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({
loadMore: loadMoreCustomers,
search: searchUsers,
result: users
}) => (
<OrderDetailsMessages> <OrderDetailsMessages>
{orderMessages => ( {orderMessages => (
<OrderOperations <OrderOperations
@ -151,8 +159,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
orderDraftFinalize.opts.loading, orderDraftFinalize.opts.loading,
maybe( maybe(
() => () =>
orderDraftFinalize.opts.data.draftOrderComplete orderDraftFinalize.opts.data.draftOrderComplete.errors
.errors
) )
); );
return ( return (
@ -160,9 +167,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
{maybe(() => order.status !== OrderStatus.DRAFT) ? ( {maybe(() => order.status !== OrderStatus.DRAFT) ? (
<> <>
<WindowTitle <WindowTitle
title={maybe( title={maybe(() => "Order #" + data.order.number)}
() => "Order #" + data.order.number
)}
/> />
<OrderDetailsPage <OrderDetailsPage
onNoteAdd={variables => onNoteAdd={variables =>
@ -177,10 +182,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
() => data.order.availableShippingMethods, () => data.order.availableShippingMethods,
[] []
)} )}
userPermissions={maybe( userPermissions={maybe(() => user.permissions, [])}
() => user.permissions,
[]
)}
onOrderCancel={() => openModal("cancel")} onOrderCancel={() => openModal("cancel")}
onOrderFulfill={() => openModal("fulfill")} onOrderFulfill={() => openModal("fulfill")}
onFulfillmentCancel={fulfillmentId => onFulfillmentCancel={fulfillmentId =>
@ -220,8 +222,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
orderCancel.opts.called, orderCancel.opts.called,
orderCancel.opts.loading, orderCancel.opts.loading,
maybe( maybe(
() => () => orderCancel.opts.data.orderCancel.errors
orderCancel.opts.data.orderCancel.errors
) )
)} )}
number={maybe(() => order.number)} number={maybe(() => order.number)}
@ -256,9 +257,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
confirmButtonState={getMutationState( confirmButtonState={getMutationState(
orderVoid.opts.called, orderVoid.opts.called,
orderVoid.opts.loading, orderVoid.opts.loading,
maybe( maybe(() => orderVoid.opts.data.orderVoid.errors)
() => orderVoid.opts.data.orderVoid.errors
)
)} )}
open={params.action === "void"} open={params.action === "void"}
onClose={closeModal} onClose={closeModal}
@ -328,8 +327,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
lines: maybe(() => order.lines, []) lines: maybe(() => order.lines, [])
.filter( .filter(
line => line =>
line.quantityFulfilled < line.quantityFulfilled < line.quantity
line.quantity
) )
.map((line, lineIndex) => ({ .map((line, lineIndex) => ({
orderLineId: line.id, orderLineId: line.id,
@ -374,8 +372,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
trackingNumber={maybe( trackingNumber={maybe(
() => () =>
data.order.fulfillments.find( data.order.fulfillments.find(
fulfillment => fulfillment => fulfillment.id === params.id
fulfillment.id === params.id
).trackingNumber ).trackingNumber
)} )}
onConfirm={variables => onConfirm={variables =>
@ -407,9 +404,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
} }
users={maybe( users={maybe(
() => () =>
users.data.search.edges.map( users.data.search.edges.map(edge => edge.node),
edge => edge.node
),
[] []
)} )}
hasMore={maybe( hasMore={maybe(
@ -428,18 +423,15 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
} }
onDraftFinalize={() => openModal("finalize")} onDraftFinalize={() => openModal("finalize")}
onDraftRemove={() => openModal("cancel")} onDraftRemove={() => openModal("cancel")}
onOrderLineAdd={() => onOrderLineAdd={() => openModal("add-order-line")}
openModal("add-order-line")
}
onBack={() => navigate(orderListUrl())} onBack={() => navigate(orderListUrl())}
order={order} order={order}
countries={maybe( countries={maybe(() => data.shop.countries, []).map(
() => data.shop.countries, country => ({
[]
).map(country => ({
code: country.code, code: country.code,
label: country.country label: country.country
}))} })
)}
onProductClick={id => () => onProductClick={id => () =>
navigate(productUrl(encodeURIComponent(id)))} navigate(productUrl(encodeURIComponent(id)))}
onBillingAddressEdit={() => onBillingAddressEdit={() =>
@ -464,10 +456,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
onProfileView={() => onProfileView={() =>
navigate(customerUrl(order.user.id)) navigate(customerUrl(order.user.id))
} }
userPermissions={maybe( userPermissions={maybe(() => user.permissions, [])}
() => user.permissions,
[]
)}
/> />
<OrderDraftCancelDialog <OrderDraftCancelDialog
confirmButtonState={getMutationState( confirmButtonState={getMutationState(
@ -475,23 +464,19 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
orderDraftCancel.opts.loading, orderDraftCancel.opts.loading,
maybe( maybe(
() => () =>
orderDraftCancel.opts.data orderDraftCancel.opts.data.draftOrderDelete
.draftOrderDelete.errors .errors
) )
)} )}
onClose={closeModal} onClose={closeModal}
onConfirm={() => onConfirm={() => orderDraftCancel.mutate({ id })}
orderDraftCancel.mutate({ id })
}
open={params.action === "cancel"} open={params.action === "cancel"}
orderNumber={maybe(() => order.number)} orderNumber={maybe(() => order.number)}
/> />
<OrderDraftFinalizeDialog <OrderDraftFinalizeDialog
confirmButtonState={finalizeTransitionState} confirmButtonState={finalizeTransitionState}
onClose={closeModal} onClose={closeModal}
onConfirm={() => onConfirm={() => orderDraftFinalize.mutate({ id })}
orderDraftFinalize.mutate({ id })
}
open={params.action === "finalize"} open={params.action === "finalize"}
orderNumber={maybe(() => order.number)} orderNumber={maybe(() => order.number)}
warnings={orderDraftFinalizeWarnings(order)} warnings={orderDraftFinalizeWarnings(order)}
@ -524,22 +509,14 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
}) })
} }
/> />
<SearchOrderVariant
variables={DEFAULT_INITIAL_SEARCH_DATA}
>
{({
loadMore,
search: variantSearch,
result: variantSearchOpts
}) => (
<OrderProductAddDialog <OrderProductAddDialog
confirmButtonState={getMutationState( confirmButtonState={getMutationState(
orderLinesAdd.opts.called, orderLinesAdd.opts.called,
orderLinesAdd.opts.loading, orderLinesAdd.opts.loading,
maybe( maybe(
() => () =>
orderLinesAdd.opts.data orderLinesAdd.opts.data.draftOrderLinesCreate
.draftOrderLinesCreate.errors .errors
) )
)} )}
loading={variantSearchOpts.loading} loading={variantSearchOpts.loading}
@ -567,17 +544,13 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
}) })
} }
/> />
)}
</SearchOrderVariant>
</> </>
)} )}
<OrderAddressEditDialog <OrderAddressEditDialog
confirmButtonState={getMutationState( confirmButtonState={getMutationState(
orderUpdate.opts.called, orderUpdate.opts.called,
orderUpdate.opts.loading, orderUpdate.opts.loading,
maybe( maybe(() => orderUpdate.opts.data.orderUpdate.errors)
() => orderUpdate.opts.data.orderUpdate.errors
)
)} )}
address={transformAddressToForm( address={transformAddressToForm(
maybe(() => order.shippingAddress) maybe(() => order.shippingAddress)
@ -608,9 +581,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
confirmButtonState={getMutationState( confirmButtonState={getMutationState(
orderUpdate.opts.called, orderUpdate.opts.called,
orderUpdate.opts.loading, orderUpdate.opts.loading,
maybe( maybe(() => orderUpdate.opts.data.orderUpdate.errors)
() => orderUpdate.opts.data.orderUpdate.errors
)
)} )}
address={transformAddressToForm( address={transformAddressToForm(
maybe(() => order.billingAddress) maybe(() => order.billingAddress)
@ -643,8 +614,6 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
</OrderOperations> </OrderOperations>
)} )}
</OrderDetailsMessages> </OrderDetailsMessages>
)}
</SearchCustomers>
); );
}} }}
</TypedOrderDetailsQuery> </TypedOrderDetailsQuery>

View file

@ -30,7 +30,7 @@ import useSearchQuery from "@saleor/hooks/useSearchQuery";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { maybe, renderCollection } from "@saleor/misc"; import { maybe, renderCollection } from "@saleor/misc";
import { FetchMoreProps } from "@saleor/types"; import { FetchMoreProps } from "@saleor/types";
import { SearchAttributes_productType_availableAttributes_edges_node } from "../../containers/SearchAttributes/types/SearchAttributes"; import { SearchAttributes_productType_availableAttributes_edges_node } from "../../hooks/useAvailableAttributeSearch/types/SearchAttributes";
const useStyles = makeStyles(theme => ({ const useStyles = makeStyles(theme => ({
actions: { actions: {

View file

@ -1,7 +1,7 @@
import { import {
SearchProductTypes_search_edges_node, SearchProductTypes_search_edges_node,
SearchProductTypes_search_edges_node_productAttributes SearchProductTypes_search_edges_node_productAttributes
} from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; } from "@saleor/searches/types/SearchProductTypes";
import { AttributeInputTypeEnum } from "../types/globalTypes"; import { AttributeInputTypeEnum } from "../types/globalTypes";
import { ProductTypeDetails_productType } from "./types/ProductTypeDetails"; import { ProductTypeDetails_productType } from "./types/ProductTypeDetails";
import { ProductTypeList_productTypes_edges_node } from "./types/ProductTypeList"; import { ProductTypeList_productTypes_edges_node } from "./types/ProductTypeList";

View file

@ -1,7 +1,7 @@
import gql from "graphql-tag"; import gql from "graphql-tag";
import makeSearch from "@saleor/hooks/makeSearch";
import { pageInfoFragment } from "@saleor/queries"; import { pageInfoFragment } from "@saleor/queries";
import BaseSearch from "../../../containers/BaseSearch";
import { import {
SearchAttributes, SearchAttributes,
SearchAttributesVariables SearchAttributesVariables
@ -37,11 +37,19 @@ export const searchAttributes = gql`
} }
`; `;
export default BaseSearch<SearchAttributes, SearchAttributesVariables>( export default makeSearch<SearchAttributes, SearchAttributesVariables>(
searchAttributes, searchAttributes,
result => result =>
result.loadMore( result.loadMore(
(prev, next) => ({ (prev, next) => {
if (
prev.productType.availableAttributes.pageInfo.endCursor ===
next.productType.availableAttributes.pageInfo.endCursor
) {
return prev;
}
return {
...prev, ...prev,
productType: { productType: {
...prev.productType, ...prev.productType,
@ -54,7 +62,8 @@ export default BaseSearch<SearchAttributes, SearchAttributesVariables>(
pageInfo: next.productType.availableAttributes.pageInfo pageInfo: next.productType.availableAttributes.pageInfo
} }
} }
}), };
},
{ {
after: result.data.productType.availableAttributes.pageInfo.endCursor after: result.data.productType.availableAttributes.pageInfo.endCursor
} }

View file

@ -4,6 +4,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import { attributeUrl } from "@saleor/attributes/urls"; import { attributeUrl } from "@saleor/attributes/urls";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import useBulkActions from "@saleor/hooks/useBulkActions"; import useBulkActions from "@saleor/hooks/useBulkActions";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
@ -19,7 +20,7 @@ import ProductTypeDetailsPage, {
ProductTypeForm ProductTypeForm
} from "../../components/ProductTypeDetailsPage"; } from "../../components/ProductTypeDetailsPage";
import ProductTypeOperations from "../../containers/ProductTypeOperations"; import ProductTypeOperations from "../../containers/ProductTypeOperations";
import SearchAttributes from "../../containers/SearchAttributes"; import useAvailableAttributeSearch from "../../hooks/useAvailableAttributeSearch";
import { TypedProductTypeDetailsQuery } from "../../queries"; import { TypedProductTypeDetailsQuery } from "../../queries";
import { AssignAttribute } from "../../types/AssignAttribute"; import { AssignAttribute } from "../../types/AssignAttribute";
import { ProductTypeDelete } from "../../types/ProductTypeDelete"; import { ProductTypeDelete } from "../../types/ProductTypeDelete";
@ -46,6 +47,12 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
const productAttributeListActions = useBulkActions(); const productAttributeListActions = useBulkActions();
const variantAttributeListActions = useBulkActions(); const variantAttributeListActions = useBulkActions();
const intl = useIntl(); const intl = useIntl();
const { loadMore, search, result } = useAvailableAttributeSearch({
variables: {
...DEFAULT_INITIAL_SEARCH_DATA,
id
}
});
return ( return (
<ProductTypeUpdateErrors> <ProductTypeUpdateErrors>
@ -330,55 +337,8 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
) )
}} }}
/> />
{!dataLoading && ( {!dataLoading &&
<SearchAttributes Object.keys(AttributeTypeEnum).map(key => (
variables={{
first: 15,
id,
query: ""
}}
>
{({ search, result }) => {
const fetchMore = () =>
result.loadMore(
(prev, next) => {
if (
prev.productType.availableAttributes
.pageInfo.endCursor ===
next.productType.availableAttributes
.pageInfo.endCursor
) {
return prev;
}
return {
...prev,
productType: {
...prev.productType,
availableAttributes: {
...prev.productType.availableAttributes,
edges: [
...prev.productType
.availableAttributes.edges,
...next.productType
.availableAttributes.edges
],
pageInfo:
next.productType.availableAttributes
.pageInfo
}
}
};
},
{
after:
result.data.productType.availableAttributes
.pageInfo.endCursor
}
);
return (
<>
{Object.keys(AttributeTypeEnum).map(key => (
<AssignAttributeDialog <AssignAttributeDialog
attributes={maybe(() => attributes={maybe(() =>
result.data.productType.availableAttributes.edges.map( result.data.productType.availableAttributes.edges.map(
@ -397,13 +357,12 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
onClose={closeModal} onClose={closeModal}
onSubmit={handleAssignAttribute} onSubmit={handleAssignAttribute}
onFetch={search} onFetch={search}
onFetchMore={fetchMore} onFetchMore={loadMore}
onOpen={result.refetch} onOpen={result.refetch}
hasMore={maybe( hasMore={maybe(
() => () =>
result.data.productType result.data.productType.availableAttributes
.availableAttributes.pageInfo .pageInfo.hasNextPage,
.hasNextPage,
false false
)} )}
open={ open={
@ -418,8 +377,7 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
...params, ...params,
ids: ids.includes(attributeId) ids: ids.includes(attributeId)
? params.ids.filter( ? params.ids.filter(
selectedId => selectedId => selectedId !== attributeId
selectedId !== attributeId
) )
: [...ids, attributeId] : [...ids, attributeId]
}) })
@ -428,11 +386,6 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
key={key} key={key}
/> />
))} ))}
</>
);
}}
</SearchAttributes>
)}
<ProductTypeDeleteDialog <ProductTypeDeleteDialog
confirmButtonState={deleteTransactionState} confirmButtonState={deleteTransactionState}
name={maybe(() => data.productType.name, "...")} name={maybe(() => data.productType.name, "...")}

View file

@ -13,9 +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 { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes";
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";
@ -25,6 +22,9 @@ 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 { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes";
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";

View file

@ -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 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 { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
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";

View file

@ -2,13 +2,13 @@ import { RawDraftContentState } from "draft-js";
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { import {
ProductDetails_product, ProductDetails_product,
ProductDetails_product_collections, ProductDetails_product_collections,
ProductDetails_product_variants ProductDetails_product_variants
} from "@saleor/products/types/ProductDetails"; } from "@saleor/products/types/ProductDetails";
import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes";
import { ProductAttributeInput } from "../components/ProductAttributes"; import { ProductAttributeInput } from "../components/ProductAttributes";
import { VariantAttributeInput } from "../components/ProductVariantAttributes"; import { VariantAttributeInput } from "../components/ProductVariantAttributes";
import { ProductVariant } from "../types/ProductVariant"; import { ProductVariant } from "../types/ProductVariant";

View file

@ -2,13 +2,13 @@ import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import SearchProductTypes from "@saleor/containers/SearchProductTypes"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
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 { DEFAULT_INITIAL_SEARCH_DATA } from "../../config"; import useCategorySearch from "@saleor/searches/useCategorySearch";
import SearchCategories from "../../containers/SearchCategories"; import useCollectionSearch from "@saleor/searches/useCollectionSearch";
import SearchCollections from "../../containers/SearchCollections"; import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
import { decimal, getMutationState, maybe } from "../../misc"; import { decimal, getMutationState, maybe } from "../../misc";
import ProductCreatePage, { import ProductCreatePage, {
ProductCreatePageSubmitData ProductCreatePageSubmitData
@ -26,28 +26,30 @@ 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 {
const handleBack = () => navigate(productListUrl());
return (
<SearchCategories variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({
loadMore: loadMoreCategories, loadMore: loadMoreCategories,
search: searchCategory, search: searchCategory,
result: searchCategoryOpts result: searchCategoryOpts
}) => ( } = useCategorySearch({
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}> variables: DEFAULT_INITIAL_SEARCH_DATA
{({ });
const {
loadMore: loadMoreCollections, loadMore: loadMoreCollections,
search: searchCollection, search: searchCollection,
result: searchCollectionOpts result: searchCollectionOpts
}) => ( } = useCollectionSearch({
<SearchProductTypes variables={DEFAULT_INITIAL_SEARCH_DATA}> variables: DEFAULT_INITIAL_SEARCH_DATA
{({ });
const {
loadMore: loadMoreProductTypes, loadMore: loadMoreProductTypes,
search: searchProductTypes, search: searchProductTypes,
result: searchProductTypesOpts result: searchProductTypesOpts
}) => { } = useProductTypeSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const handleBack = () => navigate(productListUrl());
const handleSuccess = (data: ProductCreate) => { const handleSuccess = (data: ProductCreate) => {
if (data.productCreate.errors.length === 0) { if (data.productCreate.errors.length === 0) {
notify({ notify({
@ -76,9 +78,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = () => {
loading: productCreateDataLoading loading: productCreateDataLoading
} }
) => { ) => {
const handleSubmit = ( const handleSubmit = (formData: ProductCreatePageSubmitData) => {
formData: ProductCreatePageSubmitData
) => {
productCreate({ productCreate({
variables: { variables: {
attributes: formData.attributes.map(attribute => ({ attributes: formData.attributes.map(attribute => ({
@ -89,9 +89,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = () => {
category: formData.category, category: formData.category,
chargeTaxes: formData.chargeTaxes, chargeTaxes: formData.chargeTaxes,
collections: formData.collections, collections: formData.collections,
descriptionJson: JSON.stringify( descriptionJson: JSON.stringify(formData.description),
formData.description
),
isPublished: formData.isPublished, isPublished: formData.isPublished,
name: formData.name, name: formData.name,
productType: formData.productType, productType: formData.productType,
@ -105,9 +103,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = () => {
}, },
sku: formData.sku, sku: formData.sku,
stockQuantity: stockQuantity:
formData.stockQuantity !== null formData.stockQuantity !== null ? formData.stockQuantity : 0
? formData.stockQuantity
: 0
} }
}); });
}; };
@ -136,10 +132,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = () => {
[] []
).map(edge => edge.node)} ).map(edge => edge.node)}
disabled={productCreateDataLoading} disabled={productCreateDataLoading}
errors={maybe( errors={maybe(() => productCreateData.productCreate.errors, [])}
() => productCreateData.productCreate.errors,
[]
)}
fetchCategories={searchCategory} fetchCategories={searchCategory}
fetchCollections={searchCollection} fetchCollections={searchCollection}
fetchProductTypes={searchProductTypes} fetchProductTypes={searchProductTypes}
@ -148,36 +141,28 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = () => {
description: "page header" description: "page header"
})} })}
productTypes={maybe(() => productTypes={maybe(() =>
searchProductTypesOpts.data.search.edges.map( searchProductTypesOpts.data.search.edges.map(edge => edge.node)
edge => edge.node
)
)} )}
onBack={handleBack} onBack={handleBack}
onSubmit={handleSubmit} onSubmit={handleSubmit}
saveButtonBarState={formTransitionState} saveButtonBarState={formTransitionState}
fetchMoreCategories={{ fetchMoreCategories={{
hasMore: maybe( hasMore: maybe(
() => () => searchCategoryOpts.data.search.pageInfo.hasNextPage
searchCategoryOpts.data.search.pageInfo
.hasNextPage
), ),
loading: searchCategoryOpts.loading, loading: searchCategoryOpts.loading,
onFetchMore: loadMoreCategories onFetchMore: loadMoreCategories
}} }}
fetchMoreCollections={{ fetchMoreCollections={{
hasMore: maybe( hasMore: maybe(
() => () => searchCollectionOpts.data.search.pageInfo.hasNextPage
searchCollectionOpts.data.search.pageInfo
.hasNextPage
), ),
loading: searchCollectionOpts.loading, loading: searchCollectionOpts.loading,
onFetchMore: loadMoreCollections onFetchMore: loadMoreCollections
}} }}
fetchMoreProductTypes={{ fetchMoreProductTypes={{
hasMore: maybe( hasMore: maybe(
() => () => searchProductTypesOpts.data.search.pageInfo.hasNextPage
searchProductTypesOpts.data.search.pageInfo
.hasNextPage
), ),
loading: searchProductTypesOpts.loading, loading: searchProductTypesOpts.loading,
onFetchMore: loadMoreProductTypes onFetchMore: loadMoreProductTypes
@ -188,12 +173,5 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = () => {
}} }}
</TypedProductCreateMutation> </TypedProductCreateMutation>
); );
}}
</SearchProductTypes>
)}
</SearchCollections>
)}
</SearchCategories>
);
}; };
export default ProductUpdate; export default ProductUpdate;

View file

@ -7,6 +7,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import placeholderImg from "@assets/images/placeholder255x255.png"; import placeholderImg from "@assets/images/placeholder255x255.png";
import ActionDialog from "@saleor/components/ActionDialog"; import ActionDialog from "@saleor/components/ActionDialog";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import useBulkActions from "@saleor/hooks/useBulkActions"; import useBulkActions from "@saleor/hooks/useBulkActions";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
@ -14,9 +15,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 { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; import useCategorySearch from "@saleor/searches/useCategorySearch";
import SearchCategories from "../../../containers/SearchCategories"; import useCollectionSearch from "@saleor/searches/useCollectionSearch";
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";
import ProductUpdateOperations from "../../containers/ProductUpdateOperations"; import ProductUpdateOperations from "../../containers/ProductUpdateOperations";
@ -55,6 +55,20 @@ 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 {
loadMore: loadMoreCollections,
search: searchCollections,
result: searchCollectionsOpts
} = useCollectionSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const openModal = (action: ProductUrlDialog) => const openModal = (action: ProductUrlDialog) =>
navigate( navigate(
@ -64,18 +78,6 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
); );
return ( return (
<SearchCategories variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({
loadMore: loadMoreCategories,
search: searchCategories,
result: searchCategoriesOpts
}) => (
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({
loadMore: loadMoreCollections,
search: searchCollections,
result: searchCollectionsOpts
}) => (
<TypedProductDetailsQuery <TypedProductDetailsQuery
displayLoader displayLoader
require={["product"]} require={["product"]}
@ -108,8 +110,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
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) { if (imageError) {
notify({ notify({
@ -121,8 +122,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
notify({ notify({
text: intl.formatMessage(commonMessages.savedChanges) text: intl.formatMessage(commonMessages.savedChanges)
}); });
const handleVariantAdd = () => const handleVariantAdd = () => navigate(productVariantAddUrl(id));
navigate(productVariantAddUrl(id));
const handleBulkProductVariantCreate = ( const handleBulkProductVariantCreate = (
data: ProductVariantBulkCreate data: ProductVariantBulkCreate
@ -197,29 +197,19 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
updateProduct.opts.loading || updateProduct.opts.loading ||
loading; loading;
const formTransitionState = getMutationState( const formTransitionState = getMutationState(
updateProduct.opts.called || updateProduct.opts.called || updateSimpleProduct.opts.called,
updateSimpleProduct.opts.called, updateProduct.opts.loading || updateSimpleProduct.opts.loading,
updateProduct.opts.loading || maybe(() => updateProduct.opts.data.productUpdate.errors),
updateSimpleProduct.opts.loading, maybe(() => updateSimpleProduct.opts.data.productUpdate.errors),
maybe(
() => updateProduct.opts.data.productUpdate.errors
),
maybe( maybe(
() => () =>
updateSimpleProduct.opts.data.productUpdate.errors updateSimpleProduct.opts.data.productVariantUpdate.errors
),
maybe(
() =>
updateSimpleProduct.opts.data.productVariantUpdate
.errors
) )
); );
const deleteTransitionState = getMutationState( const deleteTransitionState = getMutationState(
deleteProduct.opts.called, deleteProduct.opts.called,
deleteProduct.opts.loading, deleteProduct.opts.loading,
maybe( maybe(() => deleteProduct.opts.data.productDelete.errors)
() => deleteProduct.opts.data.productDelete.errors
)
); );
const bulkProductVariantDeleteTransitionState = getMutationState( const bulkProductVariantDeleteTransitionState = getMutationState(
@ -227,8 +217,8 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
bulkProductVariantDelete.opts.loading, bulkProductVariantDelete.opts.loading,
maybe( maybe(
() => () =>
bulkProductVariantDelete.opts.data bulkProductVariantDelete.opts.data.productVariantBulkDelete
.productVariantBulkDelete.errors .errors
) )
); );
@ -275,9 +265,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
onVariantAdd={handleVariantAdd} onVariantAdd={handleVariantAdd}
onVariantsAdd={handleVariantCreatorOpen} onVariantsAdd={handleVariantCreatorOpen}
onVariantShow={variantId => () => onVariantShow={variantId => () =>
navigate( navigate(productVariantEditUrl(product.id, variantId))}
productVariantEditUrl(product.id, variantId)
)}
onImageUpload={handleImageUpload} onImageUpload={handleImageUpload}
onImageEdit={handleImageEdit} onImageEdit={handleImageEdit}
onImageDelete={handleImageDelete} onImageDelete={handleImageDelete}
@ -303,8 +291,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
fetchMoreCategories={{ fetchMoreCategories={{
hasMore: maybe( hasMore: maybe(
() => () =>
searchCategoriesOpts.data.search.pageInfo searchCategoriesOpts.data.search.pageInfo.hasNextPage
.hasNextPage
), ),
loading: searchCategoriesOpts.loading, loading: searchCategoriesOpts.loading,
onFetchMore: loadMoreCategories onFetchMore: loadMoreCategories
@ -312,8 +299,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
fetchMoreCollections={{ fetchMoreCollections={{
hasMore: maybe( hasMore: maybe(
() => () =>
searchCollectionsOpts.data.search.pageInfo searchCollectionsOpts.data.search.pageInfo.hasNextPage
.hasNextPage
), ),
loading: searchCollectionsOpts.loading, loading: searchCollectionsOpts.loading,
onFetchMore: loadMoreCollections onFetchMore: loadMoreCollections
@ -343,9 +329,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
<ActionDialog <ActionDialog
open={params.action === "remove-variants"} open={params.action === "remove-variants"}
onClose={() => navigate(productUrl(id), true)} onClose={() => navigate(productUrl(id), true)}
confirmButtonState={ confirmButtonState={bulkProductVariantDeleteTransitionState}
bulkProductVariantDeleteTransitionState
}
onConfirm={() => onConfirm={() =>
bulkProductVariantDelete.mutate({ bulkProductVariantDelete.mutate({
ids: params.ids ids: params.ids
@ -364,9 +348,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
values={{ values={{
counter: maybe(() => params.ids.length), counter: maybe(() => params.ids.length),
displayQuantity: ( displayQuantity: (
<strong> <strong>{maybe(() => params.ids.length)}</strong>
{maybe(() => params.ids.length)}
</strong>
) )
}} }}
/> />
@ -410,10 +392,6 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
); );
}} }}
</TypedProductDetailsQuery> </TypedProductDetailsQuery>
)}
</SearchCollections>
)}
</SearchCategories>
); );
}; };
export default ProductUpdate; export default ProductUpdate;

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../../types/globalTypes"; import { AttributeInputTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: SearchProductTypes // GraphQL query operation: SearchProductTypes
@ -22,7 +22,9 @@ export interface SearchProductTypes_search_edges_node_productAttributes {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
valueRequired: boolean; valueRequired: boolean;
values: (SearchProductTypes_search_edges_node_productAttributes_values | null)[] | null; values:
| (SearchProductTypes_search_edges_node_productAttributes_values | null)[]
| null;
} }
export interface SearchProductTypes_search_edges_node { export interface SearchProductTypes_search_edges_node {
@ -30,7 +32,9 @@ export interface SearchProductTypes_search_edges_node {
id: string; id: string;
name: string; name: string;
hasVariants: boolean; hasVariants: boolean;
productAttributes: (SearchProductTypes_search_edges_node_productAttributes | null)[] | null; productAttributes:
| (SearchProductTypes_search_edges_node_productAttributes | null)[]
| null;
} }
export interface SearchProductTypes_search_edges { export interface SearchProductTypes_search_edges {

View file

@ -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
); );

View file

@ -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 {
SearchCollections, SearchCollections,
SearchCollectionsVariables SearchCollectionsVariables
@ -24,6 +24,7 @@ export const searchCollections = gql`
} }
`; `;
export default TopLevelSearch<SearchCollections, SearchCollectionsVariables>( export default makeTopLevelSearch<
searchCollections SearchCollections,
); SearchCollectionsVariables
>(searchCollections);

View file

@ -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 {
SearchCustomers, SearchCustomers,
SearchCustomersVariables SearchCustomersVariables
@ -24,6 +24,6 @@ export const searchCustomers = gql`
} }
`; `;
export default TopLevelSearch<SearchCustomers, SearchCustomersVariables>( export default makeTopLevelSearch<SearchCustomers, SearchCustomersVariables>(
searchCustomers searchCustomers
); );

View file

@ -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 { SearchPages, SearchPagesVariables } from "./types/SearchPages"; import { SearchPages, SearchPagesVariables } from "./types/SearchPages";
export const searchPages = gql` export const searchPages = gql`
@ -21,4 +21,6 @@ export const searchPages = gql`
} }
`; `;
export default TopLevelSearch<SearchPages, SearchPagesVariables>(searchPages); export default makeTopLevelSearch<SearchPages, SearchPagesVariables>(
searchPages
);

View file

@ -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 {
SearchProducts, SearchProducts,
SearchProductsVariables SearchProductsVariables
@ -27,6 +27,6 @@ export const searchProducts = gql`
} }
`; `;
export default TopLevelSearch<SearchProducts, SearchProductsVariables>( export default makeTopLevelSearch<SearchProducts, SearchProductsVariables>(
searchProducts searchProducts
); );

View file

@ -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 {
SearchProductTypes, SearchProductTypes,
SearchProductTypesVariables SearchProductTypesVariables
@ -41,6 +41,7 @@ export const searchProductTypes = gql`
} }
`; `;
export default TopLevelSearch<SearchProductTypes, SearchProductTypesVariables>( export default makeTopLevelSearch<
searchProductTypes SearchProductTypes,
); SearchProductTypesVariables
>(searchProductTypes);

View file

@ -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 {
SearchServiceAccount, SearchServiceAccount,
SearchServiceAccountVariables SearchServiceAccountVariables
@ -28,7 +28,7 @@ export const searchServiceAccount = gql`
} }
`; `;
export default TopLevelSearch< export default makeTopLevelSearch<
SearchServiceAccount, SearchServiceAccount,
SearchServiceAccountVariables SearchServiceAccountVariables
>(searchServiceAccount); >(searchServiceAccount);

View file

@ -125505,6 +125505,7 @@ exports[`Storyshots Views / Webhooks / Create webhook default 1`] = `
class="MuiInputBase-input-id MuiOutlinedInput-input-id" class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="name" name="name"
type="text" type="text"
value=""
/> />
<fieldset <fieldset
aria-hidden="true" aria-hidden="true"
@ -126037,6 +126038,7 @@ exports[`Storyshots Views / Webhooks / Create webhook form errors 1`] = `
class="MuiInputBase-input-id MuiOutlinedInput-input-id" class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="name" name="name"
type="text" type="text"
value=""
/> />
<fieldset <fieldset
aria-hidden="true" aria-hidden="true"
@ -126575,6 +126577,7 @@ exports[`Storyshots Views / Webhooks / Create webhook loading 1`] = `
disabled="" disabled=""
name="name" name="name"
type="text" type="text"
value=""
/> />
<fieldset <fieldset
aria-hidden="true" aria-hidden="true"

View file

@ -6,9 +6,9 @@ import FormSpacer from "@saleor/components/FormSpacer";
import Grid from "@saleor/components/Grid"; import Grid from "@saleor/components/Grid";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { SearchServiceAccount_search_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { SearchServiceAccount_search_edges_node } from "@saleor/searches/types/SearchServiceAccount";
import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; import WebhookEvents from "@saleor/webhooks/components/WebhookEvents";
@ -19,7 +19,6 @@ import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
export interface FormData { export interface FormData {
id: string;
events: WebhookEventTypeEnum[]; events: WebhookEventTypeEnum[];
isActive: boolean; isActive: boolean;
name: string; name: string;
@ -52,9 +51,8 @@ const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
const initialForm: FormData = { const initialForm: FormData = {
allEvents: false, allEvents: false,
events: [], events: [],
id: null,
isActive: false, isActive: false,
name: null, name: "",
secretKey: "", secretKey: "",
serviceAccount: "", serviceAccount: "",
targetUrl: "" targetUrl: ""

View file

@ -1,3 +1,6 @@
import React from "react";
import { useIntl } from "react-intl";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
import Container from "@saleor/components/Container"; import Container from "@saleor/components/Container";
@ -6,10 +9,10 @@ import FormSpacer from "@saleor/components/FormSpacer";
import Grid from "@saleor/components/Grid"; import Grid from "@saleor/components/Grid";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { SearchServiceAccount_search_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount";
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 { SearchServiceAccount_search_edges_node } from "@saleor/searches/types/SearchServiceAccount";
import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; import WebhookEvents from "@saleor/webhooks/components/WebhookEvents";
@ -18,11 +21,7 @@ import WebhookStatus from "@saleor/webhooks/components/WebhookStatus";
import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate"; import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate";
import { WebhookDetails_webhook } from "@saleor/webhooks/types/WebhookDetails"; import { WebhookDetails_webhook } from "@saleor/webhooks/types/WebhookDetails";
import React from "react";
import { useIntl } from "react-intl";
export interface FormData { export interface FormData {
id: string;
events: WebhookEventTypeEnum[]; events: WebhookEventTypeEnum[];
isActive: boolean; isActive: boolean;
name: string; name: string;
@ -63,7 +62,6 @@ const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
events: maybe(() => webhook.events, []) events: maybe(() => webhook.events, [])
.map(event => event.eventType) .map(event => event.eventType)
.filter(event => event !== WebhookEventTypeEnum.ANY_EVENTS), .filter(event => event !== WebhookEventTypeEnum.ANY_EVENTS),
id: maybe(() => webhook.id, null),
isActive: maybe(() => webhook.isActive, false), isActive: maybe(() => webhook.isActive, false),
name: maybe(() => webhook.name, ""), name: maybe(() => webhook.name, ""),
secretKey: maybe(() => webhook.secretKey, ""), secretKey: maybe(() => webhook.secretKey, ""),

View file

@ -1,13 +1,13 @@
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import SearchServiceAccount from "@saleor/containers/SearchServiceAccount"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
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 { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import useServiceAccountSearch from "@saleor/searches/useServiceAccountSearch";
import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes";
import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config";
import { getMutationState, maybe } from "../../misc"; import { getMutationState, maybe } from "../../misc";
import WebhookCreatePage, { FormData } from "../components/WebhookCreatePage"; import WebhookCreatePage, { FormData } from "../components/WebhookCreatePage";
import { TypedWebhookCreate } from "../mutations"; import { TypedWebhookCreate } from "../mutations";
@ -26,6 +26,12 @@ export const WebhooksCreate: React.FC<WebhooksCreateProps> = () => {
const navigate = useNavigator(); const navigate = useNavigator();
const notify = useNotifier(); const notify = useNotifier();
const intl = useIntl(); const intl = useIntl();
const {
search: searchServiceAccount,
result: searchServiceAccountOpt
} = useServiceAccountSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const onSubmit = (data: WebhookCreateData) => { const onSubmit = (data: WebhookCreateData) => {
if (data.webhookCreate.webhookErrors.length === 0) { if (data.webhookCreate.webhookErrors.length === 0) {
@ -39,8 +45,6 @@ export const WebhooksCreate: React.FC<WebhooksCreateProps> = () => {
const handleBack = () => navigate(webhooksListUrl()); const handleBack = () => navigate(webhooksListUrl());
return ( return (
<SearchServiceAccount variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({ search: searchServiceAccount, result: searchServiceAccountOpt }) => (
<TypedWebhookCreate onCompleted={onSubmit}> <TypedWebhookCreate onCompleted={onSubmit}>
{(webhookCreate, webhookCreateOpts) => { {(webhookCreate, webhookCreateOpts) => {
const handleSubmit = (data: FormData) => const handleSubmit = (data: FormData) =>
@ -81,9 +85,7 @@ export const WebhooksCreate: React.FC<WebhooksCreateProps> = () => {
)} )}
fetchServiceAccounts={searchServiceAccount} fetchServiceAccounts={searchServiceAccount}
services={maybe(() => services={maybe(() =>
searchServiceAccountOpt.data.search.edges.map( searchServiceAccountOpt.data.search.edges.map(edge => edge.node)
edge => edge.node
)
)} )}
onBack={handleBack} onBack={handleBack}
onSubmit={handleSubmit} onSubmit={handleSubmit}
@ -93,8 +95,6 @@ export const WebhooksCreate: React.FC<WebhooksCreateProps> = () => {
); );
}} }}
</TypedWebhookCreate> </TypedWebhookCreate>
)}
</SearchServiceAccount>
); );
}; };
WebhooksCreate.displayName = "WebhooksCreate"; WebhooksCreate.displayName = "WebhooksCreate";

View file

@ -1,15 +1,16 @@
import React from "react";
import { useIntl } from "react-intl";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import SearchServiceAccount from "@saleor/containers/SearchServiceAccount"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
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 { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import useServiceAccountSearch from "@saleor/searches/useServiceAccountSearch";
import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes";
import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog"; import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog";
import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete";
import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate"; import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate";
import React from "react";
import { useIntl } from "react-intl";
import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config";
import { getMutationState, maybe } from "../../misc"; import { getMutationState, maybe } from "../../misc";
import WebhooksDetailsPage from "../components/WebhooksDetailsPage"; import WebhooksDetailsPage from "../components/WebhooksDetailsPage";
import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations"; import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations";
@ -33,6 +34,12 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
const navigate = useNavigator(); const navigate = useNavigator();
const notify = useNotifier(); const notify = useNotifier();
const intl = useIntl(); const intl = useIntl();
const {
search: searchServiceAccount,
result: searchServiceAccountOpt
} = useServiceAccountSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const closeModal = () => const closeModal = () =>
navigate( navigate(
@ -72,8 +79,6 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
}; };
return ( return (
<SearchServiceAccount variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({ search: searchServiceAccount, result: searchServiceAccountOpt }) => (
<TypedWebhookUpdate onCompleted={onWebhookUpdate}> <TypedWebhookUpdate onCompleted={onWebhookUpdate}>
{(webhookUpdate, webhookUpdateOpts) => ( {(webhookUpdate, webhookUpdateOpts) => (
<TypedWebhookDelete onCompleted={onWebhookDelete}> <TypedWebhookDelete onCompleted={onWebhookDelete}>
@ -160,8 +165,6 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
</TypedWebhookDelete> </TypedWebhookDelete>
)} )}
</TypedWebhookUpdate> </TypedWebhookUpdate>
)}
</SearchServiceAccount>
); );
}; };
WebhooksDetails.displayName = "WebhooksDetails"; WebhooksDetails.displayName = "WebhooksDetails";