Add filters to service list

This commit is contained in:
dominik-zeglen 2020-01-10 16:05:32 +01:00
parent c90c58473f
commit a4a9703abd
7 changed files with 161 additions and 50 deletions

View file

@ -209,7 +209,7 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
</Button> </Button>
} }
onSearchChange={handleSearchChange} onSearchChange={handleSearchChange}
onFilterChange={filter => changeFilters(filter)} onFilterChange={changeFilters}
onTabSave={() => openModal("save-search")} onTabSave={() => openModal("save-search")}
onTabDelete={() => openModal("delete-search")} onTabDelete={() => openModal("delete-search")}
onTabChange={handleTabChange} onTabChange={handleTabChange}

View file

@ -6,21 +6,26 @@ import { FormattedMessage, useIntl } from "react-intl";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
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 FilterBar from "@saleor/components/FilterBar";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { import {
PageListProps, PageListProps,
SearchPageProps,
TabPageProps, TabPageProps,
SortPage SortPage,
FilterPageProps
} from "@saleor/types"; } from "@saleor/types";
import { ServiceListUrlSortField } from "@saleor/services/urls"; import { ServiceListUrlSortField } from "@saleor/services/urls";
import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList";
import ServiceList from "../ServiceList"; import ServiceList from "../ServiceList";
import {
ServiceFilterKeys,
ServiceListFilterOpts,
createFilterStructure
} from "./filters";
export interface ServiceListPageProps export interface ServiceListPageProps
extends PageListProps, extends PageListProps,
SearchPageProps, FilterPageProps<ServiceFilterKeys, ServiceListFilterOpts>,
SortPage<ServiceListUrlSortField>, SortPage<ServiceListUrlSortField>,
TabPageProps { TabPageProps {
services: ServiceList_serviceAccounts_edges_node[]; services: ServiceList_serviceAccounts_edges_node[];
@ -29,11 +34,14 @@ export interface ServiceListPageProps
} }
const ServiceListPage: React.FC<ServiceListPageProps> = ({ const ServiceListPage: React.FC<ServiceListPageProps> = ({
currencySymbol,
currentTab, currentTab,
filterOpts,
initialSearch, initialSearch,
onAdd, onAdd,
onAll, onAll,
onBack, onBack,
onFilterChange,
onSearchChange, onSearchChange,
onTabChange, onTabChange,
onTabDelete, onTabDelete,
@ -43,6 +51,8 @@ const ServiceListPage: React.FC<ServiceListPageProps> = ({
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const structure = createFilterStructure(intl, filterOpts);
return ( return (
<Container> <Container>
<AppHeader onBack={onBack}> <AppHeader onBack={onBack}>
@ -57,11 +67,13 @@ const ServiceListPage: React.FC<ServiceListPageProps> = ({
</Button> </Button>
</PageHeader> </PageHeader>
<Card> <Card>
<SearchBar <FilterBar
allTabLabel={intl.formatMessage({ allTabLabel={intl.formatMessage({
defaultMessage: "All Service Accounts", defaultMessage: "All Service Accounts",
description: "tab name" description: "tab name"
})} })}
currencySymbol={currencySymbol}
filterStructure={structure}
currentTab={currentTab} currentTab={currentTab}
initialSearch={initialSearch} initialSearch={initialSearch}
searchPlaceholder={intl.formatMessage({ searchPlaceholder={intl.formatMessage({
@ -69,6 +81,7 @@ const ServiceListPage: React.FC<ServiceListPageProps> = ({
})} })}
tabs={tabs} tabs={tabs}
onAll={onAll} onAll={onAll}
onFilterChange={onFilterChange}
onSearchChange={onSearchChange} onSearchChange={onSearchChange}
onTabChange={onTabChange} onTabChange={onTabChange}
onTabDelete={onTabDelete} onTabDelete={onTabDelete}

View file

@ -0,0 +1,47 @@
import { defineMessages, IntlShape } from "react-intl";
import { FilterOpts } from "@saleor/types";
import { IFilter } from "@saleor/components/Filter";
import { createBooleanField } from "@saleor/utils/filters/fields";
import { commonMessages } from "@saleor/intl";
export enum ServiceFilterKeys {
active = "active"
}
export interface ServiceListFilterOpts {
isActive: FilterOpts<boolean>;
}
const messages = defineMessages({
active: {
defaultMessage: "Active",
description: "service account"
},
deactivated: {
defaultMessage: "Inactive",
description: "service account"
}
});
export function createFilterStructure(
intl: IntlShape,
opts: ServiceListFilterOpts
): IFilter<ServiceFilterKeys> {
return [
{
...createBooleanField(
ServiceFilterKeys.active,
intl.formatMessage(commonMessages.status),
opts.isActive.value,
{
negative: intl.formatMessage(messages.deactivated),
positive: intl.formatMessage(messages.active)
}
),
active: opts.isActive.active
}
];
}
export default messages;

View file

@ -15,6 +15,7 @@ export const serviceSection = "/services/";
export const serviceListPath = serviceSection; export const serviceListPath = serviceSection;
export enum ServiceListUrlFiltersEnum { export enum ServiceListUrlFiltersEnum {
active = "active",
query = "query" query = "query"
} }
export type ServiceListUrlFilters = Filters<ServiceListUrlFiltersEnum>; export type ServiceListUrlFilters = Filters<ServiceListUrlFiltersEnum>;

View file

@ -20,6 +20,8 @@ import { ListViews } from "@saleor/types";
import { getSortParams } from "@saleor/utils/sort"; import { getSortParams } from "@saleor/utils/sort";
import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createSortHandler from "@saleor/utils/handlers/sortHandler";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import useShop from "@saleor/hooks/useShop";
import createFilterHandlers from "@saleor/utils/handlers/filterHandlers";
import ServiceDeleteDialog from "../../components/ServiceDeleteDialog"; import ServiceDeleteDialog from "../../components/ServiceDeleteDialog";
import ServiceListPage from "../../components/ServiceListPage"; import ServiceListPage from "../../components/ServiceListPage";
import { useServiceListQuery } from "../../queries"; import { useServiceListQuery } from "../../queries";
@ -27,7 +29,6 @@ import {
serviceAddUrl, serviceAddUrl,
serviceListUrl, serviceListUrl,
ServiceListUrlDialog, ServiceListUrlDialog,
ServiceListUrlFilters,
ServiceListUrlQueryParams, ServiceListUrlQueryParams,
serviceUrl serviceUrl
} from "../../urls"; } from "../../urls";
@ -36,9 +37,11 @@ import {
deleteFilterTab, deleteFilterTab,
getActiveFilters, getActiveFilters,
getFilterTabs, getFilterTabs,
getFilterQueryParam,
getFilterVariables, getFilterVariables,
saveFilterTab saveFilterTab,
} from "./filter"; getFilterOpts
} from "./filters";
import { getSortQueryVariables } from "./sort"; import { getSortQueryVariables } from "./sort";
interface ServiceListProps { interface ServiceListProps {
@ -49,6 +52,7 @@ export const ServiceList: React.FC<ServiceListProps> = ({ params }) => {
const navigate = useNavigator(); const navigate = useNavigator();
const notify = useNotifier(); const notify = useNotifier();
const paginate = usePaginator(); const paginate = usePaginator();
const shop = useShop();
const { updateListSettings, settings } = useListSettings( const { updateListSettings, settings } = useListSettings(
ListViews.STAFF_MEMBERS_LIST ListViews.STAFF_MEMBERS_LIST
); );
@ -77,14 +81,16 @@ export const ServiceList: React.FC<ServiceListProps> = ({ params }) => {
: 0 : 0
: parseInt(params.activeTab, 0); : parseInt(params.activeTab, 0);
const changeFilterField = (filter: ServiceListUrlFilters) => const [
navigate( changeFilters,
serviceListUrl({ resetFilters,
...getActiveFilters(params), handleSearchChange
...filter, ] = createFilterHandlers({
activeTab: undefined createUrl: serviceListUrl,
}) getFilterQueryParam,
); navigate,
params
});
const [openModal, closeModal] = createDialogActionHandlers< const [openModal, closeModal] = createDialogActionHandlers<
ServiceListUrlDialog, ServiceListUrlDialog,
@ -129,6 +135,7 @@ export const ServiceList: React.FC<ServiceListProps> = ({ params }) => {
}; };
const handleSort = createSortHandler(navigate, serviceListUrl, params); const handleSort = createSortHandler(navigate, serviceListUrl, params);
const currencySymbol = maybe(() => shop.defaultCurrency, "USD");
return ( return (
<ServiceDeleteMutation onCompleted={onRemove}> <ServiceDeleteMutation onCompleted={onRemove}>
@ -143,10 +150,13 @@ export const ServiceList: React.FC<ServiceListProps> = ({ params }) => {
return ( return (
<> <>
<ServiceListPage <ServiceListPage
currencySymbol={currencySymbol}
currentTab={currentTab} currentTab={currentTab}
filterOpts={getFilterOpts(params)}
initialSearch={params.query || ""} initialSearch={params.query || ""}
onSearchChange={query => changeFilterField({ query })} onSearchChange={handleSearchChange}
onAll={() => navigate(serviceListUrl())} onFilterChange={changeFilters}
onAll={resetFilters}
onTabChange={handleTabChange} onTabChange={handleTabChange}
onTabDelete={() => openModal("delete-search")} onTabDelete={() => openModal("delete-search")}
onTabSave={() => openModal("save-search")} onTabSave={() => openModal("save-search")}

View file

@ -1,31 +0,0 @@
import { ServiceAccountFilterInput } from "@saleor/types/globalTypes";
import {
createFilterTabUtils,
createFilterUtils
} from "../../../utils/filters";
import {
ServiceListUrlFilters,
ServiceListUrlFiltersEnum,
ServiceListUrlQueryParams
} from "../../urls";
export const STAFF_FILTERS_KEY = "staffFilters";
export function getFilterVariables(
params: ServiceListUrlFilters
): ServiceAccountFilterInput {
return {
search: params.query
};
}
export const {
deleteFilterTab,
getFilterTabs,
saveFilterTab
} = createFilterTabUtils<ServiceListUrlFilters>(STAFF_FILTERS_KEY);
export const { areFiltersApplied, getActiveFilters } = createFilterUtils<
ServiceListUrlQueryParams,
ServiceListUrlFilters
>(ServiceListUrlFiltersEnum);

View file

@ -0,0 +1,71 @@
import { ServiceAccountFilterInput } from "@saleor/types/globalTypes";
import {
ServiceListFilterOpts,
ServiceFilterKeys
} from "@saleor/services/components/ServiceListPage/filters";
import { maybe, parseBoolean } from "@saleor/misc";
import { IFilterElement } from "@saleor/components/Filter";
import {
ServiceListUrlFilters,
ServiceListUrlFiltersEnum,
ServiceListUrlQueryParams
} from "../../urls";
import {
createFilterTabUtils,
createFilterUtils
} from "../../../utils/filters";
export const STAFF_FILTERS_KEY = "staffFilters";
export function getFilterOpts(
params: ServiceListUrlFilters
): ServiceListFilterOpts {
return {
isActive: {
active: maybe(() => params.active !== undefined, false),
value:
params.active !== undefined ? parseBoolean(params.active, true) : true
}
};
}
export function getFilterVariables(
params: ServiceListUrlFilters
): ServiceAccountFilterInput {
return {
isActive:
params.active !== undefined
? parseBoolean(params.active, true)
: undefined,
search: params.query
};
}
export function getFilterQueryParam(
filter: IFilterElement<ServiceFilterKeys>
): ServiceListUrlFilters {
const { active, name, value } = filter;
switch (name) {
case ServiceFilterKeys.active:
if (!active) {
return {
active: undefined
};
}
return {
active: value[0]
};
}
}
export const {
deleteFilterTab,
getFilterTabs,
saveFilterTab
} = createFilterTabUtils<ServiceListUrlFilters>(STAFF_FILTERS_KEY);
export const { areFiltersApplied, getActiveFilters } = createFilterUtils<
ServiceListUrlQueryParams,
ServiceListUrlFilters
>(ServiceListUrlFiltersEnum);