Experimental filters: add clear button and bumps UI to support ranges (#3975)

This commit is contained in:
Krzysztof Żuraw 2023-07-24 14:45:52 +02:00 committed by GitHub
parent 10d30ca9a4
commit d2074f4824
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 120 additions and 82 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---
Experimental filters: add clear function and bumps UI to support ranges

14
package-lock.json generated
View file

@ -27,7 +27,7 @@
"@material-ui/lab": "^4.0.0-alpha.61",
"@material-ui/styles": "^4.11.4",
"@reach/auto-id": "^0.16.0",
"@saleor/macaw-ui": "0.8.0-pre.107",
"@saleor/macaw-ui": "0.8.0-pre.109",
"@saleor/sdk": "0.6.0",
"@sentry/react": "^6.0.0",
"@types/faker": "^5.1.6",
@ -8260,9 +8260,9 @@
}
},
"node_modules/@saleor/macaw-ui": {
"version": "0.8.0-pre.107",
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.107.tgz",
"integrity": "sha512-Z7xA1TM4KXjRJvz6gx6cKhw/pCB7q5BT+yYAAdGDKbfvMFRjh3mXilH8NOF3kkYwEe+3ykeLvijCyp1Bm7UH9w==",
"version": "0.8.0-pre.109",
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.109.tgz",
"integrity": "sha512-lTIe2ha18IBQk+Fy8boo1USi0Z6ISPT2jOqBd2dAP+PkPwM5quAR8hfEICuOUmac8qzjZBCQ/uv2FLbue9rquA==",
"dependencies": {
"@dessert-box/react": "^0.4.0",
"@floating-ui/react-dom-interactions": "^0.5.0",
@ -41546,9 +41546,9 @@
}
},
"@saleor/macaw-ui": {
"version": "0.8.0-pre.107",
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.107.tgz",
"integrity": "sha512-Z7xA1TM4KXjRJvz6gx6cKhw/pCB7q5BT+yYAAdGDKbfvMFRjh3mXilH8NOF3kkYwEe+3ykeLvijCyp1Bm7UH9w==",
"version": "0.8.0-pre.109",
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.109.tgz",
"integrity": "sha512-lTIe2ha18IBQk+Fy8boo1USi0Z6ISPT2jOqBd2dAP+PkPwM5quAR8hfEICuOUmac8qzjZBCQ/uv2FLbue9rquA==",
"requires": {
"@dessert-box/react": "^0.4.0",
"@floating-ui/react-dom-interactions": "^0.5.0",

View file

@ -34,7 +34,7 @@
"@material-ui/lab": "^4.0.0-alpha.61",
"@material-ui/styles": "^4.11.4",
"@reach/auto-id": "^0.16.0",
"@saleor/macaw-ui": "0.8.0-pre.107",
"@saleor/macaw-ui": "0.8.0-pre.109",
"@saleor/sdk": "0.6.0",
"@sentry/react": "^6.0.0",
"@types/faker": "^5.1.6",

View file

@ -2,8 +2,11 @@ import { ConditionalFilters } from "@dashboard/components/ConditionalFilter";
import { Box, Button, CloseIcon, Popover, Text } from "@saleor/macaw-ui/next";
import React from "react";
export const ExpressionFilters = () => (
<Popover>
export const ExpressionFilters = () => {
const [open, setOpen] = React.useState(false);
return (
<Popover open={open} onOpenChange={open => setOpen(open)}>
<Popover.Trigger>
<Button>Show filters</Button>
</Popover.Trigger>
@ -35,8 +38,9 @@ export const ExpressionFilters = () => (
</Popover.Close>
</Box>
</Box>
<ConditionalFilters />
<ConditionalFilters onClose={() => setOpen(false)} />
</Box>
</Popover.Content>
</Popover>
);
);
};

View file

@ -6,11 +6,20 @@ import { FilterContainer } from "./FilterElement";
import { FiltersArea } from "./FiltersArea";
import { LoadingFiltersArea } from "./LoadingFiltersArea";
export const ConditionalFilters: FC = () => {
const { valueProvider } = useConditionalFilterContext();
export const ConditionalFilters: FC<{ onClose: () => void }> = ({
onClose,
}) => {
const { valueProvider, containerState } = useConditionalFilterContext();
const handleConfirm = (value: FilterContainer) => {
valueProvider.persist(value);
onClose();
};
const handleCancel = () => {
valueProvider.clear();
containerState.clear();
onClose();
};
return valueProvider.loading ? (
@ -22,7 +31,7 @@ export const ConditionalFilters: FC = () => {
borderBottomLeftRadius={2}
borderBottomRightRadius={2}
>
<FiltersArea onConfirm={handleConfirm} />
<FiltersArea onConfirm={handleConfirm} onCancel={handleCancel} />
</Box>
);
};

View file

@ -4,4 +4,5 @@ export interface FilterValueProvider {
value: FilterContainer;
loading: boolean;
persist: (newValue: FilterContainer) => void;
clear: () => void;
}

View file

@ -1,5 +1,5 @@
import { _ExperimentalFilters, Box, FilterEvent } from "@saleor/macaw-ui/next";
import React from "react";
import React, { FC } from "react";
import { useConditionalFilterContext } from "./context";
import { FilterContainer } from "./FilterElement";
@ -8,9 +8,10 @@ import { useFilterContainer } from "./useFilterContainer";
interface FiltersAreaProps {
onConfirm: (value: FilterContainer) => void;
onCancel?: () => void;
}
export const FiltersArea = ({ onConfirm }: FiltersAreaProps) => {
export const FiltersArea: FC<FiltersAreaProps> = ({ onConfirm, onCancel }) => {
const { apiProvider, leftOperandsProvider } = useConditionalFilterContext();
const {
@ -72,7 +73,7 @@ export const FiltersArea = ({ onConfirm }: FiltersAreaProps) => {
+ Add row
</_ExperimentalFilters.AddRowButton>
<Box display="flex" gap={3}>
<_ExperimentalFilters.ClearButton>
<_ExperimentalFilters.ClearButton onClick={onCancel}>
Clear
</_ExperimentalFilters.ClearButton>
<_ExperimentalFilters.ConfirmButton onClick={() => onConfirm(value)}>

View file

@ -54,9 +54,17 @@ export const useUrlValueProvider = (
setValue(filterValue);
};
const clear = () => {
router.history.replace({
pathname: router.location.pathname,
});
setValue([]);
};
return {
value,
loading,
persist,
clear,
};
};

View file

@ -6,48 +6,51 @@ import { FilterValueProvider } from "./FilterValueProvider";
type StateCallback = (el: FilterElement) => void;
type Element = FilterContainer[number];
const isFilterElement = (el: unknown): el is FilterElement => typeof el !== "string" && !Array.isArray(el)
const isFilterElement = (el: unknown): el is FilterElement =>
typeof el !== "string" && !Array.isArray(el);
const removeConstraint = (container: FilterContainer) => {
return container.map((el) => {
if (!isFilterElement(el)) return el
return container.map(el => {
if (!isFilterElement(el)) return el;
if (!el.constraint?.existIn(container)) {
el.clearConstraint()
el.clearConstraint();
}
return el
})
}
return el;
});
};
const calculateIndexesToRemove = (container: FilterContainer, position: number) => {
const next = position + 1
const previous = position - 1
const indexTuple = [position]
const calculateIndexesToRemove = (
container: FilterContainer,
position: number,
) => {
const next = position + 1;
const previous = position - 1;
const indexTuple = [position];
if (typeof container[next] === "string") {
indexTuple.push(next)
indexTuple.push(next);
return indexTuple
return indexTuple;
}
if (typeof container[previous] === "string") {
indexTuple.push(previous)
indexTuple.push(previous);
}
return indexTuple
}
return indexTuple;
};
const removeElement = (container: FilterContainer, position: number) => {
const indexTuple = calculateIndexesToRemove(container, position)
const indexTuple = calculateIndexesToRemove(container, position);
const newContainer = container
.filter((_, elIndex) => !indexTuple.includes(elIndex))
const newContainer = container.filter(
(_, elIndex) => !indexTuple.includes(elIndex),
);
return removeConstraint(newContainer)
}
return removeConstraint(newContainer);
};
export const useContainerState = (valueProvider: FilterValueProvider) => {
const [value, setValue] = useState<FilterContainer>([]);
@ -81,13 +84,15 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
};
const updateBySlug = (slug: string, cb: StateCallback) => {
setValue(v => v.map((el) => {
setValue(v =>
v.map(el => {
if (isFilterElement(el) && el.value.value === slug) {
cb(el)
cb(el);
}
return el
}))
return el;
}),
);
};
const removeAt = (position: string) => {
@ -109,13 +114,17 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
};
const exist = (slug: string) => {
return value.some((entry) =>
isFilterElement(entry) && entry.value.value === slug
)
}
return value.some(
entry => isFilterElement(entry) && entry.value.value === slug,
);
};
const createEmpty = () => {
create(FilterElement.createEmpty())
create(FilterElement.createEmpty());
};
const clear = () => {
setValue([]);
};
return {
@ -126,5 +135,6 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
updateAt,
removeAt,
value,
clear,
};
};