Experimental filters: filter presets & date fixes (#4030)

This commit is contained in:
Krzysztof Żuraw 2023-07-28 13:43:58 +02:00 committed by GitHub
parent 5087dec2d5
commit e033d6bf99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 41 additions and 24 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---
Experimental filters: filter presets & date fixes

View file

@ -1,5 +1,4 @@
import { parse, ParsedQs } from "qs";
import { useRef } from "react";
import { InitialStateResponse } from "../../API/InitialStateResponse";
import { FilterContainer, FilterElement } from "../../FilterElement";
@ -91,13 +90,3 @@ export class TokenArray extends Array<string | UrlToken | TokenArray> {
});
}
}
export const useTokenArray = (url: string) => {
const instance = useRef<TokenArray | null>(null);
if (!instance.current) {
instance.current = new TokenArray(url);
}
return instance.current;
};

View file

@ -5,7 +5,7 @@ import useRouter from "use-react-router";
import { InitialAPIState } from "../API";
import { FilterContainer, FilterElement } from "../FilterElement";
import { FilterValueProvider } from "../FilterValueProvider";
import { useTokenArray } from "./TokenArray";
import { TokenArray } from "./TokenArray";
import { UrlEntry } from "./UrlToken";
type Structure = Array<string | UrlEntry | Structure>;
@ -25,20 +25,22 @@ const prepareStructure = (filterValue: FilterContainer): Structure =>
export const useUrlValueProvider = (
initialState: InitialAPIState,
locationSearch: string,
): FilterValueProvider => {
const router = useRouter();
const params = new URLSearchParams(router.location.search);
const params = new URLSearchParams(locationSearch);
const { data, loading, fetchQueries } = initialState;
const [value, setValue] = useState<FilterContainer>([]);
params.delete("asc");
params.delete("sort");
const tokenizedUrl = useTokenArray(params.toString());
const tokenizedUrl = new TokenArray(params.toString());
const fetchingParams = tokenizedUrl.getFetchingParams();
useEffect(() => {
fetchQueries(fetchingParams);
}, []);
}, [locationSearch]);
useEffect(() => {
if (loading) return;

View file

@ -93,11 +93,13 @@ export const ATTRIBUTE_INPUT_TYPE_CONDITIONS = {
{ type: "number.range", label: "between", value: "input-4" },
],
DATE_TIME: [
{ type: "datetime", label: "is", value: "input-1" },
{ type: "datetime", label: "lower", value: "input-2" },
{ type: "datetime", label: "greater", value: "input-3" },
{ type: "datetime.range", label: "between", value: "input-4" },
],
DATE: [
{ type: "date", label: "is", value: "input-1" },
{ type: "date", label: "lower", value: "input-1" },
{ type: "date", label: "greater", value: "input-2" },
{ type: "date.range", label: "between", value: "input-4" },
],
SWATCH: [{ type: "multiselect", label: "in", value: "input-2" }],

View file

@ -7,10 +7,12 @@ import { useFilterLeftOperandsProvider } from "../useFilterLeftOperands";
import { useUrlValueProvider } from "../ValueProvider/useUrlValueProvider";
import { ConditionalFilterContext } from "./context";
export const ConditionalProductFilterProvider: FC = ({ children }) => {
export const ConditionalProductFilterProvider: FC<{
locationSearch: string;
}> = ({ children, locationSearch }) => {
const apiProvider = useProductFilterAPIProvider();
const initialState = useProductInitialAPIState();
const valueProvider = useUrlValueProvider(initialState);
const valueProvider = useUrlValueProvider(initialState, locationSearch);
const leftOperandsProvider = useFilterLeftOperandsProvider();
const containerState = useContainerState(valueProvider);

View file

@ -35,7 +35,7 @@ const createStaticQueryPart = (
}
if (isTuple(value) && label === "between") {
const [lte, gte] = value;
const [gte, lte] = value;
return { range: { lte, gte } };
}
@ -59,7 +59,7 @@ const createStaticQueryPart = (
};
const getRangeQueryPartByType = (value: [string, string], type: string) => {
const [lte, gte] = value;
const [gte, lte] = value;
switch (type) {
case "datetime.range":
@ -72,6 +72,21 @@ const getRangeQueryPartByType = (value: [string, string], type: string) => {
}
};
const getQueryPartByType = (
value: string,
type: string,
what: "lte" | "gte",
) => {
switch (type) {
case "datetime":
return { dateTime: { [what]: value } };
case "date":
return { date: { [what]: value } };
default:
return { valuesRange: { [what]: parseFloat(value) } };
}
};
const createAttributeQueryPart = (
attributeSlug: string,
selected: ConditionSelected,
@ -82,11 +97,11 @@ const createAttributeQueryPart = (
const { value } = selected;
if (label === "lower" && typeof value === "string") {
return { slug: attributeSlug, valuesRange: { lte: parseFloat(value) } };
return { slug: attributeSlug, ...getQueryPartByType(value, type, "lte") };
}
if (label === "greater" && typeof value === "string") {
return { slug: attributeSlug, valuesRange: { gte: parseFloat(value) } };
return { slug: attributeSlug, ...getQueryPartByType(value, type, "gte") };
}
if (isTuple(value) && label === "between") {

View file

@ -159,6 +159,7 @@ export const FilterPresetsSelect = ({
onRemove={() => {
onRemove(index + 1);
}}
key={`filter-preset-${index}`}
>
{preset}
</FilterPresetItem>

View file

@ -45,7 +45,7 @@ const ProductList: React.FC<RouteComponentProps<any>> = ({ location }) => {
);
return (
<ConditionalProductFilterProvider>
<ConditionalProductFilterProvider locationSearch={location.search}>
<ProductListComponent params={params} />
</ConditionalProductFilterProvider>
);

View file

@ -66,6 +66,7 @@ export function getSortQueryVariables(
}
const field = getSortQueryField(params.sort);
// TODO: how to handle search & sort
return {
direction,
field,