-
Notifications
You must be signed in to change notification settings - Fork 805
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b60b67c
commit 86f6f89
Showing
10 changed files
with
360 additions
and
13 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
projects/js-packages/components/changelog/components-add-scan-report
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: minor | ||
Type: added | ||
|
||
Adds ScanReport component |
30 changes: 30 additions & 0 deletions
30
projects/js-packages/components/components/scan-report/constants.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
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 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'; |
197 changes: 197 additions & 0 deletions
197
projects/js-packages/components/components/scan-report/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
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 { __ } from '@wordpress/i18n'; | ||
import { Icon } from '@wordpress/icons'; | ||
import { useCallback, useMemo, useState } from 'react'; | ||
import ShieldIcon from '../shield-icon'; | ||
import { | ||
FIELD_NAME, | ||
FIELD_VERSION, | ||
FIELD_ICON, | ||
FIELD_STATUS, | ||
FIELD_TYPE, | ||
TYPES, | ||
ICONS, | ||
} from './constants'; | ||
import styles from './styles.module.scss'; | ||
|
||
/** | ||
* DataViews component for displaying a scan report. | ||
* | ||
* @param {object} props - Component props. | ||
* @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( { data, onChangeSelection } ): 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_STATUS, FIELD_TYPE, FIELD_NAME, FIELD_VERSION ], | ||
layout: { | ||
primaryField: FIELD_STATUS, | ||
}, | ||
}, | ||
list: { | ||
...baseView, | ||
fields: [ FIELD_STATUS, FIELD_VERSION ], | ||
layout: { | ||
primaryField: FIELD_NAME, | ||
mediaField: FIELD_ICON, | ||
}, | ||
}, | ||
}; | ||
|
||
/** | ||
* 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, | ||
label: __( 'Status', 'jetpack-components' ), | ||
render( { item }: { item: ScanReportExtension } ) { | ||
let variant: 'info' | 'warning' | '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 = 'warning'; | ||
text = __( 'Threat detected.', 'jetpack-components' ); | ||
} else { | ||
variant = 'success'; | ||
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, | ||
}, | ||
{ | ||
id: FIELD_NAME, | ||
label: __( 'Name', 'jetpack-components' ), | ||
enableGlobalSearch: true, | ||
getValue( { item }: { item: ScanReportExtension } ) { | ||
return item.name ? item.name : ''; | ||
}, | ||
}, | ||
{ | ||
id: FIELD_VERSION, | ||
label: __( 'Version', 'jetpack-components' ), | ||
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 ] ); | ||
|
||
/** | ||
* 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.id.toString(), [] ); | ||
|
||
return ( | ||
<DataViews | ||
data={ processedData } | ||
defaultLayouts={ defaultLayouts } | ||
fields={ fields } | ||
getItemId={ getItemId } | ||
onChangeSelection={ onChangeSelection } | ||
onChangeView={ onChangeView } | ||
paginationInfo={ paginationInfo } | ||
view={ view } | ||
/> | ||
); | ||
} |
72 changes: 72 additions & 0 deletions
72
projects/js-packages/components/components/scan-report/stories/index.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import ScanReport from '..'; | ||
|
||
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 = { | ||
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, | ||
}, | ||
], | ||
checked: true, | ||
type: 'files', | ||
}, | ||
], | ||
}; |
21 changes: 21 additions & 0 deletions
21
projects/js-packages/components/components/scan-report/styles.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
@import '@wordpress/dataviews/build-style/style.css'; | ||
|
||
.threat__media { | ||
width: 100%; | ||
height: 100%; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
background-color: #EDFFEE; | ||
border-color: #EDFFEE; | ||
|
||
svg { | ||
fill: var( --jp-black ); | ||
} | ||
} | ||
|
||
.tooltip { | ||
max-width: 240px; | ||
border-radius: 4px; | ||
text-align: left; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.