Add filters to staff member list
This commit is contained in:
parent
eab3d67502
commit
04e9e13c5a
7 changed files with 157 additions and 14 deletions
|
@ -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 {
|
||||||
ListProps,
|
ListProps,
|
||||||
SearchPageProps,
|
FilterPageProps,
|
||||||
TabPageProps,
|
TabPageProps,
|
||||||
SortPage
|
SortPage
|
||||||
} from "@saleor/types";
|
} from "@saleor/types";
|
||||||
import { StaffListUrlSortField } from "@saleor/staff/urls";
|
import { StaffListUrlSortField } from "@saleor/staff/urls";
|
||||||
|
import {
|
||||||
|
StaffFilterKeys,
|
||||||
|
createFilterStructure
|
||||||
|
} from "@saleor/staff/views/StaffList/filter";
|
||||||
|
import { StaffListFilterOpts } from "@saleor/staff/types";
|
||||||
import { StaffList_staffUsers_edges_node } from "../../types/StaffList";
|
import { StaffList_staffUsers_edges_node } from "../../types/StaffList";
|
||||||
import StaffList from "../StaffList/StaffList";
|
import StaffList from "../StaffList/StaffList";
|
||||||
|
|
||||||
export interface StaffListPageProps
|
export interface StaffListPageProps
|
||||||
extends ListProps,
|
extends ListProps,
|
||||||
SearchPageProps,
|
FilterPageProps<StaffFilterKeys, StaffListFilterOpts>,
|
||||||
SortPage<StaffListUrlSortField>,
|
SortPage<StaffListUrlSortField>,
|
||||||
TabPageProps {
|
TabPageProps {
|
||||||
staffMembers: StaffList_staffUsers_edges_node[];
|
staffMembers: StaffList_staffUsers_edges_node[];
|
||||||
|
@ -29,11 +34,14 @@ export interface StaffListPageProps
|
||||||
}
|
}
|
||||||
|
|
||||||
const StaffListPage: React.FC<StaffListPageProps> = ({
|
const StaffListPage: React.FC<StaffListPageProps> = ({
|
||||||
|
currencySymbol,
|
||||||
currentTab,
|
currentTab,
|
||||||
|
filterOpts,
|
||||||
initialSearch,
|
initialSearch,
|
||||||
onAdd,
|
onAdd,
|
||||||
onAll,
|
onAll,
|
||||||
onBack,
|
onBack,
|
||||||
|
onFilterChange,
|
||||||
onSearchChange,
|
onSearchChange,
|
||||||
onTabChange,
|
onTabChange,
|
||||||
onTabDelete,
|
onTabDelete,
|
||||||
|
@ -43,6 +51,8 @@ const StaffListPage: React.FC<StaffListPageProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const structure = createFilterStructure(intl, filterOpts);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
|
@ -57,18 +67,21 @@ const StaffListPage: React.FC<StaffListPageProps> = ({
|
||||||
</Button>
|
</Button>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<Card>
|
<Card>
|
||||||
<SearchBar
|
<FilterBar
|
||||||
allTabLabel={intl.formatMessage({
|
allTabLabel={intl.formatMessage({
|
||||||
defaultMessage: "All Staff Members",
|
defaultMessage: "All Staff Members",
|
||||||
description: "tab name"
|
description: "tab name"
|
||||||
})}
|
})}
|
||||||
|
currencySymbol={currencySymbol}
|
||||||
currentTab={currentTab}
|
currentTab={currentTab}
|
||||||
|
filterStructure={structure}
|
||||||
initialSearch={initialSearch}
|
initialSearch={initialSearch}
|
||||||
searchPlaceholder={intl.formatMessage({
|
searchPlaceholder={intl.formatMessage({
|
||||||
defaultMessage: "Search Staff Member"
|
defaultMessage: "Search Staff Member"
|
||||||
})}
|
})}
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
onAll={onAll}
|
onAll={onAll}
|
||||||
|
onFilterChange={onFilterChange}
|
||||||
onSearchChange={onSearchChange}
|
onSearchChange={onSearchChange}
|
||||||
onTabChange={onTabChange}
|
onTabChange={onTabChange}
|
||||||
onTabDelete={onTabDelete}
|
onTabDelete={onTabDelete}
|
||||||
|
|
6
src/staff/types.ts
Normal file
6
src/staff/types.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { FilterOpts } from "@saleor/types";
|
||||||
|
import { StaffMemberStatus } from "@saleor/types/globalTypes";
|
||||||
|
|
||||||
|
export interface StaffListFilterOpts {
|
||||||
|
status: FilterOpts<StaffMemberStatus>;
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ const staffSection = "/staff/";
|
||||||
|
|
||||||
export const staffListPath = staffSection;
|
export const staffListPath = staffSection;
|
||||||
export enum StaffListUrlFiltersEnum {
|
export enum StaffListUrlFiltersEnum {
|
||||||
|
status = "status",
|
||||||
query = "query"
|
query = "query"
|
||||||
}
|
}
|
||||||
export type StaffListUrlFilters = Filters<StaffListUrlFiltersEnum>;
|
export type StaffListUrlFilters = Filters<StaffListUrlFiltersEnum>;
|
||||||
|
|
|
@ -23,6 +23,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 { IFilter } from "@saleor/components/Filter";
|
||||||
|
import { getFilterQueryParams } from "@saleor/utils/filters";
|
||||||
import StaffAddMemberDialog, {
|
import StaffAddMemberDialog, {
|
||||||
FormData as AddStaffMemberForm
|
FormData as AddStaffMemberForm
|
||||||
} from "../../components/StaffAddMemberDialog";
|
} from "../../components/StaffAddMemberDialog";
|
||||||
|
@ -33,7 +35,6 @@ import { StaffMemberAdd } from "../../types/StaffMemberAdd";
|
||||||
import {
|
import {
|
||||||
staffListUrl,
|
staffListUrl,
|
||||||
StaffListUrlDialog,
|
StaffListUrlDialog,
|
||||||
StaffListUrlFilters,
|
|
||||||
StaffListUrlQueryParams,
|
StaffListUrlQueryParams,
|
||||||
staffMemberDetailsUrl
|
staffMemberDetailsUrl
|
||||||
} from "../../urls";
|
} from "../../urls";
|
||||||
|
@ -43,7 +44,10 @@ import {
|
||||||
getActiveFilters,
|
getActiveFilters,
|
||||||
getFilterTabs,
|
getFilterTabs,
|
||||||
getFilterVariables,
|
getFilterVariables,
|
||||||
saveFilterTab
|
saveFilterTab,
|
||||||
|
StaffFilterKeys,
|
||||||
|
getFilterQueryParam,
|
||||||
|
getFilterOpts
|
||||||
} from "./filter";
|
} from "./filter";
|
||||||
import { getSortQueryVariables } from "./sort";
|
import { getSortQueryVariables } from "./sort";
|
||||||
|
|
||||||
|
@ -62,6 +66,7 @@ export const StaffList: React.FC<StaffListProps> = ({ params }) => {
|
||||||
const shop = useShop();
|
const shop = useShop();
|
||||||
|
|
||||||
const paginationState = createPaginationState(settings.rowNumber, params);
|
const paginationState = createPaginationState(settings.rowNumber, params);
|
||||||
|
const currencySymbol = maybe(() => shop.defaultCurrency, "USD");
|
||||||
const queryVariables = React.useMemo(
|
const queryVariables = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
...paginationState,
|
...paginationState,
|
||||||
|
@ -84,15 +89,32 @@ export const StaffList: React.FC<StaffListProps> = ({ params }) => {
|
||||||
: 0
|
: 0
|
||||||
: parseInt(params.activeTab, 0);
|
: parseInt(params.activeTab, 0);
|
||||||
|
|
||||||
const changeFilterField = (filter: StaffListUrlFilters) =>
|
const changeFilters = (filter: IFilter<StaffFilterKeys>) =>
|
||||||
navigate(
|
navigate(
|
||||||
staffListUrl({
|
staffListUrl({
|
||||||
...getActiveFilters(params),
|
...params,
|
||||||
...filter,
|
...getFilterQueryParams(filter, getFilterQueryParam),
|
||||||
activeTab: undefined
|
activeTab: undefined
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const resetFilters = () =>
|
||||||
|
navigate(
|
||||||
|
staffListUrl({
|
||||||
|
asc: params.asc,
|
||||||
|
sort: params.sort
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSearchChange = (query: string) =>
|
||||||
|
navigate(
|
||||||
|
staffListUrl({
|
||||||
|
...params,
|
||||||
|
activeTab: undefined,
|
||||||
|
query
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const [openModal, closeModal] = createDialogActionHandlers<
|
const [openModal, closeModal] = createDialogActionHandlers<
|
||||||
StaffListUrlDialog,
|
StaffListUrlDialog,
|
||||||
StaffListUrlQueryParams
|
StaffListUrlQueryParams
|
||||||
|
@ -159,10 +181,13 @@ export const StaffList: React.FC<StaffListProps> = ({ params }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StaffListPage
|
<StaffListPage
|
||||||
|
currencySymbol={currencySymbol}
|
||||||
currentTab={currentTab}
|
currentTab={currentTab}
|
||||||
|
filterOpts={getFilterOpts(params)}
|
||||||
initialSearch={params.query || ""}
|
initialSearch={params.query || ""}
|
||||||
onSearchChange={query => changeFilterField({ query })}
|
onSearchChange={handleSearchChange}
|
||||||
onAll={() => navigate(staffListUrl())}
|
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,4 +1,9 @@
|
||||||
import { StaffUserInput } from "@saleor/types/globalTypes";
|
import { IntlShape } from "react-intl";
|
||||||
|
|
||||||
|
import { StaffUserInput, StaffMemberStatus } from "@saleor/types/globalTypes";
|
||||||
|
import { maybe, findValueInEnum } from "@saleor/misc";
|
||||||
|
import { IFilter, IFilterElement } from "@saleor/components/Filter";
|
||||||
|
import { createOptionsField } from "@saleor/utils/filters/fields";
|
||||||
import {
|
import {
|
||||||
createFilterTabUtils,
|
createFilterTabUtils,
|
||||||
createFilterUtils
|
createFilterUtils
|
||||||
|
@ -8,17 +13,83 @@ import {
|
||||||
StaffListUrlFiltersEnum,
|
StaffListUrlFiltersEnum,
|
||||||
StaffListUrlQueryParams
|
StaffListUrlQueryParams
|
||||||
} from "../../urls";
|
} from "../../urls";
|
||||||
|
import { StaffListFilterOpts } from "../../types";
|
||||||
|
import messages from "./messages";
|
||||||
|
|
||||||
export const STAFF_FILTERS_KEY = "staffFilters";
|
export const STAFF_FILTERS_KEY = "staffFilters";
|
||||||
|
|
||||||
|
export enum StaffFilterKeys {
|
||||||
|
status = "status"
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFilterOpts(
|
||||||
|
params: StaffListUrlFilters
|
||||||
|
): StaffListFilterOpts {
|
||||||
|
return {
|
||||||
|
status: {
|
||||||
|
active: maybe(() => params.status !== undefined, false),
|
||||||
|
value: maybe(() => findValueInEnum(params.status, StaffMemberStatus))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createFilterStructure(
|
||||||
|
intl: IntlShape,
|
||||||
|
opts: StaffListFilterOpts
|
||||||
|
): IFilter<StaffFilterKeys> {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
...createOptionsField(
|
||||||
|
StaffFilterKeys.status,
|
||||||
|
intl.formatMessage(messages.status),
|
||||||
|
[opts.status.value],
|
||||||
|
false,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: intl.formatMessage(messages.active),
|
||||||
|
value: StaffMemberStatus.ACTIVE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage(messages.deactivated),
|
||||||
|
value: StaffMemberStatus.DEACTIVATED
|
||||||
|
}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
active: opts.status.active
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export function getFilterVariables(
|
export function getFilterVariables(
|
||||||
params: StaffListUrlFilters
|
params: StaffListUrlFilters
|
||||||
): StaffUserInput {
|
): StaffUserInput {
|
||||||
return {
|
return {
|
||||||
search: params.query
|
search: params.query,
|
||||||
|
status: params.status
|
||||||
|
? findValueInEnum(params.status, StaffMemberStatus)
|
||||||
|
: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFilterQueryParam(
|
||||||
|
filter: IFilterElement<StaffFilterKeys>
|
||||||
|
): StaffListUrlFilters {
|
||||||
|
const { active, name, value } = filter;
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case StaffFilterKeys.status:
|
||||||
|
if (!active) {
|
||||||
|
return {
|
||||||
|
status: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: value[0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
deleteFilterTab,
|
deleteFilterTab,
|
||||||
getFilterTabs,
|
getFilterTabs,
|
||||||
|
|
18
src/staff/views/StaffList/messages.ts
Normal file
18
src/staff/views/StaffList/messages.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
active: {
|
||||||
|
defaultMessage: "Active",
|
||||||
|
description: "staff member's account"
|
||||||
|
},
|
||||||
|
deactivated: {
|
||||||
|
defaultMessage: "Deactivated",
|
||||||
|
description: "staff member's account"
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
defaultMessage: "Status",
|
||||||
|
description: "staff member's account"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default messages;
|
|
@ -2,11 +2,13 @@ import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { StaffListUrlSortField } from "@saleor/staff/urls";
|
import { StaffListUrlSortField } from "@saleor/staff/urls";
|
||||||
|
import { StaffMemberStatus } from "@saleor/types/globalTypes";
|
||||||
import {
|
import {
|
||||||
pageListProps,
|
pageListProps,
|
||||||
searchPageProps,
|
searchPageProps,
|
||||||
tabPageProps,
|
tabPageProps,
|
||||||
sortPageProps
|
sortPageProps,
|
||||||
|
filterPageProps
|
||||||
} from "../../../fixtures";
|
} from "../../../fixtures";
|
||||||
import StaffListPage, {
|
import StaffListPage, {
|
||||||
StaffListPageProps
|
StaffListPageProps
|
||||||
|
@ -19,6 +21,13 @@ const props: StaffListPageProps = {
|
||||||
...searchPageProps,
|
...searchPageProps,
|
||||||
...sortPageProps,
|
...sortPageProps,
|
||||||
...tabPageProps,
|
...tabPageProps,
|
||||||
|
...filterPageProps,
|
||||||
|
filterOpts: {
|
||||||
|
status: {
|
||||||
|
active: false,
|
||||||
|
value: StaffMemberStatus.ACTIVE
|
||||||
|
}
|
||||||
|
},
|
||||||
onAdd: undefined,
|
onAdd: undefined,
|
||||||
onBack: () => undefined,
|
onBack: () => undefined,
|
||||||
sort: {
|
sort: {
|
||||||
|
|
Loading…
Reference in a new issue