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

Protect: Separate scan results and history DataViews #40845

Open
wants to merge 58 commits into
base: add/protect/core
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
4dd60b7
Init project branch
nateweller Nov 14, 2024
ff92d88
Protect: Add Go to Cloud and Scan now button to Protect primary heade…
dkmyta Nov 14, 2024
39e4094
Protect: Update Scan and History headers (#40058)
dkmyta Nov 14, 2024
9fec011
Protect: de-emphasize cloud link by using link variant (#40211)
nateweller Nov 18, 2024
af172c9
Protect: add ShieldIcon component
nateweller Nov 30, 2024
00283bc
Protect: Add ShieldIcon Component (#40402)
nateweller Dec 5, 2024
f580ace
Protect: Integrate ThreatsDataViews Component (#40076)
nateweller Dec 5, 2024
c384d69
Components: Add ScanReport (#40419)
dkmyta Dec 5, 2024
68569f2
Fix type errors
nateweller Dec 6, 2024
91ee20a
Protect: Refactor AdminSectionHero (#40516)
nateweller Dec 9, 2024
5892e03
Restore history header
dkmyta Dec 10, 2024
ffb3ab0
Pass status filter presets to consumer
dkmyta Dec 10, 2024
3ad2ee8
Restore early return
dkmyta Dec 10, 2024
7ca9b41
Add plan level restrictions
dkmyta Dec 10, 2024
609a47e
Init project branch
nateweller Nov 14, 2024
43b9566
Protect: Add Go to Cloud and Scan now button to Protect primary heade…
dkmyta Nov 14, 2024
0f9d355
Protect: Update Scan and History headers (#40058)
dkmyta Nov 14, 2024
d7ec48a
Protect: de-emphasize cloud link by using link variant (#40211)
nateweller Nov 18, 2024
3195cb3
Protect: add ShieldIcon component
nateweller Nov 30, 2024
1b4eca4
Protect: Add ShieldIcon Component (#40402)
nateweller Dec 5, 2024
3d878c7
Protect: Integrate ThreatsDataViews Component (#40076)
nateweller Dec 5, 2024
e5d5b04
Components: Add ScanReport (#40419)
dkmyta Dec 5, 2024
7ef8809
Fix type errors
nateweller Dec 6, 2024
55a8d4f
Protect: Refactor AdminSectionHero (#40516)
nateweller Dec 9, 2024
f33e209
Protect: Update Scan History extension types (#40548)
dkmyta Dec 10, 2024
94c9c9a
Protect: Add Home page (#40317)
dkmyta Dec 10, 2024
88960de
Protect: Integrate ScanReport (#40420)
dkmyta Dec 11, 2024
62314b0
Fix duplicate imports
nateweller Dec 15, 2024
a0e7243
ScanReport: Fix defaultLayout (#40603)
dkmyta Dec 15, 2024
113e002
Update onboarding popover placement (#40550)
dkmyta Dec 15, 2024
338e67f
Protect Meets Core: Home Page Scan Report Data Adjustments (#40616)
nateweller Dec 18, 2024
484ce7c
Scan Report: Align Status Icon (#40617)
nateweller Dec 18, 2024
bbc2d56
Apply max width to hero content (#40618)
nateweller Dec 18, 2024
f3874ab
Protect: Hide Scan Report When No Data (#40619)
nateweller Dec 18, 2024
32bcff9
Protect: Hide Threats Report When No Data (#40620)
nateweller Dec 18, 2024
97f5c59
Protect: Update Threat Icons (#40621)
nateweller Dec 18, 2024
898ae2c
Protect: fix home page stat card spacing (#40623)
nateweller Dec 18, 2024
f2587f7
Fix ESLint issue
nateweller Jan 1, 2025
1db1e6c
ScanReport: Disable hiding relevant fields (#40602)
dkmyta Jan 2, 2025
8bd4c21
Rebase
dkmyta Jan 2, 2025
3dae6d4
Separate scan and history DataViews
dkmyta Jan 3, 2025
fbfe605
Reapply history routes
dkmyta Jan 3, 2025
f2bcbe7
Add filters
dkmyta Jan 3, 2025
4afa6fc
Add toggle group control
dkmyta Jan 3, 2025
6db0f6f
Add historic flag
dkmyta Jan 3, 2025
cdac95f
Update stories
dkmyta Jan 3, 2025
010b2c1
Remove unneeded filter handling
dkmyta Jan 3, 2025
c86dc12
Revert unnecessary threats data views updates
dkmyta Jan 3, 2025
d86c933
Fix import
dkmyta Jan 3, 2025
407e4ba
Add size prop
dkmyta Jan 3, 2025
f672f0a
Use error variant (#40832)
dkmyta Jan 3, 2025
1c72079
Merge branch 'add/protect/core' into restore/protect/history-admin-se…
dkmyta Jan 3, 2025
856479c
Rebase
dkmyta Jan 3, 2025
137f2a8
Include fixer action as label in list view action dropdown
dkmyta Jan 3, 2025
1c24e44
Add field constants
dkmyta Jan 3, 2025
8038593
Reorg
dkmyta Jan 3, 2025
4068ba6
Add initialFields prop, update active to current where applicable
dkmyta Jan 6, 2025
19b7834
Rebase, fix conflicts
dkmyta Jan 6, 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
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ import {
wordpress as coreIcon,
} from '@wordpress/icons';

export const THREAT_STATUSES: { value: string; label: string; variant?: 'success' | 'warning' }[] =
[
{ value: 'current', label: __( 'Active', 'jetpack-components' ), variant: 'warning' },
{ value: 'fixed', label: __( 'Fixed', 'jetpack-components' ), variant: 'success' },
{ value: 'ignored', label: __( 'Ignored', 'jetpack-components' ) },
];
export const THREAT_STATUSES: { value: string; label: string; variant?: 'success' }[] = [
{ value: 'fixed', label: __( 'Fixed', 'jetpack-components' ), variant: 'success' },
{ value: 'ignored', label: __( 'Ignored', 'jetpack-components' ) },
];

export const THREAT_TYPES = [
{ value: 'plugins', label: __( 'Plugin', 'jetpack-components' ) },
Expand Down Expand Up @@ -45,6 +43,26 @@ export const THREAT_FIELD_FIRST_DETECTED = 'first-detected';
export const THREAT_FIELD_FIXED_ON = 'fixed-on';
export const THREAT_FIELD_AUTO_FIX = 'auto-fix';

export const CURRENT_TABLE_FIELDS = [
THREAT_FIELD_SEVERITY,
THREAT_FIELD_TYPE,
THREAT_FIELD_AUTO_FIX,
];

export const HISTORIC_TABLE_FIELDS = [
THREAT_FIELD_SEVERITY,
THREAT_FIELD_TYPE,
THREAT_FIELD_FIRST_DETECTED,
THREAT_FIELD_FIXED_ON,
];

export const LIST_FIELDS = [
THREAT_FIELD_SEVERITY,
THREAT_FIELD_TYPE,
THREAT_FIELD_EXTENSION,
THREAT_FIELD_SIGNATURE,
];

export const THREAT_ACTION_FIX = 'fix';
export const THREAT_ACTION_IGNORE = 'ignore';
export const THREAT_ACTION_UNIGNORE = 'unignore';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getThreatType, type Threat } from '@automattic/jetpack-scan';
import { getFixerAction, getThreatType, type Threat } from '@automattic/jetpack-scan';
import {
type Action,
type ActionButton,
Expand All @@ -19,6 +19,8 @@ import Badge from '../badge';
import ThreatFixerButton from '../threat-fixer-button';
import ThreatSeverityBadge from '../threat-severity-badge';
import {
CURRENT_TABLE_FIELDS,
LIST_FIELDS,
THREAT_ACTION_FIX,
THREAT_ACTION_IGNORE,
THREAT_ACTION_UNIGNORE,
Expand All @@ -40,52 +42,60 @@ import {
THREAT_TYPES,
} from './constants';
import styles from './styles.module.scss';
import ThreatsStatusToggleGroupControl from './threats-status-toggle-group-control';

/**
* DataViews component for displaying security threats.
*
* @param {object} props - Component props.
* @param {Array} props.data - Threats data.
* @param {Array} props.filters - Initial DataView filters.
* @param {Function} props.onChangeSelection - Callback function run when an item is selected.
* @param {Function} props.onFixThreats - Threat fix action callback.
* @param {Function} props.onIgnoreThreats - Threat ignore action callback.
* @param {Function} props.onUnignoreThreats - Threat unignore action callback.
* @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 {object} props - Component props.
* @param {string} props.status - Flag to indicate if the threats are current or historic.
* @param {Array} props.data - Threats data.
* @param {Array} props.initialFilters - Initial DataView filters.
* @param {Array} props.initialFields - Initial DataView fields.
* @param {Function} props.onChangeSelection - Callback function run when an item is selected.
* @param {Function} props.onFixThreats - Threat fix action callback.
* @param {Function} props.onIgnoreThreats - Threat ignore action callback.
* @param {Function} props.onUnignoreThreats - Threat unignore action callback.
* @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 {JSX.Element} props.header - Header component.
*
* @return {JSX.Element} The ThreatsDataViews component.
*/
export default function ThreatsDataViews( {
status = 'current',
data,
filters,
initialFields,
initialFilters,
onChangeSelection,
isThreatEligibleForFix,
isThreatEligibleForIgnore,
isThreatEligibleForUnignore,
onFixThreats,
onIgnoreThreats,
onUnignoreThreats,
header,
}: {
status?: string;
data: Threat[];
filters?: Filter[];
initialFields?: string[];
initialFilters?: Filter[];
onChangeSelection?: ( selectedItemIds: string[] ) => void;
isThreatEligibleForFix?: ( threat: Threat ) => boolean;
isThreatEligibleForIgnore?: ( threat: Threat ) => boolean;
isThreatEligibleForUnignore?: ( threat: Threat ) => boolean;
onFixThreats?: ( threats: Threat[] ) => void;
onIgnoreThreats?: ActionButton< Threat >[ 'callback' ];
onUnignoreThreats?: ActionButton< Threat >[ 'callback' ];
header?: JSX.Element;
} ): JSX.Element {
const baseView = {
sort: {
field: 'severity',
direction: 'desc' as SortDirection,
},
search: '',
filters: filters || [],
filters: initialFilters || [],
page: 1,
perPage: 20,
};
Expand All @@ -100,19 +110,14 @@ export default function ThreatsDataViews( {
const defaultLayouts: SupportedLayouts = {
table: {
...baseView,
fields: [ THREAT_FIELD_SEVERITY, THREAT_FIELD_TYPE, THREAT_FIELD_AUTO_FIX ],
fields: initialFields || CURRENT_TABLE_FIELDS,
titleField: THREAT_FIELD_TITLE,
descriptionField: THREAT_FIELD_DESCRIPTION,
showMedia: false,
},
list: {
...baseView,
fields: [
THREAT_FIELD_SEVERITY,
THREAT_FIELD_TYPE,
THREAT_FIELD_EXTENSION,
THREAT_FIELD_SIGNATURE,
],
fields: LIST_FIELDS,
titleField: THREAT_FIELD_TITLE,
mediaField: THREAT_FIELD_ICON,
showMedia: true,
Expand Down Expand Up @@ -238,28 +243,6 @@ export default function ThreatsDataViews( {
);
},
},
{
id: THREAT_FIELD_STATUS,
label: __( 'Status', 'jetpack-components' ),
elements: THREAT_STATUSES,
getValue( { item }: { item: Threat } ) {
if ( ! item.status ) {
return 'current';
}
return (
THREAT_STATUSES.find( ( { value } ) => value === item.status )?.value ?? item.status
);
},
render( { item }: { item: Threat } ) {
if ( item.status ) {
const status = THREAT_STATUSES.find( ( { value } ) => value === item.status );
if ( status ) {
return <Badge variant={ status?.variant }>{ status.label }</Badge>;
}
}
return <Badge variant="warning">{ __( 'Active', 'jetpack-components' ) }</Badge>;
},
},
{
id: THREAT_FIELD_TYPE,
label: __( 'Type', 'jetpack-components' ),
Expand Down Expand Up @@ -300,6 +283,35 @@ export default function ThreatsDataViews( {
return item.extension ? item.extension.slug : '';
},
},
...( 'historic' === status && dataFields.includes( 'status' )
? [
{
id: THREAT_FIELD_STATUS,
label: __( 'Status', 'jetpack-components' ),
elements: THREAT_STATUSES,
getValue( { item }: { item: Threat } ) {
if ( ! item.status ) {
return 'current';
}
return (
THREAT_STATUSES.find( ( { value } ) => value === item.status )?.value ??
item.status
);
},
render( { item }: { item: Threat } ) {
if ( item.status ) {
const threatStatus = THREAT_STATUSES.find(
( { value } ) => value === item.status
);
if ( threatStatus ) {
return <Badge variant={ threatStatus?.variant }>{ threatStatus.label }</Badge>;
}
}
return <Badge variant="warning">{ __( 'Current', 'jetpack-components' ) }</Badge>;
},
},
]
: [] ),
...( dataFields.includes( 'severity' )
? [
{
Expand Down Expand Up @@ -366,7 +378,7 @@ export default function ThreatsDataViews( {
},
]
: [] ),
...( dataFields.includes( 'fixable' )
...( 'historic' !== status && dataFields.includes( 'fixable' )
? [
{
id: THREAT_FIELD_AUTO_FIX,
Expand Down Expand Up @@ -398,7 +410,7 @@ export default function ThreatsDataViews( {
];

return result;
}, [ dataFields, plugins, themes, signatures, onFixThreats ] );
}, [ dataFields, plugins, themes, signatures, status, onFixThreats ] );

/**
* DataView actions - collection of operations that can be performed upon each record.
Expand All @@ -408,10 +420,12 @@ export default function ThreatsDataViews( {
const actions = useMemo( () => {
const result: Action< Threat >[] = [];

if ( dataFields.includes( 'fixable' ) ) {
if ( dataFields.includes( 'fixable' ) && view.type === 'list' ) {
result.push( {
id: THREAT_ACTION_FIX,
label: __( 'Auto-fix', 'jetpack-components' ),
label: items => {
return getFixerAction( items[ 0 ] );
},
isPrimary: true,
callback: onFixThreats,
isEligible( item ) {
Expand Down Expand Up @@ -466,6 +480,7 @@ export default function ThreatsDataViews( {

return result;
}, [
view.type,
dataFields,
onFixThreats,
onIgnoreThreats,
Expand Down Expand Up @@ -511,13 +526,7 @@ export default function ThreatsDataViews( {
onChangeView={ onChangeView }
paginationInfo={ paginationInfo }
view={ view }
header={
<ThreatsStatusToggleGroupControl
data={ data }
view={ view }
onChangeView={ onChangeView }
/>
}
header={ header }
/>
);
}
Loading
Loading