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;
|