Handle oudside click for filters popover (#4021)

* Oudside click handler

* Oudside click handler

* Changeset
This commit is contained in:
Patryk Andrzejewski 2023-07-28 09:27:18 +02:00 committed by GitHub
parent d08527f7db
commit 436c2af00e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---
Handle oudside click for filters popover

View file

@ -17,7 +17,11 @@ import { useIntl } from "react-intl";
export const ExpressionFilters = () => {
const [open, setOpen] = useState(false);
const { formatMessage } = useIntl();
const { valueProvider } = useConditionalFilterContext();
const { valueProvider, containerState } = useConditionalFilterContext();
const clickOutside = () => {
containerState.clearEmpty()
}
return (
<Popover open={open} onOpenChange={open => setOpen(open)}>
@ -28,7 +32,7 @@ export const ExpressionFilters = () => {
})}
</DropdownButton>
</Popover.Trigger>
<Popover.Content align="start">
<Popover.Content align="start" onInteractOutside={clickOutside}>
<Box
__minHeight="250px"
__minWidth="636px"

View file

@ -164,6 +164,10 @@ export class FilterElement {
return UrlEntry.forStatic(this.condition.selected, this.value.value);
}
public equals(element: FilterElement) {
return this.value.value === element.value.value
}
public static isCompatible(element: unknown): element is FilterElement {
return (
typeof element === "object" &&

View file

@ -1,9 +1,10 @@
import { FilterContainer } from "./FilterElement";
import { FilterContainer, FilterElement } from "./FilterElement";
export interface FilterValueProvider {
value: FilterContainer;
loading: boolean;
persist: (newValue: FilterContainer) => void;
isPersisted: (element: FilterElement) => boolean;
clear: () => void;
count: number;
}

View file

@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
import useRouter from "use-react-router";
import { InitialAPIState } from "../API";
import { FilterContainer } from "../FilterElement";
import { FilterContainer, FilterElement } from "../FilterElement";
import { FilterValueProvider } from "../FilterValueProvider";
import { useTokenArray } from "./TokenArray";
import { UrlEntry } from "./UrlToken";
@ -61,6 +61,10 @@ export const useUrlValueProvider = (
setValue([]);
};
const isPersisted = (element: FilterElement) => {
return value.some(p => FilterElement.isCompatible(p) && p.equals(element))
}
const count = value.filter(v => typeof v !== "string").length;
return {
@ -68,6 +72,7 @@ export const useUrlValueProvider = (
loading,
persist,
clear,
isPersisted,
count,
};
};

View file

@ -49,6 +49,17 @@ const removeElement = (container: FilterContainer, position: number) => {
return removeConstraint(newContainer);
};
const removeEmptyElements = (container: FilterContainer, provider: FilterValueProvider): FilterContainer => {
const emptyIndex = container.findIndex(el =>
FilterElement.isCompatible(el) && (!provider.isPersisted(el) || el.isEmpty())
)
if (emptyIndex < 0) return container
return removeEmptyElements(removeElement(container, emptyIndex), provider)
}
export const useContainerState = (valueProvider: FilterValueProvider) => {
const [value, setValue] = useState<FilterContainer>([]);
@ -124,6 +135,10 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
setValue([]);
};
const clearEmpty = () => {
setValue(v => removeEmptyElements(v, valueProvider))
}
return {
create,
exist,
@ -133,5 +148,6 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
removeAt,
value,
clear,
clearEmpty
};
};