Add search bar to category list

This commit is contained in:
dominik-zeglen 2019-09-11 14:59:41 +02:00
parent b842e85759
commit 53ac48062f
13 changed files with 442 additions and 224 deletions

View file

@ -1,5 +1,3 @@
import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import { import {
createStyles, createStyles,
Theme, Theme,
@ -12,9 +10,9 @@ import TableCell from "@material-ui/core/TableCell";
import TableFooter from "@material-ui/core/TableFooter"; import TableFooter from "@material-ui/core/TableFooter";
import TableRow from "@material-ui/core/TableRow"; import TableRow from "@material-ui/core/TableRow";
import React from "react"; import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage } from "react-intl";
import CardTitle from "@saleor/components/CardTitle"; import { CategoryFragment } from "@saleor/categories/types/CategoryFragment";
import Checkbox from "@saleor/components/Checkbox"; import Checkbox from "@saleor/components/Checkbox";
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import TableHead from "@saleor/components/TableHead"; import TableHead from "@saleor/components/TableHead";
@ -49,20 +47,8 @@ const styles = (theme: Theme) =>
} }
}); });
interface CategoryListProps interface CategoryListProps extends ListProps, ListActions {
extends ListProps, categories?: CategoryFragment[];
ListActions,
WithStyles<typeof styles> {
categories?: Array<{
id: string;
name: string;
children: {
totalCount: number;
};
products: {
totalCount: number;
};
}>;
isRoot: boolean; isRoot: boolean;
onAdd?(); onAdd?();
} }
@ -75,39 +61,18 @@ const CategoryList = withStyles(styles, { name: "CategoryList" })(
classes, classes,
disabled, disabled,
settings, settings,
isRoot,
pageInfo, pageInfo,
isChecked, isChecked,
isRoot,
selected, selected,
toggle, toggle,
toggleAll, toggleAll,
toolbar, toolbar,
onAdd,
onNextPage, onNextPage,
onPreviousPage, onPreviousPage,
onUpdateListSettings, onUpdateListSettings,
onRowClick onRowClick
}: CategoryListProps) => { }: CategoryListProps & WithStyles<typeof styles>) => (
const intl = useIntl();
return (
<Card>
{!isRoot && (
<CardTitle
title={intl.formatMessage({
defaultMessage: "All Subcategories",
description: "section header"
})}
toolbar={
<Button color="primary" variant="text" onClick={onAdd}>
<FormattedMessage
defaultMessage="Create subcategory"
description="button"
/>
</Button>
}
/>
)}
<Table> <Table>
<TableHead <TableHead
colSpan={numberOfColumns} colSpan={numberOfColumns}
@ -138,9 +103,7 @@ const CategoryList = withStyles(styles, { name: "CategoryList" })(
<TablePagination <TablePagination
colSpan={numberOfColumns} colSpan={numberOfColumns}
settings={settings} settings={settings}
hasNextPage={ hasNextPage={pageInfo && !disabled ? pageInfo.hasNextPage : false}
pageInfo && !disabled ? pageInfo.hasNextPage : false
}
onNextPage={onNextPage} onNextPage={onNextPage}
onUpdateListSettings={onUpdateListSettings} onUpdateListSettings={onUpdateListSettings}
hasPreviousPage={ hasPreviousPage={
@ -210,9 +173,7 @@ const CategoryList = withStyles(styles, { name: "CategoryList" })(
)} )}
</TableBody> </TableBody>
</Table> </Table>
</Card> )
);
}
); );
CategoryList.displayName = "CategoryList"; CategoryList.displayName = "CategoryList";
export default CategoryList; export default CategoryList;

View file

@ -1,44 +1,55 @@
import Button from "@material-ui/core/Button"; import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import React from "react"; import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { CategoryFragment } from "@saleor/categories/types/CategoryFragment";
import Container from "@saleor/components/Container"; import Container from "@saleor/components/Container";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import SearchBar from "@saleor/components/SearchBar";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { ListActions, PageListProps } from "@saleor/types"; import {
ListActions,
PageListProps,
SearchPageProps,
TabPageProps
} from "@saleor/types";
import CategoryList from "../CategoryList"; import CategoryList from "../CategoryList";
export interface CategoryTableProps extends PageListProps, ListActions { export interface CategoryTableProps
categories: Array<{ extends PageListProps,
id: string; ListActions,
name: string; SearchPageProps,
children: { TabPageProps {
totalCount: number; categories: CategoryFragment[];
};
products: {
totalCount: number;
};
}>;
} }
export const CategoryListPage: React.StatelessComponent<CategoryTableProps> = ({ export const CategoryListPage: React.StatelessComponent<CategoryTableProps> = ({
categories, categories,
currentTab,
disabled, disabled,
settings, initialSearch,
onAdd,
onNextPage,
onPreviousPage,
onUpdateListSettings,
onRowClick,
pageInfo,
isChecked, isChecked,
pageInfo,
selected, selected,
settings,
tabs,
toggle, toggle,
toggleAll, toggleAll,
toolbar toolbar,
onAdd,
onAll,
onNextPage,
onPreviousPage,
onRowClick,
onSearchChange,
onTabChange,
onTabDelete,
onTabSave,
onUpdateListSettings
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
return ( return (
<Container> <Container>
<PageHeader title={intl.formatMessage(sectionNames.categories)}> <PageHeader title={intl.formatMessage(sectionNames.categories)}>
@ -49,23 +60,38 @@ export const CategoryListPage: React.StatelessComponent<CategoryTableProps> = ({
/> />
</Button> </Button>
</PageHeader> </PageHeader>
<Card>
<SearchBar
currentTab={currentTab}
initialSearch={initialSearch}
searchPlaceholder={intl.formatMessage({
defaultMessage: "Search Attribute"
})}
tabs={tabs}
onAll={onAll}
onSearchChange={onSearchChange}
onTabChange={onTabChange}
onTabDelete={onTabDelete}
onTabSave={onTabSave}
/>
<CategoryList <CategoryList
categories={categories} categories={categories}
onAdd={onAdd}
onRowClick={onRowClick}
disabled={disabled} disabled={disabled}
settings={settings}
isRoot={true}
onNextPage={onNextPage}
onPreviousPage={onPreviousPage}
onUpdateListSettings={onUpdateListSettings}
pageInfo={pageInfo}
isChecked={isChecked} isChecked={isChecked}
isRoot={true}
pageInfo={pageInfo}
selected={selected} selected={selected}
settings={settings}
toggle={toggle} toggle={toggle}
toggleAll={toggleAll} toggleAll={toggleAll}
toolbar={toolbar} toolbar={toolbar}
onAdd={onAdd}
onNextPage={onNextPage}
onPreviousPage={onPreviousPage}
onRowClick={onRowClick}
onUpdateListSettings={onUpdateListSettings}
/> />
</Card>
</Container> </Container>
); );
}; };

View file

@ -1,9 +1,12 @@
import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import { RawDraftContentState } from "draft-js"; import { RawDraftContentState } from "draft-js";
import React from "react"; import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import { CardSpacer } from "@saleor/components/CardSpacer"; import { CardSpacer } from "@saleor/components/CardSpacer";
import CardTitle from "@saleor/components/CardTitle";
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
import Container from "@saleor/components/Container"; import Container from "@saleor/components/Container";
import Form from "@saleor/components/Form"; import Form from "@saleor/components/Form";
@ -178,21 +181,40 @@ export const CategoryUpdatePage: React.StatelessComponent<
</TabContainer> </TabContainer>
<CardSpacer /> <CardSpacer />
{currentTab === CategoryPageTab.categories && ( {currentTab === CategoryPageTab.categories && (
<Card>
<CardTitle
title={intl.formatMessage({
defaultMessage: "All Subcategories",
description: "section header"
})}
toolbar={
<Button
color="primary"
variant="text"
onClick={onAddCategory}
>
<FormattedMessage
defaultMessage="Create subcategory"
description="button"
/>
</Button>
}
/>
<CategoryList <CategoryList
disabled={disabled}
isRoot={false}
categories={subcategories} categories={subcategories}
onAdd={onAddCategory} disabled={disabled}
onRowClick={onCategoryClick} isChecked={isChecked}
onNextPage={onNextPage} isRoot={false}
onPreviousPage={onPreviousPage}
pageInfo={pageInfo} pageInfo={pageInfo}
selected={selected}
toggle={toggle} toggle={toggle}
toggleAll={toggleAll} toggleAll={toggleAll}
selected={selected}
isChecked={isChecked}
toolbar={subcategoryListToolbar} toolbar={subcategoryListToolbar}
onNextPage={onNextPage}
onPreviousPage={onPreviousPage}
onRowClick={onCategoryClick}
/> />
</Card>
)} )}
{currentTab === CategoryPageTab.products && ( {currentTab === CategoryPageTab.products && (
<CategoryProducts <CategoryProducts

View file

@ -1,64 +1,83 @@
import { content } from "../storybook/stories/components/RichTextEditor"; import { content } from "../storybook/stories/components/RichTextEditor";
import { CategoryDetails_category } from "./types/CategoryDetails"; import { CategoryDetails_category } from "./types/CategoryDetails";
import { CategoryFragment } from "./types/CategoryFragment";
export const categories = [ export const categories: CategoryFragment[] = [
{ {
__typename: "Category",
children: { children: {
__typename: "CategoryCountableConnection",
totalCount: 2 totalCount: 2
}, },
id: "123123", id: "123123",
name: "Lorem ipsum dolor", name: "Lorem ipsum dolor",
products: { products: {
__typename: "ProductCountableConnection",
totalCount: 4 totalCount: 4
} }
}, },
{ {
__typename: "Category",
children: { children: {
__typename: "CategoryCountableConnection",
totalCount: 54 totalCount: 54
}, },
id: "876752", id: "876752",
name: "Mauris vehicula tortor vulputate", name: "Mauris vehicula tortor vulputate",
products: { products: {
__typename: "ProductCountableConnection",
totalCount: 3 totalCount: 3
} }
}, },
{ {
__typename: "Category",
children: { children: {
__typename: "CategoryCountableConnection",
totalCount: 2 totalCount: 2
}, },
id: "876542", id: "876542",
name: "Excepteur sint occaecat cupidatat non proident", name: "Excepteur sint occaecat cupidatat non proident",
products: { products: {
__typename: "ProductCountableConnection",
totalCount: 6 totalCount: 6
} }
}, },
{ {
__typename: "Category",
children: { children: {
__typename: "CategoryCountableConnection",
totalCount: 6 totalCount: 6
}, },
id: "875352", id: "875352",
name: "Ut enim ad minim veniam", name: "Ut enim ad minim veniam",
products: { products: {
__typename: "ProductCountableConnection",
totalCount: 12 totalCount: 12
} }
}, },
{ {
__typename: "Category",
children: { children: {
__typename: "CategoryCountableConnection",
totalCount: 76 totalCount: 76
}, },
id: "865752", id: "865752",
name: "Duis aute irure dolor in reprehenderit", name: "Duis aute irure dolor in reprehenderit",
products: { products: {
__typename: "ProductCountableConnection",
totalCount: 43 totalCount: 43
} }
}, },
{ {
__typename: "Category",
children: { children: {
__typename: "CategoryCountableConnection",
totalCount: 11 totalCount: 11
}, },
id: "878752", id: "878752",
name: "Neque porro quisquam est", name: "Neque porro quisquam est",
products: { products: {
__typename: "ProductCountableConnection",
totalCount: 21 totalCount: 21
} }
} }

View file

@ -7,6 +7,18 @@ import {
} from "./types/CategoryDetails"; } from "./types/CategoryDetails";
import { RootCategories } from "./types/RootCategories"; import { RootCategories } from "./types/RootCategories";
export const categoryFragment = gql`
fragment CategoryFragment on Category {
id
name
children {
totalCount
}
products {
totalCount
}
}
`;
export const categoryDetailsFragment = gql` export const categoryDetailsFragment = gql`
fragment CategoryDetailsFragment on Category { fragment CategoryDetailsFragment on Category {
id id
@ -25,11 +37,13 @@ export const categoryDetailsFragment = gql`
`; `;
export const rootCategories = gql` export const rootCategories = gql`
${categoryFragment}
query RootCategories( query RootCategories(
$first: Int $first: Int
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: CategoryFilterInput
) { ) {
categories( categories(
level: 0 level: 0
@ -37,17 +51,11 @@ export const rootCategories = gql`
after: $after after: $after
last: $last last: $last
before: $before before: $before
filter: $filter
) { ) {
edges { edges {
node { node {
id ...CategoryFragment
name
children {
totalCount
}
products {
totalCount
}
} }
} }
pageInfo { pageInfo {
@ -64,6 +72,7 @@ export const TypedRootCategoriesQuery = TypedQuery<RootCategories, {}>(
); );
export const categoryDetails = gql` export const categoryDetails = gql`
${categoryFragment}
${categoryDetailsFragment} ${categoryDetailsFragment}
query CategoryDetails( query CategoryDetails(
$id: ID! $id: ID!
@ -77,14 +86,7 @@ export const categoryDetails = gql`
children(first: 20) { children(first: 20) {
edges { edges {
node { node {
id ...CategoryFragment
name
children {
totalCount
}
products {
totalCount
}
} }
} }
} }

View file

@ -0,0 +1,25 @@
/* tslint:disable */
/* eslint-disable */
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL fragment: CategoryFragment
// ====================================================
export interface CategoryFragment_children {
__typename: "CategoryCountableConnection";
totalCount: number | null;
}
export interface CategoryFragment_products {
__typename: "ProductCountableConnection";
totalCount: number | null;
}
export interface CategoryFragment {
__typename: "Category";
id: string;
name: string;
children: CategoryFragment_children | null;
products: CategoryFragment_products | null;
}

View file

@ -2,6 +2,8 @@
/* 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 { CategoryFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: RootCategories // GraphQL query operation: RootCategories
// ==================================================== // ====================================================
@ -52,4 +54,5 @@ export interface RootCategoriesVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: CategoryFilterInput | null;
} }

View file

@ -1,14 +1,27 @@
import { stringify as stringifyQs } from "qs"; import { stringify as stringifyQs } from "qs";
import urlJoin from "url-join"; import urlJoin from "url-join";
import { ActiveTab, BulkAction, Dialog, Pagination } from "../types"; import {
ActiveTab,
BulkAction,
Dialog,
Filters,
Pagination,
TabActionDialog
} from "../types";
import { CategoryPageTab } from "./components/CategoryUpdatePage"; import { CategoryPageTab } from "./components/CategoryUpdatePage";
const categorySectionUrl = "/categories/"; const categorySectionUrl = "/categories/";
export const categoryListPath = categorySectionUrl; export const categoryListPath = categorySectionUrl;
export type CategoryListUrlDialog = "delete"; export enum CategoryListUrlFiltersEnum {
export type CategoryListUrlQueryParams = BulkAction & query = "query"
}
export type CategoryListUrlFilters = Filters<CategoryListUrlFiltersEnum>;
export type CategoryListUrlDialog = "delete" | TabActionDialog;
export type CategoryListUrlQueryParams = ActiveTab &
BulkAction &
CategoryListUrlFilters &
Dialog<CategoryListUrlDialog> & Dialog<CategoryListUrlDialog> &
Pagination; Pagination;
export const categoryListUrl = (params?: CategoryListUrlQueryParams) => export const categoryListUrl = (params?: CategoryListUrlQueryParams) =>

View file

@ -5,6 +5,10 @@ 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 DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
import SaveFilterTabDialog, {
SaveFilterTabDialogFormData
} from "@saleor/components/SaveFilterTabDialog";
import useBulkActions from "@saleor/hooks/useBulkActions"; import useBulkActions from "@saleor/hooks/useBulkActions";
import useListSettings from "@saleor/hooks/useListSettings"; import useListSettings from "@saleor/hooks/useListSettings";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
@ -13,16 +17,26 @@ import usePaginator, {
} from "@saleor/hooks/usePaginator"; } from "@saleor/hooks/usePaginator";
import { getMutationState, maybe } from "@saleor/misc"; 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 { TypedCategoryBulkDeleteMutation } from "../mutations"; import { TypedCategoryBulkDeleteMutation } from "../../mutations";
import { TypedRootCategoriesQuery } from "../queries"; import { TypedRootCategoriesQuery } from "../../queries";
import { CategoryBulkDelete } from "../types/CategoryBulkDelete"; import { CategoryBulkDelete } from "../../types/CategoryBulkDelete";
import { import {
categoryAddUrl, categoryAddUrl,
categoryListUrl, categoryListUrl,
CategoryListUrlDialog,
CategoryListUrlFilters,
CategoryListUrlQueryParams, CategoryListUrlQueryParams,
categoryUrl categoryUrl
} from "../urls"; } from "../../urls";
import {
areFiltersApplied,
deleteFilterTab,
getActiveFilters,
getFilterTabs,
getFilterVariables,
saveFilterTab
} from "./filter";
interface CategoryListProps { interface CategoryListProps {
params: CategoryListUrlQueryParams; params: CategoryListUrlQueryParams;
@ -41,9 +55,77 @@ export const CategoryList: React.StatelessComponent<CategoryListProps> = ({
); );
const intl = useIntl(); const intl = useIntl();
const tabs = getFilterTabs();
const currentTab =
params.activeTab === undefined
? areFiltersApplied(params)
? tabs.length + 1
: 0
: parseInt(params.activeTab, 0);
const changeFilterField = (filter: CategoryListUrlFilters) => {
reset();
navigate(
categoryListUrl({
...getActiveFilters(params),
...filter,
activeTab: undefined
})
);
};
const closeModal = () =>
navigate(
categoryListUrl({
...params,
action: undefined,
ids: undefined
}),
true
);
const openModal = (action: CategoryListUrlDialog, ids?: string[]) =>
navigate(
categoryListUrl({
...params,
action,
ids
})
);
const handleTabChange = (tab: number) => {
reset();
navigate(
categoryListUrl({
activeTab: tab.toString(),
...getFilterTabs()[tab - 1].data
})
);
};
const handleTabDelete = () => {
deleteFilterTab(currentTab);
reset();
navigate(categoryListUrl());
};
const handleTabSave = (data: SaveFilterTabDialogFormData) => {
saveFilterTab(data.name, getActiveFilters(params));
handleTabChange(tabs.length + 1);
};
const paginationState = createPaginationState(settings.rowNumber, params); const paginationState = createPaginationState(settings.rowNumber, params);
const queryVariables = React.useMemo(
() => ({
...paginationState,
filter: getFilterVariables(params)
}),
[params]
);
return ( return (
<TypedRootCategoriesQuery displayLoader variables={paginationState}> <TypedRootCategoriesQuery displayLoader variables={queryVariables}>
{({ data, loading, refetch }) => { {({ data, loading, refetch }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.categories.pageInfo), maybe(() => data.categories.pageInfo),
@ -78,6 +160,14 @@ export const CategoryList: React.StatelessComponent<CategoryListProps> = ({
() => data.categories.edges.map(edge => edge.node), () => data.categories.edges.map(edge => edge.node),
[] []
)} )}
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} settings={settings}
onAdd={() => navigate(categoryAddUrl())} onAdd={() => navigate(categoryAddUrl())}
onRowClick={id => () => navigate(categoryUrl(id))} onRowClick={id => () => navigate(categoryUrl(id))}
@ -134,7 +224,7 @@ export const CategoryList: React.StatelessComponent<CategoryListProps> = ({
> >
<FormattedMessage <FormattedMessage
defaultMessage="Are you sure you want to delete {counter, plural, defaultMessage="Are you sure you want to delete {counter, plural,
one {this attribute} one {this category}
other {{displayQuantity} categories} other {{displayQuantity} categories}
}?" }?"
values={{ values={{
@ -148,6 +238,19 @@ export const CategoryList: React.StatelessComponent<CategoryListProps> = ({
<FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." /> <FormattedMessage defaultMessage="Remember this will also delete all products assigned to this category." />
</DialogContentText> </DialogContentText>
</ActionDialog> </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, "...")}
/>
</> </>
); );
}} }}

View file

@ -0,0 +1,31 @@
import { CategoryFilterInput } from "@saleor/types/globalTypes";
import {
createFilterTabUtils,
createFilterUtils
} from "../../../utils/filters";
import {
CategoryListUrlFilters,
CategoryListUrlFiltersEnum,
CategoryListUrlQueryParams
} from "../../urls";
export const PRODUCT_FILTERS_KEY = "productFilters";
export function getFilterVariables(
params: CategoryListUrlFilters
): CategoryFilterInput {
return {
search: params.query
};
}
export const {
deleteFilterTab,
getFilterTabs,
saveFilterTab
} = createFilterTabUtils<CategoryListUrlFilters>(PRODUCT_FILTERS_KEY);
export const { areFiltersApplied, getActiveFilters } = createFilterUtils<
CategoryListUrlQueryParams,
CategoryListUrlFilters
>(CategoryListUrlFiltersEnum);

View file

@ -0,0 +1,2 @@
export { default } from "./CategoryList";
export * from "./CategoryList";

View file

@ -3,7 +3,12 @@ import React from "react";
import CategoryListPage from "../../../categories/components/CategoryListPage"; import CategoryListPage from "../../../categories/components/CategoryListPage";
import { categories } from "../../../categories/fixtures"; import { categories } from "../../../categories/fixtures";
import { listActionsProps, pageListProps } from "../../../fixtures"; import {
listActionsProps,
pageListProps,
searchPageProps,
tabPageProps
} from "../../../fixtures";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
const categoryTableProps = { const categoryTableProps = {
@ -11,6 +16,8 @@ const categoryTableProps = {
onAddCategory: undefined, onAddCategory: undefined,
onCategoryClick: () => undefined, onCategoryClick: () => undefined,
...listActionsProps, ...listActionsProps,
...tabPageProps,
...searchPageProps,
...pageListProps.default ...pageListProps.default
}; };

View file

@ -316,6 +316,10 @@ export interface CatalogueInput {
collections?: (string | null)[] | null; collections?: (string | null)[] | null;
} }
export interface CategoryFilterInput {
search?: string | null;
}
export interface CategoryInput { export interface CategoryInput {
description?: string | null; description?: string | null;
descriptionJson?: any | null; descriptionJson?: any | null;