Skip to content

Commit 03b82e0

Browse files
committed
update use-plugin-installation and reuse it
1 parent 70bb524 commit 03b82e0

File tree

4 files changed

+246
-184
lines changed

4 files changed

+246
-184
lines changed

projects/packages/forms/src/blocks/contact-form/components/jetpack-integrations-modal/hooks/use-plugin-installation.ts

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,138 @@
22
* External dependencies
33
*/
44
import { useAnalytics } from '@automattic/jetpack-shared-extension-utils';
5+
import { useDispatch } from '@wordpress/data';
56
import { useState, useCallback } from '@wordpress/element';
7+
import { store as noticesStore } from '@wordpress/notices';
68
/**
79
* Internal dependencies
810
*/
11+
import useConfigValue from '../../../../../hooks/use-config-value.ts';
912
import { installAndActivatePlugin, activatePlugin } from '../../../util/plugin-management.js';
1013

14+
type NoticeOptions = Record< string, unknown >;
15+
16+
type NoticeConfig = {
17+
message?: string;
18+
options?: NoticeOptions;
19+
};
20+
21+
type SuccessNotices = {
22+
install?: NoticeConfig;
23+
activate?: NoticeConfig;
24+
};
25+
26+
type UsePluginInstallationArgs = {
27+
slug: string;
28+
pluginPath: string;
29+
isInstalled: boolean;
30+
trackEventName?: string;
31+
trackEventProps?: Record< string, unknown >;
32+
onSuccess?: () => void | Promise< void >;
33+
successNotices?: SuccessNotices;
34+
errorNotice?: NoticeConfig;
35+
};
36+
1137
type PluginInstallation = {
1238
isInstalling: boolean;
1339
installPlugin: () => Promise< boolean >;
40+
canInstallPlugins: boolean;
41+
canActivatePlugins: boolean;
1442
};
1543

1644
/**
1745
* Custom hook to handle plugin installation and activation flows.
1846
*
19-
* @param {string} slug - The plugin slug (e.g., 'akismet')
20-
* @param {string} pluginPath - The plugin path (e.g., 'akismet/akismet')
21-
* @param {boolean} isInstalled - Whether the plugin is installed
22-
* @param {string} tracksEventName - The name of the tracks event to record
23-
* @return {object} Plugin installation states and handlers
47+
* @param {UsePluginInstallationArgs} args - Hook arguments.
48+
* @return {PluginInstallation} Plugin installation states and handlers.
2449
*/
25-
export const usePluginInstallation = (
26-
slug: string,
27-
pluginPath: string,
28-
isInstalled: boolean,
29-
tracksEventName: string
30-
): PluginInstallation => {
50+
export const usePluginInstallation = ( {
51+
slug,
52+
pluginPath,
53+
isInstalled,
54+
trackEventName,
55+
trackEventProps = {},
56+
onSuccess,
57+
successNotices,
58+
errorNotice,
59+
}: UsePluginInstallationArgs ): PluginInstallation => {
3160
const [ isInstalling, setIsInstalling ] = useState( false );
3261
const { tracks } = useAnalytics();
62+
const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore );
63+
const canInstallPlugins = useConfigValue( 'canInstallPlugins' );
64+
const canActivatePlugins = useConfigValue( 'canActivatePlugins' );
3365

3466
const installPlugin = useCallback( async () => {
3567
setIsInstalling( true );
3668

37-
if ( tracksEventName ) {
38-
tracks.recordEvent( tracksEventName, {
39-
screen: 'block-editor',
69+
if ( trackEventName ) {
70+
tracks.recordEvent( trackEventName, {
4071
intent: isInstalled ? 'activate-plugin' : 'install-plugin',
72+
...( trackEventProps ?? {} ),
4173
} );
4274
}
4375

4476
try {
4577
if ( isInstalled ) {
78+
if ( ! canActivatePlugins ) {
79+
return false;
80+
}
81+
4682
await activatePlugin( pluginPath );
4783
} else {
84+
if ( ! canInstallPlugins ) {
85+
return false;
86+
}
87+
4888
await installAndActivatePlugin( slug );
4989
}
90+
91+
const successNoticeConfig = isInstalled ? successNotices?.activate : successNotices?.install;
92+
93+
if ( successNoticeConfig?.message ) {
94+
createSuccessNotice( successNoticeConfig.message, successNoticeConfig.options );
95+
}
96+
97+
if ( onSuccess ) {
98+
await onSuccess();
99+
}
100+
50101
return true;
51-
} catch {
52-
// Let the component handle the error state
102+
} catch ( error ) {
103+
if ( errorNotice ) {
104+
const noticeMessage =
105+
errorNotice.message || ( error instanceof Error ? error.message : undefined );
106+
107+
if ( noticeMessage ) {
108+
createErrorNotice( noticeMessage, errorNotice.options );
109+
}
110+
}
111+
53112
return false;
54113
} finally {
55114
setIsInstalling( false );
56115
}
57-
}, [ slug, pluginPath, isInstalled, tracks, tracksEventName ] );
116+
}, [
117+
trackEventName,
118+
tracks,
119+
isInstalled,
120+
trackEventProps,
121+
successNotices?.activate,
122+
successNotices?.install,
123+
onSuccess,
124+
canActivatePlugins,
125+
pluginPath,
126+
canInstallPlugins,
127+
slug,
128+
createSuccessNotice,
129+
errorNotice,
130+
createErrorNotice,
131+
] );
58132

59133
return {
60134
isInstalling,
61135
installPlugin,
136+
canInstallPlugins,
137+
canActivatePlugins,
62138
};
63139
};

projects/packages/forms/src/blocks/contact-form/components/jetpack-integrations-modal/integration-card/plugin-action-button.tsx

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { __ } from '@wordpress/i18n';
77
/**
88
* Internal dependencies
99
*/
10-
import useConfigValue from '../../../../../hooks/use-config-value.ts';
1110
import { usePluginInstallation } from '../hooks/use-plugin-installation.ts';
1211

1312
type PluginActionButtonProps = {
@@ -27,18 +26,20 @@ const PluginActionButton = ( {
2726
refreshStatus,
2827
trackEventName,
2928
}: PluginActionButtonProps ) => {
30-
const { isInstalling, installPlugin } = usePluginInstallation(
31-
slug,
32-
pluginFile,
33-
isInstalled,
34-
trackEventName
35-
);
29+
const trackEventProps = {
30+
screen: 'block-editor',
31+
};
3632

37-
// Permissions from consolidated Forms config (shared across editor and dashboard)
38-
const canUserInstallPlugins = useConfigValue( 'canInstallPlugins' );
39-
const canUserActivatePlugins = useConfigValue( 'canActivatePlugins' );
33+
const { isInstalling, installPlugin, canInstallPlugins, canActivatePlugins } =
34+
usePluginInstallation( {
35+
slug,
36+
pluginPath: pluginFile,
37+
isInstalled,
38+
trackEventName,
39+
trackEventProps,
40+
} );
4041

41-
const canPerformAction = isInstalled ? canUserActivatePlugins : canUserInstallPlugins;
42+
const canPerformAction = isInstalled ? canActivatePlugins : canInstallPlugins;
4243
const [ isReconcilingStatus, setIsReconcilingStatus ] = useState( false );
4344
const isDisabled = isInstalling || isReconcilingStatus || ! canPerformAction;
4445

@@ -84,10 +85,10 @@ const PluginActionButton = ( {
8485
);
8586

8687
const getTooltipText = (): string => {
87-
if ( isInstalled && ! canUserActivatePlugins ) {
88+
if ( isInstalled && ! canActivatePlugins ) {
8889
return tooltipTextNoActivatePerms;
8990
}
90-
if ( ! isInstalled && ! canUserInstallPlugins ) {
91+
if ( ! isInstalled && ! canInstallPlugins ) {
9192
return tooltipTextNoInstallPerms;
9293
}
9394
return String( isInstalled ? tooltipTextActivate : tooltipTextInstall );

0 commit comments

Comments
 (0)