Skip to content

Commit

Permalink
Add threat selection in bulk view
Browse files Browse the repository at this point in the history
  • Loading branch information
dkmyta committed Dec 21, 2024
1 parent 5601445 commit f1488e7
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { getLabel, type Threat } from '@automattic/jetpack-scan';
import { Modal } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { createContext } from 'react';
import { createContext, useState, Dispatch, SetStateAction } from 'react';
import Text from '../text';
import ThreatSeverityBadge from '../threat-severity-badge';
import styles from './styles.module.scss';
import ThreatFixConfirmation from './threat-fix-confirmation';

interface ThreatModalContextType {
closeModal: () => void;
currentThreats: Threat[];
threatsList: Threat[];
setThreatsList: Dispatch< SetStateAction< Threat[] > >;
isBulk: boolean;
actionToConfirm: string | null;
isSupportedEnvironment: boolean;
Expand Down Expand Up @@ -82,8 +83,9 @@ export default function ThreatsModal( {
} & React.ComponentProps< typeof Modal > ): JSX.Element {
const userConnectionNeeded = ! isUserConnected || ! hasConnectedOwner;
const siteCredentialsNeeded = ! credentials || credentials.length === 0;
const isBulk = currentThreats.length > 1;
const firstThreat = currentThreats[ 0 ];
const [ threatsList, setThreatsList ] = useState< Threat[] >( currentThreats );
const isBulk = threatsList.length > 1;
const firstThreat = threatsList[ 0 ];

return (
<Modal
Expand All @@ -108,7 +110,8 @@ export default function ThreatsModal( {
<ThreatsModalContext.Provider
value={ {
closeModal: modalProps.onRequestClose,
currentThreats,
threatsList,
setThreatsList,
isBulk,
actionToConfirm,
isSupportedEnvironment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import { ThreatsModalContext } from '.';
const ThreatFixConfirmation = () => {
const [ isSm ] = useBreakpointMatch( [ 'sm', 'lg' ], [ null, '<' ] );

const { currentThreats, isBulk, handleUpgradeClick } = useContext( ThreatsModalContext );
const { threatsList, isBulk, handleUpgradeClick } = useContext( ThreatsModalContext );

const [ selectedThreats, setSelectedThreats ] = useState( currentThreats );
const [ selectedThreats, setSelectedThreats ] = useState( threatsList );

const handleToggleThreat = useCallback( ( threat: Threat, isChecked: boolean ) => {
setSelectedThreats( prevSelectedThreats => {
Expand All @@ -41,34 +41,64 @@ const ThreatFixConfirmation = () => {

// Memoize toggle handlers for each threat
const toggleHandlers = useMemo( () => {
return currentThreats.reduce( ( handlers, threat ) => {
return threatsList.reduce( ( handlers, threat ) => {
handlers[ threat.id ] = isChecked => handleToggleThreat( threat, isChecked );
return handlers;
}, {} );
}, [ currentThreats, handleToggleThreat ] );
}, [ threatsList, handleToggleThreat ] );

const renderBulkThreat = threat => (
<div key={ threat.id } className={ styles.bulk }>
<div className={ styles.bulk__heading }>
{ ! isSm && (
<div className={ styles.bulk__media }>
<Icon icon={ THREAT_ICONS[ getThreatType( threat ) ] } size={ 20 } />
const viewIndividualThreat = useCallback( threat => {
console.log( threat );
}, [] );

const handleThreatClick = useCallback(
threat => () => {
viewIndividualThreat( threat );
},
[ viewIndividualThreat ]
);

const handleKeyPress = useCallback(
threat => event => {
if ( event.key === 'Enter' ) {
viewIndividualThreat( threat );
}
},
[ viewIndividualThreat ]
);

const renderBulkThreat = threat => {
return (
<div
key={ threat.id }
onClick={ handleThreatClick( threat ) }
role="button"
tabIndex={ 0 }
onKeyDown={ handleKeyPress( threat ) }
>
<div className={ styles.bulk }>
<div className={ styles.bulk__heading }>
{ ! isSm && (
<div className={ styles.bulk__media }>
<Icon icon={ THREAT_ICONS[ getThreatType( threat ) ] } size={ 20 } />
</div>
) }
<div className={ styles.bulk__title }>
<Text variant="title-small">{ getLabel( threat ) }</Text>
<ThreatFixDetails showTitle={ false } threat={ threat } />
</div>
</div>
) }
<div className={ styles.bulk__title }>
<Text variant="title-small">{ getLabel( threat ) }</Text>
<ThreatFixDetails showTitle={ false } threat={ threat } />
{ !! threat.severity && <ThreatSeverityBadge severity={ threat.severity } /> }
<ToggleControl
className={ styles.bulk__toggle }
size="small"
checked={ selectedThreats.some( selectedThreat => selectedThreat.id === threat.id ) }
onChange={ toggleHandlers[ threat.id ] }
/>
</div>
</div>
{ !! threat.severity && <ThreatSeverityBadge severity={ threat.severity } /> }
<ToggleControl
className={ styles.bulk__toggle }
size="small"
checked={ selectedThreats.some( selectedThreat => selectedThreat.id === threat.id ) }
onChange={ toggleHandlers[ threat.id ] }
/>
</div>
);
);
};

const renderIndividualThreat = threat => (
<div key={ threat.id } className={ styles.individual }>
Expand All @@ -84,10 +114,10 @@ const ThreatFixConfirmation = () => {
{ isBulk ? (
<>
<Text>{ 'Jetpack will be fixing the selected threats:' }</Text>
<div>{ currentThreats.map( threat => renderBulkThreat( threat ) ) }</div>
<div>{ threatsList.map( threat => renderBulkThreat( threat ) ) }</div>
</>
) : (
currentThreats.map( threat => renderIndividualThreat( threat ) )
threatsList.map( threat => renderIndividualThreat( threat ) )
) }
<ConnectionsNotice />
{ handleUpgradeClick && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const ThreatNotice = ( {
showActions?: boolean;
} ): JSX.Element => {
const {
currentThreats,
threatsList,
isBulk,
userConnectionNeeded,
userIsConnecting,
Expand All @@ -40,8 +40,8 @@ const ThreatNotice = ( {
} = useContext( ThreatsModalContext );

if (
currentThreats.every( threat => ! threat?.status ) ||
( ! isBulk && currentThreats[ 0 ].status === 'fixed' )
threatsList.every( threat => ! threat?.status ) ||
( ! isBulk && threatsList[ 0 ].status === 'fixed' )
) {
return null;
}
Expand Down

0 comments on commit f1488e7

Please sign in to comment.