Use exclusively search hooks
This commit is contained in:
parent
13a8d398d2
commit
135658eb11
9 changed files with 127 additions and 292 deletions
|
@ -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: ""
|
||||||
|
|
|
@ -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;
|
|
|
@ -1,47 +0,0 @@
|
||||||
import { DocumentNode } from "graphql";
|
|
||||||
|
|
||||||
import { PageInfoFragment } from "@saleor/types/PageInfoFragment";
|
|
||||||
import BaseSearch, { SearchQueryVariables } from "./BaseSearch";
|
|
||||||
|
|
||||||
export interface SearchQuery {
|
|
||||||
search: {
|
|
||||||
edges: Array<{
|
|
||||||
node: any;
|
|
||||||
}>;
|
|
||||||
pageInfo: PageInfoFragment;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function TopLevelSearch<
|
|
||||||
TQuery extends SearchQuery,
|
|
||||||
TQueryVariables extends SearchQueryVariables
|
|
||||||
>(query: DocumentNode) {
|
|
||||||
return BaseSearch<TQuery, TQueryVariables>(query, result => {
|
|
||||||
if (result.data.search.pageInfo.hasNextPage) {
|
|
||||||
result.loadMore(
|
|
||||||
(prev, next) => {
|
|
||||||
if (
|
|
||||||
prev.search.pageInfo.endCursor === next.search.pageInfo.endCursor
|
|
||||||
) {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
search: {
|
|
||||||
...prev.search,
|
|
||||||
edges: [...prev.search.edges, ...next.search.edges],
|
|
||||||
pageInfo: next.search.pageInfo
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...result.variables,
|
|
||||||
after: result.data.search.pageInfo.endCursor
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TopLevelSearch;
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -81,6 +81,13 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
} = useCustomerSearch({
|
} = useCustomerSearch({
|
||||||
variables: DEFAULT_INITIAL_SEARCH_DATA
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
});
|
});
|
||||||
|
const {
|
||||||
|
loadMore,
|
||||||
|
search: variantSearch,
|
||||||
|
result: variantSearchOpts
|
||||||
|
} = useOrderVariantSearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedOrderDetailsQuery
|
<TypedOrderDetailsQuery
|
||||||
|
@ -502,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}
|
||||||
|
@ -545,8 +544,6 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</SearchOrderVariant>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<OrderAddressEditDialog
|
<OrderAddressEditDialog
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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, "...")}
|
||||||
|
|
Loading…
Reference in a new issue