Skip to content

Commit

Permalink
#635 - feat: method to clear filters
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian Roeland authored and Xaohs committed Jan 30, 2025
1 parent 93ff844 commit 709ecb5
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# fmt: off
from django.test import tag

from openarchiefbeheer.destruction.constants import ListStatus
from openarchiefbeheer.utils.tests.e2e import browser_page
from openarchiefbeheer.utils.tests.gherkin import GherkinLikeTestCase


@tag("e2e")
@tag("gh-635")
class Issue635FiltersReset(GherkinLikeTestCase):
# Tests if:
# - Reset button resets query parameters
# - Reset button resets input fields
# - Reset button resets page number to 1
# - Reset button is not shown when no filters are applied
async def test_scenario_reset_button_works(self):
async with browser_page() as page:
zaken = await self.given.zaken_are_indexed(amount=500)
record_manager = await self.given.record_manager_exists()

await self.given.list_exists(
name="Destruction list to reset filters for",
status=ListStatus.ready_to_review,
zaken=zaken,
)

await self.when.user_logs_in(page, record_manager)
await self.then.path_should_be(page, "/destruction-lists")
await self.when.user_clicks_button(page, "Destruction list to reset filters for")
await self.then.url_should_contain_text(page, "destruction-lists/")
initial_url_with_page = page.url + "?page=1"
await self.when.user_clicks_button(page, "Volgende")
await self.then.url_should_contain_text(page, "page=2")
await self.then.page_should_not_contain_text(page, "Filters wissen")
await self.when.user_filters_zaken(page, "omschrijving", "some text")
await self.then.url_should_contain_text(page, "omschrijving__icontains=")
await self.when.user_clicks_button(page, "Filters wissen")
await self.then.input_field_should_be_empty(page, "Omschrijving")
await self.then.url_should_be(page, initial_url_with_page)
12 changes: 12 additions & 0 deletions backend/src/openarchiefbeheer/utils/tests/gherkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,14 @@ async def page_should_contain_text(self, page, text, timeout=None):
element = page.locator(f"text={text}")
await expect(element.nth(0)).to_be_visible(timeout=timeout)

async def page_should_not_contain_text(self, page, text, timeout=None):
if timeout is None:
timeout = 500 if self.is_inverted else 10000

# Check if the text is not present within the timeout
element = page.locator(f"text={text}")
await expect(element).to_have_count(0, timeout=timeout)

async def page_should_contain_element_with_title(
self, page, title, timeout=5000
):
Expand Down Expand Up @@ -771,3 +779,7 @@ async def this_number_of_zaken_should_be_visible(self, page, number):
rows = await locator.locator("tbody").locator("tr").all()

self.testcase.assertEqual(len(rows), number)

async def input_field_should_be_empty(self, page, placeholder):
locator = page.get_by_placeholder(placeholder)
await expect(locator).to_have_value("")
59 changes: 55 additions & 4 deletions frontend/src/hooks/useFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export function useFields<T extends Zaak = Zaak>(
(
filterData: Partial<TypedSerializedFormData<keyof T & string>>,
) => FilterTransformReturnType<T>,
Record<string, string>,
() => void,
] {
const [fieldSelectionState, setFieldSelectionState] =
useState<FieldSelection>();
Expand All @@ -53,7 +55,7 @@ export function useFields<T extends Zaak = Zaak>(
setFieldSelectionState(fieldSelection),
);
}, []);
const [searchParams] = useSearchParams();
const [searchParams, setSearchParams] = useSearchParams();
const selectielijstKlasseChoices = useSelectielijstKlasseChoices();
const zaaktypeChoices = useZaaktypeChoices(
destructionList,
Expand All @@ -62,8 +64,9 @@ export function useFields<T extends Zaak = Zaak>(
);

// The raw, unfiltered configuration of the available base fields.
// Both filterLookup AND filterLookups will be used for clearing filters.
// NOTE: This get filtered by `getActiveFields()`.
const fields: TypedField<T>[] = [
const fields: (TypedField<T> & { filterLookups?: string[] })[] = [
{
name: "identificatie",
filterLookup: "identificatie__icontains",
Expand Down Expand Up @@ -96,6 +99,7 @@ export function useFields<T extends Zaak = Zaak>(
{
name: "startdatum",
type: "daterange",
filterLookups: ["startdatum__gte", "startdatum__lte"],
filterValue:
searchParams.get("startdatum__gte") &&
searchParams.get("startdatum__lte")
Expand All @@ -108,6 +112,7 @@ export function useFields<T extends Zaak = Zaak>(
{
name: "einddatum",
type: "daterange",
filterLookups: ["einddatum__gte", "einddatum__lte"],
filterValue:
searchParams.get("einddatum__gte") && searchParams.get("einddatum__lte")
? `${searchParams.get("einddatum__gte")}/${searchParams.get("einddatum__lte")}`
Expand Down Expand Up @@ -162,6 +167,7 @@ export function useFields<T extends Zaak = Zaak>(
name: "archiefactiedatum",
type: "daterange",
width: "130px",
filterLookups: ["archiefactiedatum__gte", "archiefactiedatum__lte"],
filterValue:
searchParams.get("archiefactiedatum__gte") &&
searchParams.get("archiefactiedatum__lte")
Expand Down Expand Up @@ -206,6 +212,17 @@ export function useFields<T extends Zaak = Zaak>(
...(extraFields || []),
];

const filterLookupValues = [
...new Set(
fields
.flatMap((field) => [
field.filterLookup,
...(field.filterLookups || []),
])
.filter(Boolean),
),
];

const getActiveFields = useCallback(() => {
return fields.map((field) => {
const isActiveFromStorage =
Expand All @@ -214,10 +231,38 @@ export function useFields<T extends Zaak = Zaak>(
typeof isActiveFromStorage === "undefined"
? field.active !== false
: isActiveFromStorage;
return { ...field, active: isActive } as TypedField;
return { ...field, active: isActive };
});
}, [fields, fieldSelectionState]);

/**
* Function to reset all the filters
* It will concat all the `filterLookup` and `filterLookups` values from the `fields` array and remove them from the searchParams
*/
const resetFilters = () => {
const newSearchParams = new URLSearchParams(searchParams);
filterLookupValues.forEach((filterLookup) => {
if (!filterLookup) return;
newSearchParams.delete(filterLookup);
});
setSearchParams(newSearchParams);
};

/**
* A function to return the current active filters
*/
const getActiveFilters = () => {
const activeFilters: Record<string, string> = {};
filterLookupValues.forEach((filterLookup) => {
if (!filterLookup) return;
const value = searchParams.get(filterLookup);
if (value) {
activeFilters[filterLookup] = value;
}
});
return activeFilters;
};

/**
* Gets called when the fields selection is changed.
* Pass this to `filterTransform` of a DataGrid component.
Expand Down Expand Up @@ -267,5 +312,11 @@ export function useFields<T extends Zaak = Zaak>(
};
};

return [getActiveFields(), setFields, filterTransform];
return [
getActiveFields(),
setFields,
filterTransform,
getActiveFilters(),
resetFilters,
];
}
31 changes: 23 additions & 8 deletions frontend/src/pages/destructionlist/abstract/BaseListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,8 @@ export function BaseListView<T extends Zaak = Zaak>({
})) as unknown as T[];

// Fields.
const [fields, setFields, filterTransform] = useFields<T>(
destructionList,
review,
extraFields,
);
const [fields, setFields, filterTransform, activeFilters, resetFilters] =
useFields<T>(destructionList, review, extraFields);
type FilterTransformData = ReturnType<typeof filterTransform>;

// Filter.
Expand Down Expand Up @@ -162,7 +159,7 @@ export function BaseListView<T extends Zaak = Zaak>({
: { ...props, disabled: selectable && !hasSelection },
);
const fixedItems = disabled
? ([
? [
{
children: (
<>
Expand All @@ -174,9 +171,27 @@ export function BaseListView<T extends Zaak = Zaak>({
wrap: false,
onClick: handleClearZaakSelection,
},
] as ButtonProps[])
]
: [];
return [...dynamicItems, ...fixedItems];
if (!Object.keys(activeFilters).length) {
return [...dynamicItems, ...fixedItems];
}

return [
...dynamicItems,
...fixedItems,
{
children: (
<>
<Solid.XCircleIcon />
Filters wissen
</>
),
variant: "warning",
wrap: false,
onClick: resetFilters,
},
];
}, [selectable, hasSelection, selectedZakenOnPage, selectionActions]);

return (
Expand Down

0 comments on commit 709ecb5

Please sign in to comment.