Skip to content

Commit 95e8e39

Browse files
committed
add cta to install and/or activate Akismet
1 parent e48c2e4 commit 95e8e39

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

projects/packages/forms/src/dashboard/components/empty-responses/index.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
/**
2+
* External dependencies
3+
*/
14
import {
5+
Button,
26
__experimentalText as Text, // eslint-disable-line @wordpress/no-unsafe-wp-apis
37
__experimentalVStack as VStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
48
} from '@wordpress/components';
59
import { __, _n, sprintf } from '@wordpress/i18n';
10+
/**
11+
* Internal dependencies
12+
*/
613
import useConfigValue from '../../../hooks/use-config-value.ts';
14+
import useInstallAkismet from '../../hooks/use-install-akismet.ts';
715
import CreateFormButton from '../create-form-button/index.tsx';
816

917
const EmptyWrapper = ( { heading = '', body = '', actions = null } ) => (
@@ -27,6 +35,15 @@ type EmptyResponsesProps = {
2735
const EmptyResponses = ( { status, isSearch, readStatusFilter }: EmptyResponsesProps ) => {
2836
const emptyTrashDays = useConfigValue( 'emptyTrashDays' ) ?? 0;
2937

38+
const {
39+
shouldShowAkismetCta,
40+
isInstallingAkismet,
41+
isIntegrationsLoading,
42+
canPerformAkismetAction,
43+
isInstalled,
44+
handleAkismetSetup,
45+
} = useInstallAkismet();
46+
3047
// Handle search and filter states first
3148
const hasReadStatusFilter = !! readStatusFilter;
3249
const searchHeading = __( 'No results found', 'jetpack-forms' );
@@ -60,7 +77,40 @@ const EmptyResponses = ( { status, isSearch, readStatusFilter }: EmptyResponsesP
6077
'Spam responses are permanently deleted after 15 days.',
6178
'jetpack-forms'
6279
);
80+
6381
if ( status === 'spam' ) {
82+
const installAndActivateMessage = __(
83+
'Install and activate Jetpack Akismet Anti-spam to automatically filter form spam.',
84+
'jetpack-forms'
85+
);
86+
87+
const activateMessage = __(
88+
'Activate Jetpack Akismet Anti-spam to automatically filter form spam.',
89+
'jetpack-forms'
90+
);
91+
92+
if ( shouldShowAkismetCta && ! isIntegrationsLoading ) {
93+
return (
94+
<EmptyWrapper
95+
heading={ noSpamHeading }
96+
body={ isInstalled ? activateMessage : installAndActivateMessage }
97+
actions={
98+
<Button
99+
variant="primary"
100+
isBusy={ isInstallingAkismet }
101+
disabled={ isInstallingAkismet || ! canPerformAkismetAction }
102+
onClick={ handleAkismetSetup }
103+
__next40pxDefaultSize
104+
>
105+
{ isInstalled
106+
? __( 'Activate Akismet Anti-spam', 'jetpack-forms' )
107+
: __( 'Install Akismet Anti-spam', 'jetpack-forms' ) }
108+
</Button>
109+
}
110+
/>
111+
);
112+
}
113+
64114
return <EmptyWrapper heading={ noSpamHeading } body={ noSpamMessage } />;
65115
}
66116

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { isSimpleSite } from '@automattic/jetpack-script-data';
5+
import { useSelect, useDispatch } from '@wordpress/data';
6+
import { useCallback, useMemo, useState } from '@wordpress/element';
7+
import { __ } from '@wordpress/i18n';
8+
import { store as noticesStore } from '@wordpress/notices';
9+
/**
10+
* Internal dependencies
11+
*/
12+
import {
13+
installAndActivatePlugin,
14+
activatePlugin,
15+
} from '../../blocks/contact-form/util/plugin-management.js';
16+
import useConfigValue from '../../hooks/use-config-value.ts';
17+
import { INTEGRATIONS_STORE } from '../../store/integrations/index.ts';
18+
/**
19+
* Types
20+
*/
21+
import type { SelectIntegrations, IntegrationsDispatch } from '../../store/integrations/index.ts';
22+
import type { Integration } from '../../types/index.ts';
23+
24+
export const useInstallAkismet = () => {
25+
const canInstallPlugins = useConfigValue( 'canInstallPlugins' );
26+
const canActivatePlugins = useConfigValue( 'canActivatePlugins' );
27+
28+
const { akismetIntegration, isIntegrationsLoading } = useSelect(
29+
( select: SelectIntegrations ) => {
30+
const store = select( INTEGRATIONS_STORE );
31+
const integrations = store.getIntegrations() || [];
32+
33+
return {
34+
akismetIntegration: integrations.find(
35+
( integration: Integration ) => integration.id === 'akismet'
36+
),
37+
isIntegrationsLoading: store.isIntegrationsLoading(),
38+
};
39+
},
40+
[]
41+
) as { akismetIntegration?: Integration; isIntegrationsLoading: boolean };
42+
43+
const { refreshIntegrations } = useDispatch( INTEGRATIONS_STORE ) as IntegrationsDispatch;
44+
const { createErrorNotice, createSuccessNotice } = useDispatch( noticesStore );
45+
const [ isInstallingAkismet, setIsInstallingAkismet ] = useState( false );
46+
47+
const akismetIntegrationReady = useMemo(
48+
() => !! akismetIntegration && ! akismetIntegration.__isPartial,
49+
[ akismetIntegration ]
50+
);
51+
52+
const isAkismetActive =
53+
akismetIntegrationReady &&
54+
!! akismetIntegration?.isInstalled &&
55+
!! akismetIntegration?.isActive;
56+
57+
const shouldShowAkismetCta = akismetIntegrationReady && ! isAkismetActive && ! isSimpleSite();
58+
59+
const akismetPluginFile = useMemo(
60+
() => akismetIntegration?.pluginFile ?? 'akismet/akismet',
61+
[ akismetIntegration?.pluginFile ]
62+
);
63+
64+
const canPerformAkismetAction =
65+
akismetIntegration?.isInstalled && akismetIntegrationReady
66+
? canActivatePlugins !== false
67+
: canInstallPlugins !== false;
68+
69+
const handleAkismetSetup = useCallback( async () => {
70+
if ( isInstallingAkismet || ! akismetIntegrationReady || ! canPerformAkismetAction ) {
71+
return;
72+
}
73+
74+
setIsInstallingAkismet( true );
75+
76+
try {
77+
if ( akismetIntegration?.isInstalled ) {
78+
await activatePlugin( akismetPluginFile );
79+
} else {
80+
await installAndActivatePlugin( 'akismet' );
81+
}
82+
83+
createSuccessNotice(
84+
akismetIntegration?.isInstalled
85+
? __( 'Akismet activated.', 'jetpack-forms' )
86+
: __( 'Akismet installed and activated.', 'jetpack-forms' ),
87+
{ type: 'snackbar', id: 'akismet-install-success' }
88+
);
89+
90+
await refreshIntegrations();
91+
} catch ( error ) {
92+
const message =
93+
error instanceof Error
94+
? error.message
95+
: __( 'Could not set up Akismet. Please try again.', 'jetpack-forms' );
96+
97+
createErrorNotice( message, {
98+
type: 'snackbar',
99+
id: 'akismet-install-error',
100+
} );
101+
} finally {
102+
setIsInstallingAkismet( false );
103+
}
104+
}, [
105+
akismetIntegration?.isInstalled,
106+
akismetIntegrationReady,
107+
akismetPluginFile,
108+
canPerformAkismetAction,
109+
createErrorNotice,
110+
createSuccessNotice,
111+
isInstallingAkismet,
112+
refreshIntegrations,
113+
] );
114+
115+
return {
116+
shouldShowAkismetCta,
117+
handleAkismetSetup,
118+
isInstallingAkismet,
119+
isIntegrationsLoading,
120+
canPerformAkismetAction,
121+
...akismetIntegration,
122+
};
123+
};
124+
125+
export default useInstallAkismet;

0 commit comments

Comments
 (0)