From 5055d8a90701c7a2ab682c8447c5ed0ff462614c Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Wed, 28 Aug 2024 15:50:42 -0400 Subject: [PATCH 01/33] Created SaveSearchModal; testing in inventory --- .../SaveSearchModal/SaveSearchModal.tsx | 123 ++++++++++++++++++ frontend/src/pages/Search/SortBar.tsx | 21 ++- 2 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/SaveSearchModal/SaveSearchModal.tsx diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx new file mode 100644 index 00000000..73254833 --- /dev/null +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -0,0 +1,123 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, + TextField, + Button, + Box, + Checkbox +} from '@mui/material/'; + +interface SaveSearchModalProps { + open: boolean; + handleClose: () => void; +} + +export default function SaveSearchModal({ + open, + handleClose +}: SaveSearchModalProps) { + const dialogRef = useRef(null); + const triggerButtonRef = useRef(null); + + useEffect(() => { + if (open && dialogRef.current) { + dialogRef.current.focus(); + } + }, [open]); + + const [checked, setChecked] = useState(false); + + const handleCheck = (event: React.ChangeEvent) => { + setChecked(event.target.checked); + }; + + const handleCloseModal = () => { + handleClose(); + // TODO: Focus on the trigger button when the modal closes + // if (triggerButtonRef.current) { + // triggerButtonRef.current.focus(); + // } + }; + + useEffect(() => { + if (!open) { + setChecked(false); + } + }, [open, setChecked]); + + return ( + <> + {/* */} + ) => { + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const formJson = Object.fromEntries((formData as any).entries()); + const savedSearch = formJson; + console.log(savedSearch); + handleCloseModal(); + }, + style: { width: '30%', minWidth: '300px' } + }} + aria-labelledby="dialog-title" + aria-describedby="dialog-description" + ref={dialogRef} + > + Save Search + + + + Name Your Search + + + + {/* + When a result is found: + */} + {/* TODO: + Not sure of functionality at this point + */} + {/* + + + */} + + + + + + + + ); +} diff --git a/frontend/src/pages/Search/SortBar.tsx b/frontend/src/pages/Search/SortBar.tsx index 51c6d8af..b1a3b548 100644 --- a/frontend/src/pages/Search/SortBar.tsx +++ b/frontend/src/pages/Search/SortBar.tsx @@ -1,13 +1,15 @@ -import React from 'react'; +import React, { useState } from 'react'; +import SaveSearchModal from '../../components/SaveSearchModal/SaveSearchModal'; import { classes, Root } from './Styling/sortBarStyle'; import { + Button, Select, FormControl, MenuItem, SelectProps, IconButton } from '@mui/material'; -import { ArrowUpward, ArrowDownward } from '@mui/icons-material'; +import { ArrowUpward, ArrowDownward, Save } from '@mui/icons-material'; import { ContextType } from 'context/SearchProvider'; import { SavedSearch } from 'types'; @@ -31,6 +33,16 @@ export const SortBar: React.FC = (props) => { existingSavedSearch } = props; + const [open, setOpen] = useState(false); + + const handleClickOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + const toggleDirection = () => { setSort(sortField, sortDirection === 'asc' ? 'desc' : 'asc'); }; @@ -55,6 +67,11 @@ export const SortBar: React.FC = (props) => { )} + + + Sort by: = (props) => { {children} -
+ {/*
{saveSearch && ( )} -
+
*/} {/* */} ); From 6fca51dc8361251a137e56daa609ebe220e42b8e Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 6 Sep 2024 12:18:21 -0400 Subject: [PATCH 05/33] Save Search modal now saves user defined Search - moved props, state, and api call from Dashboard to new Saved Search Modal. - still need to clean up code. - still need to round out create vuln functionality. --- .../SaveSearchModal/SaveSearchModal.tsx | 58 ++++--- frontend/src/pages/Search/Dashboard.tsx | 144 ++++++------------ frontend/src/pages/Search/SortBar.tsx | 16 +- 3 files changed, 84 insertions(+), 134 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index ed8d3271..92537ccd 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -1,5 +1,6 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; +import { useSavedSearchContext } from 'context/SavedSearchContext'; import { Dialog, DialogActions, @@ -12,16 +13,21 @@ import { } from '@mui/material/'; import { SavedSearch } from '../../types/saved-search'; import { useAuthContext } from '../../context'; -import { useBeforeunload } from 'react-beforeunload'; - -import { useSavedSearchContext } from '../../context/SavedSearchContext'; +import { Vulnerability } from 'types'; interface SaveSearchModalProps { - props: any; + search: any; + searchTerm: string; + setSearchTerm: any; + filters: any; + totalResults: number; + sortField: string; + sortDirection: string; } -export default function SaveSearchModal(props: any) { +export const SaveSearchModal: React.FC = (props) => { const { + search, searchTerm, setSearchTerm, filters, @@ -32,33 +38,29 @@ export default function SaveSearchModal(props: any) { const [open, setOpen] = useState(false); const { apiPost, apiPut } = useAuthContext(); - - const search: - | (SavedSearch & { - editing?: boolean; - }) - | undefined = localStorage.getItem('savedSearch') - ? JSON.parse(localStorage.getItem('savedSearch')!) - : undefined; const history = useHistory(); + + // Could be used for validation purposes in new dialogue + // const { savedSearches } = useSavedSearchContext(); + const [savedSearchValues, setSavedSearchValues] = useState< Partial & { name: string; - // vulnerabilityTemplate: Partial; + vulnerabilityTemplate: Partial; } >( search ? search : { - name: '' - // vulnerabilityTemplate: {}, - // createVulnerabilities: false + name: '', + vulnerabilityTemplate: {}, + createVulnerabilities: false } ); - // const onTextChange: React.ChangeEventHandler< - // HTMLInputElement | HTMLSelectElement - // > = (e) => handleChange(e.target.name, e.target.value); + const onTextChange: React.ChangeEventHandler< + HTMLInputElement | HTMLSelectElement + > = (e) => handleChange(e.target.name, e.target.value); const handleChange = (name: string, value: any) => { setSavedSearchValues((values) => ({ @@ -67,6 +69,12 @@ export default function SaveSearchModal(props: any) { })); }; + const onVulnerabilityTemplateChange = (e: any) => { + (savedSearchValues.vulnerabilityTemplate as any)[e.target.name] = + e.target.value; + setSavedSearchValues(savedSearchValues); + }; + // TODO: Need to verify if needed // useEffect(() => { // if (props.location.search === '') { @@ -97,8 +105,6 @@ export default function SaveSearchModal(props: any) { }; try { - console.log('Search: ', props.location.search); - if (search) { // TODO: verify search is being passed properly await apiPut('/saved-searches/' + search.id, body); @@ -138,7 +144,9 @@ export default function SaveSearchModal(props: any) { return ( <> - + ); -} +}; diff --git a/frontend/src/pages/Search/Dashboard.tsx b/frontend/src/pages/Search/Dashboard.tsx index 3a717131..12998873 100644 --- a/frontend/src/pages/Search/Dashboard.tsx +++ b/frontend/src/pages/Search/Dashboard.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { classes, Root } from './Styling/dashboardStyle'; import { Subnav } from 'components'; import { ResultCard } from './ResultCard'; @@ -9,36 +9,21 @@ import { Select, MenuItem, Typography, - Checkbox, - FormControlLabel, - FormGroup, - TextareaAutosize, - ButtonGroup, - Box + Box, + Stack } from '@mui/material'; import { Pagination } from '@mui/material'; import { withSearch } from '@elastic/react-search-ui'; import { ContextType } from '../../context/SearchProvider'; import { SortBar } from './SortBar'; -import { - Modal, - TextInput, - Label, - Dropdown, - ModalFooter, - ModalHeading, - ModalRef -} from '@trussworks/react-uswds'; -import { ModalToggleButton } from 'components'; import { useAuthContext } from 'context'; -import { useSavedSearchContext } from 'context/SavedSearchContext'; import { FilterTags } from './FilterTags'; import { SavedSearch, Vulnerability } from 'types'; import { useBeforeunload } from 'react-beforeunload'; import { NoResults } from 'components/NoResults'; import { exportCSV } from 'components/ImportExport'; import { useHistory } from 'react-router-dom'; -import SaveSearchModal from '../../components/SaveSearchModal/SaveSearchModal'; +import { SaveSearchModal } from '../../components/SaveSearchModal/SaveSearchModal'; export const DashboardUI: React.FC = ( props @@ -65,49 +50,13 @@ export const DashboardUI: React.FC = ( const [resultsScrolled] = useState(false); const { apiPost, - apiPut, + // apiPut, setLoading, showAllOrganizations, currentOrganization } = useAuthContext(); - // TODO: New handleSave - const handleSave = async (formData: Partial) => { - const body = { - ...formData, - searchTerm, - filters, - count: totalResults, - searchPath: window.location.search, - sortField, - sortDirection - }; - - try { - if (formData.id) { - await apiPut(`/saved-searches/${formData.id}`, { body }); - } else { - await apiPost('/saved-searches/', { body }); - } - history.push('/inventory'); - window.location.reload(); - } catch (e) { - console.error(e); - } - }; - - // Could be used for validation purposes in new dialogue - const { savedSearches } = useSavedSearchContext(); - const advanceFiltersReq = filters.length > 1; //Prevents a user from saving a search without advanced filters - const [open, setOpen] = useState(false); - const handleClose = () => { - setOpen(false); - }; - - const handleOpen = () => { - setOpen(true); - }; const search: | (SavedSearch & { @@ -117,39 +66,24 @@ export const DashboardUI: React.FC = ( ? JSON.parse(localStorage.getItem('savedSearch')!) : undefined; - const history = useHistory(); - const modalRef = useRef(null); - const [savedSearchValues, setSavedSearchValues] = useState< - Partial & { - name: string; - vulnerabilityTemplate: Partial; - } - >( - search - ? search - : { - name: '', - vulnerabilityTemplate: {}, - createVulnerabilities: false - } - ); + // const history = useHistory(); - const onTextChange: React.ChangeEventHandler< - HTMLInputElement | HTMLSelectElement - > = (e) => onChange(e.target.name, e.target.value); + // const onTextChange: React.ChangeEventHandler< + // HTMLInputElement | HTMLSelectElement + // > = (e) => onChange(e.target.name, e.target.value); - const onChange = (name: string, value: any) => { - setSavedSearchValues((values) => ({ - ...values, - [name]: value - })); - }; + // const onChange = (name: string, value: any) => { + // setSavedSearchValues((values) => ({ + // ...values, + // [name]: value + // })); + // }; - const onVulnerabilityTemplateChange = (e: any) => { - (savedSearchValues.vulnerabilityTemplate as any)[e.target.name] = - e.target.value; - setSavedSearchValues(savedSearchValues); - }; + // const onVulnerabilityTemplateChange = (e: any) => { + // (savedSearchValues.vulnerabilityTemplate as any)[e.target.name] = + // e.target.value; + // setSavedSearchValues(savedSearchValues); + // }; useEffect(() => { if (props.location.search === '') { @@ -216,20 +150,30 @@ export const DashboardUI: React.FC = ( > - 0 || searchTerm - // ? () => modalRef.current?.toggleModal(undefined, true) - // : undefined - // } - existingSavedSearch={search} - advancedFiltersReq={advanceFiltersReq} - /> - + + 0 || searchTerm + // ? () => modalRef.current?.toggleModal(undefined, true) + // : undefined + // } + existingSavedSearch={search} + advancedFiltersReq={advanceFiltersReq} + /> + + = (props) => { sortField, sortDirection, setSort, - saveSearch, - children, - existingSavedSearch, - advancedFiltersReq + // saveSearch, + children + // existingSavedSearch, + // advancedFiltersReq } = props; - const [open, setOpen] = useState(false); + // const [open, setOpen] = useState(false); const toggleDirection = () => { setSort(sortField, sortDirection === 'asc' ? 'desc' : 'asc'); From 27a64394a06c25529817cb100836b100b3687efc Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 6 Sep 2024 12:32:01 -0400 Subject: [PATCH 06/33] Restored SaveSearchModal and Stack to Inventory --- frontend/src/pages/Search/Inventory.tsx | 42 ++++++++++++++++--------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/frontend/src/pages/Search/Inventory.tsx b/frontend/src/pages/Search/Inventory.tsx index 53eaf28b..23055953 100644 --- a/frontend/src/pages/Search/Inventory.tsx +++ b/frontend/src/pages/Search/Inventory.tsx @@ -14,7 +14,8 @@ import { FormGroup, TextareaAutosize, ButtonGroup, - Box + Box, + Stack } from '@mui/material'; import { Pagination } from '@mui/material'; import { withSearch } from '@elastic/react-search-ui'; @@ -38,6 +39,8 @@ import { useBeforeunload } from 'react-beforeunload'; import { NoResults } from 'components/NoResults'; import { exportCSV } from 'components/ImportExport'; import { useHistory } from 'react-router-dom'; +import { Save } from '@mui/icons-material'; +import { SaveSearchModal } from 'components/SaveSearchModal/SaveSearchModal'; export const DashboardUI: React.FC = ( props @@ -196,19 +199,30 @@ export const DashboardUI: React.FC = ( > - 0 || searchTerm - ? () => modalRef.current?.toggleModal(undefined, true) - : undefined - } - existingSavedSearch={search} - advancedFiltersReq={advanceFiltersReq} - /> + + 0 || searchTerm + ? () => modalRef.current?.toggleModal(undefined, true) + : undefined + } + existingSavedSearch={search} + advancedFiltersReq={advanceFiltersReq} + /> + + Date: Fri, 6 Sep 2024 16:08:35 -0400 Subject: [PATCH 07/33] Modified Save Search button - Stack is now spaced between. - Added Save end icon to button. - Changed button variant to contained for better visibility. --- .../src/components/SaveSearchModal/SaveSearchModal.tsx | 5 +++-- frontend/src/pages/Search/Inventory.tsx | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 92537ccd..716a433c 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -14,6 +14,7 @@ import { import { SavedSearch } from '../../types/saved-search'; import { useAuthContext } from '../../context'; import { Vulnerability } from 'types'; +import { Save } from '@mui/icons-material'; interface SaveSearchModalProps { search: any; @@ -144,8 +145,8 @@ export const SaveSearchModal: React.FC = (props) => { return ( <> - = ( @@ -199,7 +198,12 @@ export const DashboardUI: React.FC = ( > - + Date: Mon, 9 Sep 2024 10:19:43 -0400 Subject: [PATCH 08/33] Implemented form validation on save search modal --- .../SaveSearchModal/SaveSearchModal.tsx | 72 +++++++------------ frontend/src/pages/Search/Inventory.tsx | 10 +-- 2 files changed, 31 insertions(+), 51 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 716a433c..4043a25f 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -19,7 +19,7 @@ import { Save } from '@mui/icons-material'; interface SaveSearchModalProps { search: any; searchTerm: string; - setSearchTerm: any; + // setSearchTerm: any; filters: any; totalResults: number; sortField: string; @@ -30,14 +30,16 @@ export const SaveSearchModal: React.FC = (props) => { const { search, searchTerm, - setSearchTerm, + // setSearchTerm, filters, totalResults, sortField, sortDirection } = props; const [open, setOpen] = useState(false); - + const [formErrors, setFormErrors] = useState({ + name: false + }); const { apiPost, apiPut } = useAuthContext(); const history = useHistory(); @@ -59,39 +61,21 @@ export const SaveSearchModal: React.FC = (props) => { } ); - const onTextChange: React.ChangeEventHandler< - HTMLInputElement | HTMLSelectElement - > = (e) => handleChange(e.target.name, e.target.value); - const handleChange = (name: string, value: any) => { setSavedSearchValues((values) => ({ ...values, [name]: value })); - }; - const onVulnerabilityTemplateChange = (e: any) => { - (savedSearchValues.vulnerabilityTemplate as any)[e.target.name] = - e.target.value; - setSavedSearchValues(savedSearchValues); + if (name === 'name') { + const isValid = validation(value); + setFormErrors((prev) => ({ + ...prev, + name: !isValid + })); + } }; - // TODO: Need to verify if needed - // useEffect(() => { - // if (props.location.search === '') { - // // Search on initial load - // setSearchTerm('', { shouldClearFilters: false }); - // } - // return () => { - // localStorage.removeItem('savedSearch'); - // setSearchTerm('', { shouldClearFilters: false }); - // }; - // }, [setSearchTerm, props.location.search]); - - // useBeforeunload((event) => { - // localStorage.removeItem('savedSearch'); - // }); - const handleSave = async (savedSearchValues: Partial) => { const body = { body: { @@ -119,30 +103,30 @@ export const SaveSearchModal: React.FC = (props) => { } }; - // TODO const handleCloseModal = () => { setOpen(false); }; const handleOpenModal = () => { setOpen(true); }; - // TODO - // const handleChange = (e: React.ChangeEvent) => { - // const { name, value } = e.target; - // setSavedSearchValues((prevValues) => ({ - // ...prevValues, - // [name]: value - // })); - // }; - // TODO const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); console.log(props); + + if (formErrors.name) { + return; + } handleSave(savedSearchValues); handleCloseModal(); }; + // Validate Saved Search Name + const validation = (name: string): boolean => { + const nameRegex = /^(?=.*[A-Za-z0-9])[A-Za-z0-9\s\'\-]+$/; + return nameRegex.test(name); + }; + return ( <> */} - + From 5e526a0d6229397e6ac35582294b2e381f454629 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Mon, 9 Sep 2024 14:40:48 -0400 Subject: [PATCH 10/33] Update saved search fixed --- .../SaveSearchModal/SaveSearchModal.tsx | 54 ++++-- frontend/src/pages/Search/Inventory.tsx | 158 +----------------- frontend/src/pages/Search/SortBar.tsx | 24 +-- 3 files changed, 45 insertions(+), 191 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index c9402886..598e9fed 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -15,36 +15,36 @@ import { SavedSearch } from '../../types/saved-search'; import { useAuthContext } from '../../context'; import { Vulnerability } from 'types'; import { Save } from '@mui/icons-material'; +import ConfirmDialog from 'components/Dialog/ConfirmDialog'; interface SaveSearchModalProps { search: any; searchTerm: string; - // setSearchTerm: any; filters: any; totalResults: number; sortField: string; sortDirection: string; + advancedFiltersReq?: boolean; } export const SaveSearchModal: React.FC = (props) => { const { search, searchTerm, - // setSearchTerm, filters, totalResults, sortField, - sortDirection + sortDirection, + advancedFiltersReq } = props; const [open, setOpen] = useState(false); + const [dialogeOpen, setDialogeOpen] = useState(false); const [formErrors, setFormErrors] = useState({ name: false, duplicate: false }); const { apiPost, apiPut } = useAuthContext(); const history = useHistory(); - - // Could be used for validation purposes in new dialogue const { savedSearches } = useSavedSearchContext(); const [savedSearchValues, setSavedSearchValues] = useState< @@ -95,7 +95,6 @@ export const SaveSearchModal: React.FC = (props) => { try { if (search) { - // TODO: verify search is being passed properly await apiPut('/saved-searches/' + search.id, body); } else { await apiPost('/saved-searches/', body); @@ -114,6 +113,35 @@ export const SaveSearchModal: React.FC = (props) => { setOpen(true); }; + const handleDialogClose = () => { + setDialogeOpen(false); + }; + const confirmUpdate = () => { + return ( + { + handleSave(savedSearchValues); + }} + /> + ); + }; + const handleClick = () => { + if (search) { + const savedSearchItem = localStorage.getItem('savedSearch'); + if (savedSearchItem) { + const savedSearchName = JSON.parse(savedSearchItem); + savedSearchValues.name = savedSearchName.name; + } + handleSave(savedSearchValues); + // console.log(savedSearchValues); + } else { + handleOpenModal(); + } + }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); console.log(props); @@ -133,8 +161,13 @@ export const SaveSearchModal: React.FC = (props) => { return ( <> - = (props) => { } /> - {/* */} diff --git a/frontend/src/pages/Search/Inventory.tsx b/frontend/src/pages/Search/Inventory.tsx index 782f690d..87e81fe1 100644 --- a/frontend/src/pages/Search/Inventory.tsx +++ b/frontend/src/pages/Search/Inventory.tsx @@ -64,13 +64,8 @@ export const DashboardUI: React.FC = ( const [selectedDomain, setSelectedDomain] = useState(''); const [resultsScrolled] = useState(false); - const { - apiPost, - apiPut, - setLoading, - showAllOrganizations, - currentOrganization - } = useAuthContext(); + const { apiPost, setLoading, showAllOrganizations, currentOrganization } = + useAuthContext(); // Could be used for validation purposes in new dialogue // const { savedSearches } = useSavedSearchContext(); @@ -102,23 +97,6 @@ export const DashboardUI: React.FC = ( } ); - const onTextChange: React.ChangeEventHandler< - HTMLInputElement | HTMLSelectElement - > = (e) => onChange(e.target.name, e.target.value); - - const onChange = (name: string, value: any) => { - setSavedSearchValues((values) => ({ - ...values, - [name]: value - })); - }; - - const onVulnerabilityTemplateChange = (e: any) => { - (savedSearchValues.vulnerabilityTemplate as any)[e.target.name] = - e.target.value; - setSavedSearchValues(savedSearchValues); - }; - useEffect(() => { if (props.location.search === '') { // Search on initial load @@ -209,22 +187,17 @@ export const DashboardUI: React.FC = ( sortDirection={sortDirection} setSort={setSort} isFixed={resultsScrolled} - saveSearch={ - filters.length > 0 || searchTerm - ? () => modalRef.current?.toggleModal(undefined, true) - : undefined - } existingSavedSearch={search} advancedFiltersReq={advanceFiltersReq} /> = ( gap="1rem" alignItems="stretch" display="flex" - // overflow="scroll" position="relative" padding="0 0 2rem 0" sx={{ overflowY: 'auto' }} @@ -324,130 +296,6 @@ export const DashboardUI: React.FC = ( { // To-do: Implement a new MUI based Save Search Dialog to replace the existing USWDS based Modal. } - - {search ? 'Update Search' : 'Save Search'} - - - -

When a new result is found:

- {/* - } - label="Email me" - /> */} - onChange(e.target.name, e.target.checked)} - id="createVulnerabilities" - name="createVulnerabilities" - /> - } - label="Create a vulnerability" - /> - {savedSearchValues.createVulnerabilities && ( - <> - - - - - - - - - - - - - - )} - {/*

Collaborators

-

- Collaborators can view vulnerabilities, and domains within - this search. Adding a team will make all members - collaborators. -

- */} -
- - - { - const body = { - body: { - ...savedSearchValues, - searchTerm, - filters, - count: totalResults, - searchPath: window.location.search, - sortField, - sortDirection - } - }; - if (search) { - await apiPut('/saved-searches/' + search.id, body); - history.push('/inventory'); - window.location.reload(); - } else { - await apiPost('/saved-searches/', body); - history.push('/inventory'); - window.location.reload(); - } - }} - > - Save - - - Cancel - - - -
); }; diff --git a/frontend/src/pages/Search/SortBar.tsx b/frontend/src/pages/Search/SortBar.tsx index 9e8e5aad..d7c32aa6 100644 --- a/frontend/src/pages/Search/SortBar.tsx +++ b/frontend/src/pages/Search/SortBar.tsx @@ -23,17 +23,7 @@ interface Props { } export const SortBar: React.FC = (props) => { - const { - sortField, - sortDirection, - setSort, - // saveSearch, - children - // existingSavedSearch, - // advancedFiltersReq - } = props; - - // const [open, setOpen] = useState(false); + const { sortField, sortDirection, setSort, children } = props; const toggleDirection = () => { setSort(sortField, sortDirection === 'asc' ? 'desc' : 'asc'); @@ -87,18 +77,6 @@ export const SortBar: React.FC = (props) => { {children} - {/*
- {saveSearch && ( - - )} -
*/} - {/* */} ); }; From 16967f9d4ce0ba2009daae06efaab3c3fbe76724 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Mon, 9 Sep 2024 14:49:40 -0400 Subject: [PATCH 11/33] Code cleanup; remove unused imports --- .../SaveSearchModal/SaveSearchModal.tsx | 63 ++++++++++--------- frontend/src/pages/Search/Inventory.tsx | 42 +------------ frontend/src/pages/Search/SortBar.tsx | 1 - 3 files changed, 33 insertions(+), 73 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 598e9fed..f321dfde 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -62,24 +62,7 @@ export const SaveSearchModal: React.FC = (props) => { } ); - const handleChange = (name: string, value: any) => { - setSavedSearchValues((values) => ({ - ...values, - [name]: value - })); - - if (name === 'name') { - const isValid = validation(value); - const isDuplicate = savedSearches.some((search) => search.name === value); - - setFormErrors((prev) => ({ - ...prev, - name: !isValid, - duplicate: isDuplicate - })); - } - }; - + // API call to save/update saved searches const handleSave = async (savedSearchValues: Partial) => { const body = { body: { @@ -116,19 +99,19 @@ export const SaveSearchModal: React.FC = (props) => { const handleDialogClose = () => { setDialogeOpen(false); }; - const confirmUpdate = () => { - return ( - { - handleSave(savedSearchValues); - }} - /> - ); - }; + // const confirmUpdate = () => { + // return ( + // { + // handleSave(savedSearchValues); + // }} + // /> + // ); + // }; const handleClick = () => { if (search) { const savedSearchItem = localStorage.getItem('savedSearch'); @@ -159,6 +142,24 @@ export const SaveSearchModal: React.FC = (props) => { return nameRegex.test(name); }; + const handleChange = (name: string, value: any) => { + setSavedSearchValues((values) => ({ + ...values, + [name]: value + })); + // Validation check for valid characters and duplicate names + if (name === 'name') { + const isValid = validation(value); + const isDuplicate = savedSearches.some((search) => search.name === value); + + setFormErrors((prev) => ({ + ...prev, + name: !isValid, + duplicate: isDuplicate + })); + } + }; + return ( <> - { - // To-do: Implement a new MUI based Save Search Dialog to replace the existing USWDS based Modal. - } ); }; diff --git a/frontend/src/pages/Search/SortBar.tsx b/frontend/src/pages/Search/SortBar.tsx index d7c32aa6..fa4540e0 100644 --- a/frontend/src/pages/Search/SortBar.tsx +++ b/frontend/src/pages/Search/SortBar.tsx @@ -15,7 +15,6 @@ interface Props { sortField: ContextType['sortField']; sortDirection?: ContextType['sortDirection']; setSort: ContextType['setSort']; - saveSearch?(): void; isFixed: boolean; existingSavedSearch?: SavedSearch; children?: React.ReactNode; From bc49d5ed04b5d5e322fbacd4d726a3016f2a6c0c Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Mon, 9 Sep 2024 15:56:11 -0400 Subject: [PATCH 12/33] Code cleanup; remove unused variable --- .../SaveSearchModal/SaveSearchModal.tsx | 68 +++++++++++++------ 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index f321dfde..c956d747 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -15,7 +15,6 @@ import { SavedSearch } from '../../types/saved-search'; import { useAuthContext } from '../../context'; import { Vulnerability } from 'types'; import { Save } from '@mui/icons-material'; -import ConfirmDialog from 'components/Dialog/ConfirmDialog'; interface SaveSearchModalProps { search: any; @@ -38,7 +37,7 @@ export const SaveSearchModal: React.FC = (props) => { advancedFiltersReq } = props; const [open, setOpen] = useState(false); - const [dialogeOpen, setDialogeOpen] = useState(false); + const [dialogeOpen, setDialogOpen] = useState(false); const [formErrors, setFormErrors] = useState({ name: false, duplicate: false @@ -46,7 +45,6 @@ export const SaveSearchModal: React.FC = (props) => { const { apiPost, apiPut } = useAuthContext(); const history = useHistory(); const { savedSearches } = useSavedSearchContext(); - const [savedSearchValues, setSavedSearchValues] = useState< Partial & { name: string; @@ -97,34 +95,23 @@ export const SaveSearchModal: React.FC = (props) => { }; const handleDialogClose = () => { - setDialogeOpen(false); + setDialogOpen(false); }; - // const confirmUpdate = () => { - // return ( - // { - // handleSave(savedSearchValues); - // }} - // /> - // ); - // }; + const handleClick = () => { if (search) { + // Check if saved search already exists const savedSearchItem = localStorage.getItem('savedSearch'); if (savedSearchItem) { const savedSearchName = JSON.parse(savedSearchItem); savedSearchValues.name = savedSearchName.name; } - handleSave(savedSearchValues); - // console.log(savedSearchValues); + setDialogOpen(true); // Open dialog to confirm update } else { handleOpenModal(); } }; + const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); console.log(props); @@ -138,7 +125,7 @@ export const SaveSearchModal: React.FC = (props) => { // Validate Saved Search Name const validation = (name: string): boolean => { - const nameRegex = /^(?=.*[A-Za-z0-9])[A-Za-z0-9\s\'\-]+$/; + const nameRegex = /^(?=.*[A-Za-z0-9])[A-Za-z0-9\s'-]+$/; return nameRegex.test(name); }; @@ -167,9 +154,43 @@ export const SaveSearchModal: React.FC = (props) => { onClick={handleClick} endIcon={} disabled={!advancedFiltersReq} + aria-label={search ? 'Update Saved Search' : 'Save Search'} > {search ? 'Update Saved Search' : 'Save Search'} + setDialogOpen(false)} + aria-labelledby="confirm-dialog-title" + aria-describedby="confirm-dialog-description" + > + Update Saved Search + + + Are you sure you want to update this saved search? + + + + + + + = (props) => { From 0cd9799df0b2ed61ef38ec2a5a4b37f06072a05b Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Mon, 9 Sep 2024 16:13:42 -0400 Subject: [PATCH 13/33] Code cleanup; remove unused useRef --- frontend/src/pages/Search/Inventory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/Search/Inventory.tsx b/frontend/src/pages/Search/Inventory.tsx index f34242e2..ce3d0fb3 100644 --- a/frontend/src/pages/Search/Inventory.tsx +++ b/frontend/src/pages/Search/Inventory.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { classes, Root } from './Styling/dashboardStyle'; import { Subnav } from 'components'; import { ResultCard } from './ResultCard'; From ab4f3eadcf1c60e428f967601bca57321f4e6960 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Mon, 9 Sep 2024 17:42:13 -0400 Subject: [PATCH 14/33] Removed window.reload with use of state instead; removed unnecessary console logs --- backend/src/api/saved-searches.ts | 7 ---- backend/src/models/saved-search.ts | 9 ----- .../SaveSearchModal/SaveSearchModal.tsx | 36 ++++++------------- 3 files changed, 10 insertions(+), 42 deletions(-) diff --git a/backend/src/api/saved-searches.ts b/backend/src/api/saved-searches.ts index 1497e429..fb0d30ba 100644 --- a/backend/src/api/saved-searches.ts +++ b/backend/src/api/saved-searches.ts @@ -61,13 +61,6 @@ class NewSavedSearch { @IsArray() filters: { field: string; values: any[]; type: string }[]; - - @IsBoolean() - createVulnerabilities: boolean; - - @IsObject() - @IsOptional() - vulnerabilityTemplate: Partial; } const PAGE_SIZE = 20; diff --git a/backend/src/models/saved-search.ts b/backend/src/models/saved-search.ts index 91a9f63f..cb8987ab 100644 --- a/backend/src/models/saved-search.ts +++ b/backend/src/models/saved-search.ts @@ -42,16 +42,7 @@ export class SavedSearch extends BaseEntity { @Column() searchPath: string; - @Column({ - default: false - }) - createVulnerabilities: boolean; - // Content of vulnerability when search is configured to create vulnerabilities from results - @Column({ type: 'jsonb', default: '{}' }) - vulnerabilityTemplate: Partial & { - title: string; - }; @ManyToOne((type) => User, { onDelete: 'SET NULL', diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index c956d747..3ed98760 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -13,7 +13,6 @@ import { } from '@mui/material/'; import { SavedSearch } from '../../types/saved-search'; import { useAuthContext } from '../../context'; -import { Vulnerability } from 'types'; import { Save } from '@mui/icons-material'; interface SaveSearchModalProps { @@ -42,23 +41,12 @@ export const SaveSearchModal: React.FC = (props) => { name: false, duplicate: false }); - const { apiPost, apiPut } = useAuthContext(); - const history = useHistory(); - const { savedSearches } = useSavedSearchContext(); + const { apiGet, apiPost, apiPut } = useAuthContext(); + const { savedSearches, setSavedSearches, setSavedSearchCount } = + useSavedSearchContext(); const [savedSearchValues, setSavedSearchValues] = useState< - Partial & { - name: string; - vulnerabilityTemplate: Partial; - } - >( - search - ? search - : { - name: '', - vulnerabilityTemplate: {}, - createVulnerabilities: false - } - ); + Partial & { name: string } + >(search ? search : { name: '' }); // API call to save/update saved searches const handleSave = async (savedSearchValues: Partial) => { @@ -80,8 +68,10 @@ export const SaveSearchModal: React.FC = (props) => { } else { await apiPost('/saved-searches/', body); } - history.push('/inventory'); - window.location.reload(); + const updatedSearches = await apiGet('/saved-searches'); // Get current saved searches + setSavedSearches(updatedSearches.result); // Update the saved searches + setSavedSearchCount(updatedSearches.result.length); // Update the count + localStorage.removeItem('savedSearch'); } catch (e) { console.error(e); } @@ -100,12 +90,7 @@ export const SaveSearchModal: React.FC = (props) => { const handleClick = () => { if (search) { - // Check if saved search already exists - const savedSearchItem = localStorage.getItem('savedSearch'); - if (savedSearchItem) { - const savedSearchName = JSON.parse(savedSearchItem); - savedSearchValues.name = savedSearchName.name; - } + savedSearchValues.name = search.name; setDialogOpen(true); // Open dialog to confirm update } else { handleOpenModal(); @@ -114,7 +99,6 @@ export const SaveSearchModal: React.FC = (props) => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - console.log(props); if (formErrors.name) { return; From aebcf5b2e61ac646114400cbb29cab3e802083e0 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 10 Sep 2024 07:59:00 -0400 Subject: [PATCH 15/33] Refactored Save Search Accordion - Removed use of local storage. - No need as search term, filters, and sort are in context and stored in state. - Saved Searches are in context and have their own state. - Created boolean based in state to determine if radio button is checked. --- frontend/src/components/DrawerInterior.tsx | 14 +++++++------- .../components/SaveSearchModal/SaveSearchModal.tsx | 2 -- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/DrawerInterior.tsx b/frontend/src/components/DrawerInterior.tsx index 98642e90..71b90e87 100644 --- a/frontend/src/components/DrawerInterior.tsx +++ b/frontend/src/components/DrawerInterior.tsx @@ -70,6 +70,8 @@ export const DrawerInterior: React.FC = (props) => { const { savedSearches, setSavedSearches, setSavedSearchCount } = useSavedSearchContext(); + const [activeSearch, setActiveSearch] = React.useState(''); + const deleteSearch = async (id: string) => { try { await apiDelete(`/saved-searches/${id}`, { body: {} }); @@ -84,7 +86,6 @@ export const DrawerInterior: React.FC = (props) => { const displaySavedSearch = (id: string) => { const savedSearch = savedSearches.find((search) => search.id === id); if (savedSearch) { - localStorage.setItem('savedSearch', JSON.stringify(savedSearch)); setSearchTerm(savedSearch.searchTerm, { shouldClearFilters: true, autocompleteResults: false @@ -96,6 +97,7 @@ export const DrawerInterior: React.FC = (props) => { addFilter(filter.field, value, 'any'); }); }); + setActiveSearch(id); }; const restoreInitialFilters = () => { initialFilters.forEach((filter) => { @@ -110,11 +112,12 @@ export const DrawerInterior: React.FC = (props) => { shouldClearFilters: true, autocompleteResults: false }); - localStorage.removeItem('savedSearch'); restoreInitialFilters(); + setActiveSearch(''); }; const toggleSavedSearches = (id: string) => { const savedSearch = savedSearches.filter((search) => search.id === id); + if (savedSearch) { if (!isSavedSearchActive(id)) { displaySavedSearch(id); @@ -124,11 +127,8 @@ export const DrawerInterior: React.FC = (props) => { } }; - const isSavedSearchActive = (id: string) => { - const activeSearch = JSON.parse( - localStorage.getItem('savedSearch') || '{}' - ); - return activeSearch.id === id; + const isSavedSearchActive = (id: string): boolean => { + return activeSearch === id; }; const filtersByColumn = useMemo( diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 3ed98760..fc6a7f2e 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import { useHistory } from 'react-router-dom'; import { useSavedSearchContext } from 'context/SavedSearchContext'; import { Dialog, @@ -71,7 +70,6 @@ export const SaveSearchModal: React.FC = (props) => { const updatedSearches = await apiGet('/saved-searches'); // Get current saved searches setSavedSearches(updatedSearches.result); // Update the saved searches setSavedSearchCount(updatedSearches.result.length); // Update the count - localStorage.removeItem('savedSearch'); } catch (e) { console.error(e); } From 36501ff73b5f3ebd8c21e6a7602b9505c8dc87a2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 10 Sep 2024 09:38:49 -0400 Subject: [PATCH 16/33] Edited saved-search type for testing - Commented out lines regarding vuln template and create vuln. --- frontend/src/types/saved-search.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/types/saved-search.ts b/frontend/src/types/saved-search.ts index 74177cb2..93e2d1e7 100644 --- a/frontend/src/types/saved-search.ts +++ b/frontend/src/types/saved-search.ts @@ -13,6 +13,6 @@ export interface SavedSearch { searchPath: string; sortField: string; sortDirection: string; - createVulnerabilities: boolean; - vulnerabilityTemplate: Partial; + // createVulnerabilities: boolean; + // vulnerabilityTemplate: Partial; } From 962d777967e0652456ba458e012e29b3ac6f1cac Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 10 Sep 2024 09:47:01 -0400 Subject: [PATCH 17/33] Commented out type def for saved searches at api --- backend/src/api/saved-searches.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/src/api/saved-searches.ts b/backend/src/api/saved-searches.ts index fb0d30ba..b03a304c 100644 --- a/backend/src/api/saved-searches.ts +++ b/backend/src/api/saved-searches.ts @@ -61,6 +61,13 @@ class NewSavedSearch { @IsArray() filters: { field: string; values: any[]; type: string }[]; + + // @IsBoolean() + // createVulnerabilities: boolean; + + // @IsObject() + // @IsOptional() + // vulnerabilityTemplate: Partial; } const PAGE_SIZE = 20; From 37e3e27eb5cee957936fd03235153f7a69d68412 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 10 Sep 2024 10:25:02 -0400 Subject: [PATCH 18/33] Updated saved-searches.test.ts and saved-search.ts - needed for testing the changes made to the saved-searches.ts file --- backend/test/saved-searches.test.ts | 84 ++++++++++++++--------------- frontend/src/types/saved-search.ts | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/backend/test/saved-searches.test.ts b/backend/test/saved-searches.test.ts index 2158122a..02f86c6c 100644 --- a/backend/test/saved-searches.test.ts +++ b/backend/test/saved-searches.test.ts @@ -45,9 +45,9 @@ describe('saved-search', () => { sortField: '', searchTerm: '', searchPath: '', - filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {} + filters: [] + // createVulnerabilities: false, + // vulnerabilityTemplate: {} }) .expect(200); expect(response.body).toMatchSnapshot({ @@ -71,14 +71,14 @@ describe('saved-search', () => { sortField: '', searchTerm: '', searchPath: '', - filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {} + filters: [] + // createVulnerabilities: false, + // vulnerabilityTemplate: {} }; const search = await SavedSearch.create(body).save(); body.name = 'test-' + Math.random(); body.searchTerm = '123'; - body.createVulnerabilities = true; + // body.createVulnerabilities = true; const response = await request(app) .put(`/saved-searches/${search.id}`) .set( @@ -104,9 +104,9 @@ describe('saved-search', () => { sortField: '', searchTerm: '', searchPath: '', - filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {} + filters: [] + // createVulnerabilities: false, + // vulnerabilityTemplate: {} }; const search = await SavedSearch.create({ ...body, @@ -114,7 +114,7 @@ describe('saved-search', () => { }).save(); body.name = 'test-' + Math.random(); body.searchTerm = '123'; - body.createVulnerabilities = true; + // body.createVulnerabilities = true; const response = await request(app) .put(`/saved-searches/${search.id}`) .set( @@ -128,9 +128,9 @@ describe('saved-search', () => { .expect(200); expect(response.body.name).toEqual(body.name); expect(response.body.searchTerm).toEqual(body.searchTerm); - expect(response.body.createVulnerabilities).toEqual( - body.createVulnerabilities - ); + // expect(response.body.createVulnerabilities).toEqual( + // body.createVulnerabilities + // ); }); it('update by standard user without access should fail', async () => { const user = await User.create({ @@ -153,8 +153,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user }; const search = await SavedSearch.create(body).save(); @@ -179,9 +179,9 @@ describe('saved-search', () => { sortField: '', searchTerm: '', searchPath: '', - filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {} + filters: [] + // createVulnerabilities: false, + // vulnerabilityTemplate: {} }; const search = await SavedSearch.create(body).save(); const response = await request(app) @@ -206,9 +206,9 @@ describe('saved-search', () => { sortField: '', searchTerm: '', searchPath: '', - filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {} + filters: [] + // createVulnerabilities: false, + // vulnerabilityTemplate: {} }).save(); const response = await request(app) .delete(`/saved-searches/${search.id}`) @@ -235,8 +235,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -272,8 +272,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -309,8 +309,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -335,9 +335,9 @@ describe('saved-search', () => { sortField: '', searchTerm: '', searchPath: '', - filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {} + filters: [] + // createVulnerabilities: false, + // vulnerabilityTemplate: {} }).save(); const response = await request(app) .get(`/saved-searches`) @@ -371,8 +371,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user }).save(); // this org should not show up in the response @@ -384,8 +384,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user1 }).save(); const response = await request(app) @@ -411,9 +411,9 @@ describe('saved-search', () => { sortField: '', searchTerm: '', searchPath: '', - filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {} + filters: [] + // createVulnerabilities: false, + // vulnerabilityTemplate: {} }).save(); const response = await request(app) .get(`/saved-searches/${search.id}`) @@ -440,8 +440,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -477,8 +477,8 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - createVulnerabilities: false, - vulnerabilityTemplate: {}, + // createVulnerabilities: false, + // vulnerabilityTemplate: {}, createdBy: user1 }).save(); const response = await request(app) diff --git a/frontend/src/types/saved-search.ts b/frontend/src/types/saved-search.ts index 93e2d1e7..1e61fb5d 100644 --- a/frontend/src/types/saved-search.ts +++ b/frontend/src/types/saved-search.ts @@ -1,5 +1,5 @@ import { User } from './user'; -import { Vulnerability } from './vulnerability'; +// import { Vulnerability } from './vulnerability'; export interface SavedSearch { id: string; From 56dec3eeeff50e8eb306b2dabce0252ec02fcc33 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 10 Sep 2024 10:42:03 -0400 Subject: [PATCH 19/33] More test edits --- backend/src/tasks/saved-search.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/backend/src/tasks/saved-search.ts b/backend/src/tasks/saved-search.ts index cc63911b..d2e7e90f 100644 --- a/backend/src/tasks/saved-search.ts +++ b/backend/src/tasks/saved-search.ts @@ -51,20 +51,20 @@ export const handler = async (commandOptions: CommandOptions) => { search.count = hits; search.save(); - if (search.createVulnerabilities) { - const results = await fetchAllResults(filters, restrictions); - const vulnerabilities: Vulnerability[] = results.map((domain) => - plainToClass(Vulnerability, { - domain: domain, - lastSeen: new Date(Date.now()), - ...search.vulnerabilityTemplate, - state: 'open', - source: 'saved-search', - needsPopulation: false - }) - ); - await saveVulnerabilitiesToDb(vulnerabilities, false); - } + // if (search.createVulnerabilities) { + // const results = await fetchAllResults(filters, restrictions); + // const vulnerabilities: Vulnerability[] = results.map((domain) => + // plainToClass(Vulnerability, { + // domain: domain, + // lastSeen: new Date(Date.now()), + // ...search.vulnerabilityTemplate, + // state: 'open', + // source: 'saved-search', + // needsPopulation: false + // }) + // ); + // await saveVulnerabilitiesToDb(vulnerabilities, false); + // } } console.log(`Saved search finished for ${savedSearches.length} searches`); From 9b5d31b09c9f3866e0cd8cb5d63915d19364700f Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Tue, 10 Sep 2024 12:24:37 -0400 Subject: [PATCH 20/33] Updated saved-search snapshots; commented out vulnerability fields for saved-search in models --- backend/src/models/saved-search.ts | 13 +++++++++++-- .../test/__snapshots__/saved-searches.test.ts.snap | 2 -- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/backend/src/models/saved-search.ts b/backend/src/models/saved-search.ts index cb8987ab..bcd2d0bc 100644 --- a/backend/src/models/saved-search.ts +++ b/backend/src/models/saved-search.ts @@ -41,8 +41,17 @@ export class SavedSearch extends BaseEntity { @Column() searchPath: string; - - // Content of vulnerability when search is configured to create vulnerabilities from results + // TODO: Add this back if we have the ability to create vulnerabilities from search results + // @Column({ + // default: false + // }) + // createVulnerabilities: boolean; + + // // Content of vulnerability when search is configured to create vulnerabilities from results + // @Column({ type: 'jsonb', default: '{}' }) + // vulnerabilityTemplate: Partial & { + // title: string; + // }; @ManyToOne((type) => User, { onDelete: 'SET NULL', diff --git a/backend/test/__snapshots__/saved-searches.test.ts.snap b/backend/test/__snapshots__/saved-searches.test.ts.snap index efd26fcd..94c479ac 100644 --- a/backend/test/__snapshots__/saved-searches.test.ts.snap +++ b/backend/test/__snapshots__/saved-searches.test.ts.snap @@ -3,7 +3,6 @@ exports[`saved-search create create by user should succeed 1`] = ` Object { "count": 3, - "createVulnerabilities": false, "createdAt": Any, "createdBy": Object { "id": Any, @@ -16,6 +15,5 @@ Object { "sortDirection": "", "sortField": "", "updatedAt": Any, - "vulnerabilityTemplate": Object {}, } `; From c462f2e0fc9ef1c11499b7aa1e6e3be3f7b8c41d Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 10 Sep 2024 14:08:12 -0400 Subject: [PATCH 21/33] Created new state in SavedSearchContext - activeSearch is now stored in SavedSearchContext. - selectedSearch is now stored in SavedSearchContext. - activeSearchId is now stored in SavedSearchContext. - activeSearchId is determined in DrawerInterior and used to determine activeSearch and selectedSearch. - those are then passed to SaveSearchModal. --- frontend/src/components/DrawerInterior.tsx | 17 ++++++++++------- .../SaveSearchModal/SaveSearchModal.tsx | 12 ++++++------ frontend/src/context/SavedSearchContext.ts | 5 +++++ .../src/context/SavedSearchContextProvider.tsx | 15 ++++++++++++++- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/DrawerInterior.tsx b/frontend/src/components/DrawerInterior.tsx index 71b90e87..0e3a00f4 100644 --- a/frontend/src/components/DrawerInterior.tsx +++ b/frontend/src/components/DrawerInterior.tsx @@ -67,10 +67,13 @@ export const DrawerInterior: React.FC = (props) => { } = props; const { apiGet, apiDelete } = useAuthContext(); - const { savedSearches, setSavedSearches, setSavedSearchCount } = - useSavedSearchContext(); - - const [activeSearch, setActiveSearch] = React.useState(''); + const { + savedSearches, + setSavedSearches, + setSavedSearchCount, + activeSearchId, + setActiveSearchId + } = useSavedSearchContext(); const deleteSearch = async (id: string) => { try { @@ -97,7 +100,7 @@ export const DrawerInterior: React.FC = (props) => { addFilter(filter.field, value, 'any'); }); }); - setActiveSearch(id); + setActiveSearchId(id); }; const restoreInitialFilters = () => { initialFilters.forEach((filter) => { @@ -113,7 +116,7 @@ export const DrawerInterior: React.FC = (props) => { autocompleteResults: false }); restoreInitialFilters(); - setActiveSearch(''); + setActiveSearchId(''); }; const toggleSavedSearches = (id: string) => { const savedSearch = savedSearches.filter((search) => search.id === id); @@ -128,7 +131,7 @@ export const DrawerInterior: React.FC = (props) => { }; const isSavedSearchActive = (id: string): boolean => { - return activeSearch === id; + return activeSearchId === id; }; const filtersByColumn = useMemo( diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index fc6a7f2e..a8080652 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -41,11 +41,11 @@ export const SaveSearchModal: React.FC = (props) => { duplicate: false }); const { apiGet, apiPost, apiPut } = useAuthContext(); - const { savedSearches, setSavedSearches, setSavedSearchCount } = + const { savedSearches, setSavedSearches, setSavedSearchCount, activeSearch } = useSavedSearchContext(); const [savedSearchValues, setSavedSearchValues] = useState< Partial & { name: string } - >(search ? search : { name: '' }); + >(activeSearch ? activeSearch : { name: '' }); // API call to save/update saved searches const handleSave = async (savedSearchValues: Partial) => { @@ -87,8 +87,8 @@ export const SaveSearchModal: React.FC = (props) => { }; const handleClick = () => { - if (search) { - savedSearchValues.name = search.name; + if (activeSearch) { + savedSearchValues.name = activeSearch.name; setDialogOpen(true); // Open dialog to confirm update } else { handleOpenModal(); @@ -136,9 +136,9 @@ export const SaveSearchModal: React.FC = (props) => { onClick={handleClick} endIcon={} disabled={!advancedFiltersReq} - aria-label={search ? 'Update Saved Search' : 'Save Search'} + aria-label={activeSearch ? 'Update Saved Search' : 'Save Search'} > - {search ? 'Update Saved Search' : 'Save Search'} + {activeSearch ? 'Update Saved Search' : 'Save Search'} void; savedSearchCount: number; setSavedSearchCount: (savedSearchCount: number) => void; + activeSearchId: string; + setActiveSearchId: (activeSearchId: string) => void; + selectedSearch: SavedSearch | null; + setSelectedSearch: (selectedSearch: SavedSearch | null) => void; + activeSearch: SavedSearch | undefined; } export const SavedSearchContext = React.createContext( diff --git a/frontend/src/context/SavedSearchContextProvider.tsx b/frontend/src/context/SavedSearchContextProvider.tsx index 2d418adc..3c26b930 100644 --- a/frontend/src/context/SavedSearchContextProvider.tsx +++ b/frontend/src/context/SavedSearchContextProvider.tsx @@ -12,6 +12,10 @@ export const SavedSearchContextProvider: React.FC< > = ({ children }) => { const [savedSearches, setSavedSearches] = useState([]); const [savedSearchCount, setSavedSearchCount] = useState(0); + const [activeSearchId, setActiveSearchId] = useState(''); + const [selectedSearch, setSelectedSearch] = useState( + null + ); const { apiGet, user } = useAuthContext(); const fetchSearches = useCallback(async () => { @@ -24,6 +28,10 @@ export const SavedSearchContextProvider: React.FC< } }, [apiGet, setSavedSearches, setSavedSearchCount]); + const activeSearch = useMemo(() => { + return savedSearches.find((search) => search.id === activeSearchId); + }, [activeSearchId, savedSearches]); + useEffect(() => { if (user) fetchSearches(); }, [user, fetchSearches]); @@ -41,7 +49,12 @@ export const SavedSearchContextProvider: React.FC< savedSearches: memoizedSavedSearches, setSavedSearches, savedSearchCount: memoizedSavedSearchCount, - setSavedSearchCount + setSavedSearchCount, + activeSearchId, + setActiveSearchId, + selectedSearch, + setSelectedSearch, + activeSearch }} > {children} From cf4afea75ba83cac557dca78ec5bc5eae01f4a26 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Tue, 10 Sep 2024 16:07:44 -0400 Subject: [PATCH 22/33] Fixed update save search; removed search from Inventory; removed existingSearch from SortBar --- .../SaveSearchModal/SaveSearchModal.tsx | 57 ++++++++++++++----- frontend/src/pages/Search/Inventory.tsx | 25 -------- frontend/src/pages/Search/SortBar.tsx | 2 - 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index a8080652..9744e443 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -15,7 +15,6 @@ import { useAuthContext } from '../../context'; import { Save } from '@mui/icons-material'; interface SaveSearchModalProps { - search: any; searchTerm: string; filters: any; totalResults: number; @@ -26,7 +25,6 @@ interface SaveSearchModalProps { export const SaveSearchModal: React.FC = (props) => { const { - search, searchTerm, filters, totalResults, @@ -46,7 +44,6 @@ export const SaveSearchModal: React.FC = (props) => { const [savedSearchValues, setSavedSearchValues] = useState< Partial & { name: string } >(activeSearch ? activeSearch : { name: '' }); - // API call to save/update saved searches const handleSave = async (savedSearchValues: Partial) => { const body = { @@ -62,8 +59,8 @@ export const SaveSearchModal: React.FC = (props) => { }; try { - if (search) { - await apiPut('/saved-searches/' + search.id, body); + if (activeSearch) { + await apiPut('/saved-searches/' + activeSearch.id, body); } else { await apiPost('/saved-searches/', body); } @@ -111,15 +108,17 @@ export const SaveSearchModal: React.FC = (props) => { return nameRegex.test(name); }; - const handleChange = (name: string, value: any) => { - setSavedSearchValues((values) => ({ - ...values, - [name]: value + const handleChange = (textInputName: string, textInput: string) => { + setSavedSearchValues((inputValues) => ({ + ...inputValues, + [textInputName]: textInput })); // Validation check for valid characters and duplicate names - if (name === 'name') { - const isValid = validation(value); - const isDuplicate = savedSearches.some((search) => search.name === value); + if (textInputName === 'name') { + const isValid = validation(textInput); + const isDuplicate = savedSearches.some( + (search) => search.name === textInput + ); setFormErrors((prev) => ({ ...prev, @@ -145,16 +144,44 @@ export const SaveSearchModal: React.FC = (props) => { onClose={() => setDialogOpen(false)} aria-labelledby="confirm-dialog-title" aria-describedby="confirm-dialog-description" + PaperProps={{ + component: 'form', + onSubmit: handleSubmit, + style: { width: '30%', minWidth: '300px' } + }} > Update Saved Search - Are you sure you want to update this saved search? + handleChange(e.target.name, e.target.value)} + inputProps={{ + 'aria-label': 'Enter a name for your saved search' + }} + error={formErrors.name} + helperText={ + formErrors.name + ? 'Name is required and must contain only alphanumeric characters, spaces, hyphens, or apostrophes.' + : formErrors.duplicate + ? 'This name is already taken. Please choose a different name.' + : '' + } + /> diff --git a/frontend/src/pages/Search/Inventory.tsx b/frontend/src/pages/Search/Inventory.tsx index ce3d0fb3..8aa2b2c8 100644 --- a/frontend/src/pages/Search/Inventory.tsx +++ b/frontend/src/pages/Search/Inventory.tsx @@ -18,8 +18,6 @@ import { ContextType } from '../../context/SearchProvider'; import { SortBar } from './SortBar'; import { useAuthContext } from 'context'; import { FilterTags } from './FilterTags'; -import { SavedSearch } from 'types'; -import { useBeforeunload } from 'react-beforeunload'; import { NoResults } from 'components/NoResults'; import { exportCSV } from 'components/ImportExport'; import { SaveSearchModal } from 'components/SaveSearchModal/SaveSearchModal'; @@ -52,27 +50,6 @@ export const DashboardUI: React.FC = ( const advanceFiltersReq = filters.length > 1 || searchTerm !== ''; //Prevents a user from saving a search without advanced filters - const search: - | (SavedSearch & { - editing?: boolean; - }) - | undefined = localStorage.getItem('savedSearch') - ? JSON.parse(localStorage.getItem('savedSearch')!) - : undefined; - - useEffect(() => { - if (props.location.search === '') { - // Search on initial load - } - return () => { - localStorage.removeItem('savedSearch'); - }; - }, [setSearchTerm, props.location.search]); - - useBeforeunload((event) => { - localStorage.removeItem('savedSearch'); - }); - const fetchDomainsExport = async (): Promise => { try { const body: any = { @@ -150,11 +127,9 @@ export const DashboardUI: React.FC = ( sortDirection={sortDirection} setSort={setSort} isFixed={resultsScrolled} - existingSavedSearch={search} advancedFiltersReq={advanceFiltersReq} /> Date: Tue, 10 Sep 2024 17:07:03 -0400 Subject: [PATCH 23/33] Cleaned up Saved Search Context and Modal - Removed unused state from SavedSearchContext and SavedSearchContextProvider. - Added boolean check to allow user to resuse a name for a saved search if it is the same search. - Added disbale props to the update search dialogue. --- .../src/components/SaveSearchModal/SaveSearchModal.tsx | 8 +++++++- frontend/src/context/SavedSearchContext.ts | 2 -- frontend/src/context/SavedSearchContextProvider.tsx | 5 ----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 9744e443..3a3adee1 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -13,6 +13,7 @@ import { import { SavedSearch } from '../../types/saved-search'; import { useAuthContext } from '../../context'; import { Save } from '@mui/icons-material'; +import { act } from 'react-dom/test-utils'; interface SaveSearchModalProps { searchTerm: string; @@ -114,7 +115,7 @@ export const SaveSearchModal: React.FC = (props) => { [textInputName]: textInput })); // Validation check for valid characters and duplicate names - if (textInputName === 'name') { + if (textInputName === 'name' && textInput !== activeSearch?.name) { const isValid = validation(textInput); const isDuplicate = savedSearches.some( (search) => search.name === textInput @@ -193,6 +194,11 @@ export const SaveSearchModal: React.FC = (props) => { console.error(e); } }} + disabled={ + formErrors.name || + formErrors.duplicate || + !savedSearchValues.name.trim() + } color="primary" autoFocus > diff --git a/frontend/src/context/SavedSearchContext.ts b/frontend/src/context/SavedSearchContext.ts index a7252771..c34b0697 100644 --- a/frontend/src/context/SavedSearchContext.ts +++ b/frontend/src/context/SavedSearchContext.ts @@ -8,8 +8,6 @@ export interface SavedSearchContextType { setSavedSearchCount: (savedSearchCount: number) => void; activeSearchId: string; setActiveSearchId: (activeSearchId: string) => void; - selectedSearch: SavedSearch | null; - setSelectedSearch: (selectedSearch: SavedSearch | null) => void; activeSearch: SavedSearch | undefined; } diff --git a/frontend/src/context/SavedSearchContextProvider.tsx b/frontend/src/context/SavedSearchContextProvider.tsx index 3c26b930..15f9ae65 100644 --- a/frontend/src/context/SavedSearchContextProvider.tsx +++ b/frontend/src/context/SavedSearchContextProvider.tsx @@ -13,9 +13,6 @@ export const SavedSearchContextProvider: React.FC< const [savedSearches, setSavedSearches] = useState([]); const [savedSearchCount, setSavedSearchCount] = useState(0); const [activeSearchId, setActiveSearchId] = useState(''); - const [selectedSearch, setSelectedSearch] = useState( - null - ); const { apiGet, user } = useAuthContext(); const fetchSearches = useCallback(async () => { @@ -52,8 +49,6 @@ export const SavedSearchContextProvider: React.FC< setSavedSearchCount, activeSearchId, setActiveSearchId, - selectedSearch, - setSelectedSearch, activeSearch }} > From f343aad657342e8c9cd55076a0974eeb798737b5 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 10 Sep 2024 18:25:54 -0400 Subject: [PATCH 24/33] Edits to save src modal, drawer int, & inventory - Saved Search list is now sorted ascending by name. - Removed unused imports from SaveSearchModal and Inventory. - Changed names of dialogs to be more descriptive. - update handler is now handleUpdate. --- frontend/src/components/DrawerInterior.tsx | 10 ++++++-- .../SaveSearchModal/SaveSearchModal.tsx | 25 +++++++++---------- frontend/src/pages/Search/Inventory.tsx | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/DrawerInterior.tsx b/frontend/src/components/DrawerInterior.tsx index 0e3a00f4..42aac3de 100644 --- a/frontend/src/components/DrawerInterior.tsx +++ b/frontend/src/components/DrawerInterior.tsx @@ -134,6 +134,12 @@ export const DrawerInterior: React.FC = (props) => { return activeSearchId === id; }; + const ascendingSavedSearches = savedSearches.sort((a, b) => + a.name.localeCompare(b.name) + ); + + console.log(ascendingSavedSearches); + const filtersByColumn = useMemo( () => filters.reduce( @@ -408,9 +414,9 @@ export const DrawerInterior: React.FC = (props) => { Saved Searches - {savedSearches.length > 0 ? ( + {ascendingSavedSearches.length > 0 ? ( - {savedSearches.map((search) => ( + {ascendingSavedSearches.map((search) => ( = (props) => { sortDirection, advancedFiltersReq } = props; - const [open, setOpen] = useState(false); - const [dialogeOpen, setDialogOpen] = useState(false); + const [saveDialogOpen, setSaveDialogOpen] = useState(false); + const [updateDialogOpen, setUpdateDialogOpen] = useState(false); const [formErrors, setFormErrors] = useState({ name: false, duplicate: false @@ -74,20 +73,20 @@ export const SaveSearchModal: React.FC = (props) => { }; const handleCloseModal = () => { - setOpen(false); + setSaveDialogOpen(false); }; const handleOpenModal = () => { - setOpen(true); + setSaveDialogOpen(true); }; const handleDialogClose = () => { - setDialogOpen(false); + setUpdateDialogOpen(false); }; - const handleClick = () => { + const handleUpdate = () => { if (activeSearch) { savedSearchValues.name = activeSearch.name; - setDialogOpen(true); // Open dialog to confirm update + setUpdateDialogOpen(true); // Open dialog to confirm update } else { handleOpenModal(); } @@ -133,7 +132,7 @@ export const SaveSearchModal: React.FC = (props) => { <> setDialogOpen(false)} + open={updateDialogOpen} + onClose={() => setUpdateDialogOpen(false)} aria-labelledby="confirm-dialog-title" aria-describedby="confirm-dialog-description" PaperProps={{ @@ -189,7 +188,7 @@ export const SaveSearchModal: React.FC = (props) => { onClick={() => { try { handleSave(savedSearchValues); - setDialogOpen(false); + setUpdateDialogOpen(false); } catch (e) { console.error(e); } @@ -207,7 +206,7 @@ export const SaveSearchModal: React.FC = (props) => { Date: Wed, 11 Sep 2024 09:36:44 -0400 Subject: [PATCH 25/33] Fixed save search/update search placeholder text --- frontend/src/components/SaveSearchModal/SaveSearchModal.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 4a689429..50a07f46 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -81,6 +81,7 @@ export const SaveSearchModal: React.FC = (props) => { const handleDialogClose = () => { setUpdateDialogOpen(false); + savedSearchValues.name = ''; }; const handleUpdate = () => { @@ -189,6 +190,7 @@ export const SaveSearchModal: React.FC = (props) => { try { handleSave(savedSearchValues); setUpdateDialogOpen(false); + savedSearchValues.name = ''; } catch (e) { console.error(e); } From 4c45b9e408008b9ce69ce46d7f9da8a74dfe05d2 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Wed, 11 Sep 2024 09:53:04 -0400 Subject: [PATCH 26/33] Fixed new save search not clearing placeholder text --- frontend/src/components/SaveSearchModal/SaveSearchModal.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 50a07f46..f24afddb 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -74,6 +74,7 @@ export const SaveSearchModal: React.FC = (props) => { const handleCloseModal = () => { setSaveDialogOpen(false); + savedSearchValues.name = ''; }; const handleOpenModal = () => { setSaveDialogOpen(true); From 47c38e367cfb3f99c4bc17f79fc76d7a191bca64 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Wed, 11 Sep 2024 12:55:52 -0400 Subject: [PATCH 27/33] Removed unnecessary log --- frontend/src/components/DrawerInterior.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/components/DrawerInterior.tsx b/frontend/src/components/DrawerInterior.tsx index 42aac3de..3b43e432 100644 --- a/frontend/src/components/DrawerInterior.tsx +++ b/frontend/src/components/DrawerInterior.tsx @@ -138,8 +138,6 @@ export const DrawerInterior: React.FC = (props) => { a.name.localeCompare(b.name) ); - console.log(ascendingSavedSearches); - const filtersByColumn = useMemo( () => filters.reduce( From 54c14400f5bcc7b7a7e92f07b64291c8a580f27c Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Wed, 11 Sep 2024 13:38:57 -0400 Subject: [PATCH 28/33] documented deprecation of create vulnerability function --- backend/src/api/saved-searches.ts | 3 ++ backend/src/models/saved-search.ts | 5 ++-- backend/src/tasks/saved-search.ts | 3 ++ backend/test/saved-searches.test.ts | 45 +++++++++++++++++++++++++++++ frontend/src/types/saved-search.ts | 3 ++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/backend/src/api/saved-searches.ts b/backend/src/api/saved-searches.ts index b03a304c..72b69066 100644 --- a/backend/src/api/saved-searches.ts +++ b/backend/src/api/saved-searches.ts @@ -62,6 +62,9 @@ class NewSavedSearch { @IsArray() filters: { field: string; values: any[]; type: string }[]; + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // @IsBoolean() // createVulnerabilities: boolean; diff --git a/backend/src/models/saved-search.ts b/backend/src/models/saved-search.ts index bcd2d0bc..1d0a21ac 100644 --- a/backend/src/models/saved-search.ts +++ b/backend/src/models/saved-search.ts @@ -41,8 +41,9 @@ export class SavedSearch extends BaseEntity { @Column() searchPath: string; - // TODO: Add this back if we have the ability to create vulnerabilities from search results - // @Column({ + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // @Column({ // default: false // }) // createVulnerabilities: boolean; diff --git a/backend/src/tasks/saved-search.ts b/backend/src/tasks/saved-search.ts index d2e7e90f..2d73f50f 100644 --- a/backend/src/tasks/saved-search.ts +++ b/backend/src/tasks/saved-search.ts @@ -51,6 +51,9 @@ export const handler = async (commandOptions: CommandOptions) => { search.count = hits; search.save(); + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // if (search.createVulnerabilities) { // const results = await fetchAllResults(filters, restrictions); // const vulnerabilities: Vulnerability[] = results.map((domain) => diff --git a/backend/test/saved-searches.test.ts b/backend/test/saved-searches.test.ts index 02f86c6c..3bca9f4b 100644 --- a/backend/test/saved-searches.test.ts +++ b/backend/test/saved-searches.test.ts @@ -46,6 +46,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {} }) @@ -105,6 +108,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {} }; @@ -128,6 +134,9 @@ describe('saved-search', () => { .expect(200); expect(response.body.name).toEqual(body.name); expect(response.body.searchTerm).toEqual(body.searchTerm); + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // expect(response.body.createVulnerabilities).toEqual( // body.createVulnerabilities // ); @@ -153,6 +162,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user @@ -180,6 +192,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {} }; @@ -207,6 +222,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {} }).save(); @@ -235,6 +253,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user @@ -272,6 +293,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user @@ -309,6 +333,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user @@ -336,6 +363,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {} }).save(); @@ -371,6 +401,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user @@ -384,6 +417,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user1 @@ -412,6 +448,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {} }).save(); @@ -440,6 +479,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user @@ -477,6 +519,9 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: false, // vulnerabilityTemplate: {}, createdBy: user1 diff --git a/frontend/src/types/saved-search.ts b/frontend/src/types/saved-search.ts index 1e61fb5d..1c138e8e 100644 --- a/frontend/src/types/saved-search.ts +++ b/frontend/src/types/saved-search.ts @@ -13,6 +13,9 @@ export interface SavedSearch { searchPath: string; sortField: string; sortDirection: string; + // The following properties are deprecated due to the refactor of the Save Search Modal. + // The Create Vulnerabilities functionality has been removed as it is no longer needed. + // These properties are kept here for reference and will be removed in future versions. // createVulnerabilities: boolean; // vulnerabilityTemplate: Partial; } From 5044045ee3fd011bbde3845f44b326a76b99cc8d Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Wed, 11 Sep 2024 15:30:49 -0400 Subject: [PATCH 29/33] Added onKeyDown for SaveSearchModal; address 508 compliance requirements --- .../SaveSearchModal/SaveSearchModal.tsx | 64 ++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index f24afddb..9b7244cf 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -133,6 +133,7 @@ export const SaveSearchModal: React.FC = (props) => { return ( <> + From 6021f16569ff708cb24904d7ba851db38ec09459 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Wed, 11 Sep 2024 15:49:10 -0400 Subject: [PATCH 30/33] Fixed onKeyDown event not working; Updated onKeyDown to submit form --- .../SaveSearchModal/SaveSearchModal.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index 9b7244cf..c0e325ce 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -316,8 +316,19 @@ export const SaveSearchModal: React.FC = (props) => { formErrors.duplicate || !savedSearchValues.name.trim() } - onKeyDown={() => { - handleSubmit; + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + try { + if (formErrors.name) { + return; + } + handleSave(savedSearchValues); + handleCloseModal(); + } catch (e) { + console.error(e); + } + } }} aria-label="Save the search" color="primary" From b66f357223c0472e06bdbe1c089f7e79106157e4 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Wed, 11 Sep 2024 16:25:16 -0400 Subject: [PATCH 31/33] Added aria labels to forms and buttons within SaveSearchModal --- .../SaveSearchModal/SaveSearchModal.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx index c0e325ce..193613fd 100644 --- a/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx +++ b/frontend/src/components/SaveSearchModal/SaveSearchModal.tsx @@ -145,17 +145,20 @@ export const SaveSearchModal: React.FC = (props) => { setUpdateDialogOpen(false)} - aria-labelledby="confirm-dialog-title" - aria-describedby="confirm-dialog-description" + aria-label="Save Search form" + aria-labelledby="save-search-form-title" + aria-describedby="save-search-form-description" PaperProps={{ component: 'form', onSubmit: handleSubmit, style: { width: '30%', minWidth: '300px' } }} > - Update Saved Search + + Update Saved Search + - + = (props) => { } } }} + aria-label="Cancel and close the dialog" > Cancel @@ -236,6 +240,7 @@ export const SaveSearchModal: React.FC = (props) => { }} color="primary" autoFocus + aria-label="Save the search" > Save @@ -249,7 +254,8 @@ export const SaveSearchModal: React.FC = (props) => { onSubmit: handleSubmit, style: { width: '30%', minWidth: '300px' } }} - aria-labelledby="dialog-title" + aria-label="Save Search" + aria-labelledby="save-search-dialog-title" aria-describedby="dialog-description" > Save Search From ab3030cdfc855e0d01486f0027afe25a5b88ee90 Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Thu, 12 Sep 2024 12:35:22 -0400 Subject: [PATCH 32/33] Removed deprecated code --- backend/src/api/saved-searches.ts | 10 ---- backend/src/models/saved-search.ts | 12 ----- backend/src/tasks/saved-search.ts | 18 ------- backend/test/saved-searches.test.ts | 77 ----------------------------- frontend/src/types/saved-search.ts | 6 --- 5 files changed, 123 deletions(-) diff --git a/backend/src/api/saved-searches.ts b/backend/src/api/saved-searches.ts index 72b69066..fb0d30ba 100644 --- a/backend/src/api/saved-searches.ts +++ b/backend/src/api/saved-searches.ts @@ -61,16 +61,6 @@ class NewSavedSearch { @IsArray() filters: { field: string; values: any[]; type: string }[]; - - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // @IsBoolean() - // createVulnerabilities: boolean; - - // @IsObject() - // @IsOptional() - // vulnerabilityTemplate: Partial; } const PAGE_SIZE = 20; diff --git a/backend/src/models/saved-search.ts b/backend/src/models/saved-search.ts index 1d0a21ac..c8b42a07 100644 --- a/backend/src/models/saved-search.ts +++ b/backend/src/models/saved-search.ts @@ -41,18 +41,6 @@ export class SavedSearch extends BaseEntity { @Column() searchPath: string; - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. // @Column({ - // default: false - // }) - // createVulnerabilities: boolean; - - // // Content of vulnerability when search is configured to create vulnerabilities from results - // @Column({ type: 'jsonb', default: '{}' }) - // vulnerabilityTemplate: Partial & { - // title: string; - // }; @ManyToOne((type) => User, { onDelete: 'SET NULL', diff --git a/backend/src/tasks/saved-search.ts b/backend/src/tasks/saved-search.ts index 2d73f50f..8e8afca1 100644 --- a/backend/src/tasks/saved-search.ts +++ b/backend/src/tasks/saved-search.ts @@ -50,24 +50,6 @@ export const handler = async (commandOptions: CommandOptions) => { const hits: number = searchResults.body.hits.total.value; search.count = hits; search.save(); - - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // if (search.createVulnerabilities) { - // const results = await fetchAllResults(filters, restrictions); - // const vulnerabilities: Vulnerability[] = results.map((domain) => - // plainToClass(Vulnerability, { - // domain: domain, - // lastSeen: new Date(Date.now()), - // ...search.vulnerabilityTemplate, - // state: 'open', - // source: 'saved-search', - // needsPopulation: false - // }) - // ); - // await saveVulnerabilitiesToDb(vulnerabilities, false); - // } } console.log(`Saved search finished for ${savedSearches.length} searches`); diff --git a/backend/test/saved-searches.test.ts b/backend/test/saved-searches.test.ts index 3bca9f4b..434f667d 100644 --- a/backend/test/saved-searches.test.ts +++ b/backend/test/saved-searches.test.ts @@ -46,11 +46,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {} }) .expect(200); expect(response.body).toMatchSnapshot({ @@ -108,11 +103,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {} }; const search = await SavedSearch.create({ ...body, @@ -120,7 +110,6 @@ describe('saved-search', () => { }).save(); body.name = 'test-' + Math.random(); body.searchTerm = '123'; - // body.createVulnerabilities = true; const response = await request(app) .put(`/saved-searches/${search.id}`) .set( @@ -134,12 +123,6 @@ describe('saved-search', () => { .expect(200); expect(response.body.name).toEqual(body.name); expect(response.body.searchTerm).toEqual(body.searchTerm); - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // expect(response.body.createVulnerabilities).toEqual( - // body.createVulnerabilities - // ); }); it('update by standard user without access should fail', async () => { const user = await User.create({ @@ -162,11 +145,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user }; const search = await SavedSearch.create(body).save(); @@ -192,11 +170,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {} }; const search = await SavedSearch.create(body).save(); const response = await request(app) @@ -222,11 +195,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {} }).save(); const response = await request(app) .delete(`/saved-searches/${search.id}`) @@ -253,11 +221,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -293,11 +256,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -333,11 +291,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -363,11 +316,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {} }).save(); const response = await request(app) .get(`/saved-searches`) @@ -401,11 +349,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user }).save(); // this org should not show up in the response @@ -417,11 +360,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user1 }).save(); const response = await request(app) @@ -448,11 +386,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {} }).save(); const response = await request(app) .get(`/saved-searches/${search.id}`) @@ -479,11 +412,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user }).save(); const response = await request(app) @@ -519,11 +447,6 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [], - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: false, - // vulnerabilityTemplate: {}, createdBy: user1 }).save(); const response = await request(app) diff --git a/frontend/src/types/saved-search.ts b/frontend/src/types/saved-search.ts index 1c138e8e..14444f7a 100644 --- a/frontend/src/types/saved-search.ts +++ b/frontend/src/types/saved-search.ts @@ -1,5 +1,4 @@ import { User } from './user'; -// import { Vulnerability } from './vulnerability'; export interface SavedSearch { id: string; @@ -13,9 +12,4 @@ export interface SavedSearch { searchPath: string; sortField: string; sortDirection: string; - // The following properties are deprecated due to the refactor of the Save Search Modal. - // The Create Vulnerabilities functionality has been removed as it is no longer needed. - // These properties are kept here for reference and will be removed in future versions. - // createVulnerabilities: boolean; - // vulnerabilityTemplate: Partial; } From a143154a2592275233a71f0696119d32d1d5872d Mon Sep 17 00:00:00 2001 From: Chrtorres Date: Thu, 12 Sep 2024 12:40:52 -0400 Subject: [PATCH 33/33] Removed commented code --- backend/test/saved-searches.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/test/saved-searches.test.ts b/backend/test/saved-searches.test.ts index 434f667d..fc87a624 100644 --- a/backend/test/saved-searches.test.ts +++ b/backend/test/saved-searches.test.ts @@ -70,13 +70,10 @@ describe('saved-search', () => { searchTerm: '', searchPath: '', filters: [] - // createVulnerabilities: false, - // vulnerabilityTemplate: {} }; const search = await SavedSearch.create(body).save(); body.name = 'test-' + Math.random(); body.searchTerm = '123'; - // body.createVulnerabilities = true; const response = await request(app) .put(`/saved-searches/${search.id}`) .set(