Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4c95bfe
Init project branch
nateweller Nov 14, 2024
91ce2ed
Protect: Refactor AdminSectionHero (#40516)
nateweller Dec 9, 2024
35cd0cf
Restore history header
dkmyta Dec 10, 2024
5ad53b7
Pass status filter presets to consumer
dkmyta Dec 10, 2024
e21bb59
Restore early return
dkmyta Dec 10, 2024
50a5849
Add plan level restrictions
dkmyta Dec 10, 2024
d738a65
Init project branch
nateweller Nov 14, 2024
b93cfa2
Protect: Integrate ThreatsDataViews Component (#40076)
nateweller Dec 5, 2024
19bc943
Separate scan and history DataViews
dkmyta Jan 3, 2025
561ab57
Reapply history routes
dkmyta Jan 3, 2025
13ec8a0
Add filters
dkmyta Jan 3, 2025
996649a
Add toggle group control
dkmyta Jan 3, 2025
5a0871e
Add historic flag
dkmyta Jan 3, 2025
939263c
Update stories
dkmyta Jan 3, 2025
a34d4bd
Remove unneeded filter handling
dkmyta Jan 3, 2025
84a2ebc
Revert unnecessary threats data views updates
dkmyta Jan 3, 2025
1d3733f
Fix import
dkmyta Jan 3, 2025
61ee84d
Include fixer action as label in list view action dropdown
dkmyta Jan 3, 2025
a847325
Add field constants
dkmyta Jan 3, 2025
23b791f
Reorg
dkmyta Jan 3, 2025
9cd5469
Add initialFields prop, update active to current where applicable
dkmyta Jan 6, 2025
ad201c2
Init project branch
nateweller Nov 14, 2024
8960ec6
Fix exports and imports
dkmyta Jan 7, 2025
ec33096
Move default values to function params
nateweller Jan 12, 2025
5ccae12
Fix ts warning
nateweller Jan 12, 2025
dcb2887
minor adjustment to definition of initial filters
nateweller Jan 12, 2025
c8cd20e
Add tsc-expect-error to dummy arg for minification cases
nateweller Jan 12, 2025
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
Prev Previous commit
Next Next commit
Pass status filter presets to consumer
  • Loading branch information
dkmyta authored and nateweller committed Jan 12, 2025
commit 5ad53b72d3533fede84990d7e546f7243f5698f9
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getThreatType, type Threat } from '@automattic/jetpack-scan';
import { getThreatType, type Threat, type ThreatStatus } from '@automattic/jetpack-scan';
import {
type Action,
type ActionButton,
Expand All @@ -14,7 +14,7 @@ import {
import { dateI18n } from '@wordpress/date';
import { __ } from '@wordpress/i18n';
import { Icon } from '@wordpress/icons';
import { useCallback, useMemo, useState } from 'react';
import { useCallback, useMemo, useState, useEffect } from 'react';
import Badge from '../badge';
import ThreatFixerButton from '../threat-fixer-button';
import ThreatSeverityBadge from '../threat-severity-badge';
Expand Down Expand Up @@ -55,6 +55,7 @@ import ThreatsStatusToggleGroupControl from './threats-status-toggle-group-contr
* @param {Function} props.isThreatEligibleForFix - Function to determine if a threat is eligible for fixing.
* @param {Function} props.isThreatEligibleForIgnore - Function to determine if a threat is eligible for ignoring.
* @param {Function} props.isThreatEligibleForUnignore - Function to determine if a threat is eligible for unignoring.
* @param {Function} props.onStatusFilterChange - Callback function run when the status filter changes.
*
* @return {JSX.Element} The ThreatsDataViews component.
*/
Expand All @@ -68,6 +69,7 @@ export default function ThreatsDataViews( {
onFixThreats,
onIgnoreThreats,
onUnignoreThreats,
onStatusFilterChange,
}: {
data: Threat[];
filters?: Filter[];
Expand All @@ -78,6 +80,7 @@ export default function ThreatsDataViews( {
onFixThreats?: ( threats: Threat[] ) => void;
onIgnoreThreats?: ActionButton< Threat >[ 'callback' ];
onUnignoreThreats?: ActionButton< Threat >[ 'callback' ];
onStatusFilterChange?: ( newStatus: 'active' | 'historic' | null ) => void;
} ): JSX.Element {
const baseView = {
sort: {
Expand Down Expand Up @@ -475,6 +478,33 @@ export default function ThreatsDataViews( {
isThreatEligibleForUnignore,
] );

/**
* Memoized function to determine if a status filter is selected.
*
* @param {Array} threatStatuses - List of threat statuses.
*/
const isStatusFilterSelected = useMemo(
() => ( threatStatuses: ThreatStatus[] ) =>
view.filters.some(
filter =>
filter.field === 'status' &&
Array.isArray( filter.value ) &&
filter.value.length === threatStatuses.length &&
threatStatuses.every( threatStatus => filter.value.includes( threatStatus ) )
),
[ view.filters ]
);

const selectedStatusFilter = useMemo( () => {
if ( isStatusFilterSelected( [ 'current' ] ) ) {
return 'active' as const;
}
if ( isStatusFilterSelected( [ 'fixed', 'ignored' ] ) ) {
return 'historic' as const;
}
return null;
}, [ isStatusFilterSelected ] );

/**
* Apply the view settings (i.e. filters, sorting, pagination) to the dataset.
*
Expand All @@ -500,6 +530,11 @@ export default function ThreatsDataViews( {
*/
const getItemId = useCallback( ( item: Threat ) => item.id.toString(), [] );

// Notify the consumer whenever the selectedStatusFilter changes
useEffect( () => {
onStatusFilterChange?.( selectedStatusFilter );
}, [ selectedStatusFilter, onStatusFilterChange ] );

return (
<DataViews
actions={ actions }
Expand All @@ -516,6 +551,7 @@ export default function ThreatsDataViews( {
data={ data }
view={ view }
onChangeView={ onChangeView }
selectedStatusFilter={ selectedStatusFilter }
/>
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type Threat, type ThreatStatus } from '@automattic/jetpack-scan';
import { type Threat } from '@automattic/jetpack-scan';
import {
__experimentalToggleGroupControl as ToggleGroupControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
__experimentalToggleGroupControlOption as ToggleGroupControlOption, // eslint-disable-line @wordpress/no-unsafe-wp-apis
Expand All @@ -10,20 +10,23 @@ import styles from './styles.module.scss';

/**
* ToggleGroupControl component for filtering threats by status.
* @param {object} props - Component props.
* @param { Threat[]} props.data - Threats data.
* @param { View } props.view - The current view.
* @param { Function } props.onChangeView - Callback function to handle view changes.
* @param {object} props - Component props.
* @param { Threat[]} props.data - Threats data.
* @param { View } props.view - The current view.
* @param { string } props.selectedStatusFilter - The selected status filter.
* @param { Function } props.onChangeView - Callback function to handle view changes.
*
* @return {JSX.Element|null} The component or null.
*/
export default function ThreatsStatusToggleGroupControl( {
data,
view,
selectedStatusFilter,
onChangeView,
}: {
data: Threat[];
view: View;
selectedStatusFilter: string;
onChangeView: ( newView: View ) => void;
} ): JSX.Element {
/**
Expand Down Expand Up @@ -88,43 +91,12 @@ export default function ThreatsStatusToggleGroupControl( {
[ view, onChangeView ]
);

/**
* Memoized function to determine if a status filter is selected.
*
* @param {Array} threatStatuses - List of threat statuses.
*/
const isStatusFilterSelected = useMemo(
() => ( threatStatuses: ThreatStatus[] ) =>
view.filters.some(
filter =>
filter.field === 'status' &&
Array.isArray( filter.value ) &&
filter.value.length === threatStatuses.length &&
threatStatuses.every( threatStatus => filter.value.includes( threatStatus ) )
),
[ view.filters ]
);

const selectedValue = useMemo( () => {
if ( isStatusFilterSelected( [ 'current' ] ) ) {
return 'active' as const;
}
if ( isStatusFilterSelected( [ 'fixed', 'ignored' ] ) ) {
return 'historic' as const;
}
return '' as const;
}, [ isStatusFilterSelected ] );

if ( ! ( activeThreatsCount + historicThreatsCount ) ) {
return null;
}

try {
return (
<div>
<div className={ styles[ 'toggle-group-control' ] }>
<ToggleGroupControl
value={ selectedValue }
value={ selectedStatusFilter }
onChange={ onStatusFilterChange }
isBlock
hideLabelFromVision
Expand Down
1 change: 0 additions & 1 deletion projects/plugins/protect/src/js/routes/scan/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const ScanPage = () => {
const { data: history } = useHistoryQuery();

const [ scanResultsAnchor, setScanResultsAnchor ] = useState( null );
const [ isViewingHistory, setIsViewingHistory ] = useState( false );

let currentScanStatus;
if ( status.error ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import useModal from '../../hooks/use-modal';
/**
* Scan Results Data View
*
* @param {object} props - Component props.
* @param {Array} props.filters - Default filters to apply to the data view.
* @param {object} props - Component props.
* @param {Array} props.filters - Default filters to apply to the data view.
* @param {Function} props.onStatusFilterChange - Callback function to handle status filter changes.
*
* @return {JSX.Element} ScanResultDataView component.
*/
export default function ScanResultsDataView( {
filters = [],
onStatusFilterChange,
}: {
filters: React.ComponentProps< typeof ThreatsDataViews >[ 'filters' ];
onStatusFilterChange: ( newStatus: 'active' | 'historic' | null ) => void;
} ) {
const { setModal } = useModal();

Expand Down Expand Up @@ -51,6 +54,7 @@ export default function ScanResultsDataView( {
onFixThreats={ onFixThreats }
onIgnoreThreats={ onIgnoreThreats }
onUnignoreThreats={ onUnignoreThreats }
onStatusFilterChange={ onStatusFilterChange }
/>
);
}