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 Meets Core: Project Branch #40191

Draft
wants to merge 54 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
76e4c62
Init project branch
nateweller Nov 14, 2024
f5daa56
Protect: Add Go to Cloud and Scan now button to Protect primary heade…
dkmyta Nov 14, 2024
0d57966
Protect: Update Scan and History headers (#40058)
dkmyta Nov 14, 2024
8218695
Protect: de-emphasize cloud link by using link variant (#40211)
nateweller Nov 18, 2024
49a26fd
Protect: add ShieldIcon component
nateweller Nov 30, 2024
a69819e
Protect: Add ShieldIcon Component (#40402)
nateweller Dec 5, 2024
f38a7a6
Protect: Integrate ThreatsDataViews Component (#40076)
nateweller Dec 5, 2024
62ec5d8
Components: Add ScanReport (#40419)
dkmyta Dec 5, 2024
8263fff
Fix type errors
nateweller Dec 6, 2024
262a47a
Protect: Refactor AdminSectionHero (#40516)
nateweller Dec 9, 2024
91c8aa1
Protect: Update Scan History extension types (#40548)
dkmyta Dec 10, 2024
fb2c44c
Protect: Add Home page (#40317)
dkmyta Dec 10, 2024
42c7de9
Protect: Integrate ScanReport (#40420)
dkmyta Dec 11, 2024
ea88d26
Fix duplicate imports
nateweller Dec 15, 2024
463632c
ScanReport: Fix defaultLayout (#40603)
dkmyta Dec 15, 2024
c413a79
Update onboarding popover placement (#40550)
dkmyta Dec 15, 2024
6a5ef67
Protect Meets Core: Home Page Scan Report Data Adjustments (#40616)
nateweller Dec 18, 2024
501fb14
Scan Report: Align Status Icon (#40617)
nateweller Dec 18, 2024
30a0fb9
Apply max width to hero content (#40618)
nateweller Dec 18, 2024
a4977a6
Protect: Hide Scan Report When No Data (#40619)
nateweller Dec 18, 2024
4bb8555
Protect: Hide Threats Report When No Data (#40620)
nateweller Dec 18, 2024
ea4af61
Protect: Update Threat Icons (#40621)
nateweller Dec 18, 2024
657089b
Protect: fix home page stat card spacing (#40623)
nateweller Dec 18, 2024
27abf44
Fix ESLint issue
nateweller Jan 1, 2025
1da1a03
ScanReport: Disable hiding relevant fields (#40602)
dkmyta Jan 2, 2025
cdb57a6
Use error variant (#40832)
dkmyta Jan 3, 2025
d739b84
Protect: Restore HistoryAdminSectionHero (#40551)
dkmyta Jan 4, 2025
b90fd02
Protect: Separate scan results and history DataViews (#40845)
dkmyta Jan 14, 2025
f386309
ThreatsDataViews: Improve responsiveness (#40670)
dkmyta Jan 14, 2025
467ac5b
ThreatsDataViews: ThreatModal integration (#40202)
dkmyta Jan 14, 2025
1c8c3c0
Protect Meets Core: Fix "0" rendered by conditional render chain (#40…
nateweller Jan 14, 2025
4ab7996
Fix: add missing return
nateweller Jan 16, 2025
eec7070
Fix: reduce of empty array with no initial value
nateweller Jan 16, 2025
b72035e
Fix: hide home report when first protect report scan initializing
nateweller Jan 16, 2025
617d615
minor adjustments
nateweller Jan 31, 2025
fb479e3
Update lockfile
nateweller Jan 31, 2025
1169e60
Remove changes to protect-status package
nateweller Jan 31, 2025
fb00e93
Remove changes to badge components, moved to #41450
nateweller Jan 31, 2025
cf5c650
Fix type error
nateweller Feb 3, 2025
1f1c359
Fix stories
nateweller Feb 4, 2025
fe56960
Fix case where status.core is empty
nateweller Feb 4, 2025
f9b61e6
Spacing and sizing adjustments
nateweller Feb 5, 2025
40e5597
Restore unintended webpack-cli version change
nateweller Feb 5, 2025
36f2433
Fix ThreatsDataViews test
nateweller Feb 6, 2025
04ce70d
changelog
nateweller Feb 9, 2025
480ee62
Fix width of hero content
nateweller Feb 9, 2025
cbd6c5e
Improve threat ignore/unignore queries
nateweller Feb 9, 2025
118ba4a
Remove close button from threat details modal actions
nateweller Feb 9, 2025
dc9df04
Remove unneccessary changes to protect-status package
nateweller Feb 22, 2025
731cda5
Fix z-index conflict between Notice and DataViews components
nateweller Feb 22, 2025
e0ee566
Fix ThreatsDataViews title line wrapping
nateweller Feb 22, 2025
1b1a2a7
Add alternate 'how to fix it' message when no fixer or fixed in versi…
nateweller Feb 23, 2025
ce9c0e6
Fix imports and enhance types
nateweller Feb 23, 2025
3673c90
Additional import fixes and type improvements
nateweller Feb 23, 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
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Integrates ThreatModal in ThreatsDataViews
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Stat Card: add hideValue prop
4 changes: 4 additions & 0 deletions projects/js-packages/components/changelog/add-shield-icon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Add ShieldIcon component
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Adds ScanReport component
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { __ } from '@wordpress/i18n';
import {
code as fileIcon,
color as themeIcon,
plugins as pluginIcon,
shield as shieldIcon,
wordpress as coreIcon,
} from '@wordpress/icons';

export const STATUS_TYPES = [
{ value: 'checked', label: __( 'Checked', 'jetpack-components' ) },
{ value: 'unchecked', label: __( 'Unchecked', 'jetpack-components' ) },
{ value: 'threat', label: __( 'Threat', 'jetpack-components' ) },
];

export const TYPES = [
{ value: 'core', label: __( 'WordPress', 'jetpack-components' ) },
{ value: 'plugins', label: __( 'Plugin', 'jetpack-components' ) },
{ value: 'themes', label: __( 'Theme', 'jetpack-components' ) },
{ value: 'files', label: __( 'Files', 'jetpack-components' ) },
];

export const ICONS = {
plugins: pluginIcon,
themes: themeIcon,
core: coreIcon,
files: fileIcon,
default: shieldIcon,
};

export const FIELD_ICON = 'icon';
export const FIELD_TYPE = 'type';
export const FIELD_NAME = 'name';
export const FIELD_STATUS = 'status';
export const FIELD_UPDATE = 'update';
export const FIELD_VERSION = 'version';
248 changes: 248 additions & 0 deletions projects/js-packages/components/components/scan-report/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import { type ScanReportExtension } from '@automattic/jetpack-scan';
import { Tooltip } from '@wordpress/components';
import {
type SupportedLayouts,
type View,
type Field,
DataViews,
filterSortAndPaginate,
} from '@wordpress/dataviews';
import { __, _n } from '@wordpress/i18n';
import { Icon } from '@wordpress/icons';
import { useCallback, useMemo, useState } from 'react';
import ShieldIcon from '../shield-icon/index.js';
import {
FIELD_NAME,
FIELD_VERSION,
FIELD_ICON,
FIELD_STATUS,
FIELD_TYPE,
STATUS_TYPES,
TYPES,
ICONS,
} from './constants.js';
import styles from './styles.module.scss';

/**
* DataViews component for displaying a scan report.
*
* @param {object} props - Component props.
* @param {string} props.dataSource - Data source.
* @param {Array} props.data - Scan report data.
* @param {Function} props.onChangeSelection - Callback function run when an item is selected.
*
* @return {JSX.Element} The ScanReport component.
*/
export default function ScanReport( {
dataSource,
data,
onChangeSelection,
}: {
dataSource: string;
data: ScanReportExtension[];
onChangeSelection: ( selected: string[] ) => void;
} ): JSX.Element {
const baseView = {
search: '',
filters: [],
page: 1,
perPage: 20,
};

/**
* DataView default layouts.
*
* This property provides layout information about the view types that are active. If empty, enables all layout types (see “Layout Types”) with empty layout data.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#defaultlayouts-record-string-view
*/
const defaultLayouts: SupportedLayouts = {
table: {
...baseView,
fields: [ FIELD_TYPE, FIELD_NAME, FIELD_VERSION ],
titleField: FIELD_STATUS,
showMedia: false,
},
list: {
...baseView,
fields: [ FIELD_STATUS, FIELD_VERSION, FIELD_TYPE ],
titleField: FIELD_NAME,
mediaField: FIELD_ICON,
showMedia: true,
},
};

/**
* DataView view object - configures how the dataset is visible to the user.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#view-object
*/
const [ view, setView ] = useState< View >( {
type: 'table',
...defaultLayouts.table,
} );

/**
* DataView fields - describes the visible items for each record in the dataset.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#fields-object
*/
const fields = useMemo( () => {
const iconHeight = 20;
const result: Field< ScanReportExtension >[] = [
{
id: FIELD_STATUS,
elements: STATUS_TYPES,
label: __( 'Status', 'jetpack-components' ),
enableHiding: false,
getValue( { item } ) {
if ( item.checked ) {
if ( item.threats.length > 0 ) {
return 'threat';
}
return 'checked';
}
return 'unchecked';
},
render( { item }: { item: ScanReportExtension } ) {
const scanApi = 'scan_api' === dataSource;
let variant: 'info' | 'error' | 'success' = 'info';
let text = __(
'This item was added to your site after the most recent scan. We will check for threats during the next scheduled one.',
'jetpack-components'
);

if ( item.checked ) {
if ( item.threats.length > 0 ) {
variant = 'error';
text = _n(
'Vulnerability detected.',
'Vulnerabilities detected.',
item.threats.length,
'jetpack-components'
);

if ( scanApi ) {
text = _n(
'Threat detected.',
'Threats detected.',
item.threats.length,
'jetpack-components'
);
}
} else {
variant = 'success';
text = __(
'No known vulnerabilities found that affect this version.',
'jetpack-components'
);

if ( scanApi ) {
text = __(
'No known threats found that affect this version.',
'jetpack-components'
);
}
}
}

return (
<Tooltip className={ styles.tooltip } text={ text }>
<div className={ styles.icon }>
<ShieldIcon variant={ variant } height={ iconHeight } />
</div>
</Tooltip>
);
},
},
{
id: FIELD_TYPE,
label: __( 'Type', 'jetpack-components' ),
elements: TYPES,
enableHiding: false,
},
{
id: FIELD_NAME,
label: __( 'Name', 'jetpack-components' ),
enableHiding: false,
enableGlobalSearch: true,
getValue( { item }: { item: ScanReportExtension } ) {
return item.name ? item.name : '';
},
},
{
id: FIELD_VERSION,
label: __( 'Version', 'jetpack-components' ),
enableHiding: false,
enableSorting: false,
enableGlobalSearch: true,
getValue( { item }: { item: ScanReportExtension } ) {
return item.version ? item.version : '';
},
},
...( view.type === 'list'
? [
{
id: FIELD_ICON,
label: __( 'Icon', 'jetpack-components' ),
enableSorting: false,
enableHiding: false,
getValue( { item }: { item: ScanReportExtension } ) {
return ICONS[ item.type ] || '';
},
render( { item }: { item: ScanReportExtension } ) {
return (
<div className={ styles.threat__media }>
<Icon icon={ ICONS[ item.type ] } />
</div>
);
},
},
]
: [] ),
];

return result;
}, [ view, dataSource ] );

/**
* Apply the view settings (i.e. filters, sorting, pagination) to the dataset.
*
* @see https://github.com/WordPress/gutenberg/blob/trunk/packages/dataviews/src/filter-and-sort-data-view.ts
*/
const { data: processedData, paginationInfo } = useMemo( () => {
return filterSortAndPaginate( data, view, fields );
}, [ data, view, fields ] );

/**
* Callback function to update the view state.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#onchangeview-function
*/
const onChangeView = useCallback( ( newView: View ) => {
setView( newView );
}, [] );

/**
* DataView getItemId function - returns the unique ID for each record in the dataset.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#getitemid-function
*/
const getItemId = useCallback(
( item: ScanReportExtension ) => `${ item.type }_${ item.slug }_${ item.version }`,
[]
);

return (
<DataViews
data={ processedData }
defaultLayouts={ defaultLayouts }
fields={ fields }
getItemId={ getItemId }
onChangeSelection={ onChangeSelection }
onChangeView={ onChangeView }
paginationInfo={ paginationInfo }
view={ view }
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import ScanReport from '../index.js';

export default {
title: 'JS Packages/Components/Scan Report',
component: ScanReport,
parameters: {
backgrounds: {
default: 'light',
values: [ { name: 'light', value: 'white' } ],
},
},
decorators: [
Story => (
<div style={ { maxWidth: '100%', backgroundColor: 'white' } }>
<Story />
</div>
),
],
};

export const Default = args => <ScanReport { ...args } />;
Default.args = {
dataSource: 'scan_api',
data: [
{
id: 1,
name: 'WordPress',
slug: null,
version: '6.7.1',
threats: [],
checked: true,
type: 'core',
},
{
id: 2,
name: 'Jetpack',
slug: 'jetpack/jetpack.php',
version: '14.1-a.7',
threats: [],
checked: false,
type: 'plugins',
},
{
id: 3,
name: 'Twenty Fifteen',
slug: 'twentyfifteen',
version: '1.1',
threats: [
{
id: 198352527,
signature: 'Vulnerable.WP.Extension',
description: 'Vulnerable WordPress extension',
severity: 3,
},
],
checked: true,
type: 'themes',
},
{
id: 4,
threats: [
{
id: 198352406,
signature: 'EICAR_AV_Test_Suspicious',
title: 'Malicious code found in file: jptt_eicar.php',
severity: 1,
},
{
id: 198352407,
signature: 'EICAR_AV_Test_Suspicious',
title: 'Malicious code found in file: jptt_eicar.php',
severity: 1,
},
],
checked: true,
type: 'files',
},
],
};
Loading
Loading