From 6c819b01cee5a36ea650dec98ce5757aa447190d Mon Sep 17 00:00:00 2001 From: Max Cao Date: Tue, 15 Nov 2022 15:12:30 -0500 Subject: [PATCH] filters, but Score filter doesn't work --- .../AutomatedAnalysisCard.tsx | 124 +++++---- .../AutomatedAnalysisFilters.tsx | 240 ++++++++++++++++++ .../Filters/AutomatedAnalysisNameFilter.tsx | 89 +++++++ .../Filters/AutomatedAnalysisScoreFilter.tsx | 74 ++++++ .../Filters/AutomatedAnalysisTopicFilter.tsx | 83 ++++++ .../Redux/AutomatedAnalysisFilterActions.tsx | 119 +++++++++ .../Redux/AutomatedAnalysisFilterReducer.tsx | 176 +++++++++++++ src/app/Shared/Redux/ReduxStore.tsx | 3 + src/app/Shared/Services/Api.service.tsx | 8 + src/app/utils/LocalStorage.ts | 1 + .../Recordings/ActiveRecordingsTable.test.tsx | 3 + .../ArchivedRecordingsTable.test.tsx | 3 + src/test/Recordings/RecordingFilters.test.tsx | 3 + 13 files changed, 871 insertions(+), 55 deletions(-) create mode 100644 src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisFilters.tsx create mode 100644 src/app/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisNameFilter.tsx create mode 100644 src/app/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisScoreFilter.tsx create mode 100644 src/app/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisTopicFilter.tsx create mode 100644 src/app/Shared/Redux/AutomatedAnalysisFilterActions.tsx create mode 100644 src/app/Shared/Redux/AutomatedAnalysisFilterReducer.tsx diff --git a/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx b/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx index fe32d0834c..21acc30d7d 100644 --- a/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx +++ b/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx @@ -36,7 +36,6 @@ * SOFTWARE. */ import * as React from 'react'; -import { BreadcrumbTrail } from '@app/BreadcrumbPage/BreadcrumbPage'; import { ServiceContext } from '@app/Shared/Services/Services'; import { Button, @@ -47,23 +46,14 @@ import { CardHeader, CardTitle, Checkbox, - Dropdown, Grid, GridItem, - HelperText, - HelperTextItem, - KebabToggle, - Label, LabelGroup, - LabelProps, - Select, - SelectOption, - Spinner, - Stack, - StackItem, Text, TextContent, TextVariants, + Toolbar, + ToolbarContent, Tooltip, } from '@patternfly/react-core'; import { useSubscriptions } from '@app/utils/useSubscriptions'; @@ -77,6 +67,11 @@ import { ArchivedRecording, defaultAutomatedAnalysis, } from '@app/Shared/Services/Api.service'; +import { AutomatedAnalysisFilters, AutomatedAnalysisFiltersCategories, emptyAutomatedAnalysisFilters, filterAutomatedAnalysis } from './AutomatedAnalysisFilters'; +import { useDispatch, useSelector } from 'react-redux'; +import { RootState, StateDispatch } from '@app/Shared/Redux/ReduxStore'; +import { TargetAutomatedAnalysisFilters } from '@app/Shared/Redux/AutomatedAnalysisFilterReducer'; +import { automatedAnalysisAddFilterIntent, automatedAnalysisAddTargetIntent, automatedAnalysisDeleteAllFiltersIntent, automatedAnalysisDeleteCategoryFiltersIntent, automatedAnalysisDeleteFilterIntent } from '@app/Shared/Redux/AutomatedAnalysisFilterActions'; interface AutomatedAnalysisCardProps { pageTitle: string; @@ -85,16 +80,16 @@ interface AutomatedAnalysisCardProps { export const AutomatedAnalysisCard: React.FunctionComponent = (props) => { const context = React.useContext(ServiceContext); const addSubscription = useSubscriptions(); + const dispatch = useDispatch(); + const [targetConnectURL, setTargetConnectURL] = React.useState(''); const [categorizedEvaluation, setCategorizedEvaluation] = React.useState<[string, RuleEvaluation[]][]>( [] as [string, RuleEvaluation[]][] ); - const [criticalCategorizedEvaluation, setCriticalCategorizedEvaluation] = React.useState< + const [filteredCategorizedEvaluation, setFilteredCategorizedEvaluation] = React.useState< [string, RuleEvaluation[]][] >([] as [string, RuleEvaluation[]][]); const [isExpanded, setIsExpanded] = React.useState(true); - const [isKebabOpen, setIsKebabOpen] = React.useState(false); - const [isChecked, setIsChecked] = React.useState(false); const [isError, setIsError] = React.useState(false); const [errorMessage, setErrorMessage] = React.useState(''); const [isLoading, setIsLoading] = React.useState(false); @@ -109,6 +104,14 @@ export const AutomatedAnalysisCard: React.FunctionComponent { + const filters = state.automatedAnalysisFilters.list.filter( + (targetFilter: TargetAutomatedAnalysisFilters) => targetFilter.target === targetConnectURL + ); + return filters.length > 0 ? filters[0].filters : emptyAutomatedAnalysisFilters; + + }) as AutomatedAnalysisFiltersCategories; + const categorizeEvaluation = React.useCallback( (arr: [string, RuleEvaluation][]) => { const map = new Map(); @@ -231,6 +234,8 @@ export const AutomatedAnalysisCard: React.FunctionComponent { handleLoading(); + setTargetConnectURL(target.connectUrl); + dispatch(automatedAnalysisAddTargetIntent(target.connectUrl)); context.api.createSnapshotV2().pipe(first()).subscribe({ next: (snapshot) => { context.reports @@ -260,9 +265,11 @@ export const AutomatedAnalysisCard: React.FunctionComponent { - const criticalScores = categorizedEvaluation.map(([topic, evaluations]) => { - return [topic, evaluations.filter((evaluation) => evaluation.score >= ORANGE_SCORE_THRESHOLD)] as [ - string, - RuleEvaluation[] - ]; - }); - setCriticalCategorizedEvaluation(criticalScores); - }, [categorizedEvaluation, setCriticalCategorizedEvaluation]); - React.useEffect(() => { addSubscription( context.target.authFailure().subscribe(() => { handleStateErrors("Authentication failure"); }) ); - }, [addSubscription, context.target.authFailure, handleStateErrors]); + }, [addSubscription, context.target, handleStateErrors]); React.useEffect(() => { takeSnapshot(); @@ -353,16 +350,8 @@ export const AutomatedAnalysisCard: React.FunctionComponent { - if (isChecked) { - showCriticalScores(); - } else { - setCriticalCategorizedEvaluation(categorizedEvaluation); - } - }, [isChecked, categorizedEvaluation, showCriticalScores, setCriticalCategorizedEvaluation]); - - const onClick = (checked: boolean) => { - setIsChecked(checked); - }; + setFilteredCategorizedEvaluation(filterAutomatedAnalysis(categorizedEvaluation, targetAutomatedAnalysisFilters)); + }, [categorizedEvaluation, targetAutomatedAnalysisFilters, filterAutomatedAnalysis, setFilteredCategorizedEvaluation]); const onExpand = (event: React.MouseEvent, id: string) => { setIsExpanded(!isExpanded); @@ -371,7 +360,7 @@ export const AutomatedAnalysisCard: React.FunctionComponent { return ( - {criticalCategorizedEvaluation + {filteredCategorizedEvaluation .filter(([_, evaluations]) => evaluations.length > 0) .map(([topic, evaluations]) => { return ( @@ -386,7 +375,7 @@ export const AutomatedAnalysisCard: React.FunctionComponent ); - }, [criticalCategorizedEvaluation]); + }, [filteredCategorizedEvaluation]); const clearCachedReports = React.useCallback(() => { addSubscription( @@ -406,6 +395,25 @@ export const AutomatedAnalysisCard: React.FunctionComponent { + if (deleted) { + if (deleteOptions && deleteOptions.all) { + dispatch(automatedAnalysisDeleteCategoryFiltersIntent(target, filterKey)); + } else { + dispatch(automatedAnalysisDeleteFilterIntent(target, filterKey, filterValue)); + } + } else { + dispatch(automatedAnalysisAddFilterIntent(target, filterKey, filterValue)); + } + }, + [dispatch, automatedAnalysisDeleteCategoryFiltersIntent, automatedAnalysisDeleteFilterIntent, automatedAnalysisAddFilterIntent] + ); + + const handleClearFilters = React.useCallback(() => { + dispatch(automatedAnalysisDeleteAllFiltersIntent(targetConnectURL)); + }, [dispatch, automatedAnalysisDeleteAllFiltersIntent, targetConnectURL]); + const reportStalenessText = React.useMemo(() => { if (isLoading || !(usingArchivedReport || usingCachedReport)) { return ''; @@ -463,23 +471,29 @@ export const AutomatedAnalysisCard: React.FunctionComponent Automated Analysis - -