import { getRecommendation, recordActivity, } from '@recommendations/utils/record-activity'; import { recordPluginActivity } from '@shared/api/DataApi'; import { activatePlugin, installPlugin } from '@shared/api/wp'; import { retryOperation, sleep } from '@shared/lib/utils'; import { Button } from '@wordpress/components'; import { useCallback, useEffect, useState } from '@wordpress/element'; import { decodeEntities } from '@wordpress/html-entities'; import { __, _x, sprintf } from '@wordpress/i18n'; import { caution, check, external, Icon } from '@wordpress/icons'; export const RecommendationCard = ({ slug: product, title, description, ctaContent, provider, image, ctaType, ctaPluginSlug, ctaExternalLink, ctaInternalLink, priceTag, }) => { useEffect(() => { recordActivity({ slot: 'plugin-search', event: 'view', product }); }, [product]); return (
{image && (ctaType === 'plugin' ? ( recordActivity({ slot: 'plugin-search', event: 'click-logo', product, }) } // These WP classes (thickbox open-plugin-details-modal) are needed for the link to open in an iframe like WP does. className="thickbox open-plugin-details-modal block no-underline" // The hardcoded iframe dimensions are the default ones, but some WP magic makes them responsive. href={`${window.extSharedData?.adminUrl}/plugin-install.php?tab=plugin-information&plugin=${ctaPluginSlug}&TB_iframe=true&width=600&height=550`} > {title} ) : ( {title} ))}

{ctaType === 'plugin' ? ( recordActivity({ slot: 'plugin-search', event: 'click-title', product, }) } // These WP classes (thickbox open-plugin-details-modal) are needed for the link to open in an iframe like WP does. className="thickbox open-plugin-details-modal no-underline focus:shadow-none" // The hardcoded iframe dimensions are the default ones, but some WP magic makes them responsive. href={`${window.extSharedData?.adminUrl}/plugin-install.php?tab=plugin-information&plugin=${ctaPluginSlug}&TB_iframe=true&width=600&height=550`} > {decodeEntities(title)} ) : ( decodeEntities(title) )}

{sprintf( // translators: %s is a name _x( 'By %s', 'Preposition for "By Author Name"', 'extendify-local', ), provider, )}

{decodeEntities(description)}

{priceTag && (

)} {ctaType === 'plugin' && ( )} {ctaType === 'external-link' && ( )} {ctaType === 'internal-link' && ( )}

); }; const InstallPluginAction = ({ product, ctaContent, ctaPluginSlug }) => { const [status, setStatus] = useState('idle'); const [error, setError] = useState(null); const handleInstall = useCallback(async () => { recordActivity({ slot: 'plugin-search', event: 'click-install', product, }); try { setStatus('installing'); await Promise.all([ retryOperation(() => installPlugin(ctaPluginSlug), { maxAttempts: 2 }), // Sleep makes sure the installing UI is displayed for at least 1 second. sleep(1000), ]); } catch (_) { setError(__('Failed to install the plugin', 'extendify-local')); setStatus('error'); return; } const recommendation = getRecommendation({ product }); recordPluginActivity({ slug: recommendation || product, source: 'search-recommendation-card', }); try { setStatus('activating'); await Promise.all([ retryOperation(() => activatePlugin(ctaPluginSlug), { maxAttempts: 2 }), // Sleep makes sure the activating UI is displayed for at least 1 second. sleep(1000), ]); } catch (_) { setError(__('Failed to activate the plugin', 'extendify-local')); setStatus('error'); return; } setStatus('activated'); }, [product, ctaPluginSlug]); const actionText = { idle: ctaContent, installing: _x( 'Installing...', 'Plugin installation status', 'extendify-local', ), activating: _x( 'Activating...', 'Plugin activation status', 'extendify-local', ), activated: _x('Activated', 'Plugin activation status', 'extendify-local'), error, }; if (status === 'error') { return (

{actionText[status]}

); } if (status === 'activated') { return (

{actionText[status]}

); } return ( ); }; const ExternalLinkAction = ({ product, ctaContent, ctaExternalLink }) => { const ctaExternalLinkWithPartner = decodeEntities(ctaExternalLink).replace( '{PARTNERID}', window.extSharedData?.partnerId, ); return ( recordActivity({ slot: 'plugin-search', event: 'click-link-external', product, }) } href={ctaExternalLinkWithPartner} target="_blank" className="relative flex min-h-8 min-w-24 cursor-pointer items-center justify-center whitespace-normal wrap-break-word rounded-xs bg-wp-theme-main fill-design-text py-1.5 pl-3 pr-9 text-center text-sm leading-tight text-design-text no-underline hover:opacity-90 focus:shadow-none" > {ctaContent} ); }; const InternalLinkAction = ({ product, ctaContent, ctaInternalLink }) => { return ( recordActivity({ slot: 'plugin-search', event: 'click-link-internal', product, }) } href={ctaInternalLink} className="relative flex min-h-8 min-w-24 cursor-pointer items-center justify-center whitespace-normal break-words rounded-xs bg-wp-theme-main fill-design-text px-3 py-[6px] text-center text-sm leading-tight text-design-text no-underline hover:opacity-90 focus:shadow-none" > {ctaContent} ); };