Back

0% Statements 0/31
0% Branches 0/41
0% Functions 0/5
0% Lines 0/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                                                                                                                                                                                                                                       
/**
 * External dependencies
 */
import { Button, Spinner } from '@wordpress/components';
import { useEffect, useId, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { Tooltip, VisuallyHidden } from '@wordpress/ui';
/**
 * Internal dependencies
 */
import { usePluginInstallation } from '../../../../../hooks/use-plugin-installation.ts';
 
type PluginActionButtonProps = {
	slug: string;
	pluginFile: string;
	isInstalled: boolean;
	isActive: boolean;
	refreshStatus: () => void;
	trackEventName: string;
};
 
const PluginActionButton = ( {
	slug,
	pluginFile,
	isInstalled,
	isActive,
	refreshStatus,
	trackEventName,
}: PluginActionButtonProps ) => {
	const descriptionId = useId();
	const trackEventProps = {
		screen: 'block-editor',
	};
 
	const { isInstalling, installPlugin, canInstallPlugins, canActivatePlugins } =
		usePluginInstallation( {
			slug,
			pluginPath: pluginFile,
			isInstalled,
			trackEventName,
			trackEventProps,
		} );
 
	const canPerformAction = isInstalled ? canActivatePlugins : canInstallPlugins;
	const [ isReconcilingStatus, setIsReconcilingStatus ] = useState( false );
	const isDisabled = isInstalling || isReconcilingStatus || ! canPerformAction;
 
	const handleAction = async ( event: React.MouseEvent< HTMLButtonElement > ) => {
		event.stopPropagation();
		if ( isDisabled ) {
			return;
		}
		const success = await installPlugin();
 
		if ( success && refreshStatus ) {
			setIsReconcilingStatus( true ); // Keeps button in loading state until integrations refresh.
			refreshStatus();
		}
	};
 
	useEffect( () => {
		if ( isReconcilingStatus && isActive ) {
			setIsReconcilingStatus( false ); // Removes button loading state when integratoin status is recevied and isActive.
		}
	}, [ isReconcilingStatus, isActive ] );
 
	const getButtonText = () => {
		return (
			( ( isInstalling || isReconcilingStatus ) &&
				isInstalled &&
				__( 'Activating…', 'jetpack-forms' ) ) ||
			( ( isInstalling || isReconcilingStatus ) && __( 'Installing…', 'jetpack-forms' ) ) ||
			( isInstalled && __( 'Activate', 'jetpack-forms' ) ) ||
			__( 'Install', 'jetpack-forms' )
		);
	};
 
	const tooltipTextActivate = __( 'Activate this plugin', 'jetpack-forms' );
	const tooltipTextInstall = __( 'Install this plugin', 'jetpack-forms' );
	const tooltipTextNoInstallPerms = __(
		'You do not have permission to install plugins.',
		'jetpack-forms'
	);
	const tooltipTextNoActivatePerms = __(
		'You do not have permission to activate plugins.',
		'jetpack-forms'
	);
 
	const getTooltipText = (): string => {
		if ( isInstalled && ! canActivatePlugins ) {
			return tooltipTextNoActivatePerms;
		}
		if ( ! isInstalled && ! canInstallPlugins ) {
			return tooltipTextNoInstallPerms;
		}
		return String( isInstalled ? tooltipTextActivate : tooltipTextInstall );
	};
 
	return (
		<Tooltip.Root>
			<Tooltip.Trigger render={ <span style={ { display: 'inline-flex' } } /> }>
				<Button
					variant="primary"
					onClick={ handleAction }
					disabled={ isDisabled }
					style={ isDisabled ? { pointerEvents: 'none' } : undefined }
					icon={ isInstalling || isReconcilingStatus ? <Spinner /> : undefined }
					__next40pxDefaultSize
					aria-describedby={ descriptionId }
				>
					{ getButtonText() }
				</Button>
				{ /* The popup is visual-only, so this carries the sentence to screen readers. */ }
				<VisuallyHidden id={ descriptionId } render={ <span /> }>
					{ getTooltipText() }
				</VisuallyHidden>
			</Tooltip.Trigger>
			<Tooltip.Popup>{ getTooltipText() }</Tooltip.Popup>
		</Tooltip.Root>
	);
};
 
export default PluginActionButton;