Code cleanup

This commit is contained in:
dominik-zeglen 2019-12-20 16:53:03 +01:00
parent c155cf36e4
commit 1f3cbfda82
11 changed files with 156 additions and 73 deletions

View file

@ -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 {

View file

@ -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
View 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[]>;
}

View file

@ -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)}

View file

@ -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:

View file

@ -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
View 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>;
}

View file

@ -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),

View file

@ -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)
};
}
}

View file

@ -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;
}

View file

@ -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]