Add filters to service list
This commit is contained in:
parent
c90c58473f
commit
a4a9703abd
7 changed files with 161 additions and 50 deletions
|
@ -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}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
47
src/services/components/ServiceListPage/filters.ts
Normal file
47
src/services/components/ServiceListPage/filters.ts
Normal 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;
|
|
@ -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>;
|
||||||
|
|
|
@ -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")}
|
||||||
|
|
|
@ -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);
|
|
71
src/services/views/ServiceList/filters.ts
Normal file
71
src/services/views/ServiceList/filters.ts
Normal 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);
|
Loading…
Reference in a new issue