Code cleanup
This commit is contained in:
parent
c155cf36e4
commit
1f3cbfda82
11 changed files with 156 additions and 73 deletions
|
@ -351,14 +351,14 @@ export function findInEnum<TEnum extends object>(
|
|||
export function findValueInEnum<TEnum extends object>(
|
||||
needle: string,
|
||||
haystack: TEnum
|
||||
) {
|
||||
): TEnum[keyof TEnum] {
|
||||
const match = Object.entries(haystack).find(([_, value]) => value === needle);
|
||||
|
||||
if (!!match) {
|
||||
return match[1] as TEnum;
|
||||
if (!match) {
|
||||
throw new Error(`Value ${needle} not found in enum`);
|
||||
}
|
||||
|
||||
throw new Error(`Value ${needle} not found in enum`);
|
||||
return (needle as unknown) as TEnum[keyof TEnum];
|
||||
}
|
||||
|
||||
export function parseBoolean(a: string, defaultValue: boolean): boolean {
|
||||
|
|
|
@ -21,11 +21,12 @@ import {
|
|||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import { OrderList_orders_edges_node } from "../../types/OrderList";
|
||||
import OrderList from "../OrderList";
|
||||
import { OrderListFilterOpts } from "../../types";
|
||||
|
||||
export interface OrderListPageProps
|
||||
extends PageListProps,
|
||||
ListActions,
|
||||
FilterPageProps<OrderFilterKeys>,
|
||||
FilterPageProps<OrderFilterKeys, OrderListFilterOpts>,
|
||||
SortPage<OrderListUrlSortField> {
|
||||
orders: OrderList_orders_edges_node[];
|
||||
}
|
||||
|
@ -34,6 +35,7 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
currencySymbol,
|
||||
currentTab,
|
||||
initialSearch,
|
||||
filterOpts,
|
||||
tabs,
|
||||
onAdd,
|
||||
onAll,
|
||||
|
@ -46,7 +48,7 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const filterStructure = createFilterStructure(intl);
|
||||
const filterStructure = createFilterStructure(intl, filterOpts);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
|
7
src/orders/types.ts
Normal file
7
src/orders/types.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { FilterOpts, MinMax } from "@saleor/types";
|
||||
import { OrderStatusFilter } from "@saleor/types/globalTypes";
|
||||
|
||||
export interface OrderListFilterOpts {
|
||||
created: FilterOpts<MinMax>;
|
||||
status: FilterOpts<OrderStatusFilter[]>;
|
||||
}
|
|
@ -41,6 +41,7 @@ import {
|
|||
deleteFilterTab,
|
||||
getActiveFilters,
|
||||
getFilterTabs,
|
||||
getFilterOpts,
|
||||
getFilterVariables,
|
||||
saveFilterTab,
|
||||
OrderFilterKeys,
|
||||
|
@ -200,6 +201,7 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
settings={settings}
|
||||
currentTab={currentTab}
|
||||
disabled={loading}
|
||||
filterOpts={getFilterOpts(params)}
|
||||
orders={maybe(() => data.orders.edges.map(edge => edge.node))}
|
||||
pageInfo={pageInfo}
|
||||
sort={getSortParams(params)}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { IntlShape } from "react-intl";
|
||||
|
||||
import { findInEnum, maybe, orderStatusMessages } from "@saleor/misc";
|
||||
import {
|
||||
findInEnum,
|
||||
maybe,
|
||||
orderStatusMessages,
|
||||
findValueInEnum
|
||||
} from "@saleor/misc";
|
||||
import {
|
||||
createDateField,
|
||||
createOptionsField
|
||||
|
@ -22,6 +27,7 @@ import {
|
|||
OrderListUrlFiltersWithMultipleValuesEnum,
|
||||
OrderListUrlQueryParams
|
||||
} from "../../urls";
|
||||
import { OrderListFilterOpts } from "../../types";
|
||||
import messages from "./messages";
|
||||
|
||||
export const ORDER_FILTERS_KEY = "orderFilters";
|
||||
|
@ -31,39 +37,56 @@ export enum OrderFilterKeys {
|
|||
status = "status"
|
||||
}
|
||||
|
||||
export function createFilterStructure(
|
||||
intl: IntlShape,
|
||||
export function getFilterOpts(
|
||||
params: OrderListUrlFilters
|
||||
): IFilter<OrderFilterKeys> {
|
||||
return [
|
||||
{
|
||||
...createDateField(
|
||||
OrderFilterKeys.created,
|
||||
intl.formatMessage(messages.placed),
|
||||
{
|
||||
max: maybe(() => params.createdTo, ""),
|
||||
min: maybe(() => params.createdFrom, "")
|
||||
}
|
||||
),
|
||||
): OrderListFilterOpts {
|
||||
return {
|
||||
created: {
|
||||
active: maybe(
|
||||
() =>
|
||||
[params.createdFrom, params.createdTo].some(
|
||||
field => field !== undefined
|
||||
),
|
||||
false
|
||||
),
|
||||
value: {
|
||||
max: maybe(() => params.createdTo, ""),
|
||||
min: maybe(() => params.createdFrom, "")
|
||||
}
|
||||
},
|
||||
status: {
|
||||
active: maybe(() => params.status !== undefined, false),
|
||||
value: maybe(
|
||||
() =>
|
||||
dedupeFilter(
|
||||
params.status.map(status =>
|
||||
findValueInEnum(status, OrderStatusFilter)
|
||||
)
|
||||
),
|
||||
[]
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function createFilterStructure(
|
||||
intl: IntlShape,
|
||||
opts: OrderListFilterOpts
|
||||
): IFilter<OrderFilterKeys> {
|
||||
return [
|
||||
{
|
||||
...createDateField(
|
||||
OrderFilterKeys.created,
|
||||
intl.formatMessage(messages.placed),
|
||||
opts.created.value
|
||||
),
|
||||
active: opts.created.active
|
||||
},
|
||||
{
|
||||
...createOptionsField(
|
||||
OrderFilterKeys.status,
|
||||
intl.formatMessage(messages.status),
|
||||
maybe(
|
||||
() =>
|
||||
dedupeFilter(
|
||||
params.status.map(status => findInEnum(status, OrderStatusFilter))
|
||||
),
|
||||
[]
|
||||
),
|
||||
opts.status.value,
|
||||
true,
|
||||
[
|
||||
{
|
||||
|
@ -84,7 +107,7 @@ export function createFilterStructure(
|
|||
}
|
||||
]
|
||||
),
|
||||
active: maybe(() => params.status !== undefined, false)
|
||||
active: opts.status.active
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@ -108,14 +131,21 @@ export function getFilterVariables(
|
|||
export function getFilterQueryParam(
|
||||
filter: IFilterElement<OrderFilterKeys>
|
||||
): OrderListUrlFilters {
|
||||
const { active, name, value } = filter;
|
||||
const { active, multiple, name, value } = filter;
|
||||
|
||||
if (active) {
|
||||
switch (name) {
|
||||
case OrderFilterKeys.created:
|
||||
if (multiple) {
|
||||
return {
|
||||
createdFrom: value[0],
|
||||
createdTo: value[1]
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
createdFrom: value[0],
|
||||
createdTo: value[1]
|
||||
createdTo: value[0]
|
||||
};
|
||||
|
||||
case OrderFilterKeys.status:
|
||||
|
|
|
@ -24,17 +24,18 @@ import {
|
|||
SortPage
|
||||
} from "@saleor/types";
|
||||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import { ProductListFilterOpts } from "@saleor/products/types";
|
||||
import { ProductListUrlSortField } from "../../urls";
|
||||
import {
|
||||
createFilterStructure,
|
||||
ProductFilterKeys
|
||||
} from "@saleor/products/views/ProductList/filters";
|
||||
import { ProductListUrlSortField } from "../../urls";
|
||||
} from "../../views/ProductList/filters";
|
||||
import ProductList from "../ProductList";
|
||||
|
||||
export interface ProductListPageProps
|
||||
extends PageListProps<ProductListColumns>,
|
||||
ListActions,
|
||||
FilterPageProps<ProductFilterKeys>,
|
||||
FilterPageProps<ProductFilterKeys, ProductListFilterOpts>,
|
||||
FetchMoreProps,
|
||||
SortPage<ProductListUrlSortField> {
|
||||
activeAttributeSortId: string;
|
||||
|
@ -61,6 +62,7 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
defaultSettings,
|
||||
gridAttributes,
|
||||
availableInGridAttributes,
|
||||
filterOpts,
|
||||
hasMore,
|
||||
initialSearch,
|
||||
loading,
|
||||
|
@ -84,7 +86,7 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
const handleSave = (columns: ProductListColumns[]) =>
|
||||
onUpdateListSettings("columns", columns);
|
||||
|
||||
const filterStructure = createFilterStructure(intl);
|
||||
const filterStructure = createFilterStructure(intl, filterOpts);
|
||||
|
||||
const columns: ColumnPickerChoice[] = [
|
||||
{
|
||||
|
|
13
src/products/types.ts
Normal file
13
src/products/types.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { FilterOpts, MinMax } from "@saleor/types";
|
||||
import { StockAvailability } from "@saleor/types/globalTypes";
|
||||
|
||||
export enum ProductStatus {
|
||||
PUBLISHED = "published",
|
||||
HIDDEN = "hidden"
|
||||
}
|
||||
|
||||
export interface ProductListFilterOpts {
|
||||
price: FilterOpts<MinMax>;
|
||||
status: FilterOpts<ProductStatus>;
|
||||
stockStatus: FilterOpts<StockAvailability>;
|
||||
}
|
|
@ -54,7 +54,8 @@ import {
|
|||
getFilterVariables,
|
||||
saveFilterTab,
|
||||
ProductFilterKeys,
|
||||
createFilterQueryParams
|
||||
createFilterQueryParams,
|
||||
getFilterOpts
|
||||
} from "./filters";
|
||||
import { getSortQueryVariables } from "./sort";
|
||||
|
||||
|
@ -234,6 +235,7 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
|
|||
defaultSettings={
|
||||
defaultListSettings[ListViews.PRODUCT_LIST]
|
||||
}
|
||||
filterOpts={getFilterOpts(params)}
|
||||
gridAttributes={maybe(
|
||||
() =>
|
||||
attributes.data.grid.edges.map(edge => edge.node),
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { IntlShape } from "react-intl";
|
||||
|
||||
import { findInEnum, maybe } from "@saleor/misc";
|
||||
import { maybe, findValueInEnum } from "@saleor/misc";
|
||||
import {
|
||||
createOptionsField,
|
||||
createPriceField
|
||||
} from "@saleor/utils/filters/fields";
|
||||
import { ProductStatus, ProductListFilterOpts } from "@saleor/products/types";
|
||||
import { IFilterElement, IFilter } from "../../../components/Filter";
|
||||
import {
|
||||
ProductFilterInput,
|
||||
|
@ -29,21 +30,42 @@ export enum ProductFilterKeys {
|
|||
stock = "stock"
|
||||
}
|
||||
|
||||
export enum ProductStatus {
|
||||
PUBLISHED = "published",
|
||||
HIDDEN = "hidden"
|
||||
export function getFilterOpts(
|
||||
params: ProductListUrlFilters
|
||||
): ProductListFilterOpts {
|
||||
return {
|
||||
price: {
|
||||
active: maybe(
|
||||
() =>
|
||||
[params.priceFrom, params.priceTo].some(field => field !== undefined),
|
||||
false
|
||||
),
|
||||
value: {
|
||||
max: maybe(() => params.priceTo, "0"),
|
||||
min: maybe(() => params.priceFrom, "0")
|
||||
}
|
||||
},
|
||||
status: {
|
||||
active: maybe(() => params.status !== undefined, false),
|
||||
value: maybe(() => findValueInEnum(params.status, ProductStatus))
|
||||
},
|
||||
stockStatus: {
|
||||
active: maybe(() => params.stockStatus !== undefined, false),
|
||||
value: maybe(() => findValueInEnum(params.stockStatus, StockAvailability))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function createFilterStructure(
|
||||
intl: IntlShape,
|
||||
params: ProductListUrlFilters
|
||||
opts: ProductListFilterOpts
|
||||
): IFilter<ProductFilterKeys> {
|
||||
return [
|
||||
{
|
||||
...createOptionsField(
|
||||
ProductFilterKeys.status,
|
||||
intl.formatMessage(messages.visibility),
|
||||
[ProductStatus.PUBLISHED],
|
||||
[opts.status.value],
|
||||
false,
|
||||
[
|
||||
{
|
||||
|
@ -56,13 +78,13 @@ export function createFilterStructure(
|
|||
}
|
||||
]
|
||||
),
|
||||
active: maybe(() => params.status !== undefined, false)
|
||||
active: opts.status.active
|
||||
},
|
||||
{
|
||||
...createOptionsField(
|
||||
ProductFilterKeys.stock,
|
||||
intl.formatMessage(messages.quantity),
|
||||
[StockAvailability.IN_STOCK],
|
||||
[opts.stockStatus.value],
|
||||
false,
|
||||
[
|
||||
{
|
||||
|
@ -75,22 +97,15 @@ export function createFilterStructure(
|
|||
}
|
||||
]
|
||||
),
|
||||
active: maybe(() => params.stockStatus !== undefined, false)
|
||||
active: opts.stockStatus.active
|
||||
},
|
||||
{
|
||||
...createPriceField(
|
||||
ProductFilterKeys.price,
|
||||
intl.formatMessage(messages.price),
|
||||
{
|
||||
max: maybe(() => params.priceTo, "0"),
|
||||
min: maybe(() => params.priceFrom, "0")
|
||||
}
|
||||
opts.price.value
|
||||
),
|
||||
active: maybe(
|
||||
() =>
|
||||
[params.priceFrom, params.priceTo].some(field => field !== undefined),
|
||||
false
|
||||
)
|
||||
active: opts.price.active
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@ -108,33 +123,41 @@ export function getFilterVariables(
|
|||
lte: parseFloat(params.priceTo)
|
||||
},
|
||||
search: params.query,
|
||||
stockAvailability: StockAvailability[params.stockStatus]
|
||||
stockAvailability:
|
||||
params.stockStatus !== undefined
|
||||
? findValueInEnum(params.stockStatus, StockAvailability)
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
export function getFilterQueryParam(
|
||||
filter: IFilterElement<ProductFilterKeys>
|
||||
): ProductListUrlFilters {
|
||||
const { active, name, value } = filter;
|
||||
const { active, multiple, name, value } = filter;
|
||||
|
||||
if (active) {
|
||||
switch (name) {
|
||||
case ProductFilterKeys.price:
|
||||
if (multiple) {
|
||||
return {
|
||||
priceFrom: value[0],
|
||||
priceTo: value[1]
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
priceFrom: value[0],
|
||||
priceTo: value[1]
|
||||
priceTo: value[0]
|
||||
};
|
||||
|
||||
case ProductFilterKeys.status:
|
||||
return {
|
||||
status: (
|
||||
findInEnum(value[0], ProductStatus) === ProductStatus.PUBLISHED
|
||||
).toString()
|
||||
status: findValueInEnum(value[0], ProductStatus)
|
||||
};
|
||||
|
||||
case ProductFilterKeys.stock:
|
||||
return {
|
||||
status: findInEnum(value[0], StockAvailability)
|
||||
stockStatus: findValueInEnum(value[0], StockAvailability)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
23
src/types.ts
23
src/types.ts
|
@ -82,20 +82,16 @@ export interface SearchPageProps {
|
|||
initialSearch: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
}
|
||||
export interface FilterPageProps<TKeys extends string>
|
||||
extends SearchPageProps,
|
||||
export interface FilterPageProps<TKeys extends string, TOpts extends object>
|
||||
extends FilterProps<TKeys>,
|
||||
SearchPageProps,
|
||||
TabPageProps {
|
||||
currencySymbol: string;
|
||||
onFilterChange: (filter: IFilter<TKeys>) => void;
|
||||
filterOpts: TOpts;
|
||||
}
|
||||
|
||||
export interface SearchProps {
|
||||
searchPlaceholder: string;
|
||||
}
|
||||
export interface FilterProps<TKeys extends string>
|
||||
extends FilterPageProps<TKeys>,
|
||||
SearchProps {
|
||||
export interface FilterProps<TKeys extends string> {
|
||||
currencySymbol: string;
|
||||
onFilterChange: (filter: IFilter<TKeys>) => void;
|
||||
}
|
||||
|
||||
export interface TabPageProps {
|
||||
|
@ -170,3 +166,10 @@ export interface UserPermissionProps {
|
|||
export interface MutationResultAdditionalProps {
|
||||
status: ConfirmButtonTransitionState;
|
||||
}
|
||||
|
||||
export type MinMax = Record<"min" | "max", string>;
|
||||
|
||||
export interface FilterOpts<T> {
|
||||
active: boolean;
|
||||
value: T;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { IFilterElement, FieldType } from "@saleor/components/Filter";
|
||||
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
|
||||
|
||||
type MinMax = Record<"min" | "max", string>;
|
||||
import { MinMax } from "@saleor/types";
|
||||
|
||||
export function createPriceField<T extends string>(
|
||||
name: T,
|
||||
|
@ -26,7 +25,7 @@ export function createDateField<T extends string>(
|
|||
return {
|
||||
active: false,
|
||||
label,
|
||||
multiple: true,
|
||||
multiple: defaultValue.min !== defaultValue.max,
|
||||
name,
|
||||
type: FieldType.date,
|
||||
value: [defaultValue.min, defaultValue.max]
|
||||
|
|
Loading…
Reference in a new issue