From 42bb6084d3c3b01b05a400ba7743111e1370c937 Mon Sep 17 00:00:00 2001 From: Vera Kahn Date: Wed, 8 Nov 2023 12:52:18 -0500 Subject: [PATCH] add applied filter string func --- src/models/itemFilterData.ts | 14 ++++++ src/utils/itemFilterUtils.ts | 26 ++++++++++ src/utils/utilsTests/itemFilterUtils.test.tsx | 49 +++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/src/models/itemFilterData.ts b/src/models/itemFilterData.ts index a283ffc08..f2103842d 100644 --- a/src/models/itemFilterData.ts +++ b/src/models/itemFilterData.ts @@ -19,6 +19,20 @@ export class ItemFilterData { displayOptions(): Option[] { return this.options } + + labelForValue(value: string) { + return this.displayOptions().find((opt: Option) => { + return opt.value === value + })?.label + } + + labelsForConcatenatedValues(values: string) { + return Array.from( + new Set( + values.split(",").map((val: string) => `'${this.labelForValue(val)}'`) + ) + ).join(", ") + } } export class LocationFilterData extends ItemFilterData { diff --git a/src/utils/itemFilterUtils.ts b/src/utils/itemFilterUtils.ts index 5a308809e..33b61d4b4 100644 --- a/src/utils/itemFilterUtils.ts +++ b/src/utils/itemFilterUtils.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import type { ItemFilterData } from "../models/itemFilterData" import type { AppliedFilters } from "../types/filterTypes" export const isRecapLocation = (loc: string) => { @@ -48,3 +49,28 @@ export const buildItemFilterQueryParams = ( const query = encodeURI(`?${location_query}${format_query}${status_query}`) return query.length > 3 ? query : "" } + +export const buildAppliedFiltersString = ( + query: BibPageQueryParams, + numItems = 20, + itemAggs: ItemFilterData[] +) => { + const items = `Item${numItems === 1 ? "" : "s"}` + if (Object.keys(query).length === 0) return `${numItems} ${items}` + const num = numItems === 0 ? "No" : numItems + const numMatchingItems = `${num} ${items} Matching ` + const filters = Object.keys(query) + .map((field: string) => { + const queryPerField = query[field] + if (queryPerField) { + const fieldAggregations = itemAggs.find( + (agg: ItemFilterData) => agg.field === field.substring(5) + ) + const labels = + fieldAggregations.labelsForConcatenatedValues(queryPerField) + return field.substring(5) + ": " + labels + } + }) + .filter((filter) => filter) + return numMatchingItems + "Filtered by " + filters.join(", ") +} diff --git a/src/utils/utilsTests/itemFilterUtils.test.tsx b/src/utils/utilsTests/itemFilterUtils.test.tsx index 4ae418de1..c4b6152ce 100644 --- a/src/utils/utilsTests/itemFilterUtils.test.tsx +++ b/src/utils/utilsTests/itemFilterUtils.test.tsx @@ -3,7 +3,10 @@ import { combineRecapLocations, parseItemFilterQueryParams, buildItemFilterQueryParams, + buildAppliedFiltersString, } from "../itemFilterUtils" +import testAggregations from "../../../__test__/fixtures/testAggregations" +import { ItemFilterData } from "../../models/itemFilterData" describe("Item Filter Utils", () => { describe("isRecapLocation", () => { @@ -86,4 +89,50 @@ describe("Item Filter Utils", () => { ) }) }) + + describe("buildAppliedFiltersString", () => { + const query = { + item_location: "loc:rc2ma,loc:rcma2", + item_status: "status:a", + item_format: "Text", + } + const aggs = testAggregations.map((agg) => new ItemFilterData(agg)) + it("can handle no filters", () => { + expect(buildAppliedFiltersString({}, 30, [])).toBe("30 Items") + }) + it("no items with filters", () => { + const query = { + item_location: "loc:rc2ma,loc:rcma2", + item_status: "status:a", + item_format: "Text", + } + expect(buildAppliedFiltersString(query, 0, aggs)).toBe( + "No Items Matching Filtered by location: 'Offsite', status: 'Available', format: 'Text'" + ) + }) + it("some items no filters", () => { + expect(buildAppliedFiltersString({}, 5, aggs)).toBe("5 Items") + }) + it("some items with filters", () => { + expect(buildAppliedFiltersString(query, 5, aggs)).toBe( + "5 Items Matching Filtered by location: 'Offsite', status: 'Available', format: 'Text'" + ) + }) + it("one item with filters", () => { + expect(buildAppliedFiltersString(query, 1, aggs)).toBe( + "1 Item Matching Filtered by location: 'Offsite', status: 'Available', format: 'Text'" + ) + }) + it("some items one filter", () => { + expect( + buildAppliedFiltersString( + { item_status: "status:a,status:na" }, + 5, + aggs + ) + ).toBe( + "5 Items Matching Filtered by status: 'Available', 'Not available'" + ) + }) + }) })