diff --git a/projects/plugins/protect/changelog/update-protect-scan-and-history-headers b/projects/plugins/protect/changelog/update-protect-scan-and-history-headers new file mode 100644 index 0000000000000..cd930e395e0ed --- /dev/null +++ b/projects/plugins/protect/changelog/update-protect-scan-and-history-headers @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +Updates the structure and content of the Scan and History page headers diff --git a/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx b/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx index 9c8f30b7b8067..4aa517f5f120b 100644 --- a/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx +++ b/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx @@ -1,11 +1,10 @@ -import { Status, Text } from '@automattic/jetpack-components'; +import { Text } from '@automattic/jetpack-components'; import { dateI18n } from '@wordpress/date'; import { __, sprintf } from '@wordpress/i18n'; import { useMemo } from 'react'; import { useParams } from 'react-router-dom'; import AdminSectionHero from '../../../components/admin-section-hero'; import ErrorAdminSectionHero from '../../../components/error-admin-section-hero'; -import ScanNavigation from '../../../components/scan-navigation'; import useThreatsList from '../../../components/threats-list/use-threats-list'; import useProtectData from '../../../hooks/use-protect-data'; import styles from './styles.module.scss'; @@ -48,35 +47,34 @@ const HistoryAdminSectionHero: React.FC = () => { - + + { oldestFirstDetected ? ( + + { sprintf( + /* translators: %s: Oldest first detected date */ + __( '%s - Today', 'jetpack-protect' ), + dateI18n( 'F jS g:i A', oldestFirstDetected, false ) + ) } + + ) : ( + __( 'Most recent results', 'jetpack-protect' ) + ) } + { numAllThreats > 0 ? sprintf( /* translators: %s: Total number of threats */ - __( '%1$s previously active %2$s', 'jetpack-protect' ), + __( '%1$s previous %2$s', 'jetpack-protect' ), numAllThreats, numAllThreats === 1 ? 'threat' : 'threats' ) - : __( 'No previously active threats', 'jetpack-protect' ) } + : __( 'No previous threats', 'jetpack-protect' ) } - { oldestFirstDetected ? ( - - { sprintf( - /* translators: %s: Oldest first detected date */ - __( '%s - Today', 'jetpack-protect' ), - dateI18n( 'F jS g:i A', oldestFirstDetected, false ) - ) } - - ) : ( - __( 'Most recent results', 'jetpack-protect' ) - ) } + { __( 'Here you can view all of your threats till this date.', 'jetpack-protect' ) } -
- -
} /> diff --git a/projects/plugins/protect/src/js/routes/scan/history/styles.module.scss b/projects/plugins/protect/src/js/routes/scan/history/styles.module.scss index f66602e59a9e9..d30f3e0ac3344 100644 --- a/projects/plugins/protect/src/js/routes/scan/history/styles.module.scss +++ b/projects/plugins/protect/src/js/routes/scan/history/styles.module.scss @@ -8,10 +8,6 @@ flex-direction: column; } -.subheading-content { - font-weight: bold; -} - .list-header { display: flex; justify-content: flex-end; @@ -38,8 +34,4 @@ .list-title { display: none; } -} - -.scan-navigation { - margin-top: calc( var( --spacing-base ) * 3 ); // 24px } \ No newline at end of file diff --git a/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx b/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx index 60d484cd4a16f..1c5cc6cac49b9 100644 --- a/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx +++ b/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx @@ -1,30 +1,49 @@ -import { Text, Status, useBreakpointMatch } from '@automattic/jetpack-components'; +import { Text, Button, useBreakpointMatch } from '@automattic/jetpack-components'; import { dateI18n } from '@wordpress/date'; import { __, _n, sprintf } from '@wordpress/i18n'; import { useState } from 'react'; +import { useMemo } from 'react'; import AdminSectionHero from '../../components/admin-section-hero'; import ErrorAdminSectionHero from '../../components/error-admin-section-hero'; import OnboardingPopover from '../../components/onboarding-popover'; -import ScanNavigation from '../../components/scan-navigation'; +import useThreatsList from '../../components/threats-list/use-threats-list'; import useScanStatusQuery, { isScanInProgress } from '../../data/scan/use-scan-status-query'; +import useFixers from '../../hooks/use-fixers'; +import useModal from '../../hooks/use-modal'; import usePlan from '../../hooks/use-plan'; import useProtectData from '../../hooks/use-protect-data'; import ScanningAdminSectionHero from './scanning-admin-section-hero'; import styles from './styles.module.scss'; const ScanAdminSectionHero: React.FC = () => { - const { hasPlan } = usePlan(); - const [ isSm ] = useBreakpointMatch( 'sm' ); const { counts: { current: { threats: numThreats }, }, lastChecked, } = useProtectData(); + const { hasPlan } = usePlan(); + const [ isSm ] = useBreakpointMatch( 'sm' ); const { data: status } = useScanStatusQuery(); + const { list } = useThreatsList(); + const { isThreatFixInProgress, isThreatFixStale } = useFixers(); + const { setModal } = useModal(); // Popover anchor const [ dailyScansPopoverAnchor, setDailyScansPopoverAnchor ] = useState( null ); + const [ showAutoFixersPopoverAnchor, setShowAutoFixersPopoverAnchor ] = useState( null ); + + // List of fixable threats that do not have a fix in progress + const fixableList = useMemo( () => { + return list.filter( threat => { + const threatId = parseInt( threat.id ); + return ( + threat.fixable && ! isThreatFixInProgress( threatId ) && ! isThreatFixStale( threatId ) + ); + } ); + }, [ list, isThreatFixInProgress, isThreatFixStale ] ); + + const scanning = isScanInProgress( status ); let lastCheckedLocalTimestamp = null; if ( lastChecked ) { @@ -32,7 +51,17 @@ const ScanAdminSectionHero: React.FC = () => { lastCheckedLocalTimestamp = new Date( lastChecked + ' UTC' ).getTime(); } - if ( isScanInProgress( status ) ) { + const handleShowAutoFixersClick = threatList => { + return event => { + event.preventDefault(); + setModal( { + type: 'FIX_ALL_THREATS', + props: { threatList }, + } ); + }; + }; + + if ( scanning ) { return ; } @@ -50,12 +79,27 @@ const ScanAdminSectionHero: React.FC = () => { - + + { lastCheckedLocalTimestamp + ? sprintf( + // translators: %s: date and time of the last scan + __( '%s results', 'jetpack-protect' ), + dateI18n( 'F jS g:i A', lastCheckedLocalTimestamp, false ) + ) + : __( 'Most recent results', 'jetpack-protect' ) } + + { ! hasPlan && ( + + ) } { numThreats > 0 ? sprintf( /* translators: %s: Total number of threats/vulnerabilities */ - __( '%1$s %2$s found', 'jetpack-protect' ), + __( '%1$s active %2$s', 'jetpack-protect' ), numThreats, hasPlan ? _n( 'threat', 'threats', numThreats, 'jetpack-protect' ) @@ -63,7 +107,7 @@ const ScanAdminSectionHero: React.FC = () => { ) : sprintf( /* translators: %s: Pluralized type of threat/vulnerability */ - __( 'No %s found', 'jetpack-protect' ), + __( 'No active %s', 'jetpack-protect' ), hasPlan ? __( 'threats', 'jetpack-protect' ) : __( @@ -75,31 +119,38 @@ const ScanAdminSectionHero: React.FC = () => { <> - - { lastCheckedLocalTimestamp ? ( - <> - - { dateI18n( 'F jS g:i A', lastCheckedLocalTimestamp, false ) } - -   - { __( 'results', 'jetpack-protect' ) } - - ) : ( - __( 'Most recent results', 'jetpack-protect' ) + + { __( + 'We actively review your sites files line-by-line to identify threats and vulnerabilities.', + 'jetpack-protect' ) } - { ! hasPlan && ( - + { fixableList.length > 0 && ( + <> + + { ! scanning && ( + -
- -
} /> diff --git a/projects/plugins/protect/src/js/routes/scan/styles.module.scss b/projects/plugins/protect/src/js/routes/scan/styles.module.scss index 8651420159fa1..908e34f6e71d7 100644 --- a/projects/plugins/protect/src/js/routes/scan/styles.module.scss +++ b/projects/plugins/protect/src/js/routes/scan/styles.module.scss @@ -1,5 +1,5 @@ -.subheading-content { - font-weight: bold; +.subheading-text { + white-space: nowrap; } .product-section, .info-section { @@ -7,6 +7,6 @@ margin-bottom: calc( var( --spacing-base ) * 7 ); // 56px } -.scan-navigation { - margin-top: calc( var( --spacing-base ) * 3 ); // 24px +.auto-fixers { + margin-top: calc( var( --spacing-base ) * 4 ); // 32px } \ No newline at end of file