Split filters, searches and tabs

This commit is contained in:
dominik-zeglen 2019-09-10 17:14:11 +02:00
parent f4e3149f89
commit 544d13754a
16 changed files with 392 additions and 178 deletions

View 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;

View file

@ -6,9 +6,8 @@ import Debounce from "../Debounce";
import { IFilter } from "../Filter/types"; import { IFilter } from "../Filter/types";
import FilterTabs, { FilterChips, FilterTab } from "../TableFilter"; import FilterTabs, { FilterChips, FilterTab } from "../TableFilter";
export interface FilterBarProps<TUrlFilters = object, TFilterKeys = any> export interface FilterBarProps extends FilterProps {
extends FilterProps<TUrlFilters, TFilterKeys> { filterMenu: IFilter;
filterMenu: IFilter<TFilterKeys>;
} }
const FilterBar: React.FC<FilterBarProps> = ({ const FilterBar: React.FC<FilterBarProps> = ({
@ -16,32 +15,32 @@ const FilterBar: React.FC<FilterBarProps> = ({
currencySymbol, currencySymbol,
filterLabel, filterLabel,
filtersList, filtersList,
filterTabs,
filterMenu, filterMenu,
currentTab, currentTab,
initialSearch, initialSearch,
searchPlaceholder, searchPlaceholder,
tabs,
onAll, onAll,
onSearchChange, onSearchChange,
onFilterAdd, onFilterAdd,
onFilterSave,
onTabChange, onTabChange,
onFilterDelete onTabDelete,
onTabSave
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const [search, setSearch] = React.useState(initialSearch); const [search, setSearch] = React.useState(initialSearch);
React.useEffect(() => setSearch(initialSearch), [currentTab, initialSearch]); React.useEffect(() => setSearch(initialSearch), [currentTab, initialSearch]);
const isCustom = currentTab === filterTabs.length + 1; const isCustom = currentTab === tabs.length + 1;
return ( return (
<> <>
<FilterTabs currentTab={currentTab}> <FilterTabs currentTab={currentTab}>
<FilterTab label={allTabLabel} onClick={onAll} /> <FilterTab label={allTabLabel} onClick={onAll} />
{filterTabs.map((tab, tabIndex) => ( {tabs.map((tab, tabIndex) => (
<FilterTab <FilterTab
onClick={() => onTabChange(tabIndex + 1)} onClick={() => onTabChange(tabIndex + 1)}
label={tab.name} label={tab}
key={tabIndex} key={tabIndex}
/> />
))} ))}
@ -72,9 +71,9 @@ const FilterBar: React.FC<FilterBarProps> = ({
search={search} search={search}
onSearchChange={handleSearchChange} onSearchChange={handleSearchChange}
onFilterAdd={onFilterAdd} onFilterAdd={onFilterAdd}
onFilterSave={onFilterSave} onFilterSave={onTabDelete}
isCustomSearch={isCustom} isCustomSearch={isCustom}
onFilterDelete={onFilterDelete} onFilterDelete={onTabSave}
/> />
); );
}} }}

View 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;

View file

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

View file

@ -1,14 +1,14 @@
import ButtonBase from "@material-ui/core/ButtonBase"; import ButtonBase from "@material-ui/core/ButtonBase";
import { Theme } from "@material-ui/core/styles"; import { Theme } from "@material-ui/core/styles";
import { fade } from "@material-ui/core/styles/colorManipulator"; import { fade } from "@material-ui/core/styles/colorManipulator";
import TextField, { TextFieldProps } from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import ClearIcon from "@material-ui/icons/Clear"; 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 React from "react";
import { FormattedMessage } from "react-intl"; 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 Hr from "../Hr";
import Link from "../Link"; import Link from "../Link";
@ -17,104 +17,68 @@ export interface Filter {
onClick: () => void; 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( const useStyles = makeStyles(
(theme: Theme) => (theme: Theme) => ({
createStyles({ filterButton: {
actionContainer: { alignItems: "center",
display: "flex", backgroundColor: fade(theme.palette.primary.main, 0.8),
flexWrap: "wrap", borderRadius: "19px",
padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 3}px ${ display: "flex",
theme.spacing.unit height: "38px",
}px ${theme.spacing.unit * 3}px` justifyContent: "space-around",
margin: `0 ${theme.spacing.unit * 2}px ${theme.spacing.unit}px`,
marginLeft: 0,
padding: "0 16px"
},
filterChipContainer: {
display: "flex",
flex: 1,
flexWrap: "wrap"
},
filterContainer: {
"& a": {
paddingBottom: 10
}, },
filterButton: { borderBottom: `1px solid ${theme.palette.divider}`,
alignItems: "center", display: "flex",
backgroundColor: fade(theme.palette.primary.main, 0.8), marginTop: theme.spacing.unit,
borderRadius: "19px", padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit}px`
display: "flex", },
height: "38px", filterIcon: {
justifyContent: "space-around", color: theme.palette.common.white,
margin: `0 ${theme.spacing.unit * 2}px ${theme.spacing.unit}px`, height: 16,
marginLeft: 0, width: 16
padding: "0 16px" },
}, filterIconContainer: {
filterChipContainer: { WebkitAppearance: "none",
display: "flex", background: "transparent",
flex: 1, border: "none",
flexWrap: "wrap" borderRadius: "100%",
}, cursor: "pointer",
filterContainer: { height: 32,
"& a": { marginRight: -13,
paddingBottom: 10 padding: 8,
}, width: 32
borderBottom: `1px solid ${theme.palette.divider}`, },
display: "flex", filterLabel: {
marginTop: theme.spacing.unit, marginBottom: theme.spacing.unit
padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit}px` },
}, filterText: {
filterIcon: { color: theme.palette.common.white,
color: theme.palette.common.white, fontSize: 14,
height: 16, fontWeight: 400 as 400,
width: 16 lineHeight: "38px"
}, }
filterIconContainer: { }),
WebkitAppearance: "none",
background: "transparent",
border: "none",
borderRadius: "100%",
cursor: "pointer",
height: 32,
marginRight: -13,
padding: 8,
width: 32
},
filterLabel: {
marginBottom: theme.spacing.unit
},
filterText: {
color: theme.palette.common.white,
fontSize: 14,
fontWeight: 400 as 400,
lineHeight: "38px"
}
}),
{ {
name: "FilterChips" name: "FilterChips"
} }
); );
interface FilterChipProps<TFilterKeys = string> { interface FilterChipProps extends FilterActionsProps {
currencySymbol: string;
menu: IFilter<TFilterKeys>;
filtersList: Filter[]; filtersList: Filter[];
filterLabel: string;
placeholder: string;
search: string; search: string;
isCustomSearch: boolean; isCustomSearch: boolean;
onSearchChange: (event: React.ChangeEvent<any>) => void;
onFilterAdd: (filter: FilterContentSubmitData<TFilterKeys>) => void;
onFilterDelete: () => void; onFilterDelete: () => void;
onFilterSave: () => void; onFilterSave: () => void;
} }
@ -137,20 +101,15 @@ export const FilterChips: React.FC<FilterChipProps> = ({
return ( return (
<> <>
<div className={classes.actionContainer}> <FilterActions
<Filter currencySymbol={currencySymbol}
currencySymbol={currencySymbol} menu={menu}
menu={menu} filterLabel={filterLabel}
filterLabel={filterLabel} placeholder={placeholder}
onFilterAdd={onFilterAdd} search={search}
/> onSearchChange={onSearchChange}
<Search onFilterAdd={onFilterAdd}
fullWidth />
placeholder={placeholder}
value={search}
onChange={onSearchChange}
/>
</div>
{search || (filtersList && filtersList.length) ? ( {search || (filtersList && filtersList.length) ? (
<div className={classes.filterContainer}> <div className={classes.filterContainer}>
<div className={classes.filterChipContainer}> <div className={classes.filterChipContainer}>

View file

@ -3,7 +3,9 @@ import {
FetchMoreProps, FetchMoreProps,
FilterPageProps, FilterPageProps,
ListActions, ListActions,
PageListProps PageListProps,
SearchPageProps,
TabPageProps
} from "./types"; } from "./types";
const pageInfo = { const pageInfo = {
@ -46,23 +48,26 @@ export const countries = [
{ code: "AS", label: "American Samoa" } { code: "AS", label: "American Samoa" }
]; ];
export const filterPageProps: FilterPageProps<{}, unknown> = { export const tabPageProps: TabPageProps = {
currencySymbol: "USD",
currentTab: 0, currentTab: 0,
filterTabs: [
{
data: {},
name: "Tab X"
}
],
filtersList: [],
initialSearch: "",
onAll: () => undefined, onAll: () => undefined,
onFilterAdd: () => undefined, onTabChange: () => undefined,
onFilterDelete: () => undefined, onTabDelete: () => undefined,
onFilterSave: () => undefined, onTabSave: () => undefined,
onSearchChange: () => undefined, tabs: ["Tab X"]
onTabChange: () => undefined };
export const searchPageProps: SearchPageProps = {
initialSearch: "",
onSearchChange: () => undefined
};
export const filterPageProps: FilterPageProps = {
...searchPageProps,
...tabPageProps,
currencySymbol: "USD",
filtersList: [],
onFilterAdd: () => undefined
}; };
export const filters: Filter[] = [ export const filters: Filter[] = [

View file

@ -8,9 +8,8 @@ import FilterBar from "@saleor/components/FilterBar";
import TimezoneContext from "@saleor/components/Timezone"; import TimezoneContext from "@saleor/components/Timezone";
import { FilterProps } from "../../../types"; import { FilterProps } from "../../../types";
import { OrderStatusFilter } from "../../../types/globalTypes"; import { OrderStatusFilter } from "../../../types/globalTypes";
import { OrderListUrlFilters } from "../../urls";
type OrderListFilterProps = FilterProps<OrderListUrlFilters, OrderFilterKeys>; type OrderListFilterProps = FilterProps;
export enum OrderFilterKeys { export enum OrderFilterKeys {
date = "date", date = "date",

View file

@ -10,14 +10,13 @@ import { sectionNames } from "@saleor/intl";
import { OrderFilterKeys } from "@saleor/orders/components/OrderListFilter"; import { OrderFilterKeys } from "@saleor/orders/components/OrderListFilter";
import { FilterPageProps, ListActions, PageListProps } from "@saleor/types"; import { FilterPageProps, ListActions, PageListProps } from "@saleor/types";
import { OrderList_orders_edges_node } from "../../types/OrderList"; import { OrderList_orders_edges_node } from "../../types/OrderList";
import { OrderListUrlFilters } from "../../urls";
import OrderList from "../OrderList"; import OrderList from "../OrderList";
import OrderListFilter from "../OrderListFilter"; import OrderListFilter from "../OrderListFilter";
export interface OrderListPageProps export interface OrderListPageProps
extends PageListProps, extends PageListProps,
ListActions, ListActions,
FilterPageProps<OrderListUrlFilters, OrderFilterKeys> { FilterPageProps {
orders: OrderList_orders_edges_node[]; orders: OrderList_orders_edges_node[];
} }
@ -25,8 +24,8 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
currencySymbol, currencySymbol,
currentTab, currentTab,
filtersList, filtersList,
filterTabs,
initialSearch, initialSearch,
tabs,
onAdd, onAdd,
onAll, onAll,
onSearchChange, onSearchChange,
@ -59,7 +58,7 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
filterLabel={intl.formatMessage({ filterLabel={intl.formatMessage({
defaultMessage: "Select all orders where:" defaultMessage: "Select all orders where:"
})} })}
filterTabs={filterTabs} filterTabs={tabs}
filtersList={filtersList} filtersList={filtersList}
initialSearch={initialSearch} initialSearch={initialSearch}
searchPlaceholder={intl.formatMessage({ searchPlaceholder={intl.formatMessage({

View file

@ -8,7 +8,8 @@ import {
Filters, Filters,
FiltersWithMultipleValues, FiltersWithMultipleValues,
Pagination, Pagination,
SingleAction SingleAction,
TabActionDialog
} from "../types"; } from "../types";
const orderSectionUrl = "/orders"; const orderSectionUrl = "/orders";
@ -25,7 +26,7 @@ export enum OrderListUrlFiltersWithMultipleValuesEnum {
} }
export type OrderListUrlFilters = Filters<OrderListUrlFiltersEnum> & export type OrderListUrlFilters = Filters<OrderListUrlFiltersEnum> &
FiltersWithMultipleValues<OrderListUrlFiltersWithMultipleValuesEnum>; FiltersWithMultipleValues<OrderListUrlFiltersWithMultipleValuesEnum>;
export type OrderListUrlDialog = "cancel" | "save-search" | "delete-search"; export type OrderListUrlDialog = "cancel" | TabActionDialog;
export type OrderListUrlQueryParams = BulkAction & export type OrderListUrlQueryParams = BulkAction &
Dialog<OrderListUrlDialog> & Dialog<OrderListUrlDialog> &
OrderListUrlFilters & OrderListUrlFilters &

View file

@ -236,7 +236,7 @@ export const OrderList: React.StatelessComponent<OrderListProps> = ({
onFilterDelete={() => openModal("delete-search")} onFilterDelete={() => openModal("delete-search")}
onTabChange={handleTabChange} onTabChange={handleTabChange}
initialSearch={params.email || ""} initialSearch={params.email || ""}
filterTabs={getFilterTabs()} filterTabs={getFilterTabs().map(tab => tab.name)}
onAll={() => onAll={() =>
changeFilters({ changeFilters({
status: undefined status: undefined

View file

@ -5,11 +5,10 @@ import { FieldType, IFilter } from "@saleor/components/Filter";
import FilterBar from "@saleor/components/FilterBar"; import FilterBar from "@saleor/components/FilterBar";
import { FilterProps } from "@saleor/types"; import { FilterProps } from "@saleor/types";
import { StockAvailability } from "@saleor/types/globalTypes"; import { StockAvailability } from "@saleor/types/globalTypes";
import { ProductListUrlFilters } from "../../urls";
type ProductListFilterProps = FilterProps< type ProductListFilterProps = Omit<
ProductListUrlFilters, FilterProps,
ProductFilterKeys "allTabLabel" | "filterLabel" | "searchPlaceholder"
>; >;
export enum ProductFilterKeys { 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"; ProductListFilter.displayName = "ProductListFilter";
export default ProductListFilter; export default ProductListFilter;

View file

@ -24,14 +24,13 @@ import {
ListActions, ListActions,
PageListProps PageListProps
} from "@saleor/types"; } from "@saleor/types";
import { ProductListUrlFilters } from "../../urls";
import ProductList from "../ProductList"; import ProductList from "../ProductList";
import ProductListFilter, { ProductFilterKeys } from "../ProductListFilter"; import ProductListFilter, { ProductFilterKeys } from "../ProductListFilter";
export interface ProductListPageProps export interface ProductListPageProps
extends PageListProps<ProductListColumns>, extends PageListProps<ProductListColumns>,
ListActions, ListActions,
FilterPageProps<ProductListUrlFilters, ProductFilterKeys>, FilterPageProps,
FetchMoreProps { FetchMoreProps {
availableInGridAttributes: AvailableInGridAttributes_availableInGrid_edges_node[]; availableInGridAttributes: AvailableInGridAttributes_availableInGrid_edges_node[];
currencySymbol: string; currencySymbol: string;
@ -52,13 +51,13 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
currentTab, currentTab,
defaultSettings, defaultSettings,
filtersList, filtersList,
filterTabs,
gridAttributes, gridAttributes,
availableInGridAttributes, availableInGridAttributes,
hasMore, hasMore,
initialSearch, initialSearch,
loading, loading,
settings, settings,
tabs,
totalGridAttributes, totalGridAttributes,
onAdd, onAdd,
onAll, onAll,
@ -137,21 +136,11 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
</PageHeader> </PageHeader>
<Card> <Card>
<ProductListFilter <ProductListFilter
allTabLabel={intl.formatMessage({
defaultMessage: "All Products",
description: "tab name"
})}
currencySymbol={currencySymbol} currencySymbol={currencySymbol}
currentTab={currentTab} currentTab={currentTab}
filterLabel={intl.formatMessage({
defaultMessage: "Select all products where:"
})}
filterTabs={filterTabs}
filtersList={filtersList} filtersList={filtersList}
initialSearch={initialSearch} initialSearch={initialSearch}
searchPlaceholder={intl.formatMessage({ tabs={tabs}
defaultMessage: "Search Products..."
})}
onAll={onAll} onAll={onAll}
onSearchChange={onSearchChange} onSearchChange={onSearchChange}
onFilterAdd={onFilterAdd} onFilterAdd={onFilterAdd}

View file

@ -1,7 +1,14 @@
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, Filters, Pagination } from "../types"; import {
ActiveTab,
BulkAction,
Dialog,
Filters,
Pagination,
TabActionDialog
} from "../types";
const productSection = "/products/"; const productSection = "/products/";
@ -13,8 +20,7 @@ export type ProductListUrlDialog =
| "publish" | "publish"
| "unpublish" | "unpublish"
| "delete" | "delete"
| "save-search" | TabActionDialog;
| "delete-search";
export enum ProductListUrlFiltersEnum { export enum ProductListUrlFiltersEnum {
isPublished = "isPublished", isPublished = "isPublished",
priceFrom = "priceFrom", priceFrom = "priceFrom",

View file

@ -355,7 +355,7 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
onFilterDelete={() => openModal("delete-search")} onFilterDelete={() => openModal("delete-search")}
onTabChange={handleTabChange} onTabChange={handleTabChange}
initialSearch={params.query || ""} initialSearch={params.query || ""}
filterTabs={getFilterTabs()} tabs={getFilterTabs().map(tab => tab.name)}
/> />
<ActionDialog <ActionDialog
open={params.action === "delete"} open={params.action === "delete"}

View file

@ -1,4 +1,5 @@
import { defineMessages, IntlShape } from "react-intl"; import { defineMessages, IntlShape } from "react-intl";
import { FilterContentSubmitData } from "../../../components/Filter"; import { FilterContentSubmitData } from "../../../components/Filter";
import { Filter } from "../../../components/TableFilter"; import { Filter } from "../../../components/TableFilter";
import { import {

View file

@ -2,7 +2,6 @@ import { MutationResult } from "react-apollo";
import { FilterContentSubmitData } from "./components/Filter"; import { FilterContentSubmitData } from "./components/Filter";
import { Filter } from "./components/TableFilter"; import { Filter } from "./components/TableFilter";
import { GetFilterTabsOutput } from "./utils/filters";
export interface UserError { export interface UserError {
field: string; field: string;
@ -65,24 +64,32 @@ export interface PageListProps<TColumns extends string = string>
defaultSettings?: ListSettings<TColumns>; defaultSettings?: ListSettings<TColumns>;
onAdd: () => void; onAdd: () => void;
} }
export interface FilterPageProps<TUrlFilters, TFilterKeys> {
currencySymbol: string; export interface SearchPageProps {
currentTab: number;
filterTabs: GetFilterTabsOutput<TUrlFilters>;
filtersList: Filter[];
initialSearch: string; initialSearch: string;
onAll: () => void;
onSearchChange: (value: string) => void; onSearchChange: (value: string) => void;
onFilterAdd: (filter: FilterContentSubmitData<TFilterKeys>) => void;
onFilterDelete: () => void;
onFilterSave: () => void;
onTabChange: (tab: number) => void;
} }
export interface FilterProps<TUrlFilters, TFilterKeys> export interface FilterPageProps extends SearchPageProps, TabPageProps {
extends FilterPageProps<TUrlFilters, TFilterKeys> { currencySymbol: string;
filtersList: Filter[];
onFilterAdd: (filter: FilterContentSubmitData) => void;
}
export interface SearchProps {
searchPlaceholder: string;
}
export interface FilterProps extends FilterPageProps, SearchProps {
allTabLabel: string; allTabLabel: string;
filterLabel: 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< export interface PartialMutationProviderOutput<
@ -134,3 +141,5 @@ export interface FetchMoreProps {
hasMore: boolean; hasMore: boolean;
onFetchMore: () => void; onFetchMore: () => void;
} }
export type TabActionDialog = "save-search" | "delete-search";