Add tracks for plugin installation and activation (#37261)
* Add @woocommerce/tracks to @woocommerce/data dependencies * Add tracks for plugin actions and handle plugin error properly * Add changelog * Add doc * Update doc
This commit is contained in:
parent
c5564a15c1
commit
7b10baff00
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: enhancement
|
||||||
|
|
||||||
|
Add tracks for plugin actions and handle plugin error properly
|
|
@ -28,6 +28,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@woocommerce/date": "workspace:*",
|
"@woocommerce/date": "workspace:*",
|
||||||
"@woocommerce/navigation": "workspace:*",
|
"@woocommerce/navigation": "workspace:*",
|
||||||
|
"@woocommerce/tracks": "workspace:*",
|
||||||
"@wordpress/api-fetch": "wp-6.0",
|
"@wordpress/api-fetch": "wp-6.0",
|
||||||
"@wordpress/compose": "wp-6.0",
|
"@wordpress/compose": "wp-6.0",
|
||||||
"@wordpress/core-data": "wp-6.0",
|
"@wordpress/core-data": "wp-6.0",
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
import { _n, sprintf } from '@wordpress/i18n';
|
import { _n, sprintf } from '@wordpress/i18n';
|
||||||
import { DispatchFromMap } from '@automattic/data-stores';
|
import { DispatchFromMap } from '@automattic/data-stores';
|
||||||
import { controls } from '@wordpress/data';
|
import { controls } from '@wordpress/data';
|
||||||
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -49,21 +50,22 @@ const isPluginResponseError = (
|
||||||
typeof error === 'object' && error !== null && plugins[ 0 ] in error;
|
typeof error === 'object' && error !== null && plugins[ 0 ] in error;
|
||||||
|
|
||||||
const formatErrorMessage = (
|
const formatErrorMessage = (
|
||||||
pluginErrors: PluginResponseErrors,
|
actionType: 'install' | 'activate' = 'install',
|
||||||
actionType = 'install'
|
plugins: Partial< PluginNames >[],
|
||||||
|
rawErrorMessage: string
|
||||||
) => {
|
) => {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
/* translators: %(actionType): install or activate (the plugin). %(pluginName): a plugin slug (e.g. woocommerce-services). %(error): a single error message or in plural a comma separated error message list.*/
|
/* translators: %(actionType): install or activate (the plugin). %(pluginName): a plugin slug (e.g. woocommerce-services). %(error): a single error message or in plural a comma separated error message list.*/
|
||||||
_n(
|
_n(
|
||||||
'Could not %(actionType)s %(pluginName)s plugin, %(error)s',
|
'Could not %(actionType)s %(pluginName)s plugin, %(error)s',
|
||||||
'Could not %(actionType)s the following plugins: %(pluginName)s with these Errors: %(error)s',
|
'Could not %(actionType)s the following plugins: %(pluginName)s with these Errors: %(error)s',
|
||||||
Object.keys( pluginErrors ).length || 1,
|
Object.keys( plugins ).length || 1,
|
||||||
'woocommerce'
|
'woocommerce'
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
actionType,
|
actionType,
|
||||||
pluginName: Object.keys( pluginErrors ).join( ', ' ),
|
pluginName: plugins.join( ', ' ),
|
||||||
error: Object.values( pluginErrors ).join( ', \n' ),
|
error: rawErrorMessage,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -174,35 +176,42 @@ export function setRecommendedPlugins(
|
||||||
}
|
}
|
||||||
|
|
||||||
function* handlePluginAPIError(
|
function* handlePluginAPIError(
|
||||||
actionType: string,
|
actionType: 'install' | 'activate',
|
||||||
plugins: Partial< PluginNames >[],
|
plugins: Partial< PluginNames >[],
|
||||||
error: unknown
|
error: unknown
|
||||||
) {
|
) {
|
||||||
yield setError( 'installPlugins', error );
|
let rawErrorMessage;
|
||||||
|
|
||||||
let pluginResponseError = error;
|
if ( isPluginResponseError( plugins, error ) ) {
|
||||||
if (
|
// Backend error messages are in the form of { plugin-slug: [ error messages ] }.
|
||||||
( error instanceof Error || isRestApiError( error ) ) &&
|
rawErrorMessage = Object.values( error ).join( ', \n' );
|
||||||
plugins[ 0 ]
|
|
||||||
) {
|
|
||||||
pluginResponseError = {
|
|
||||||
[ plugins[ 0 ] ]: [ error.message ],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isPluginResponseError( plugins, pluginResponseError ) ) {
|
|
||||||
throw new PluginError(
|
|
||||||
formatErrorMessage( pluginResponseError, actionType ),
|
|
||||||
pluginResponseError
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
throw new PluginError(
|
// Other error such as API connection errors.
|
||||||
`Unexpected Plugin Error: ${ JSON.stringify(
|
rawErrorMessage =
|
||||||
pluginResponseError
|
isRestApiError( error ) || error instanceof Error
|
||||||
) }`,
|
? error.message
|
||||||
pluginResponseError
|
: JSON.stringify( error );
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track the error.
|
||||||
|
switch ( actionType ) {
|
||||||
|
case 'install':
|
||||||
|
recordEvent( 'install_plugins_error', {
|
||||||
|
plugins: plugins.join( ', ' ),
|
||||||
|
message: rawErrorMessage,
|
||||||
|
} );
|
||||||
|
break;
|
||||||
|
case 'activate':
|
||||||
|
recordEvent( 'activate_plugins_error', {
|
||||||
|
plugins: plugins.join( ', ' ),
|
||||||
|
message: rawErrorMessage,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PluginError(
|
||||||
|
formatErrorMessage( actionType, plugins, rawErrorMessage ),
|
||||||
|
error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action Creator Generators
|
// Action Creator Generators
|
||||||
|
@ -225,6 +234,7 @@ export function* installPlugins( plugins: Partial< PluginNames >[] ) {
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
} catch ( error ) {
|
} catch ( error ) {
|
||||||
|
yield setError( 'installPlugins', error );
|
||||||
yield handlePluginAPIError( 'install', plugins, error );
|
yield handlePluginAPIError( 'install', plugins, error );
|
||||||
} finally {
|
} finally {
|
||||||
yield setIsRequesting( 'installPlugins', false );
|
yield setIsRequesting( 'installPlugins', false );
|
||||||
|
@ -251,6 +261,7 @@ export function* activatePlugins( plugins: Partial< PluginNames >[] ) {
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
} catch ( error ) {
|
} catch ( error ) {
|
||||||
|
yield setError( 'activatePlugins', error );
|
||||||
yield handlePluginAPIError( 'activate', plugins, error );
|
yield handlePluginAPIError( 'activate', plugins, error );
|
||||||
} finally {
|
} finally {
|
||||||
yield setIsRequesting( 'activatePlugins', false );
|
yield setIsRequesting( 'activatePlugins', false );
|
||||||
|
@ -305,7 +316,7 @@ export function* connectToJetpack(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* installJetpackAndConnect(
|
export function* installJetpackAndConnect(
|
||||||
errorAction: ( errorMesage: string ) => void,
|
errorAction: ( errorMessage: string ) => void,
|
||||||
getAdminLink: ( endpoint: string ) => string
|
getAdminLink: ( endpoint: string ) => string
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
@ -329,7 +340,7 @@ export function* installJetpackAndConnect(
|
||||||
|
|
||||||
export function* connectToJetpackWithFailureRedirect(
|
export function* connectToJetpackWithFailureRedirect(
|
||||||
failureRedirect: string,
|
failureRedirect: string,
|
||||||
errorAction: ( errorMesage: string ) => void,
|
errorAction: ( errorMessage: string ) => void,
|
||||||
getAdminLink: ( endpoint: string ) => string
|
getAdminLink: ( endpoint: string ) => string
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -608,6 +608,7 @@ importers:
|
||||||
'@woocommerce/date': workspace:*
|
'@woocommerce/date': workspace:*
|
||||||
'@woocommerce/eslint-plugin': workspace:*
|
'@woocommerce/eslint-plugin': workspace:*
|
||||||
'@woocommerce/navigation': workspace:*
|
'@woocommerce/navigation': workspace:*
|
||||||
|
'@woocommerce/tracks': workspace:*
|
||||||
'@wordpress/api-fetch': wp-6.0
|
'@wordpress/api-fetch': wp-6.0
|
||||||
'@wordpress/compose': wp-6.0
|
'@wordpress/compose': wp-6.0
|
||||||
'@wordpress/core-data': wp-6.0
|
'@wordpress/core-data': wp-6.0
|
||||||
|
@ -635,6 +636,7 @@ importers:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@woocommerce/date': link:../date
|
'@woocommerce/date': link:../date
|
||||||
'@woocommerce/navigation': link:../navigation
|
'@woocommerce/navigation': link:../navigation
|
||||||
|
'@woocommerce/tracks': link:../tracks
|
||||||
'@wordpress/api-fetch': 6.3.1
|
'@wordpress/api-fetch': 6.3.1
|
||||||
'@wordpress/compose': 5.4.1_react@17.0.2
|
'@wordpress/compose': 5.4.1_react@17.0.2
|
||||||
'@wordpress/core-data': 4.4.5_react@17.0.2
|
'@wordpress/core-data': 4.4.5_react@17.0.2
|
||||||
|
|
Loading…
Reference in New Issue