Fix numeric attribute filters (#2145)

* Handle numeric attribute filters

* Fix filter behaviour

* Backwards compatibility
This commit is contained in:
Michał Droń 2022-08-01 11:39:20 +02:00 committed by GitHub
parent 1a974e380c
commit 4ee9e4fc59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 9 deletions

View file

@ -35,6 +35,9 @@ export const FilterSingleSelectField: React.FC<FilterSingleSelectFieldProps> = (
name: filter.name,
update: {
multiple: event.target.value === FilterType.MULTIPLE,
...(event.target.value !== FilterType.MULTIPLE && {
value: filter.value.slice(0, 1) as string[],
}),
},
},
type: "set-property",

View file

@ -14,6 +14,7 @@ import {
createDateField,
createDateTimeField,
createKeyValueField,
createNumberField,
createOptionsField,
createPriceField,
} from "@saleor/utils/filters/fields";
@ -121,6 +122,9 @@ export function createFilterStructure(
const dateTimeAttributes = attributes.filter(
filterByType(AttributeInputTypeEnum.DATE_TIME),
);
const numericAttributes = attributes.filter(
filterByType(AttributeInputTypeEnum.NUMERIC),
);
const defaultAttributes = opts.attributes.filter(
({ inputType }) =>
@ -128,6 +132,7 @@ export function createFilterStructure(
AttributeInputTypeEnum.BOOLEAN,
AttributeInputTypeEnum.DATE,
AttributeInputTypeEnum.DATE_TIME,
AttributeInputTypeEnum.NUMERIC,
].includes(inputType),
);
@ -273,6 +278,14 @@ export function createFilterStructure(
active: attr.active,
group: ProductFilterKeys.attributes,
})),
...numericAttributes.map(attr => ({
...createNumberField(attr.slug, attr.name, {
min: attr.value[0],
max: attr.value[1] ?? attr.value[0],
}),
active: attr.active,
group: ProductFilterKeys.attributes,
})),
...defaultAttributes.map(attr => ({
...createAutocompleteField(
attr.slug,

View file

@ -467,8 +467,8 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
confirmButtonState={exportProductsOpts.status}
errors={exportProductsOpts.data?.exportProducts.errors || []}
productQuantity={{
all: countAllProducts.data?.products.totalCount,
filter: data?.products.totalCount,
all: countAllProducts.data?.products?.totalCount,
filter: data?.products?.totalCount,
}}
selectedProducts={listElements.length}
warehouses={mapEdgesToItems(warehouses?.data?.warehouses) || []}

View file

@ -27,7 +27,6 @@ import {
mapNodeToChoice,
mapSlugNodeToChoice,
} from "@saleor/utils/maps";
import isArray from "lodash/isArray";
import moment from "moment-timezone";
import {
@ -238,12 +237,12 @@ const parseFilterValue = (
params: ProductListUrlFilters,
key: string,
): {
type: "boolean" | "date" | "dateTime" | "string";
type: "boolean" | "date" | "dateTime" | "numeric" | "string";
isMulti: boolean;
value: string[];
} => {
const value = params.attributes[key];
const isMulti = isArray(params.attributes[key]);
const isMulti = params.attributes[key].length > 1;
const isBooleanValue = value.every(val => val === "true" || val === "false");
const isDateValue = (isMulti ? value : [value]).some(val =>
@ -252,8 +251,9 @@ const parseFilterValue = (
const isDateTimeValue = (isMulti ? value : [value]).some(val =>
moment(val, moment.ISO_8601, true).isValid(),
);
const isNumericValue = value.some(value => !isNaN(parseFloat(value)));
const data = { isMulti, value: (isMulti ? value : [value]) as string[] };
const data = { isMulti, value };
if (isBooleanValue) {
return { ...data, type: "boolean" };
@ -261,6 +261,8 @@ const parseFilterValue = (
return { ...data, type: "date" };
} else if (isDateTimeValue) {
return { ...data, type: "dateTime" };
} else if (isNumericValue) {
return { ...data, type: "numeric" };
}
return { ...data, type: "string" };
};
@ -317,6 +319,15 @@ function getFilteredAttributeValue(
}),
};
case "numeric":
return {
...name,
valuesRange: {
gte: value[0] || undefined,
lte: isMulti ? value[1] || undefined : value[0] || undefined,
},
};
default:
return { ...name, values: value };
}

View file

@ -70,15 +70,15 @@ export function createDateTimeField<K extends string>(
export function createNumberField<K extends string>(
name: K,
label: string,
defaultValue: MinMax,
value: MinMax,
): FilterElementGeneric<K, FieldType.number> {
return {
active: false,
label,
multiple: true,
multiple: value.min !== value.max,
name,
type: FieldType.number,
value: [defaultValue.min, defaultValue.max],
value: [value.min, value.max],
};
}