Add SmartPluginCardBody component.
This commit is contained in:
parent
542b26e346
commit
5da2385d41
|
@ -0,0 +1,114 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { useState } from '@wordpress/element';
|
||||||
|
import { useDispatch } from '@wordpress/data';
|
||||||
|
import { Button } from '@wordpress/components';
|
||||||
|
import { Pill } from '@woocommerce/components';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
|
import { PLUGINS_STORE_NAME } from '@woocommerce/data';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { PluginCardBody } from '~/marketing/components';
|
||||||
|
import { RecommendedPlugin } from '~/marketing/types';
|
||||||
|
import { getInAppPurchaseUrl } from '~/lib/in-app-purchase';
|
||||||
|
import { createNoticesFromResponse } from '~/lib/notices';
|
||||||
|
import './PluginCardBody.scss';
|
||||||
|
|
||||||
|
type SmartPluginCardBodyProps = {
|
||||||
|
plugin: RecommendedPlugin;
|
||||||
|
onInstalledAndActivated?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A smart wrapper around PluginCardBody that accepts a `plugin` prop.
|
||||||
|
*
|
||||||
|
* It knows how to render the action button for the plugin,
|
||||||
|
* and has the logic for installing and activating plugin.
|
||||||
|
* This allows users to install and activate multiple plugins at the same time.
|
||||||
|
*/
|
||||||
|
export const SmartPluginCardBody = ( {
|
||||||
|
plugin,
|
||||||
|
onInstalledAndActivated = () => {},
|
||||||
|
}: SmartPluginCardBodyProps ) => {
|
||||||
|
const [ currentPlugin, setCurrentPlugin ] = useState< string | null >(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const { installAndActivatePlugins } = useDispatch( PLUGINS_STORE_NAME );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install and activate a plugin.
|
||||||
|
*
|
||||||
|
* When the process is successful, `onInstalledAndActivated` will be called.
|
||||||
|
* A success notice will be displayed.
|
||||||
|
*
|
||||||
|
* When the process is not successful, an error notice will be displayed.
|
||||||
|
*/
|
||||||
|
const installAndActivate = async () => {
|
||||||
|
setCurrentPlugin( plugin.product );
|
||||||
|
|
||||||
|
try {
|
||||||
|
recordEvent( 'marketing_recommended_extension', {
|
||||||
|
name: plugin.title,
|
||||||
|
} );
|
||||||
|
|
||||||
|
const response = await installAndActivatePlugins( [
|
||||||
|
plugin.product,
|
||||||
|
] );
|
||||||
|
|
||||||
|
onInstalledAndActivated();
|
||||||
|
createNoticesFromResponse( response );
|
||||||
|
} catch ( error ) {
|
||||||
|
createNoticesFromResponse( error );
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentPlugin( null );
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderButton = () => {
|
||||||
|
const buttonDisabled = !! currentPlugin;
|
||||||
|
|
||||||
|
if ( plugin.direct_install ) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
isBusy={ currentPlugin === plugin.product }
|
||||||
|
disabled={ buttonDisabled }
|
||||||
|
onClick={ installAndActivate }
|
||||||
|
>
|
||||||
|
{ __( 'Install plugin', 'woocommerce' ) }
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
href={ getInAppPurchaseUrl( plugin.url ) }
|
||||||
|
disabled={ buttonDisabled }
|
||||||
|
onClick={ () => {
|
||||||
|
recordEvent( 'marketing_recommended_extension', {
|
||||||
|
name: plugin.title,
|
||||||
|
} );
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
{ __( 'View details', 'woocommerce' ) }
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PluginCardBody
|
||||||
|
icon={ <img src={ plugin.icon } alt={ plugin.title } /> }
|
||||||
|
name={ plugin.title }
|
||||||
|
pills={ plugin.tags.map( ( tag ) => (
|
||||||
|
<Pill key={ tag.slug }>{ tag.name }</Pill>
|
||||||
|
) ) }
|
||||||
|
description={ plugin.description }
|
||||||
|
button={ renderButton() }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1 +1,2 @@
|
||||||
export { PluginCardBody } from './PluginCardBody';
|
export { PluginCardBody } from './PluginCardBody';
|
||||||
|
export { SmartPluginCardBody } from './SmartPluginCardBody';
|
||||||
|
|
|
@ -4,7 +4,7 @@ export { default as ProductIcon } from './product-icon';
|
||||||
export { default as Slider } from './slider';
|
export { default as Slider } from './slider';
|
||||||
export { default as ReadBlogMessage } from './ReadBlogMessage';
|
export { default as ReadBlogMessage } from './ReadBlogMessage';
|
||||||
export { CollapsibleCard, CardBody, CardDivider } from './CollapsibleCard';
|
export { CollapsibleCard, CardBody, CardDivider } from './CollapsibleCard';
|
||||||
export { PluginCardBody } from './PluginCardBody';
|
export { PluginCardBody, SmartPluginCardBody } from './PluginCardBody';
|
||||||
export { CardHeaderTitle } from './CardHeaderTitle';
|
export { CardHeaderTitle } from './CardHeaderTitle';
|
||||||
export { CardHeaderDescription } from './CardHeaderDescription';
|
export { CardHeaderDescription } from './CardHeaderDescription';
|
||||||
export { CenteredSpinner } from './CenteredSpinner';
|
export { CenteredSpinner } from './CenteredSpinner';
|
||||||
|
|
Loading…
Reference in New Issue