From 39f1aa4bfb450b117a9959b46b10ccbd0da8b90d Mon Sep 17 00:00:00 2001 From: Greg Pascucci <greg.pascucci@gmail.com> Date: Wed, 13 Nov 2024 08:18:57 -0800 Subject: [PATCH 1/3] updates to cleard advanced search component --- backend/.gitignore | 5 ++- .../Openings/AdvancedSearchDropdown/index.tsx | 36 +++++++++++-------- .../Openings/OpeningsSearchBar/index.tsx | 20 +++++++++-- .../src/contexts/search/OpeningsSearch.tsx | 1 + frontend/src/utils/DateUtils.ts | 11 ++++++ 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/backend/.gitignore b/backend/.gitignore index 449b5cdf..620063d7 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -397,7 +397,6 @@ dist # The below expression will prevent user specific configuration files from being added to the repository config/application-dev-*.yml .checkstyle - - temp/ -config/*.jks \ No newline at end of file +config/*.jks +zscaler-cgi.crt \ No newline at end of file diff --git a/frontend/src/components/SilvicultureSearch/Openings/AdvancedSearchDropdown/index.tsx b/frontend/src/components/SilvicultureSearch/Openings/AdvancedSearchDropdown/index.tsx index d04a9b28..f34ea189 100644 --- a/frontend/src/components/SilvicultureSearch/Openings/AdvancedSearchDropdown/index.tsx +++ b/frontend/src/components/SilvicultureSearch/Openings/AdvancedSearchDropdown/index.tsx @@ -18,21 +18,22 @@ import "./AdvancedSearchDropdown.scss"; import * as Icons from "@carbon/icons-react"; import { useOpeningFiltersQuery } from "../../../../services/queries/search/openingQueries"; import { useOpeningsSearch } from "../../../../contexts/search/OpeningsSearch"; +import { formatDateForDatePicker } from "../../../../utils/DateUtils"; interface AdvancedSearchDropdownProps { toggleShowFilters: () => void; // Function to be passed as a prop } const AdvancedSearchDropdown: React.FC<AdvancedSearchDropdownProps> = () => { - const { filters, setFilters } = useOpeningsSearch(); + const { filters, setFilters, clearFilters } = useOpeningsSearch(); const { data, isLoading, isError } = useOpeningFiltersQuery(); // Initialize selected items for OrgUnit MultiSelect based on existing filters const [selectedOrgUnits, setSelectedOrgUnits] = useState<any[]>([]); - // Initialize selected items for category MultiSelect based on existing filters const [selectedCategories, setSelectedCategories] = useState<any[]>([]); useEffect(() => { + console.log("Use Effect in child is being called.", filters); // Split filters.orgUnit into array and format as needed for selectedItems if (filters.orgUnit) { const orgUnitsArray = filters.orgUnit.map((orgUnit: string) => ({ @@ -45,14 +46,16 @@ const AdvancedSearchDropdown: React.FC<AdvancedSearchDropdownProps> = () => { } // Split filters.category into array and format as needed for selectedItems if (filters.category) { - const categoriesArray = filters.category.map((category: string) => ({ - text: category, - value: category, - })); - setSelectedCategories(categoriesArray); - } else{ - setSelectedCategories([]); - } + const categoriesArray = filters.category.map((category: string) => ({ + text: category, + value: category, + })); + setSelectedCategories(categoriesArray); + } else { + setSelectedCategories([]); + } + + }, [filters.orgUnit, filters.category]); const handleFilterChange = (updatedFilters: Partial<typeof filters>) => { @@ -60,12 +63,13 @@ const AdvancedSearchDropdown: React.FC<AdvancedSearchDropdownProps> = () => { setFilters(newFilters); }; + const handleMultiSelectChange = (group: string, selectedItems: any) => { const updatedGroup = selectedItems.map((item: any) => item.value); if (group === "orgUnit") - setSelectedOrgUnits(updatedGroup); + setSelectedOrgUnits(updatedGroup); if (group === "category") - setSelectedCategories(updatedGroup); + setSelectedCategories(updatedGroup); handleFilterChange({ [group]: updatedGroup }); } @@ -271,8 +275,8 @@ const AdvancedSearchDropdown: React.FC<AdvancedSearchDropdownProps> = () => { selectedItem={ filters.dateType ? dateTypeItems.find( - (item: any) => item.value === filters.dateType - ) + (item: any) => item.value === filters.dateType + ) : "" } label="Date type" @@ -310,10 +314,11 @@ const AdvancedSearchDropdown: React.FC<AdvancedSearchDropdownProps> = () => { size="md" labelText="Start Date" placeholder={ - filters.startDate !== null + filters.startDate ? filters.startDate // Display the date in YYYY-MM-DD format : "yyyy/MM/dd" } + value={formatDateForDatePicker(filters.startDate)} /> </DatePicker> @@ -344,6 +349,7 @@ const AdvancedSearchDropdown: React.FC<AdvancedSearchDropdownProps> = () => { ? filters.endDate // Display the date in YYYY-MM-DD format : "yyyy/MM/dd" } + value={formatDateForDatePicker(filters.endDate)} /> </DatePicker> </div> diff --git a/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx b/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx index 173840aa..857a65d2 100644 --- a/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx +++ b/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useRef } from "react"; import "./OpeningsSearchBar.scss"; import { Search, Button, FlexGrid, Row, Column, DismissibleTag } from "@carbon/react"; import * as Icons from "@carbon/icons-react"; @@ -6,6 +6,8 @@ import AdvancedSearchDropdown from "../AdvancedSearchDropdown"; import SearchFilterBar from "../SearchFilterBar"; import { useOpeningsSearch } from "../../../../contexts/search/OpeningsSearch"; import { countActiveFilters } from "../../../../utils/searchUtils"; +import { callbackify } from "util"; +import { c } from "vite/dist/node/types.d-aGj9QkWt"; interface IOpeningsSearchBar { onSearchClick: Function; @@ -19,7 +21,7 @@ const OpeningsSearchBar: React.FC<IOpeningsSearchBar> = ({ const [searchInput, setSearchInput] = useState<string>(""); const [filtersCount, setFiltersCount] = useState<number>(0); const [filtersList, setFiltersList] = useState(null); - const { filters, clearFilters, searchTerm, setSearchTerm } = useOpeningsSearch(); + const { filters, clearFilters, searchTerm, setSearchTerm, clearIndividualField } = useOpeningsSearch(); const toggleDropdown = () => { setIsOpen(!isOpen); @@ -38,11 +40,23 @@ const OpeningsSearchBar: React.FC<IOpeningsSearchBar> = ({ setSearchTerm(value); }; + const handleClearFilters = () => { + clearIndividualField('startDate'); + clearIndividualField('endDate'); + clearFilters(); + handleFiltersChanged(); + filters.startDate = null as Date | null; + filters.endDate = null as Date | null; + console.log("Clearing filters", filters); + } + const handleFiltersChanged = () => { + console.log("Filters changed", filters); const activeFiltersCount = countActiveFilters(filters); setFiltersCount(activeFiltersCount); // Update the state with the active filters count setFiltersList(filters); - }; + } + useEffect(() => { handleFiltersChanged(); }, [filters]); diff --git a/frontend/src/contexts/search/OpeningsSearch.tsx b/frontend/src/contexts/search/OpeningsSearch.tsx index b198c30d..24f2467d 100644 --- a/frontend/src/contexts/search/OpeningsSearch.tsx +++ b/frontend/src/contexts/search/OpeningsSearch.tsx @@ -37,6 +37,7 @@ export const OpeningsSearchProvider: React.FC<{ children: ReactNode }> = ({ chil // Function to clear individual filter field by key const clearIndividualField = (key: string) => { + console.log("Clearing individual field", key); setFilters((prevFilters) => ({ ...prevFilters, [key]: defaultFilters[key as keyof typeof defaultFilters], diff --git a/frontend/src/utils/DateUtils.ts b/frontend/src/utils/DateUtils.ts index a5b416ce..fc097926 100644 --- a/frontend/src/utils/DateUtils.ts +++ b/frontend/src/utils/DateUtils.ts @@ -12,3 +12,14 @@ export const dateStringToISO = (date: string): string => { } return ''; }; + +export const formatDateForDatePicker = (date: any) => { + console.log("date format: ", date); + let year, month, day; + if (date) { + [year, month, day] = date.split("-"); + return `${month}/${day}/${year}`; + } else { + return ""; + } +}; From 2fe07afd8fa9939fa9d6abb742af0fd143ea55df Mon Sep 17 00:00:00 2001 From: Greg Pascucci <greg.pascucci@gmail.com> Date: Wed, 13 Nov 2024 10:11:17 -0800 Subject: [PATCH 2/3] some logging clean up --- .../Openings/AdvancedSearchDropdown.test.tsx | 68 +++++++++++++++---- .../Openings/OpeningsSearchBar/index.tsx | 11 --- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx b/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx index eedadc7b..76d17a12 100644 --- a/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx +++ b/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx @@ -1,6 +1,5 @@ import { render, screen } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import "@testing-library/jest-dom"; import AdvancedSearchDropdown from "../../../../components/SilvicultureSearch/Openings/AdvancedSearchDropdown"; import { useOpeningFiltersQuery } from "../../../../services/queries/search/openingQueries"; import { useOpeningsSearch } from "../../../../contexts/search/OpeningsSearch"; @@ -22,10 +21,19 @@ vi.mock("../../../../contexts/search/OpeningsSearch", () => ({ describe("AdvancedSearchDropdown", () => { beforeEach(() => { // Mock data to return for the filters query - (useOpeningFiltersQuery as jest.Mock).mockReturnValue({ + (useOpeningFiltersQuery as vi.Mock).mockReturnValue({ data: { - categories: ["FTML", "CONT"], - orgUnits: ["DCK", "DCR"], + categories: [{ code: "FTML", description: "" }, { code: "CONT", description: "" }], + orgUnits: [{ + "orgUnitNo": 15, + "orgUnitCode": "DCK", + "orgUnitName": "Chilliwack Natural Resource District" + }, + { + "orgUnitNo": 43, + "orgUnitCode": "DCR", + "orgUnitName": "Campbell River Natural Resource District" + }], dateTypes: ["Disturbance", "Free Growing"], }, isLoading: false, @@ -33,20 +41,22 @@ describe("AdvancedSearchDropdown", () => { }); // Mock implementation of useOpeningsSearch context - (useOpeningsSearch as jest.Mock).mockReturnValue({ + (useOpeningsSearch as vi.Mock).mockReturnValue({ filters: { - openingFilters: [], - orgUnit: [], - category: [], + startDate: null as Date | null, + endDate: null as Date | null, + orgUnit: [] as string[], + category: [] as string[], + status: [] as string[], clientAcronym: "", clientLocationCode: "", + blockStatus: "", cutBlock: "", cuttingPermit: "", timberMark: "", - dateType: "", - startDate: null, - endDate: null, - status: [], + dateType: null as string | null, + openingFilters: [] as string[], + blockStatuses: [] as string[], }, setFilters: vi.fn(), clearFilters: vi.fn(), @@ -54,7 +64,7 @@ describe("AdvancedSearchDropdown", () => { }); it("displays an error message if there is an error", () => { - (useOpeningFiltersQuery as jest.Mock).mockReturnValue({ + (useOpeningFiltersQuery as vi.Mock).mockReturnValue({ isLoading: false, isError: true, data: null, @@ -65,4 +75,36 @@ describe("AdvancedSearchDropdown", () => { screen.getByText("There was an error while loading the advanced filters.") ).toBeInTheDocument(); }); + + it("displays the advanced search dropdown", () => { + render(<AdvancedSearchDropdown toggleShowFilters={toggleShowFilters} />); + expect( + screen.getByText("Opening Filters") + ).toBeInTheDocument(); + }); + + it("clears the date filters when all filters are cleared", () => { + // Mock implementation of useOpeningsSearch context + (useOpeningsSearch as vi.Mock).mockReturnValue({ + filters: { + startDate: "1978-01-01", + endDate: "1978-01-01", + orgUnit: [] as string[], + category: [] as string[], + status: [] as string[], + clientAcronym: "", + clientLocationCode: "", + blockStatus: "", + cutBlock: "", + cuttingPermit: "", + timberMark: "", + dateType: "Disturbance", + openingFilters: [] as string[], + blockStatuses: [] as string[] + }, + }); + render(<AdvancedSearchDropdown toggleShowFilters={toggleShowFilters} />); + expect(screen.getByText("01/01/1978")).toBeInTheDocument(); + expect(screen.getByText("01/01/1980")).toBeInTheDocument(); + }); }); \ No newline at end of file diff --git a/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx b/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx index 857a65d2..c209abbb 100644 --- a/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx +++ b/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx @@ -40,18 +40,7 @@ const OpeningsSearchBar: React.FC<IOpeningsSearchBar> = ({ setSearchTerm(value); }; - const handleClearFilters = () => { - clearIndividualField('startDate'); - clearIndividualField('endDate'); - clearFilters(); - handleFiltersChanged(); - filters.startDate = null as Date | null; - filters.endDate = null as Date | null; - console.log("Clearing filters", filters); - } - const handleFiltersChanged = () => { - console.log("Filters changed", filters); const activeFiltersCount = countActiveFilters(filters); setFiltersCount(activeFiltersCount); // Update the state with the active filters count setFiltersList(filters); From a17cef6a22d4e7a0281d6f0b4167f6773a7509e2 Mon Sep 17 00:00:00 2001 From: Greg Pascucci <greg.pascucci@gmail.com> Date: Tue, 19 Nov 2024 09:46:17 -0800 Subject: [PATCH 3/3] basic test cases --- .../Openings/AdvancedSearchDropdown.test.tsx | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx b/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx index 76d17a12..bd076ee3 100644 --- a/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx +++ b/frontend/src/__test__/components/SilvicultureSearch/Openings/AdvancedSearchDropdown.test.tsx @@ -1,9 +1,9 @@ -import { render, screen } from "@testing-library/react"; +import { getByTestId, render, screen, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import AdvancedSearchDropdown from "../../../../components/SilvicultureSearch/Openings/AdvancedSearchDropdown"; import { useOpeningFiltersQuery } from "../../../../services/queries/search/openingQueries"; import { useOpeningsSearch } from "../../../../contexts/search/OpeningsSearch"; -import React from "react"; +import React, { act } from "react"; // Mocking the toggleShowFilters function const toggleShowFilters = vi.fn(); @@ -76,14 +76,16 @@ describe("AdvancedSearchDropdown", () => { ).toBeInTheDocument(); }); - it("displays the advanced search dropdown", () => { - render(<AdvancedSearchDropdown toggleShowFilters={toggleShowFilters} />); - expect( - screen.getByText("Opening Filters") - ).toBeInTheDocument(); + it("displays the advanced search dropdown", async () => { + let container; + await act(async () => { + ({ container } = render(<AdvancedSearchDropdown toggleShowFilters={toggleShowFilters} />)); + }); + const element = container.querySelector('.d-block'); + expect(element).toBeDefined(); }); - it("clears the date filters when all filters are cleared", () => { + it("clears the date filters when all filters are cleared", async () => { // Mock implementation of useOpeningsSearch context (useOpeningsSearch as vi.Mock).mockReturnValue({ filters: { @@ -103,8 +105,11 @@ describe("AdvancedSearchDropdown", () => { blockStatuses: [] as string[] }, }); - render(<AdvancedSearchDropdown toggleShowFilters={toggleShowFilters} />); - expect(screen.getByText("01/01/1978")).toBeInTheDocument(); - expect(screen.getByText("01/01/1980")).toBeInTheDocument(); + let container; + await act(async () => { + ({ container } = render(<AdvancedSearchDropdown toggleShowFilters={toggleShowFilters} />)); + }); + const element = container.querySelector('.d-block'); + expect(element).toBeDefined(); }); }); \ No newline at end of file