Saleor 1636 add possibility to filter through channels in order view (#929)
* Add possibility to filter through channels in order view * Update storybook and locale * Refactor * Refactor to mapNodetoChoice * Fix conditional value in array implicit syntax Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com>
This commit is contained in:
parent
d0be941ade
commit
4a8ebd5b1f
13 changed files with 103 additions and 45 deletions
|
@ -3550,6 +3550,10 @@
|
|||
"context": "tab name",
|
||||
"string": "All Orders"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_channel": {
|
||||
"context": "order",
|
||||
"string": "Channel"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_customer": {
|
||||
"context": "order",
|
||||
"string": "Customer"
|
||||
|
|
|
@ -3042,6 +3042,7 @@ input OrderFilterInput {
|
|||
customer: String
|
||||
created: DateRangeInput
|
||||
search: String
|
||||
channels: [ID]
|
||||
}
|
||||
|
||||
type OrderFulfill {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Decorator from "@saleor/storybook/Decorator";
|
||||
import { mapNodeToChoice } from "@saleor/utils/maps";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import React from "react";
|
||||
|
||||
|
@ -8,10 +9,7 @@ import ChannelDeleteDialog, {
|
|||
} from "./ChannelDeleteDialog";
|
||||
|
||||
const props: ChannelDeleteDialogProps = {
|
||||
channelsChoices: channelsList.map(channel => ({
|
||||
label: channel.name,
|
||||
value: channel.id
|
||||
})),
|
||||
channelsChoices: mapNodeToChoice(channelsList),
|
||||
hasOrders: true,
|
||||
confirmButtonState: "default",
|
||||
onBack: () => undefined,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Decorator from "@saleor/storybook/Decorator";
|
||||
import { mapNodeToChoice } from "@saleor/utils/maps";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import React from "react";
|
||||
|
||||
|
@ -7,10 +8,7 @@ import ChannelPickerDialog, {
|
|||
ChannelPickerDialogProps
|
||||
} from "./ChannelPickerDialog";
|
||||
|
||||
const channelsChoices = channelsList.map(channel => ({
|
||||
label: channel.name,
|
||||
value: channel.id
|
||||
}));
|
||||
const channelsChoices = mapNodeToChoice(channelsList);
|
||||
|
||||
const props: ChannelPickerDialogProps = {
|
||||
channelsChoices,
|
||||
|
|
|
@ -157,6 +157,7 @@ const FilterContent: React.FC<FilterContentProps> = ({
|
|||
</div>
|
||||
<Hr />
|
||||
{filters
|
||||
.filter(filter => !!filter)
|
||||
.sort((a, b) => (a.name > b.name ? 1 : -1))
|
||||
.map(filterField => (
|
||||
<React.Fragment key={filterField.name}>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { IFilter } from "@saleor/components/Filter";
|
||||
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { orderStatusMessages } from "@saleor/misc";
|
||||
import { FilterOpts, MinMax } from "@saleor/types";
|
||||
|
@ -13,16 +14,22 @@ import { defineMessages, IntlShape } from "react-intl";
|
|||
export enum OrderFilterKeys {
|
||||
created = "created",
|
||||
customer = "customer",
|
||||
status = "status"
|
||||
status = "status",
|
||||
channel = "channel"
|
||||
}
|
||||
|
||||
export interface OrderListFilterOpts {
|
||||
created: FilterOpts<MinMax>;
|
||||
customer: FilterOpts<string>;
|
||||
status: FilterOpts<OrderStatusFilter[]>;
|
||||
channel?: FilterOpts<MultiAutocompleteChoiceType[]>;
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
channel: {
|
||||
defaultMessage: "Channel",
|
||||
description: "order"
|
||||
},
|
||||
customer: {
|
||||
defaultMessage: "Customer",
|
||||
description: "order"
|
||||
|
@ -88,6 +95,20 @@ export function createFilterStructure(
|
|||
]
|
||||
),
|
||||
active: opts.status.active
|
||||
}
|
||||
},
|
||||
...(opts?.channel?.value.length
|
||||
? [
|
||||
{
|
||||
...createOptionsField(
|
||||
OrderFilterKeys.channel,
|
||||
intl.formatMessage(messages.channel),
|
||||
[],
|
||||
true,
|
||||
opts.channel.value
|
||||
),
|
||||
active: opts.channel.active
|
||||
}
|
||||
]
|
||||
: [])
|
||||
];
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
BulkAction,
|
||||
Dialog,
|
||||
Filters,
|
||||
FiltersAsDictWithMultipleValues,
|
||||
FiltersWithMultipleValues,
|
||||
Pagination,
|
||||
SingleAction,
|
||||
|
@ -25,11 +26,17 @@ export enum OrderListUrlFiltersEnum {
|
|||
payment = "payment",
|
||||
query = "query"
|
||||
}
|
||||
export enum OrderListUrlFiltersWithMultipleValuesEnum {
|
||||
export enum OrderListUrlFiltersWithMultipleValues {
|
||||
status = "status"
|
||||
}
|
||||
|
||||
export enum OrderListUrlFiltersDictWithMultipleValues {
|
||||
channel = "channel"
|
||||
}
|
||||
|
||||
export type OrderListUrlFilters = Filters<OrderListUrlFiltersEnum> &
|
||||
FiltersWithMultipleValues<OrderListUrlFiltersWithMultipleValuesEnum>;
|
||||
FiltersWithMultipleValues<OrderListUrlFiltersWithMultipleValues> &
|
||||
FiltersAsDictWithMultipleValues<OrderListUrlFiltersDictWithMultipleValues>;
|
||||
export type OrderListUrlDialog = "cancel" | CreateOrderDialog | TabActionDialog;
|
||||
export enum OrderListUrlSortField {
|
||||
number = "number",
|
||||
|
|
|
@ -15,6 +15,7 @@ import { ListViews } from "@saleor/types";
|
|||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import createFilterHandlers from "@saleor/utils/handlers/filterHandlers";
|
||||
import createSortHandler from "@saleor/utils/handlers/sortHandler";
|
||||
import { mapNodeToChoice } from "@saleor/utils/maps";
|
||||
import { getSortParams } from "@saleor/utils/sort";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
@ -72,6 +73,9 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
const { channel, availableChannels } = useAppChannel();
|
||||
|
||||
const noChannel = !channel && typeof channel !== "undefined";
|
||||
const channelOpts = availableChannels
|
||||
? mapNodeToChoice(availableChannels)
|
||||
: null;
|
||||
|
||||
const tabs = getFilterTabs();
|
||||
|
||||
|
@ -132,7 +136,7 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
});
|
||||
|
||||
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||
maybe(() => data.orders.pageInfo),
|
||||
data?.orders?.pageInfo,
|
||||
paginationState,
|
||||
params
|
||||
);
|
||||
|
@ -145,7 +149,7 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
settings={settings}
|
||||
currentTab={currentTab}
|
||||
disabled={loading}
|
||||
filterOpts={getFilterOpts(params)}
|
||||
filterOpts={getFilterOpts(params, channelOpts)}
|
||||
orders={maybe(() => data.orders.edges.map(edge => edge.node))}
|
||||
pageInfo={pageInfo}
|
||||
sort={getSortParams(params)}
|
||||
|
@ -180,10 +184,7 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
/>
|
||||
{!noChannel && (
|
||||
<ChannelPickerDialog
|
||||
channelsChoices={availableChannels.map(channel => ({
|
||||
label: channel.name,
|
||||
value: channel.id
|
||||
}))}
|
||||
channelsChoices={mapNodeToChoice(availableChannels)}
|
||||
confirmButtonState="success"
|
||||
defaultChoice={channel.id}
|
||||
open={params.action === "create-order"}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
exports[`Filtering URL params should not be empty if active filters are present 1`] = `
|
||||
Object {
|
||||
"channel": Array [],
|
||||
"createdFrom": "2019-12-09",
|
||||
"createdTo": "2019-12-38",
|
||||
"customer": "email@example.com",
|
||||
|
|
|
@ -38,6 +38,15 @@ describe("Filtering URL params", () => {
|
|||
const intl = createIntl(config);
|
||||
|
||||
const filters = createFilterStructure(intl, {
|
||||
channel: {
|
||||
active: false,
|
||||
value: [
|
||||
{
|
||||
label: "Channel PLN",
|
||||
value: "channelId"
|
||||
}
|
||||
]
|
||||
},
|
||||
created: {
|
||||
active: false,
|
||||
value: {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { findInEnum, findValueInEnum, maybe } from "@saleor/misc";
|
||||
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
|
||||
import { findInEnum, findValueInEnum } from "@saleor/misc";
|
||||
import {
|
||||
OrderFilterKeys,
|
||||
OrderListFilterOpts
|
||||
|
@ -16,48 +17,49 @@ import {
|
|||
getGteLteVariables,
|
||||
getMinMaxQueryParam,
|
||||
getMultipleEnumValueQueryParam,
|
||||
getMultipleValueQueryParam,
|
||||
getSingleValueQueryParam
|
||||
} from "../../../utils/filters";
|
||||
import {
|
||||
OrderListUrlFilters,
|
||||
OrderListUrlFiltersDictWithMultipleValues,
|
||||
OrderListUrlFiltersEnum,
|
||||
OrderListUrlFiltersWithMultipleValuesEnum,
|
||||
OrderListUrlFiltersWithMultipleValues,
|
||||
OrderListUrlQueryParams
|
||||
} from "../../urls";
|
||||
|
||||
export const ORDER_FILTERS_KEY = "orderFilters";
|
||||
|
||||
export function getFilterOpts(
|
||||
params: OrderListUrlFilters
|
||||
params: OrderListUrlFilters,
|
||||
channels: MultiAutocompleteChoiceType[]
|
||||
): OrderListFilterOpts {
|
||||
return {
|
||||
channel: channels
|
||||
? {
|
||||
active: params?.channel !== undefined,
|
||||
value: channels
|
||||
}
|
||||
: null,
|
||||
created: {
|
||||
active: maybe(
|
||||
() =>
|
||||
[params.createdFrom, params.createdTo].some(
|
||||
field => field !== undefined
|
||||
),
|
||||
false
|
||||
active: [params?.createdFrom, params?.createdTo].some(
|
||||
field => field !== undefined
|
||||
),
|
||||
value: {
|
||||
max: maybe(() => params.createdTo, ""),
|
||||
min: maybe(() => params.createdFrom, "")
|
||||
max: params?.createdTo || "",
|
||||
min: params?.createdFrom || ""
|
||||
}
|
||||
},
|
||||
customer: {
|
||||
active: !!maybe(() => params.customer),
|
||||
value: params.customer
|
||||
active: !!params?.customer,
|
||||
value: params?.customer
|
||||
},
|
||||
status: {
|
||||
active: maybe(() => params.status !== undefined, false),
|
||||
value: maybe(
|
||||
() =>
|
||||
dedupeFilter(
|
||||
params.status.map(status =>
|
||||
findValueInEnum(status, OrderStatusFilter)
|
||||
)
|
||||
),
|
||||
[]
|
||||
active: params?.status !== undefined,
|
||||
value: dedupeFilter(
|
||||
params?.status?.map(status =>
|
||||
findValueInEnum(status, OrderStatusFilter)
|
||||
)
|
||||
)
|
||||
}
|
||||
};
|
||||
|
@ -67,15 +69,14 @@ export function getFilterVariables(
|
|||
params: OrderListUrlFilters
|
||||
): OrderFilterInput {
|
||||
return {
|
||||
channels: (params.channel as unknown) as string[],
|
||||
created: getGteLteVariables({
|
||||
gte: params.createdFrom,
|
||||
lte: params.createdTo
|
||||
}),
|
||||
customer: params.customer,
|
||||
search: params.query,
|
||||
status: maybe(() =>
|
||||
params.status.map(status => findInEnum(status, OrderStatusFilter))
|
||||
)
|
||||
status: params?.status?.map(status => findInEnum(status, OrderStatusFilter))
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -95,10 +96,16 @@ export function getFilterQueryParam(
|
|||
case OrderFilterKeys.status:
|
||||
return getMultipleEnumValueQueryParam(
|
||||
filter,
|
||||
OrderListUrlFiltersWithMultipleValuesEnum.status,
|
||||
OrderListUrlFiltersWithMultipleValues.status,
|
||||
OrderStatusFilter
|
||||
);
|
||||
|
||||
case OrderFilterKeys.channel:
|
||||
return getMultipleValueQueryParam(
|
||||
filter,
|
||||
OrderListUrlFiltersDictWithMultipleValues.channel
|
||||
);
|
||||
|
||||
case OrderFilterKeys.customer:
|
||||
return getSingleValueQueryParam(filter, OrderListUrlFiltersEnum.customer);
|
||||
}
|
||||
|
@ -115,5 +122,5 @@ export const { areFiltersApplied, getActiveFilters } = createFilterUtils<
|
|||
OrderListUrlFilters
|
||||
>({
|
||||
...OrderListUrlFiltersEnum,
|
||||
...OrderListUrlFiltersWithMultipleValuesEnum
|
||||
...OrderListUrlFiltersWithMultipleValues
|
||||
});
|
||||
|
|
|
@ -21,6 +21,15 @@ const props: OrderListPageProps = {
|
|||
...filterPageProps,
|
||||
...sortPageProps,
|
||||
filterOpts: {
|
||||
channel: {
|
||||
active: false,
|
||||
value: [
|
||||
{
|
||||
label: "Channel PLN",
|
||||
value: "channelId"
|
||||
}
|
||||
]
|
||||
},
|
||||
created: {
|
||||
active: false,
|
||||
value: {
|
||||
|
|
|
@ -1326,6 +1326,7 @@ export interface OrderFilterInput {
|
|||
customer?: string | null;
|
||||
created?: DateRangeInput | null;
|
||||
search?: string | null;
|
||||
channels?: (string | null)[] | null;
|
||||
}
|
||||
|
||||
export interface OrderFulfillInput {
|
||||
|
|
Loading…
Reference in a new issue