Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Save search modal #603

Merged
merged 37 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5055d8a
Created SaveSearchModal; testing in inventory
chrtorres Aug 28, 2024
f46759e
Merge branch '543-refactor-of-saved-search-accordion' into save-searc…
chrtorres Aug 28, 2024
d0595dc
Remove unused import
chrtorres Aug 29, 2024
3c40209
Troubleshooting modal functions
chrtorres Sep 5, 2024
37a4875
Troubeshooting API requests Save Search Modal
chrtorres Sep 5, 2024
4a98b7e
Merge remote-tracking branch 'origin' into save-search-modal
chrtorres Sep 6, 2024
6fca51d
Save Search modal now saves user defined Search
hawkishpolicy Sep 6, 2024
a09b482
Merge branch 'save-search-modal' of https://github.com/cisagov/XFD in…
hawkishpolicy Sep 6, 2024
27a6439
Restored SaveSearchModal and Stack to Inventory
hawkishpolicy Sep 6, 2024
6b7f42a
Merge remote-tracking branch 'origin/develop' into save-search-modal
hawkishpolicy Sep 6, 2024
9d3b047
Modified Save Search button
hawkishpolicy Sep 6, 2024
f5c72b1
Implemented form validation on save search modal
chrtorres Sep 9, 2024
0c97205
Added form validation for duplicate entries
chrtorres Sep 9, 2024
5e526a0
Update saved search fixed
chrtorres Sep 9, 2024
16967f9
Code cleanup; remove unused imports
chrtorres Sep 9, 2024
bc49d5e
Code cleanup; remove unused variable
chrtorres Sep 9, 2024
0cd9799
Code cleanup; remove unused useRef
chrtorres Sep 9, 2024
ab4f3ea
Removed window.reload with use of state instead; removed unnecessary …
chrtorres Sep 9, 2024
aebcf5b
Refactored Save Search Accordion
hawkishpolicy Sep 10, 2024
36501ff
Edited saved-search type for testing
hawkishpolicy Sep 10, 2024
962d777
Commented out type def for saved searches at api
hawkishpolicy Sep 10, 2024
37e3e27
Updated saved-searches.test.ts and saved-search.ts
hawkishpolicy Sep 10, 2024
56dec3e
More test edits
hawkishpolicy Sep 10, 2024
9b5d31b
Updated saved-search snapshots; commented out vulnerability fields fo…
chrtorres Sep 10, 2024
c462f2e
Created new state in SavedSearchContext
hawkishpolicy Sep 10, 2024
cf4afea
Fixed update save search; removed search from Inventory; removed exis…
chrtorres Sep 10, 2024
f119e9e
Cleaned up Saved Search Context and Modal
hawkishpolicy Sep 10, 2024
f343aad
Edits to save src modal, drawer int, & inventory
hawkishpolicy Sep 10, 2024
ea1e13a
Fixed save search/update search placeholder text
chrtorres Sep 11, 2024
4c45b9e
Fixed new save search not clearing placeholder text
chrtorres Sep 11, 2024
47c38e3
Removed unnecessary log
chrtorres Sep 11, 2024
54c1440
documented deprecation of create vulnerability function
chrtorres Sep 11, 2024
5044045
Added onKeyDown for SaveSearchModal; address 508 compliance requirements
chrtorres Sep 11, 2024
6021f16
Fixed onKeyDown event not working; Updated onKeyDown to submit form
chrtorres Sep 11, 2024
b66f357
Added aria labels to forms and buttons within SaveSearchModal
chrtorres Sep 11, 2024
ab3030c
Removed deprecated code
chrtorres Sep 12, 2024
a143154
Removed commented code
chrtorres Sep 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions backend/src/api/saved-searches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,6 @@ class NewSavedSearch {

@IsArray()
filters: { field: string; values: any[]; type: string }[];

@IsBoolean()
createVulnerabilities: boolean;

@IsObject()
@IsOptional()
vulnerabilityTemplate: Partial<Vulnerability>;
}

const PAGE_SIZE = 20;
Expand Down
11 changes: 0 additions & 11 deletions backend/src/models/saved-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,6 @@ 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<Vulnerability> & {
title: string;
};

@ManyToOne((type) => User, {
onDelete: 'SET NULL',
onUpdate: 'CASCADE'
Expand Down
15 changes: 0 additions & 15 deletions backend/src/tasks/saved-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,6 @@ export const handler = async (commandOptions: CommandOptions) => {
const hits: number = searchResults.body.hits.total.value;
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);
}
}

console.log(`Saved search finished for ${savedSearches.length} searches`);
Expand Down
2 changes: 0 additions & 2 deletions backend/test/__snapshots__/saved-searches.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
exports[`saved-search create create by user should succeed 1`] = `
Object {
"count": 3,
"createVulnerabilities": false,
"createdAt": Any<String>,
"createdBy": Object {
"id": Any<String>,
Expand All @@ -16,6 +15,5 @@ Object {
"sortDirection": "",
"sortField": "",
"updatedAt": Any<String>,
"vulnerabilityTemplate": Object {},
}
`;
49 changes: 7 additions & 42 deletions backend/test/saved-searches.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ describe('saved-search', () => {
sortField: '',
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {}
filters: []
})
.expect(200);
expect(response.body).toMatchSnapshot({
Expand All @@ -71,14 +69,11 @@ describe('saved-search', () => {
sortField: '',
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {}
filters: []
};
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(
Expand All @@ -104,17 +99,14 @@ describe('saved-search', () => {
sortField: '',
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {}
filters: []
};
const search = await SavedSearch.create({
...body,
createdBy: user
}).save();
body.name = 'test-' + Math.random();
body.searchTerm = '123';
body.createVulnerabilities = true;
const response = await request(app)
.put(`/saved-searches/${search.id}`)
.set(
Expand All @@ -128,9 +120,6 @@ 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
);
});
it('update by standard user without access should fail', async () => {
const user = await User.create({
Expand All @@ -153,8 +142,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user
};
const search = await SavedSearch.create(body).save();
Expand All @@ -179,9 +166,7 @@ describe('saved-search', () => {
sortField: '',
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {}
filters: []
};
const search = await SavedSearch.create(body).save();
const response = await request(app)
Expand All @@ -206,9 +191,7 @@ describe('saved-search', () => {
sortField: '',
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {}
filters: []
}).save();
const response = await request(app)
.delete(`/saved-searches/${search.id}`)
Expand All @@ -235,8 +218,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user
}).save();
const response = await request(app)
Expand Down Expand Up @@ -272,8 +253,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user
}).save();
const response = await request(app)
Expand Down Expand Up @@ -309,8 +288,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user
}).save();
const response = await request(app)
Expand All @@ -335,9 +312,7 @@ describe('saved-search', () => {
sortField: '',
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {}
filters: []
}).save();
const response = await request(app)
.get(`/saved-searches`)
Expand Down Expand Up @@ -371,8 +346,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user
}).save();
// this org should not show up in the response
Expand All @@ -384,8 +357,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user1
}).save();
const response = await request(app)
Expand All @@ -411,9 +382,7 @@ describe('saved-search', () => {
sortField: '',
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {}
filters: []
}).save();
const response = await request(app)
.get(`/saved-searches/${search.id}`)
Expand All @@ -440,8 +409,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user
}).save();
const response = await request(app)
Expand Down Expand Up @@ -477,8 +444,6 @@ describe('saved-search', () => {
searchTerm: '',
searchPath: '',
filters: [],
createVulnerabilities: false,
vulnerabilityTemplate: {},
createdBy: user1
}).save();
const response = await request(app)
Expand Down
29 changes: 18 additions & 11 deletions frontend/src/components/DrawerInterior.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,13 @@ export const DrawerInterior: React.FC<Props> = (props) => {
} = props;
const { apiGet, apiDelete } = useAuthContext();

const { savedSearches, setSavedSearches, setSavedSearchCount } =
useSavedSearchContext();
const {
savedSearches,
setSavedSearches,
setSavedSearchCount,
activeSearchId,
setActiveSearchId
} = useSavedSearchContext();

const deleteSearch = async (id: string) => {
try {
Expand All @@ -84,7 +89,6 @@ export const DrawerInterior: React.FC<Props> = (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
Expand All @@ -96,6 +100,7 @@ export const DrawerInterior: React.FC<Props> = (props) => {
addFilter(filter.field, value, 'any');
});
});
setActiveSearchId(id);
};
const restoreInitialFilters = () => {
initialFilters.forEach((filter) => {
Expand All @@ -110,11 +115,12 @@ export const DrawerInterior: React.FC<Props> = (props) => {
shouldClearFilters: true,
autocompleteResults: false
});
localStorage.removeItem('savedSearch');
restoreInitialFilters();
setActiveSearchId('');
};
const toggleSavedSearches = (id: string) => {
const savedSearch = savedSearches.filter((search) => search.id === id);

if (savedSearch) {
if (!isSavedSearchActive(id)) {
displaySavedSearch(id);
Expand All @@ -124,13 +130,14 @@ export const DrawerInterior: React.FC<Props> = (props) => {
}
};

const isSavedSearchActive = (id: string) => {
const activeSearch = JSON.parse(
localStorage.getItem('savedSearch') || '{}'
);
return activeSearch.id === id;
const isSavedSearchActive = (id: string): boolean => {
return activeSearchId === id;
};

const ascendingSavedSearches = savedSearches.sort((a, b) =>
a.name.localeCompare(b.name)
);

const filtersByColumn = useMemo(
() =>
filters.reduce(
Expand Down Expand Up @@ -405,9 +412,9 @@ export const DrawerInterior: React.FC<Props> = (props) => {
<Typography>Saved Searches</Typography>
</AccordionSummary>
<AccordionDetails>
{savedSearches.length > 0 ? (
{ascendingSavedSearches.length > 0 ? (
<List>
{savedSearches.map((search) => (
{ascendingSavedSearches.map((search) => (
<ListItem
key={search.id}
sx={{ justifyContent: 'space-between', padding: '0px' }}
Expand Down
Loading
Loading