Create makeQuery hook
This commit is contained in:
parent
b12f3c35fa
commit
8a6cd1ef1f
4 changed files with 470 additions and 375 deletions
|
@ -1,6 +1,7 @@
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
import { pageInfoFragment, TypedQuery } from "../queries";
|
import makeQuery from "@saleor/hooks/makeQuery";
|
||||||
|
import { pageInfoFragment } from "../queries";
|
||||||
import {
|
import {
|
||||||
CategoryDetails,
|
CategoryDetails,
|
||||||
CategoryDetailsVariables
|
CategoryDetailsVariables
|
||||||
|
@ -65,7 +66,7 @@ export const rootCategories = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const TypedRootCategoriesQuery = TypedQuery<RootCategories, {}>(
|
export const useRootCategoriesQuery = makeQuery<RootCategories, {}>(
|
||||||
rootCategories
|
rootCategories
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -119,7 +120,7 @@ export const categoryDetails = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const TypedCategoryDetailsQuery = TypedQuery<
|
export const useCategoryDetailsQuery = makeQuery<
|
||||||
CategoryDetails,
|
CategoryDetails,
|
||||||
CategoryDetailsVariables
|
CategoryDetailsVariables
|
||||||
>(categoryDetails);
|
>(categoryDetails);
|
||||||
|
|
|
@ -28,7 +28,7 @@ import {
|
||||||
useCategoryDeleteMutation,
|
useCategoryDeleteMutation,
|
||||||
useCategoryUpdateMutation
|
useCategoryUpdateMutation
|
||||||
} from "../mutations";
|
} from "../mutations";
|
||||||
import { TypedCategoryDetailsQuery } from "../queries";
|
import { useCategoryDetailsQuery } from "../queries";
|
||||||
import { CategoryBulkDelete } from "../types/CategoryBulkDelete";
|
import { CategoryBulkDelete } from "../types/CategoryBulkDelete";
|
||||||
import { CategoryDelete } from "../types/CategoryDelete";
|
import { CategoryDelete } from "../types/CategoryDelete";
|
||||||
import { CategoryUpdate } from "../types/CategoryUpdate";
|
import { CategoryUpdate } from "../types/CategoryUpdate";
|
||||||
|
@ -63,6 +63,13 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
|
||||||
);
|
);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
|
const { data, loading, refetch } = useCategoryDetailsQuery({
|
||||||
|
displayLoader: true,
|
||||||
|
require: ["category"],
|
||||||
|
variables: { ...paginationState, id }
|
||||||
|
});
|
||||||
|
|
||||||
const handleCategoryDelete = (data: CategoryDelete) => {
|
const handleCategoryDelete = (data: CategoryDelete) => {
|
||||||
if (data.categoryDelete.errors.length === 0) {
|
if (data.categoryDelete.errors.length === 0) {
|
||||||
notify({
|
notify({
|
||||||
|
@ -140,7 +147,6 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const paginationState = createPaginationState(PAGINATE_BY, params);
|
|
||||||
const formTransitionState = getMutationState(
|
const formTransitionState = getMutationState(
|
||||||
updateResult.called,
|
updateResult.called,
|
||||||
updateResult.loading,
|
updateResult.loading,
|
||||||
|
@ -152,245 +158,221 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
|
||||||
maybe(() => deleteResult.data.categoryDelete.errors)
|
maybe(() => deleteResult.data.categoryDelete.errors)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleBulkProductDelete = (data: productBulkDelete) => {
|
||||||
|
if (data.productBulkDelete.errors.length === 0) {
|
||||||
|
closeModal();
|
||||||
|
notify({
|
||||||
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
|
});
|
||||||
|
refetch();
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||||
|
params.activeTab === CategoryPageTab.categories
|
||||||
|
? maybe(() => data.category.children.pageInfo)
|
||||||
|
: maybe(() => data.category.products.pageInfo),
|
||||||
|
paginationState,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedCategoryDetailsQuery
|
<>
|
||||||
displayLoader
|
<WindowTitle title={maybe(() => data.category.name)} />
|
||||||
variables={{ ...paginationState, id }}
|
<TypedProductBulkDeleteMutation onCompleted={handleBulkProductDelete}>
|
||||||
require={["category"]}
|
{(productBulkDelete, productBulkDeleteOpts) => {
|
||||||
>
|
const categoryBulkDeleteMutationState = getMutationState(
|
||||||
{({ data, loading, refetch }) => {
|
categoryBulkDeleteOpts.called,
|
||||||
const handleBulkProductDelete = (data: productBulkDelete) => {
|
categoryBulkDeleteOpts.loading,
|
||||||
if (data.productBulkDelete.errors.length === 0) {
|
maybe(() => categoryBulkDeleteOpts.data.categoryBulkDelete.errors)
|
||||||
closeModal();
|
);
|
||||||
notify({
|
const productBulkDeleteMutationState = getMutationState(
|
||||||
text: intl.formatMessage(commonMessages.savedChanges)
|
productBulkDeleteOpts.called,
|
||||||
});
|
productBulkDeleteOpts.loading,
|
||||||
refetch();
|
maybe(() => productBulkDeleteOpts.data.productBulkDelete.errors)
|
||||||
reset();
|
);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
return (
|
||||||
params.activeTab === CategoryPageTab.categories
|
<>
|
||||||
? maybe(() => data.category.children.pageInfo)
|
<CategoryUpdatePage
|
||||||
: maybe(() => data.category.products.pageInfo),
|
changeTab={changeTab}
|
||||||
paginationState,
|
currentTab={params.activeTab}
|
||||||
params
|
category={maybe(() => data.category)}
|
||||||
);
|
disabled={loading}
|
||||||
|
errors={maybe(() => updateResult.data.categoryUpdate.errors)}
|
||||||
return (
|
onAddCategory={() => navigate(categoryAddUrl(id))}
|
||||||
<>
|
onAddProduct={() => navigate(productAddUrl)}
|
||||||
<WindowTitle title={maybe(() => data.category.name)} />
|
onBack={() =>
|
||||||
<TypedProductBulkDeleteMutation
|
navigate(
|
||||||
onCompleted={handleBulkProductDelete}
|
maybe(
|
||||||
>
|
() => categoryUrl(data.category.parent.id),
|
||||||
{(productBulkDelete, productBulkDeleteOpts) => {
|
categoryListUrl()
|
||||||
const categoryBulkDeleteMutationState = getMutationState(
|
)
|
||||||
categoryBulkDeleteOpts.called,
|
|
||||||
categoryBulkDeleteOpts.loading,
|
|
||||||
maybe(
|
|
||||||
() => categoryBulkDeleteOpts.data.categoryBulkDelete.errors
|
|
||||||
)
|
)
|
||||||
);
|
}
|
||||||
const productBulkDeleteMutationState = getMutationState(
|
onCategoryClick={id => () => navigate(categoryUrl(id))}
|
||||||
productBulkDeleteOpts.called,
|
onDelete={() => openModal("delete")}
|
||||||
productBulkDeleteOpts.loading,
|
onImageDelete={() =>
|
||||||
maybe(
|
updateCategory({
|
||||||
() => productBulkDeleteOpts.data.productBulkDelete.errors
|
variables: {
|
||||||
)
|
id,
|
||||||
);
|
input: {
|
||||||
|
backgroundImage: null
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<CategoryUpdatePage
|
|
||||||
changeTab={changeTab}
|
|
||||||
currentTab={params.activeTab}
|
|
||||||
category={maybe(() => data.category)}
|
|
||||||
disabled={loading}
|
|
||||||
errors={maybe(
|
|
||||||
() => updateResult.data.categoryUpdate.errors
|
|
||||||
)}
|
|
||||||
onAddCategory={() => navigate(categoryAddUrl(id))}
|
|
||||||
onAddProduct={() => navigate(productAddUrl)}
|
|
||||||
onBack={() =>
|
|
||||||
navigate(
|
|
||||||
maybe(
|
|
||||||
() => categoryUrl(data.category.parent.id),
|
|
||||||
categoryListUrl()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
onCategoryClick={id => () => navigate(categoryUrl(id))}
|
}
|
||||||
onDelete={() => openModal("delete")}
|
})
|
||||||
onImageDelete={() =>
|
}
|
||||||
updateCategory({
|
onImageUpload={file =>
|
||||||
variables: {
|
updateCategory({
|
||||||
id,
|
variables: {
|
||||||
input: {
|
id,
|
||||||
backgroundImage: null
|
input: {
|
||||||
}
|
backgroundImage: file
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
onImageUpload={file =>
|
}
|
||||||
updateCategory({
|
})
|
||||||
variables: {
|
}
|
||||||
id,
|
onNextPage={loadNextPage}
|
||||||
input: {
|
onPreviousPage={loadPreviousPage}
|
||||||
backgroundImage: file
|
pageInfo={pageInfo}
|
||||||
}
|
onProductClick={id => () => navigate(productUrl(id))}
|
||||||
}
|
onSubmit={formData =>
|
||||||
})
|
updateCategory({
|
||||||
|
variables: {
|
||||||
|
id,
|
||||||
|
input: {
|
||||||
|
backgroundImageAlt: formData.backgroundImageAlt,
|
||||||
|
descriptionJson: JSON.stringify(formData.description),
|
||||||
|
name: formData.name,
|
||||||
|
seo: {
|
||||||
|
description: formData.seoDescription,
|
||||||
|
title: formData.seoTitle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onNextPage={loadNextPage}
|
}
|
||||||
onPreviousPage={loadPreviousPage}
|
})
|
||||||
pageInfo={pageInfo}
|
}
|
||||||
onProductClick={id => () => navigate(productUrl(id))}
|
products={maybe(() =>
|
||||||
onSubmit={formData =>
|
data.category.products.edges.map(edge => edge.node)
|
||||||
updateCategory({
|
)}
|
||||||
variables: {
|
saveButtonBarState={formTransitionState}
|
||||||
id,
|
subcategories={maybe(() =>
|
||||||
input: {
|
data.category.children.edges.map(edge => edge.node)
|
||||||
backgroundImageAlt: formData.backgroundImageAlt,
|
)}
|
||||||
descriptionJson: JSON.stringify(
|
subcategoryListToolbar={
|
||||||
formData.description
|
<IconButton
|
||||||
),
|
color="primary"
|
||||||
name: formData.name,
|
onClick={() => openModal("delete-categories", listElements)}
|
||||||
seo: {
|
>
|
||||||
description: formData.seoDescription,
|
<DeleteIcon />
|
||||||
title: formData.seoTitle
|
</IconButton>
|
||||||
}
|
}
|
||||||
}
|
productListToolbar={
|
||||||
}
|
<IconButton
|
||||||
})
|
color="primary"
|
||||||
}
|
onClick={() => openModal("delete-products", listElements)}
|
||||||
products={maybe(() =>
|
>
|
||||||
data.category.products.edges.map(edge => edge.node)
|
<DeleteIcon />
|
||||||
)}
|
</IconButton>
|
||||||
saveButtonBarState={formTransitionState}
|
}
|
||||||
subcategories={maybe(() =>
|
isChecked={isSelected}
|
||||||
data.category.children.edges.map(edge => edge.node)
|
selected={listElements.length}
|
||||||
)}
|
toggle={toggle}
|
||||||
subcategoryListToolbar={
|
toggleAll={toggleAll}
|
||||||
<IconButton
|
/>
|
||||||
color="primary"
|
<ActionDialog
|
||||||
onClick={() =>
|
confirmButtonState={removeDialogTransitionState}
|
||||||
openModal("delete-categories", listElements)
|
onClose={closeModal}
|
||||||
}
|
onConfirm={() => deleteCategory({ variables: { id } })}
|
||||||
>
|
open={params.action === "delete"}
|
||||||
<DeleteIcon />
|
title={intl.formatMessage({
|
||||||
</IconButton>
|
defaultMessage: "Delete category",
|
||||||
}
|
description: "dialog title"
|
||||||
productListToolbar={
|
})}
|
||||||
<IconButton
|
variant="delete"
|
||||||
color="primary"
|
>
|
||||||
onClick={() =>
|
<DialogContentText>
|
||||||
openModal("delete-products", listElements)
|
<FormattedMessage
|
||||||
}
|
defaultMessage="Are you sure you want to delete {categoryName}?"
|
||||||
>
|
values={{
|
||||||
<DeleteIcon />
|
categoryName: (
|
||||||
</IconButton>
|
<strong>
|
||||||
}
|
{maybe(() => data.category.name, "...")}
|
||||||
isChecked={isSelected}
|
</strong>
|
||||||
selected={listElements.length}
|
)
|
||||||
toggle={toggle}
|
}}
|
||||||
toggleAll={toggleAll}
|
/>
|
||||||
/>
|
</DialogContentText>
|
||||||
<ActionDialog
|
<DialogContentText>
|
||||||
confirmButtonState={removeDialogTransitionState}
|
<FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." />
|
||||||
onClose={closeModal}
|
</DialogContentText>
|
||||||
onConfirm={() => deleteCategory({ variables: { id } })}
|
</ActionDialog>
|
||||||
open={params.action === "delete"}
|
<ActionDialog
|
||||||
title={intl.formatMessage({
|
open={
|
||||||
defaultMessage: "Delete category",
|
params.action === "delete-categories" &&
|
||||||
description: "dialog title"
|
maybe(() => params.ids.length > 0)
|
||||||
})}
|
}
|
||||||
variant="delete"
|
confirmButtonState={categoryBulkDeleteMutationState}
|
||||||
>
|
onClose={closeModal}
|
||||||
<DialogContentText>
|
onConfirm={() =>
|
||||||
<FormattedMessage
|
categoryBulkDelete({
|
||||||
defaultMessage="Are you sure you want to delete {categoryName}?"
|
variables: { ids: params.ids }
|
||||||
values={{
|
}).then(() => refetch())
|
||||||
categoryName: (
|
}
|
||||||
<strong>
|
title={intl.formatMessage({
|
||||||
{maybe(() => data.category.name, "...")}
|
defaultMessage: "Delete categories",
|
||||||
</strong>
|
description: "dialog title"
|
||||||
)
|
})}
|
||||||
}}
|
variant="delete"
|
||||||
/>
|
>
|
||||||
</DialogContentText>
|
<DialogContentText>
|
||||||
<DialogContentText>
|
<FormattedMessage
|
||||||
<FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." />
|
defaultMessage="Are you sure you want to delete {counter,plural,one{this category} other{{displayQuantity} categories}}?"
|
||||||
</DialogContentText>
|
values={{
|
||||||
</ActionDialog>
|
counter: maybe(() => params.ids.length),
|
||||||
<ActionDialog
|
displayQuantity: (
|
||||||
open={
|
<strong>{maybe(() => params.ids.length)}</strong>
|
||||||
params.action === "delete-categories" &&
|
)
|
||||||
maybe(() => params.ids.length > 0)
|
}}
|
||||||
}
|
/>
|
||||||
confirmButtonState={categoryBulkDeleteMutationState}
|
</DialogContentText>
|
||||||
onClose={closeModal}
|
<DialogContentText>
|
||||||
onConfirm={() =>
|
<FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." />
|
||||||
categoryBulkDelete({
|
</DialogContentText>
|
||||||
variables: { ids: params.ids }
|
</ActionDialog>
|
||||||
}).then(() => refetch())
|
<ActionDialog
|
||||||
}
|
open={params.action === "delete-products"}
|
||||||
title={intl.formatMessage({
|
confirmButtonState={productBulkDeleteMutationState}
|
||||||
defaultMessage: "Delete categories",
|
onClose={closeModal}
|
||||||
description: "dialog title"
|
onConfirm={() =>
|
||||||
})}
|
productBulkDelete({
|
||||||
variant="delete"
|
variables: { ids: params.ids }
|
||||||
>
|
}).then(() => refetch())
|
||||||
<DialogContentText>
|
}
|
||||||
<FormattedMessage
|
title={intl.formatMessage({
|
||||||
defaultMessage="Are you sure you want to delete {counter,plural,one{this category} other{{displayQuantity} categories}}?"
|
defaultMessage: "Delete products",
|
||||||
values={{
|
description: "dialog title"
|
||||||
counter: maybe(() => params.ids.length),
|
})}
|
||||||
displayQuantity: (
|
variant="delete"
|
||||||
<strong>{maybe(() => params.ids.length)}</strong>
|
>
|
||||||
)
|
<DialogContentText>
|
||||||
}}
|
<FormattedMessage
|
||||||
/>
|
defaultMessage="Are you sure you want to delete {counter,plural,one{this product} other{{displayQuantity} products}}?"
|
||||||
</DialogContentText>
|
values={{
|
||||||
<DialogContentText>
|
counter: maybe(() => params.ids.length),
|
||||||
<FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." />
|
displayQuantity: (
|
||||||
</DialogContentText>
|
<strong>{maybe(() => params.ids.length)}</strong>
|
||||||
</ActionDialog>
|
)
|
||||||
<ActionDialog
|
}}
|
||||||
open={params.action === "delete-products"}
|
/>
|
||||||
confirmButtonState={productBulkDeleteMutationState}
|
</DialogContentText>
|
||||||
onClose={closeModal}
|
</ActionDialog>
|
||||||
onConfirm={() =>
|
</>
|
||||||
productBulkDelete({
|
);
|
||||||
variables: { ids: params.ids }
|
}}
|
||||||
}).then(() => refetch())
|
</TypedProductBulkDeleteMutation>
|
||||||
}
|
</>
|
||||||
title={intl.formatMessage({
|
|
||||||
defaultMessage: "Delete products",
|
|
||||||
description: "dialog title"
|
|
||||||
})}
|
|
||||||
variant="delete"
|
|
||||||
>
|
|
||||||
<DialogContentText>
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Are you sure you want to delete {counter,plural,one{this product} other{{displayQuantity} products}}?"
|
|
||||||
values={{
|
|
||||||
counter: maybe(() => params.ids.length),
|
|
||||||
displayQuantity: (
|
|
||||||
<strong>{maybe(() => params.ids.length)}</strong>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContentText>
|
|
||||||
</ActionDialog>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</TypedProductBulkDeleteMutation>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</TypedCategoryDetailsQuery>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default CategoryDetails;
|
export default CategoryDetails;
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { getMutationState, maybe } from "@saleor/misc";
|
||||||
import { ListViews } from "@saleor/types";
|
import { ListViews } from "@saleor/types";
|
||||||
import { CategoryListPage } from "../../components/CategoryListPage/CategoryListPage";
|
import { CategoryListPage } from "../../components/CategoryListPage/CategoryListPage";
|
||||||
import { useCategoryBulkDeleteMutation } from "../../mutations";
|
import { useCategoryBulkDeleteMutation } from "../../mutations";
|
||||||
import { TypedRootCategoriesQuery } from "../../queries";
|
import { useRootCategoriesQuery } from "../../queries";
|
||||||
import { CategoryBulkDelete } from "../../types/CategoryBulkDelete";
|
import { CategoryBulkDelete } from "../../types/CategoryBulkDelete";
|
||||||
import {
|
import {
|
||||||
categoryAddUrl,
|
categoryAddUrl,
|
||||||
|
@ -53,6 +53,20 @@ export const CategoryList: React.FC<CategoryListProps> = ({ params }) => {
|
||||||
);
|
);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const paginationState = createPaginationState(settings.rowNumber, params);
|
||||||
|
const queryVariables = React.useMemo(
|
||||||
|
() => ({
|
||||||
|
...paginationState,
|
||||||
|
filter: getFilterVariables(params)
|
||||||
|
}),
|
||||||
|
[params]
|
||||||
|
);
|
||||||
|
const { data, loading, refetch } = useRootCategoriesQuery({
|
||||||
|
displayLoader: true,
|
||||||
|
require: ["categories"],
|
||||||
|
variables: queryVariables
|
||||||
|
});
|
||||||
|
|
||||||
const tabs = getFilterTabs();
|
const tabs = getFilterTabs();
|
||||||
|
|
||||||
const currentTab =
|
const currentTab =
|
||||||
|
@ -113,146 +127,129 @@ export const CategoryList: React.FC<CategoryListProps> = ({ params }) => {
|
||||||
handleTabChange(tabs.length + 1);
|
handleTabChange(tabs.length + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const paginationState = createPaginationState(settings.rowNumber, params);
|
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||||
const queryVariables = React.useMemo(
|
maybe(() => data.categories.pageInfo),
|
||||||
() => ({
|
paginationState,
|
||||||
...paginationState,
|
params
|
||||||
filter: getFilterVariables(params)
|
);
|
||||||
}),
|
|
||||||
[params]
|
const handleCategoryBulkDelete = (data: CategoryBulkDelete) => {
|
||||||
|
if (data.categoryBulkDelete.errors.length === 0) {
|
||||||
|
navigate(categoryListUrl(), true);
|
||||||
|
refetch();
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [
|
||||||
|
categoryBulkDelete,
|
||||||
|
categoryBulkDeleteOpts
|
||||||
|
] = useCategoryBulkDeleteMutation({
|
||||||
|
onCompleted: handleCategoryBulkDelete
|
||||||
|
});
|
||||||
|
|
||||||
|
const bulkDeleteState = getMutationState(
|
||||||
|
categoryBulkDeleteOpts.called,
|
||||||
|
categoryBulkDeleteOpts.loading,
|
||||||
|
maybe(() => categoryBulkDeleteOpts.data.categoryBulkDelete.errors)
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedRootCategoriesQuery displayLoader variables={queryVariables}>
|
<>
|
||||||
{({ data, loading, refetch }) => {
|
<CategoryListPage
|
||||||
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
categories={maybe(
|
||||||
maybe(() => data.categories.pageInfo),
|
() => data.categories.edges.map(edge => edge.node),
|
||||||
paginationState,
|
[]
|
||||||
params
|
)}
|
||||||
);
|
currentTab={currentTab}
|
||||||
|
initialSearch={params.query || ""}
|
||||||
const handleCategoryBulkDelete = (data: CategoryBulkDelete) => {
|
onSearchChange={query => changeFilterField({ query })}
|
||||||
if (data.categoryBulkDelete.errors.length === 0) {
|
onAll={() => navigate(categoryListUrl())}
|
||||||
navigate(categoryListUrl(), true);
|
onTabChange={handleTabChange}
|
||||||
refetch();
|
onTabDelete={() => openModal("delete-search")}
|
||||||
reset();
|
onTabSave={() => openModal("save-search")}
|
||||||
}
|
tabs={tabs.map(tab => tab.name)}
|
||||||
};
|
settings={settings}
|
||||||
|
onAdd={() => navigate(categoryAddUrl())}
|
||||||
const [
|
onRowClick={id => () => navigate(categoryUrl(id))}
|
||||||
categoryBulkDelete,
|
disabled={loading}
|
||||||
categoryBulkDeleteOpts
|
onNextPage={loadNextPage}
|
||||||
] = useCategoryBulkDeleteMutation({
|
onPreviousPage={loadPreviousPage}
|
||||||
onCompleted: handleCategoryBulkDelete
|
onUpdateListSettings={updateListSettings}
|
||||||
});
|
pageInfo={pageInfo}
|
||||||
|
isChecked={isSelected}
|
||||||
const bulkDeleteState = getMutationState(
|
selected={listElements.length}
|
||||||
categoryBulkDeleteOpts.called,
|
toggle={toggle}
|
||||||
categoryBulkDeleteOpts.loading,
|
toggleAll={toggleAll}
|
||||||
maybe(() => categoryBulkDeleteOpts.data.categoryBulkDelete.errors)
|
toolbar={
|
||||||
);
|
<IconButton
|
||||||
|
color="primary"
|
||||||
return (
|
onClick={() =>
|
||||||
<>
|
navigate(
|
||||||
<CategoryListPage
|
categoryListUrl({
|
||||||
categories={maybe(
|
...params,
|
||||||
() => data.categories.edges.map(edge => edge.node),
|
action: "delete",
|
||||||
[]
|
ids: listElements
|
||||||
)}
|
|
||||||
currentTab={currentTab}
|
|
||||||
initialSearch={params.query || ""}
|
|
||||||
onSearchChange={query => changeFilterField({ query })}
|
|
||||||
onAll={() => navigate(categoryListUrl())}
|
|
||||||
onTabChange={handleTabChange}
|
|
||||||
onTabDelete={() => openModal("delete-search")}
|
|
||||||
onTabSave={() => openModal("save-search")}
|
|
||||||
tabs={tabs.map(tab => tab.name)}
|
|
||||||
settings={settings}
|
|
||||||
onAdd={() => navigate(categoryAddUrl())}
|
|
||||||
onRowClick={id => () => navigate(categoryUrl(id))}
|
|
||||||
disabled={loading}
|
|
||||||
onNextPage={loadNextPage}
|
|
||||||
onPreviousPage={loadPreviousPage}
|
|
||||||
onUpdateListSettings={updateListSettings}
|
|
||||||
pageInfo={pageInfo}
|
|
||||||
isChecked={isSelected}
|
|
||||||
selected={listElements.length}
|
|
||||||
toggle={toggle}
|
|
||||||
toggleAll={toggleAll}
|
|
||||||
toolbar={
|
|
||||||
<IconButton
|
|
||||||
color="primary"
|
|
||||||
onClick={() =>
|
|
||||||
navigate(
|
|
||||||
categoryListUrl({
|
|
||||||
...params,
|
|
||||||
action: "delete",
|
|
||||||
ids: listElements
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<DeleteIcon />
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<ActionDialog
|
|
||||||
confirmButtonState={bulkDeleteState}
|
|
||||||
onClose={() =>
|
|
||||||
navigate(
|
|
||||||
categoryListUrl({
|
|
||||||
...params,
|
|
||||||
action: undefined,
|
|
||||||
ids: undefined
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onConfirm={() =>
|
|
||||||
categoryBulkDelete({
|
|
||||||
variables: {
|
|
||||||
ids: params.ids
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
)
|
||||||
open={params.action === "delete"}
|
}
|
||||||
title={intl.formatMessage({
|
>
|
||||||
defaultMessage: "Delete categories",
|
<DeleteIcon />
|
||||||
description: "dialog title"
|
</IconButton>
|
||||||
})}
|
}
|
||||||
variant="delete"
|
/>
|
||||||
>
|
<ActionDialog
|
||||||
<DialogContentText>
|
confirmButtonState={bulkDeleteState}
|
||||||
<FormattedMessage
|
onClose={() =>
|
||||||
defaultMessage="Are you sure you want to delete {counter,plural,one{this category} other{{displayQuantity} categories}}?"
|
navigate(
|
||||||
values={{
|
categoryListUrl({
|
||||||
counter: maybe(() => params.ids.length),
|
...params,
|
||||||
displayQuantity: (
|
action: undefined,
|
||||||
<strong>{maybe(() => params.ids.length)}</strong>
|
ids: undefined
|
||||||
)
|
})
|
||||||
}}
|
)
|
||||||
/>
|
}
|
||||||
</DialogContentText>
|
onConfirm={() =>
|
||||||
<DialogContentText>
|
categoryBulkDelete({
|
||||||
<FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." />
|
variables: {
|
||||||
</DialogContentText>
|
ids: params.ids
|
||||||
</ActionDialog>
|
}
|
||||||
<SaveFilterTabDialog
|
})
|
||||||
open={params.action === "save-search"}
|
}
|
||||||
confirmButtonState="default"
|
open={params.action === "delete"}
|
||||||
onClose={closeModal}
|
title={intl.formatMessage({
|
||||||
onSubmit={handleTabSave}
|
defaultMessage: "Delete categories",
|
||||||
/>
|
description: "dialog title"
|
||||||
<DeleteFilterTabDialog
|
})}
|
||||||
open={params.action === "delete-search"}
|
variant="delete"
|
||||||
confirmButtonState="default"
|
>
|
||||||
onClose={closeModal}
|
<DialogContentText>
|
||||||
onSubmit={handleTabDelete}
|
<FormattedMessage
|
||||||
tabName={maybe(() => tabs[currentTab - 1].name, "...")}
|
defaultMessage="Are you sure you want to delete {counter,plural,one{this category} other{{displayQuantity} categories}}?"
|
||||||
/>
|
values={{
|
||||||
</>
|
counter: maybe(() => params.ids.length),
|
||||||
);
|
displayQuantity: <strong>{maybe(() => params.ids.length)}</strong>
|
||||||
}}
|
}}
|
||||||
</TypedRootCategoriesQuery>
|
/>
|
||||||
|
</DialogContentText>
|
||||||
|
<DialogContentText>
|
||||||
|
<FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." />
|
||||||
|
</DialogContentText>
|
||||||
|
</ActionDialog>
|
||||||
|
<SaveFilterTabDialog
|
||||||
|
open={params.action === "save-search"}
|
||||||
|
confirmButtonState="default"
|
||||||
|
onClose={closeModal}
|
||||||
|
onSubmit={handleTabSave}
|
||||||
|
/>
|
||||||
|
<DeleteFilterTabDialog
|
||||||
|
open={params.action === "delete-search"}
|
||||||
|
confirmButtonState="default"
|
||||||
|
onClose={closeModal}
|
||||||
|
onSubmit={handleTabDelete}
|
||||||
|
tabName={maybe(() => tabs[currentTab - 1].name, "...")}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default CategoryList;
|
export default CategoryList;
|
||||||
|
|
115
src/hooks/makeQuery.ts
Normal file
115
src/hooks/makeQuery.ts
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import { ApolloQueryResult } from "apollo-client";
|
||||||
|
import { DocumentNode } from "graphql";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { QueryResult, useQuery as useBaseQuery } from "react-apollo";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { maybe, RequireAtLeastOne } from "@saleor/misc";
|
||||||
|
import useAppState from "./useAppState";
|
||||||
|
import useNotifier from "./useNotifier";
|
||||||
|
|
||||||
|
export interface LoadMore<TData, TVariables> {
|
||||||
|
loadMore: (
|
||||||
|
mergeFunc: (prev: TData, next: TData) => TData,
|
||||||
|
extraVariables: Partial<TVariables>
|
||||||
|
) => Promise<ApolloQueryResult<TData>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type UseQuery<TData, TVariables> = QueryResult<TData, TVariables> &
|
||||||
|
LoadMore<TData, TVariables>;
|
||||||
|
type UseQueryOpts<TData, TVariables> = Partial<{
|
||||||
|
displayLoader: boolean;
|
||||||
|
require: Array<keyof TData>;
|
||||||
|
skip: boolean;
|
||||||
|
variables: TVariables;
|
||||||
|
}>;
|
||||||
|
type UseQueryHook<TData, TVariables> = (
|
||||||
|
opts: UseQueryOpts<TData, TVariables>
|
||||||
|
) => UseQuery<TData, TVariables>;
|
||||||
|
|
||||||
|
function makeQuery<TData, TVariables>(
|
||||||
|
query: DocumentNode
|
||||||
|
): UseQueryHook<TData, TVariables> {
|
||||||
|
function useQuery<TData, TVariables>({
|
||||||
|
displayLoader,
|
||||||
|
require,
|
||||||
|
skip,
|
||||||
|
variables
|
||||||
|
}: UseQueryOpts<TData, TVariables>): UseQuery<TData, TVariables> {
|
||||||
|
const notify = useNotifier();
|
||||||
|
const intl = useIntl();
|
||||||
|
const [, dispatchAppState] = useAppState();
|
||||||
|
const queryData = useBaseQuery(query, {
|
||||||
|
context: {
|
||||||
|
useBatching: true
|
||||||
|
},
|
||||||
|
errorPolicy: "all",
|
||||||
|
fetchPolicy: "cache-and-network",
|
||||||
|
skip,
|
||||||
|
variables
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (displayLoader) {
|
||||||
|
dispatchAppState({
|
||||||
|
payload: {
|
||||||
|
value: queryData.loading
|
||||||
|
},
|
||||||
|
type: "displayLoader"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [queryData.loading]);
|
||||||
|
|
||||||
|
if (queryData.error) {
|
||||||
|
if (
|
||||||
|
!queryData.error.graphQLErrors.every(
|
||||||
|
err =>
|
||||||
|
maybe(() => err.extensions.exception.code) === "PermissionDenied"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
notify({
|
||||||
|
text: intl.formatMessage(commonMessages.somethingWentWrong)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadMore = (
|
||||||
|
mergeFunc: (previousResults: TData, fetchMoreResult: TData) => TData,
|
||||||
|
extraVariables: RequireAtLeastOne<TVariables>
|
||||||
|
) =>
|
||||||
|
queryData.fetchMore({
|
||||||
|
query,
|
||||||
|
updateQuery: (previousResults, { fetchMoreResult }) => {
|
||||||
|
if (!fetchMoreResult) {
|
||||||
|
return previousResults;
|
||||||
|
}
|
||||||
|
return mergeFunc(previousResults, fetchMoreResult);
|
||||||
|
},
|
||||||
|
variables: { ...variables, ...extraVariables }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
!queryData.loading &&
|
||||||
|
require &&
|
||||||
|
queryData.data &&
|
||||||
|
!require.reduce((acc, key) => acc && queryData.data[key] !== null, true)
|
||||||
|
) {
|
||||||
|
dispatchAppState({
|
||||||
|
payload: {
|
||||||
|
error: "not-found"
|
||||||
|
},
|
||||||
|
type: "displayError"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...queryData,
|
||||||
|
loadMore
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return useQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default makeQuery;
|
Loading…
Reference in a new issue