Back

96.87% Statements 31/32
95.23% Branches 20/21
100% Functions 3/3
96.87% Lines 31/32

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                              9x   9x 9x 9x   9x 9x     9x 9x     9x     9x   9x 4x       1x 1x 1x         3x 3x 3x   3x 3x 3x 3x 2x 2x     2x   1x       3x                         9x                         9x 1x                       8x    
import { useAiFeature } from '@automattic/jetpack-ai-client';
import { Button } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { useCallback, useId } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { lock } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
import { Tooltip, VisuallyHidden } from '@wordpress/ui';
import { useSectionHasDraft } from '../hooks/use-drafts';
import { suggestGuidelines } from '../lib/api';
import { readSectionDraft } from '../lib/drafts';
import { recordGuidelinesEvent } from '../lib/tracks';
import { AI_STORE_NAME } from '../store';
 
export default function SectionGenerateButton( { slug, isShortLabel = false } ) {
	const { createErrorNotice } = useDispatch( noticesStore );
	const { startSectionLoading, stopSectionLoading, setSuggestion, showUpgradeNotice } =
		useDispatch( AI_STORE_NAME );
	const { hasFeature } = useAiFeature();
	const descriptionId = useId();
 
	const sectionLoading = useSelect(
		select => select( AI_STORE_NAME ).isSectionLoading( slug ),
		[ slug ]
	);
	const isEmpty = ! useSectionHasDraft( slug );
	const generateLabel = isShortLabel
		? __( 'Generate', 'jetpack' )
		: __( 'Generate guidelines', 'jetpack', /* dummy arg to avoid bad minification */ 0 );
	const improveLabel = isShortLabel
		? __( 'Improve', 'jetpack' )
		: __( 'Improve guidelines', 'jetpack', /* dummy arg to avoid bad minification */ 0 );
	const label = isEmpty ? generateLabel : improveLabel;
 
	const handleClick = useCallback( async () => {
		if ( ! hasFeature ) {
			// No AI plan: the locked button opens the upgrade notice instead of
			// generating. The click is a fresh intent signal, so the notice
			// reappears even after a persisted dismissal.
			recordGuidelinesEvent( 'upgrade_notice', { trigger: 'section', slug } );
			showUpgradeNotice();
			return;
		}
 
		// Snapshot the draft at click time — the render-time hook value could
		// be stale if a page-driven change slipped past the notifications.
		const currentDraft = readSectionDraft( slug );
		const action = currentDraft ? 'improve' : 'generate';
		recordGuidelinesEvent( 'generate', { type: 'section', slug, action } );
 
		startSectionLoading( slug );
		try {
			const existingContent = currentDraft ? { [ slug ]: currentDraft } : {};
			const response = await suggestGuidelines( [ slug ], existingContent );
			const suggestion = response?.suggestions?.[ slug ];
			Iif ( ! suggestion ) {
				throw new Error( 'No suggestion returned.' );
			}
			setSuggestion( slug, suggestion );
		} catch {
			createErrorNotice( __( 'Failed to generate guidelines. Please try again.', 'jetpack' ), {
				type: 'snackbar',
			} );
		} finally {
			stopSectionLoading( slug );
		}
	}, [
		slug,
		hasFeature,
		startSectionLoading,
		stopSectionLoading,
		setSuggestion,
		showUpgradeNotice,
		createErrorNotice,
	] );
 
	const button = (
		<Button
			variant="tertiary"
			icon={ hasFeature ? undefined : lock }
			onClick={ handleClick }
			disabled={ sectionLoading }
			accessibleWhenDisabled
			aria-describedby={ hasFeature ? undefined : descriptionId }
			className="jetpack-content-guidelines-ai__section-generate-button"
		>
			{ label }
		</Button>
	);
 
	if ( ! hasFeature ) {
		return (
			<Tooltip.Root>
				<Tooltip.Trigger render={ button } />
				{ /* The popup is visual-only, so this carries the sentence to screen readers. */ }
				<VisuallyHidden id={ descriptionId } render={ <span /> }>
					{ __( 'Upgrade to unlock the AI assistant', 'jetpack' ) }
				</VisuallyHidden>
				<Tooltip.Popup>{ __( 'Upgrade to unlock the AI assistant', 'jetpack' ) }</Tooltip.Popup>
			</Tooltip.Root>
		);
	}
 
	return button;
}