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

View file

@ -164,6 +164,10 @@ export class FilterElement {
return UrlEntry.forStatic(this.condition.selected, this.value.value); 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 { public static isCompatible(element: unknown): element is FilterElement {
return ( return (
typeof element === "object" && typeof element === "object" &&

View file

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

View file

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

View file

@ -49,6 +49,17 @@ const removeElement = (container: FilterContainer, position: number) => {
return removeConstraint(newContainer); 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) => { export const useContainerState = (valueProvider: FilterValueProvider) => {
const [value, setValue] = useState<FilterContainer>([]); const [value, setValue] = useState<FilterContainer>([]);
@ -124,6 +135,10 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
setValue([]); setValue([]);
}; };
const clearEmpty = () => {
setValue(v => removeEmptyElements(v, valueProvider))
}
return { return {
create, create,
exist, exist,
@ -133,5 +148,6 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
removeAt, removeAt,
value, value,
clear, clear,
clearEmpty
}; };
}; };