Split filters, searches and tabs
This commit is contained in:
parent
f4e3149f89
commit
544d13754a
16 changed files with 392 additions and 178 deletions
109
src/components/Filter/FilterActions.tsx
Normal file
109
src/components/Filter/FilterActions.tsx
Normal file
|
@ -0,0 +1,109 @@
|
|||
import { Theme } from "@material-ui/core/styles";
|
||||
import TextField, { TextFieldProps } from "@material-ui/core/TextField";
|
||||
import { makeStyles } from "@material-ui/styles";
|
||||
import React from "react";
|
||||
|
||||
import { FilterContentSubmitData, IFilter } from "../Filter";
|
||||
import Filter from "./Filter";
|
||||
|
||||
const useInputStyles = makeStyles({
|
||||
input: {
|
||||
padding: "10px 12px"
|
||||
},
|
||||
root: {
|
||||
flex: 1
|
||||
}
|
||||
});
|
||||
|
||||
const Search: React.FC<TextFieldProps> = props => {
|
||||
const classes = useInputStyles({});
|
||||
return (
|
||||
<TextField
|
||||
{...props}
|
||||
className={classes.root}
|
||||
inputProps={{
|
||||
className: classes.input
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(
|
||||
(theme: Theme) => ({
|
||||
actionContainer: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
padding: `${theme.spacing.unit * 1.5}px ${theme.spacing.unit * 3}px ${
|
||||
theme.spacing.unit
|
||||
}px`
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "FilterActions"
|
||||
}
|
||||
);
|
||||
|
||||
export interface FilterActionsPropsSearch {
|
||||
placeholder: string;
|
||||
search: string;
|
||||
onSearchChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
export interface FilterActionsPropsFilters {
|
||||
currencySymbol: string;
|
||||
menu: IFilter;
|
||||
filterLabel: string;
|
||||
onFilterAdd: (filter: FilterContentSubmitData) => void;
|
||||
}
|
||||
|
||||
export const FilterActionsOnlySearch: React.FC<
|
||||
FilterActionsPropsSearch
|
||||
> = props => {
|
||||
const { onSearchChange, placeholder, search } = props;
|
||||
const classes = useStyles(props);
|
||||
|
||||
return (
|
||||
<div className={classes.actionContainer}>
|
||||
<Search
|
||||
fullWidth
|
||||
placeholder={placeholder}
|
||||
value={search}
|
||||
onChange={onSearchChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export type FilterActionsProps = FilterActionsPropsSearch &
|
||||
FilterActionsPropsFilters;
|
||||
const FilterActions: React.FC<FilterActionsProps> = props => {
|
||||
const {
|
||||
currencySymbol,
|
||||
filterLabel,
|
||||
menu,
|
||||
onFilterAdd,
|
||||
onSearchChange,
|
||||
placeholder,
|
||||
search
|
||||
} = props;
|
||||
const classes = useStyles(props);
|
||||
|
||||
return (
|
||||
<div className={classes.actionContainer}>
|
||||
<Filter
|
||||
currencySymbol={currencySymbol}
|
||||
menu={menu}
|
||||
filterLabel={filterLabel}
|
||||
onFilterAdd={onFilterAdd}
|
||||
/>
|
||||
<Search
|
||||
fullWidth
|
||||
placeholder={placeholder}
|
||||
value={search}
|
||||
onChange={onSearchChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
FilterActions.displayName = "FilterActions";
|
||||
export default FilterActions;
|
|
@ -6,9 +6,8 @@ import Debounce from "../Debounce";
|
|||
import { IFilter } from "../Filter/types";
|
||||
import FilterTabs, { FilterChips, FilterTab } from "../TableFilter";
|
||||
|
||||
export interface FilterBarProps<TUrlFilters = object, TFilterKeys = any>
|
||||
extends FilterProps<TUrlFilters, TFilterKeys> {
|
||||
filterMenu: IFilter<TFilterKeys>;
|
||||
export interface FilterBarProps extends FilterProps {
|
||||
filterMenu: IFilter;
|
||||
}
|
||||
|
||||
const FilterBar: React.FC<FilterBarProps> = ({
|
||||
|
@ -16,32 +15,32 @@ const FilterBar: React.FC<FilterBarProps> = ({
|
|||
currencySymbol,
|
||||
filterLabel,
|
||||
filtersList,
|
||||
filterTabs,
|
||||
filterMenu,
|
||||
currentTab,
|
||||
initialSearch,
|
||||
searchPlaceholder,
|
||||
tabs,
|
||||
onAll,
|
||||
onSearchChange,
|
||||
onFilterAdd,
|
||||
onFilterSave,
|
||||
onTabChange,
|
||||
onFilterDelete
|
||||
onTabDelete,
|
||||
onTabSave
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const [search, setSearch] = React.useState(initialSearch);
|
||||
React.useEffect(() => setSearch(initialSearch), [currentTab, initialSearch]);
|
||||
|
||||
const isCustom = currentTab === filterTabs.length + 1;
|
||||
const isCustom = currentTab === tabs.length + 1;
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterTabs currentTab={currentTab}>
|
||||
<FilterTab label={allTabLabel} onClick={onAll} />
|
||||
{filterTabs.map((tab, tabIndex) => (
|
||||
{tabs.map((tab, tabIndex) => (
|
||||
<FilterTab
|
||||
onClick={() => onTabChange(tabIndex + 1)}
|
||||
label={tab.name}
|
||||
label={tab}
|
||||
key={tabIndex}
|
||||
/>
|
||||
))}
|
||||
|
@ -72,9 +71,9 @@ const FilterBar: React.FC<FilterBarProps> = ({
|
|||
search={search}
|
||||
onSearchChange={handleSearchChange}
|
||||
onFilterAdd={onFilterAdd}
|
||||
onFilterSave={onFilterSave}
|
||||
onFilterSave={onTabDelete}
|
||||
isCustomSearch={isCustom}
|
||||
onFilterDelete={onFilterDelete}
|
||||
onFilterDelete={onTabSave}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
|
122
src/components/SearchBar/SearchBar.tsx
Normal file
122
src/components/SearchBar/SearchBar.tsx
Normal file
|
@ -0,0 +1,122 @@
|
|||
import { Theme } from "@material-ui/core/styles";
|
||||
import { makeStyles } from "@material-ui/styles";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { SearchPageProps, TabPageProps } from "@saleor/types";
|
||||
import Debounce from "../Debounce";
|
||||
import { FilterActionsOnlySearch } from "../Filter/FilterActions";
|
||||
import Hr from "../Hr";
|
||||
import Link from "../Link";
|
||||
import FilterTabs, { FilterTab } from "../TableFilter";
|
||||
|
||||
export interface SearchBarProps extends SearchPageProps, TabPageProps {
|
||||
searchPlaceholder: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
tabAction: {
|
||||
display: "inline-block"
|
||||
},
|
||||
tabActionContainer: {
|
||||
borderBottom: "1px solid #e8e8e8",
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
marginTop: theme.spacing.unit,
|
||||
padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit}px`
|
||||
}
|
||||
}));
|
||||
|
||||
const SearchBar: React.FC<SearchBarProps> = props => {
|
||||
const {
|
||||
currentTab,
|
||||
initialSearch,
|
||||
onSearchChange,
|
||||
searchPlaceholder,
|
||||
tabs,
|
||||
onAll,
|
||||
onTabChange,
|
||||
onTabDelete,
|
||||
onTabSave
|
||||
} = props;
|
||||
const classes = useStyles(props);
|
||||
const [search, setSearch] = React.useState(initialSearch);
|
||||
const intl = useIntl();
|
||||
React.useEffect(() => setSearch(initialSearch), [initialSearch]);
|
||||
|
||||
const isCustom = currentTab === tabs.length + 1;
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterTabs currentTab={currentTab}>
|
||||
<FilterTab
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "All Attributes",
|
||||
description: "tab name"
|
||||
})}
|
||||
onClick={onAll}
|
||||
/>
|
||||
{tabs.map((tab, tabIndex) => (
|
||||
<FilterTab
|
||||
onClick={() => onTabChange(tabIndex + 1)}
|
||||
label={tab}
|
||||
key={tabIndex}
|
||||
/>
|
||||
))}
|
||||
{isCustom && (
|
||||
<FilterTab
|
||||
onClick={() => undefined}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Custom Filter"
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</FilterTabs>
|
||||
<Debounce debounceFn={onSearchChange}>
|
||||
{debounceSearchChange => {
|
||||
const handleSearchChange = (event: React.ChangeEvent<any>) => {
|
||||
const value = event.target.value;
|
||||
setSearch(value);
|
||||
debounceSearchChange(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterActionsOnlySearch
|
||||
{...props}
|
||||
placeholder={searchPlaceholder}
|
||||
search={search}
|
||||
onSearchChange={handleSearchChange}
|
||||
/>
|
||||
<div className={classes.tabActionContainer}>
|
||||
<div className={classes.tabAction}>
|
||||
{search || (tabs && tabs.length) > 0 ? (
|
||||
isCustom ? (
|
||||
<Link onClick={onTabSave}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Save Custom Search"
|
||||
description="button"
|
||||
/>
|
||||
</Link>
|
||||
) : (
|
||||
<Link onClick={onTabDelete}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Delete Search"
|
||||
description="button"
|
||||
/>
|
||||
</Link>
|
||||
)
|
||||
) : (
|
||||
<Hr />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Debounce>
|
||||
</>
|
||||
);
|
||||
};
|
||||
SearchBar.displayName = "SearchBar";
|
||||
export default SearchBar;
|
2
src/components/SearchBar/index.ts
Normal file
2
src/components/SearchBar/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./SearchBar";
|
||||
export * from "./SearchBar";
|
|
@ -1,14 +1,14 @@
|
|||
import ButtonBase from "@material-ui/core/ButtonBase";
|
||||
import { Theme } from "@material-ui/core/styles";
|
||||
import { fade } from "@material-ui/core/styles/colorManipulator";
|
||||
import TextField, { TextFieldProps } from "@material-ui/core/TextField";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import ClearIcon from "@material-ui/icons/Clear";
|
||||
import { createStyles, makeStyles, useTheme } from "@material-ui/styles";
|
||||
import { makeStyles, useTheme } from "@material-ui/styles";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import Filter, { FilterContentSubmitData, IFilter } from "../Filter";
|
||||
import Filter from "../Filter";
|
||||
import FilterActions, { FilterActionsProps } from "../Filter/FilterActions";
|
||||
import Hr from "../Hr";
|
||||
import Link from "../Link";
|
||||
|
||||
|
@ -17,38 +17,8 @@ export interface Filter {
|
|||
onClick: () => void;
|
||||
}
|
||||
|
||||
const useInputStyles = makeStyles({
|
||||
input: {
|
||||
padding: "10px 12px"
|
||||
},
|
||||
root: {
|
||||
flex: 1
|
||||
}
|
||||
});
|
||||
|
||||
const Search: React.FC<TextFieldProps> = props => {
|
||||
const classes = useInputStyles({});
|
||||
return (
|
||||
<TextField
|
||||
{...props}
|
||||
className={classes.root}
|
||||
inputProps={{
|
||||
className: classes.input
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(
|
||||
(theme: Theme) =>
|
||||
createStyles({
|
||||
actionContainer: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 3}px ${
|
||||
theme.spacing.unit
|
||||
}px ${theme.spacing.unit * 3}px`
|
||||
},
|
||||
(theme: Theme) => ({
|
||||
filterButton: {
|
||||
alignItems: "center",
|
||||
backgroundColor: fade(theme.palette.primary.main, 0.8),
|
||||
|
@ -105,16 +75,10 @@ const useStyles = makeStyles(
|
|||
}
|
||||
);
|
||||
|
||||
interface FilterChipProps<TFilterKeys = string> {
|
||||
currencySymbol: string;
|
||||
menu: IFilter<TFilterKeys>;
|
||||
interface FilterChipProps extends FilterActionsProps {
|
||||
filtersList: Filter[];
|
||||
filterLabel: string;
|
||||
placeholder: string;
|
||||
search: string;
|
||||
isCustomSearch: boolean;
|
||||
onSearchChange: (event: React.ChangeEvent<any>) => void;
|
||||
onFilterAdd: (filter: FilterContentSubmitData<TFilterKeys>) => void;
|
||||
onFilterDelete: () => void;
|
||||
onFilterSave: () => void;
|
||||
}
|
||||
|
@ -137,20 +101,15 @@ export const FilterChips: React.FC<FilterChipProps> = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className={classes.actionContainer}>
|
||||
<Filter
|
||||
<FilterActions
|
||||
currencySymbol={currencySymbol}
|
||||
menu={menu}
|
||||
filterLabel={filterLabel}
|
||||
placeholder={placeholder}
|
||||
search={search}
|
||||
onSearchChange={onSearchChange}
|
||||
onFilterAdd={onFilterAdd}
|
||||
/>
|
||||
<Search
|
||||
fullWidth
|
||||
placeholder={placeholder}
|
||||
value={search}
|
||||
onChange={onSearchChange}
|
||||
/>
|
||||
</div>
|
||||
{search || (filtersList && filtersList.length) ? (
|
||||
<div className={classes.filterContainer}>
|
||||
<div className={classes.filterChipContainer}>
|
||||
|
|
|
@ -3,7 +3,9 @@ import {
|
|||
FetchMoreProps,
|
||||
FilterPageProps,
|
||||
ListActions,
|
||||
PageListProps
|
||||
PageListProps,
|
||||
SearchPageProps,
|
||||
TabPageProps
|
||||
} from "./types";
|
||||
|
||||
const pageInfo = {
|
||||
|
@ -46,23 +48,26 @@ export const countries = [
|
|||
{ code: "AS", label: "American Samoa" }
|
||||
];
|
||||
|
||||
export const filterPageProps: FilterPageProps<{}, unknown> = {
|
||||
currencySymbol: "USD",
|
||||
export const tabPageProps: TabPageProps = {
|
||||
currentTab: 0,
|
||||
filterTabs: [
|
||||
{
|
||||
data: {},
|
||||
name: "Tab X"
|
||||
}
|
||||
],
|
||||
filtersList: [],
|
||||
initialSearch: "",
|
||||
onAll: () => undefined,
|
||||
onFilterAdd: () => undefined,
|
||||
onFilterDelete: () => undefined,
|
||||
onFilterSave: () => undefined,
|
||||
onSearchChange: () => undefined,
|
||||
onTabChange: () => undefined
|
||||
onTabChange: () => undefined,
|
||||
onTabDelete: () => undefined,
|
||||
onTabSave: () => undefined,
|
||||
tabs: ["Tab X"]
|
||||
};
|
||||
|
||||
export const searchPageProps: SearchPageProps = {
|
||||
initialSearch: "",
|
||||
onSearchChange: () => undefined
|
||||
};
|
||||
|
||||
export const filterPageProps: FilterPageProps = {
|
||||
...searchPageProps,
|
||||
...tabPageProps,
|
||||
currencySymbol: "USD",
|
||||
filtersList: [],
|
||||
onFilterAdd: () => undefined
|
||||
};
|
||||
|
||||
export const filters: Filter[] = [
|
||||
|
|
|
@ -8,9 +8,8 @@ import FilterBar from "@saleor/components/FilterBar";
|
|||
import TimezoneContext from "@saleor/components/Timezone";
|
||||
import { FilterProps } from "../../../types";
|
||||
import { OrderStatusFilter } from "../../../types/globalTypes";
|
||||
import { OrderListUrlFilters } from "../../urls";
|
||||
|
||||
type OrderListFilterProps = FilterProps<OrderListUrlFilters, OrderFilterKeys>;
|
||||
type OrderListFilterProps = FilterProps;
|
||||
|
||||
export enum OrderFilterKeys {
|
||||
date = "date",
|
||||
|
|
|
@ -10,14 +10,13 @@ import { sectionNames } from "@saleor/intl";
|
|||
import { OrderFilterKeys } from "@saleor/orders/components/OrderListFilter";
|
||||
import { FilterPageProps, ListActions, PageListProps } from "@saleor/types";
|
||||
import { OrderList_orders_edges_node } from "../../types/OrderList";
|
||||
import { OrderListUrlFilters } from "../../urls";
|
||||
import OrderList from "../OrderList";
|
||||
import OrderListFilter from "../OrderListFilter";
|
||||
|
||||
export interface OrderListPageProps
|
||||
extends PageListProps,
|
||||
ListActions,
|
||||
FilterPageProps<OrderListUrlFilters, OrderFilterKeys> {
|
||||
FilterPageProps {
|
||||
orders: OrderList_orders_edges_node[];
|
||||
}
|
||||
|
||||
|
@ -25,8 +24,8 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
currencySymbol,
|
||||
currentTab,
|
||||
filtersList,
|
||||
filterTabs,
|
||||
initialSearch,
|
||||
tabs,
|
||||
onAdd,
|
||||
onAll,
|
||||
onSearchChange,
|
||||
|
@ -59,7 +58,7 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
filterLabel={intl.formatMessage({
|
||||
defaultMessage: "Select all orders where:"
|
||||
})}
|
||||
filterTabs={filterTabs}
|
||||
filterTabs={tabs}
|
||||
filtersList={filtersList}
|
||||
initialSearch={initialSearch}
|
||||
searchPlaceholder={intl.formatMessage({
|
||||
|
|
|
@ -8,7 +8,8 @@ import {
|
|||
Filters,
|
||||
FiltersWithMultipleValues,
|
||||
Pagination,
|
||||
SingleAction
|
||||
SingleAction,
|
||||
TabActionDialog
|
||||
} from "../types";
|
||||
|
||||
const orderSectionUrl = "/orders";
|
||||
|
@ -25,7 +26,7 @@ export enum OrderListUrlFiltersWithMultipleValuesEnum {
|
|||
}
|
||||
export type OrderListUrlFilters = Filters<OrderListUrlFiltersEnum> &
|
||||
FiltersWithMultipleValues<OrderListUrlFiltersWithMultipleValuesEnum>;
|
||||
export type OrderListUrlDialog = "cancel" | "save-search" | "delete-search";
|
||||
export type OrderListUrlDialog = "cancel" | TabActionDialog;
|
||||
export type OrderListUrlQueryParams = BulkAction &
|
||||
Dialog<OrderListUrlDialog> &
|
||||
OrderListUrlFilters &
|
||||
|
|
|
@ -236,7 +236,7 @@ export const OrderList: React.StatelessComponent<OrderListProps> = ({
|
|||
onFilterDelete={() => openModal("delete-search")}
|
||||
onTabChange={handleTabChange}
|
||||
initialSearch={params.email || ""}
|
||||
filterTabs={getFilterTabs()}
|
||||
filterTabs={getFilterTabs().map(tab => tab.name)}
|
||||
onAll={() =>
|
||||
changeFilters({
|
||||
status: undefined
|
||||
|
|
|
@ -5,11 +5,10 @@ import { FieldType, IFilter } from "@saleor/components/Filter";
|
|||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import { FilterProps } from "@saleor/types";
|
||||
import { StockAvailability } from "@saleor/types/globalTypes";
|
||||
import { ProductListUrlFilters } from "../../urls";
|
||||
|
||||
type ProductListFilterProps = FilterProps<
|
||||
ProductListUrlFilters,
|
||||
ProductFilterKeys
|
||||
type ProductListFilterProps = Omit<
|
||||
FilterProps,
|
||||
"allTabLabel" | "filterLabel" | "searchPlaceholder"
|
||||
>;
|
||||
|
||||
export enum ProductFilterKeys {
|
||||
|
@ -133,7 +132,22 @@ const ProductListFilter: React.FC<ProductListFilterProps> = props => {
|
|||
}
|
||||
];
|
||||
|
||||
return <FilterBar {...props} filterMenu={filterMenu} />;
|
||||
return (
|
||||
<FilterBar
|
||||
{...props}
|
||||
allTabLabel={intl.formatMessage({
|
||||
defaultMessage: "All Products",
|
||||
description: "tab name"
|
||||
})}
|
||||
filterMenu={filterMenu}
|
||||
filterLabel={intl.formatMessage({
|
||||
defaultMessage: "Select all products where:"
|
||||
})}
|
||||
searchPlaceholder={intl.formatMessage({
|
||||
defaultMessage: "Search Products..."
|
||||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
ProductListFilter.displayName = "ProductListFilter";
|
||||
export default ProductListFilter;
|
||||
|
|
|
@ -24,14 +24,13 @@ import {
|
|||
ListActions,
|
||||
PageListProps
|
||||
} from "@saleor/types";
|
||||
import { ProductListUrlFilters } from "../../urls";
|
||||
import ProductList from "../ProductList";
|
||||
import ProductListFilter, { ProductFilterKeys } from "../ProductListFilter";
|
||||
|
||||
export interface ProductListPageProps
|
||||
extends PageListProps<ProductListColumns>,
|
||||
ListActions,
|
||||
FilterPageProps<ProductListUrlFilters, ProductFilterKeys>,
|
||||
FilterPageProps,
|
||||
FetchMoreProps {
|
||||
availableInGridAttributes: AvailableInGridAttributes_availableInGrid_edges_node[];
|
||||
currencySymbol: string;
|
||||
|
@ -52,13 +51,13 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
currentTab,
|
||||
defaultSettings,
|
||||
filtersList,
|
||||
filterTabs,
|
||||
gridAttributes,
|
||||
availableInGridAttributes,
|
||||
hasMore,
|
||||
initialSearch,
|
||||
loading,
|
||||
settings,
|
||||
tabs,
|
||||
totalGridAttributes,
|
||||
onAdd,
|
||||
onAll,
|
||||
|
@ -137,21 +136,11 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
</PageHeader>
|
||||
<Card>
|
||||
<ProductListFilter
|
||||
allTabLabel={intl.formatMessage({
|
||||
defaultMessage: "All Products",
|
||||
description: "tab name"
|
||||
})}
|
||||
currencySymbol={currencySymbol}
|
||||
currentTab={currentTab}
|
||||
filterLabel={intl.formatMessage({
|
||||
defaultMessage: "Select all products where:"
|
||||
})}
|
||||
filterTabs={filterTabs}
|
||||
filtersList={filtersList}
|
||||
initialSearch={initialSearch}
|
||||
searchPlaceholder={intl.formatMessage({
|
||||
defaultMessage: "Search Products..."
|
||||
})}
|
||||
tabs={tabs}
|
||||
onAll={onAll}
|
||||
onSearchChange={onSearchChange}
|
||||
onFilterAdd={onFilterAdd}
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
import { stringify as stringifyQs } from "qs";
|
||||
import urlJoin from "url-join";
|
||||
|
||||
import { ActiveTab, BulkAction, Dialog, Filters, Pagination } from "../types";
|
||||
import {
|
||||
ActiveTab,
|
||||
BulkAction,
|
||||
Dialog,
|
||||
Filters,
|
||||
Pagination,
|
||||
TabActionDialog
|
||||
} from "../types";
|
||||
|
||||
const productSection = "/products/";
|
||||
|
||||
|
@ -13,8 +20,7 @@ export type ProductListUrlDialog =
|
|||
| "publish"
|
||||
| "unpublish"
|
||||
| "delete"
|
||||
| "save-search"
|
||||
| "delete-search";
|
||||
| TabActionDialog;
|
||||
export enum ProductListUrlFiltersEnum {
|
||||
isPublished = "isPublished",
|
||||
priceFrom = "priceFrom",
|
||||
|
|
|
@ -355,7 +355,7 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
|||
onFilterDelete={() => openModal("delete-search")}
|
||||
onTabChange={handleTabChange}
|
||||
initialSearch={params.query || ""}
|
||||
filterTabs={getFilterTabs()}
|
||||
tabs={getFilterTabs().map(tab => tab.name)}
|
||||
/>
|
||||
<ActionDialog
|
||||
open={params.action === "delete"}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { defineMessages, IntlShape } from "react-intl";
|
||||
|
||||
import { FilterContentSubmitData } from "../../../components/Filter";
|
||||
import { Filter } from "../../../components/TableFilter";
|
||||
import {
|
||||
|
|
37
src/types.ts
37
src/types.ts
|
@ -2,7 +2,6 @@ import { MutationResult } from "react-apollo";
|
|||
|
||||
import { FilterContentSubmitData } from "./components/Filter";
|
||||
import { Filter } from "./components/TableFilter";
|
||||
import { GetFilterTabsOutput } from "./utils/filters";
|
||||
|
||||
export interface UserError {
|
||||
field: string;
|
||||
|
@ -65,24 +64,32 @@ export interface PageListProps<TColumns extends string = string>
|
|||
defaultSettings?: ListSettings<TColumns>;
|
||||
onAdd: () => void;
|
||||
}
|
||||
export interface FilterPageProps<TUrlFilters, TFilterKeys> {
|
||||
currencySymbol: string;
|
||||
currentTab: number;
|
||||
filterTabs: GetFilterTabsOutput<TUrlFilters>;
|
||||
filtersList: Filter[];
|
||||
|
||||
export interface SearchPageProps {
|
||||
initialSearch: string;
|
||||
onAll: () => void;
|
||||
onSearchChange: (value: string) => void;
|
||||
onFilterAdd: (filter: FilterContentSubmitData<TFilterKeys>) => void;
|
||||
onFilterDelete: () => void;
|
||||
onFilterSave: () => void;
|
||||
onTabChange: (tab: number) => void;
|
||||
}
|
||||
export interface FilterProps<TUrlFilters, TFilterKeys>
|
||||
extends FilterPageProps<TUrlFilters, TFilterKeys> {
|
||||
export interface FilterPageProps extends SearchPageProps, TabPageProps {
|
||||
currencySymbol: string;
|
||||
filtersList: Filter[];
|
||||
onFilterAdd: (filter: FilterContentSubmitData) => void;
|
||||
}
|
||||
|
||||
export interface SearchProps {
|
||||
searchPlaceholder: string;
|
||||
}
|
||||
export interface FilterProps extends FilterPageProps, SearchProps {
|
||||
allTabLabel: string;
|
||||
filterLabel: string;
|
||||
searchPlaceholder: string;
|
||||
}
|
||||
|
||||
export interface TabPageProps {
|
||||
currentTab: number;
|
||||
tabs: string[];
|
||||
onAll: () => void;
|
||||
onTabChange: (tab: number) => void;
|
||||
onTabDelete: () => void;
|
||||
onTabSave: () => void;
|
||||
}
|
||||
|
||||
export interface PartialMutationProviderOutput<
|
||||
|
@ -134,3 +141,5 @@ export interface FetchMoreProps {
|
|||
hasMore: boolean;
|
||||
onFetchMore: () => void;
|
||||
}
|
||||
|
||||
export type TabActionDialog = "save-search" | "delete-search";
|
||||
|
|
Loading…
Reference in a new issue