Skip to content

Commit 002ac9e

Browse files
authored
[FIX] remove filter when submitting filter form without value (#5860)
1 parent 01b81b8 commit 002ac9e

File tree

5 files changed

+140
-23
lines changed

5 files changed

+140
-23
lines changed

frontend/app/src/entities/nodes/object/ui/filters/attribute-filter-form.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from "@/entities/nodes/object/ui/filters/filter-condition-select";
77
import { AttributeSchema } from "@/entities/schema/types";
88
import { getCurrentFilterCondition } from "@/shared/components/filters/utils/get-current-filter-condition";
9-
import { FormFieldValue } from "@/shared/components/form/type";
9+
import { FormAttributeValue } from "@/shared/components/form/type";
1010
import { Form, FormField, FormSubmit } from "@/shared/components/ui/form";
1111
import useFilters, { Filter } from "@/shared/hooks/useFilters";
1212
import { useState } from "react";
@@ -19,20 +19,21 @@ export type AttributeFilterFormProps = {
1919
export function AttributeFilterForm({ attributeSchema, onSuccess }: AttributeFilterFormProps) {
2020
const [filters, setFilters] = useFilters();
2121
const currentFilter = filters.find((filter) => filter.name.startsWith(attributeSchema.name));
22-
const [condition, setCondition] = useState<FilterCondition | undefined>(
22+
const [condition, setCondition] = useState<FilterCondition>(
2323
getCurrentFilterCondition(currentFilter) ?? FILTER_CONDITION.CONTAINS
2424
);
2525

26-
const handleSubmit = (formData: Record<string, FormFieldValue>) => {
26+
const handleSubmit = (formData: Record<string, FormAttributeValue["value"]>) => {
2727
if (condition === FILTER_CONDITION.CONTAINS) {
2828
const { attribute } = formData;
2929

30-
if (attribute === undefined) {
31-
return;
30+
if (!attribute && attribute !== 0) {
31+
return setFilters(filters.filter((f) => !f.name.startsWith(attributeSchema.name)));
3232
}
3333

34+
const isAttributeArray = Array.isArray(attribute);
3435
const newFilter: Filter = {
35-
name: `${attributeSchema.name}__value`,
36+
name: `${attributeSchema.name}__${isAttributeArray ? "values" : "value"}`,
3637
value: attribute,
3738
};
3839

@@ -87,7 +88,12 @@ export function AttributeFilterForm({ attributeSchema, onSuccess }: AttributeFil
8788
{condition === FILTER_CONDITION.CONTAINS && (
8889
<FormField
8990
name="attribute"
90-
defaultValue={currentFilter?.value}
91+
defaultValue={
92+
currentFilter &&
93+
getCurrentFilterCondition(currentFilter) === FILTER_CONDITION.CONTAINS
94+
? currentFilter.value
95+
: undefined
96+
}
9197
render={({ field }) => {
9298
return <DynamicFilterInput {...field} fieldSchema={attributeSchema} />;
9399
}}

frontend/app/src/entities/nodes/object/ui/filters/relationship-filter-form.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ export function RelationshipFilterForm({
3333
}: RelationshipFilterFormProps) {
3434
const [filters, setFilters] = useFilters();
3535
const currentFilter = filters.find((filter) => filter.name.startsWith(relationshipSchema.name));
36-
const [condition, setCondition] = useState<FilterCondition | undefined>(
37-
getCurrentFilterCondition(currentFilter) ?? "is any of"
36+
const [condition, setCondition] = useState<FilterCondition>(
37+
getCurrentFilterCondition(currentFilter) ?? FILTER_CONDITION.IS_ANY_OF
3838
);
3939

4040
const handleSubmit = (data: FormData) => {
@@ -98,10 +98,15 @@ export function RelationshipFilterForm({
9898
}}
9999
data-testid="relationship-filter-form"
100100
>
101-
{condition === "is any of" && (
101+
{condition === FILTER_CONDITION.IS_ANY_OF && (
102102
<FormField
103103
name="relationships"
104-
defaultValue={currentFilter?.value}
104+
defaultValue={
105+
currentFilter &&
106+
getCurrentFilterCondition(currentFilter) === FILTER_CONDITION.IS_ANY_OF
107+
? currentFilter.value
108+
: undefined
109+
}
105110
render={({ field }) => {
106111
const value = field.value as RelationshipNode[] | undefined;
107112

frontend/app/src/entities/nodes/object/ui/object-table/cells/table-column-header.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { AttributeFilterForm } from "@/entities/nodes/object/ui/filters/attribut
22
import { RelationshipFilterForm } from "@/entities/nodes/object/ui/filters/relationship-filter-form";
33
import { TableColumnHeaderIcon } from "@/entities/nodes/object/ui/object-table/cells/table-column-header-icon";
44
import { AttributeSchema, ModelSchema, RelationshipSchema } from "@/entities/schema/types";
5-
import { getObjectFromFilters } from "@/shared/components/filters/utils/getObjectFromFilters";
65
import { cellHeaderStyle, cellsStyle } from "@/shared/components/table/style";
76
import { Popover, PopoverContent, PopoverTrigger } from "@/shared/components/ui/popover";
87
import useFilters from "@/shared/hooks/useFilters";
@@ -19,8 +18,7 @@ export interface TableColumnHeaderProps extends PopoverTriggerProps {
1918
export function TableColumnHeader({ schema, columnSchema, ...props }: TableColumnHeaderProps) {
2019
const [filters] = useFilters();
2120
const [showFilters, setShowFilters] = useState(false);
22-
const filtersAsObjectData = getObjectFromFilters(schema, filters);
23-
const currentColumnFilters = filtersAsObjectData[columnSchema.name];
21+
const currentColumnFilters = filters.find((f) => f.name.startsWith(columnSchema.name));
2422

2523
const closePopover = () => {
2624
setShowFilters(false);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { FILTER_CONDITION } from "@/entities/nodes/object/ui/filters/filter-condition-select";
2+
import { Filter } from "@/shared/hooks/useFilters";
3+
import { describe, expect, it } from "vitest";
4+
import { getCurrentFilterCondition } from "./get-current-filter-condition";
5+
6+
describe("getCurrentFilterCondition", () => {
7+
it("should return undefined when no filter is provided", () => {
8+
// GIVEN
9+
const filter = undefined;
10+
11+
// WHEN
12+
const result = getCurrentFilterCondition(filter);
13+
14+
// THEN
15+
expect(result).toBeUndefined();
16+
});
17+
18+
it("should return CONTAINS condition for field__value filter", () => {
19+
// GIVEN
20+
const filter: Filter = { name: "field__value", value: "test" };
21+
22+
// WHEN
23+
const result = getCurrentFilterCondition(filter);
24+
25+
// THEN
26+
expect(result).toEqual(FILTER_CONDITION.CONTAINS);
27+
});
28+
29+
it("should return IS_ANY_OF condition for field__ids filter", () => {
30+
// GIVEN
31+
const filter: Filter = { name: "field__ids", value: ["id1", "id2"] };
32+
33+
// WHEN
34+
const result = getCurrentFilterCondition(filter);
35+
36+
// THEN
37+
expect(result).toEqual(FILTER_CONDITION.IS_ANY_OF);
38+
});
39+
40+
it("should return IS_ANY_OF condition for field__values filter", () => {
41+
// GIVEN
42+
const filter: Filter = { name: "field__values", value: ["value1", "value2"] };
43+
44+
// WHEN
45+
const result = getCurrentFilterCondition(filter);
46+
47+
// THEN
48+
expect(result).toEqual(FILTER_CONDITION.IS_ANY_OF);
49+
});
50+
51+
it("should return IS_EMPTY condition for field__isnull filter with true value", () => {
52+
// GIVEN
53+
const filter: Filter = { name: "field__isnull", value: true };
54+
55+
// WHEN
56+
const result = getCurrentFilterCondition(filter);
57+
58+
// THEN
59+
expect(result).toEqual(FILTER_CONDITION.IS_EMPTY);
60+
});
61+
62+
it("should return IS_NOT_EMPTY condition for field__isnull filter with false value", () => {
63+
// GIVEN
64+
const filter: Filter = { name: "field__isnull", value: false };
65+
66+
// WHEN
67+
const result = getCurrentFilterCondition(filter);
68+
69+
// THEN
70+
expect(result).toEqual(FILTER_CONDITION.IS_NOT_EMPTY);
71+
});
72+
73+
it("should return undefined for filter with unknown condition suffix", () => {
74+
// GIVEN
75+
const filter: Filter = { name: "field__unknown", value: "test" };
76+
77+
// WHEN
78+
const result = getCurrentFilterCondition(filter);
79+
80+
// THEN
81+
expect(result).toBeUndefined();
82+
});
83+
84+
it("should return undefined for filter with no condition suffix", () => {
85+
// GIVEN
86+
const filter: Filter = { name: "field", value: "test" } as unknown as Filter;
87+
88+
// WHEN
89+
const result = getCurrentFilterCondition(filter);
90+
91+
// THEN
92+
expect(result).toBeUndefined();
93+
});
94+
});
Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,30 @@
1-
import { FILTER_CONDITION } from "@/entities/nodes/object/ui/filters/filter-condition-select";
1+
import {
2+
FILTER_CONDITION,
3+
FilterCondition,
4+
} from "@/entities/nodes/object/ui/filters/filter-condition-select";
25
import { Filter } from "@/shared/hooks/useFilters";
36

4-
export function getCurrentFilterCondition(filter?: Filter) {
7+
/**
8+
* Determines the current filter condition based on the filter name and value.
9+
*
10+
* @param filter - The filter object to analyze
11+
* @returns The corresponding filter condition or undefined if no filter is provided
12+
*/
13+
export function getCurrentFilterCondition(filter?: Filter): FilterCondition | undefined {
514
if (!filter) return undefined;
615

7-
const condition = filter.name.split("__")[1];
16+
const parts = filter.name.split("__");
17+
const condition = parts.length > 1 ? parts[1] : "";
818

9-
if (condition === "ids") {
10-
return FILTER_CONDITION.IS_ANY_OF;
11-
}
12-
13-
if (condition === "isnull") {
14-
return filter.value ? FILTER_CONDITION.IS_EMPTY : FILTER_CONDITION.IS_NOT_EMPTY;
19+
switch (condition) {
20+
case "value":
21+
return FILTER_CONDITION.CONTAINS;
22+
case "ids":
23+
case "values":
24+
return FILTER_CONDITION.IS_ANY_OF;
25+
case "isnull":
26+
return filter.value ? FILTER_CONDITION.IS_EMPTY : FILTER_CONDITION.IS_NOT_EMPTY;
27+
default:
28+
return undefined;
1529
}
1630
}

0 commit comments

Comments
 (0)