+
diff --git a/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/connect-account-button.tsx b/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/connect-account-button.tsx
new file mode 100644
index 00000000000..d45c9e4f381
--- /dev/null
+++ b/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/connect-account-button.tsx
@@ -0,0 +1,29 @@
+/**
+ * External dependencies
+ */
+import { Button } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { getAdminSetting } from '../../../../../utils/admin-settings';
+
+interface RenewProps {
+ variant?: Button.ButtonVariant;
+ install?: string;
+}
+
+export default function ConnectAccountButton( props: RenewProps ) {
+ const wccomSettings = getAdminSetting( 'wccomHelper', {} );
+
+ const url = new URL( wccomSettings?.connectURL ?? '' );
+ if ( props.install ) {
+ url.searchParams.set( 'install', props.install );
+ }
+ return (
+
+ );
+}
diff --git a/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/install-modal.tsx b/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/install-modal.tsx
new file mode 100644
index 00000000000..98bb8e760ec
--- /dev/null
+++ b/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/install-modal.tsx
@@ -0,0 +1,228 @@
+/**
+ * External dependencies
+ */
+import { Button, ButtonGroup, Modal, Notice } from '@wordpress/components';
+import { __, sprintf } from '@wordpress/i18n';
+import { getNewPath, navigateTo, useQuery } from '@woocommerce/navigation';
+import {
+ useCallback,
+ useContext,
+ useEffect,
+ useState,
+} from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { Subscription } from '../../types';
+import { getAdminSetting } from '../../../../../utils/admin-settings';
+import Install from './install';
+import { SubscriptionsContext } from '../../../../contexts/subscriptions-context';
+import { MARKETPLACE_PATH, WP_ADMIN_PLUGIN_LIST_URL } from '../../../constants';
+import ConnectAccountButton from './connect-account-button';
+import ProductCard from '../../../product-card/product-card';
+import { addNotice, subscriptionToProduct } from '../../../../utils/functions';
+import { NoticeStatus } from '../../../../contexts/types';
+
+export default function InstallModal() {
+ const query = useQuery();
+ const installingProductKey = query?.install;
+
+ const wccomSettings = getAdminSetting( 'wccomHelper', {} );
+ const isConnected = !! wccomSettings?.isConnected;
+
+ const [ showModal, setShowModal ] = useState< boolean >( false );
+ const [ isInstalled, setIsInstalled ] = useState< boolean >( false );
+
+ const { subscriptions, isLoading } = useContext( SubscriptionsContext );
+
+ const subscription: Subscription | undefined = subscriptions.find(
+ ( s: Subscription ) => s.product_key === installingProductKey
+ );
+
+ const removeInstallQuery = useCallback( () => {
+ navigateTo( {
+ url: getNewPath(
+ {
+ ...query,
+ install: undefined,
+ },
+ MARKETPLACE_PATH,
+ {}
+ ),
+ } );
+ }, [ query ] );
+
+ useEffect( () => {
+ if ( isLoading ) {
+ return;
+ }
+
+ // If subscriptions loaded, but we don't have a subscription for the product key, show an error.
+ if (
+ installingProductKey &&
+ isConnected &&
+ ! isLoading &&
+ ! subscription
+ ) {
+ addNotice(
+ installingProductKey,
+ sprintf(
+ /* translators: %s is the product key */
+ __(
+ 'Could not find subscription with product key %s.',
+ 'woocommerce'
+ ),
+ installingProductKey
+ ),
+ NoticeStatus.Error
+ );
+ removeInstallQuery();
+ } else {
+ setShowModal( !! installingProductKey );
+ }
+ }, [
+ isConnected,
+ isLoading,
+ installingProductKey,
+ removeInstallQuery,
+ subscription,
+ ] );
+
+ useEffect( () => {
+ if ( subscription && subscription.local.installed ) {
+ setIsInstalled( true );
+ }
+ }, [ subscription ] );
+
+ const onClose = () => {
+ removeInstallQuery();
+ setShowModal( false );
+ };
+
+ const modalTitle = () => {
+ if ( isInstalled ) {
+ return __( 'You are ready to go!', 'woocommerce' );
+ }
+
+ return __( 'Add to store', 'woocommerce' );
+ };
+
+ const modalContent = () => {
+ if ( ! isConnected ) {
+ return (
+
+ { __(
+ 'In order to install a product, you need to first connect your account.',
+ 'woocommerce'
+ ) }
+
+ );
+ } else if ( subscription ) {
+ const installContent = isInstalled
+ ? __(
+ 'Keep the momentum going and start setting up your extension.',
+ 'woocommerce'
+ )
+ : __(
+ 'Would you like to install this extension?',
+ 'woocommerce'
+ );
+ return (
+ <>
+
+ { installContent }
+
+
+ >
+ );
+ }
+ };
+ const modalButtons = () => {
+ const buttons = [];
+ if ( isInstalled ) {
+ buttons.push(
+
+ );
+ buttons.push(
+
+ );
+ } else {
+ buttons.push(
+
+ );
+
+ if ( ! isConnected ) {
+ buttons.push(
+
+ );
+ } else if ( subscription ) {
+ buttons.push(
+
+ );
+ }
+ }
+ return (
+
+ { buttons }
+
+ );
+ };
+
+ if ( ! showModal ) {
+ return null;
+ }
+
+ return (
+
+ { modalContent() }
+ { modalButtons() }
+
+ );
+}
diff --git a/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/install.tsx b/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/install.tsx
index 9de06cb7101..f57206d9628 100644
--- a/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/install.tsx
+++ b/plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/table/actions/install.tsx
@@ -22,6 +22,9 @@ import { NoticeStatus } from '../../../../contexts/types';
interface InstallProps {
subscription: Subscription;
+ variant?: Button.ButtonVariant;
+ onSuccess?: () => void;
+ onError?: () => void;
}
export default function Install( props: InstallProps ) {
@@ -76,6 +79,10 @@ export default function Install( props: InstallProps ) {
product_id: props.subscription.product_id,
product_current_version: props.subscription.version,
} );
+
+ if ( props.onSuccess ) {
+ props.onSuccess();
+ }
} )
.catch( ( error ) => {
loadSubscriptions( false ).then( () => {
@@ -101,19 +108,24 @@ export default function Install( props: InstallProps ) {
}
);
stopInstall();
+
+ if ( props.onError ) {
+ props.onError();
+ }
} );
recordEvent( 'marketplace_product_install_failed', {
product_zip_slug: props.subscription.zip_slug,
product_id: props.subscription.product_id,
product_current_version: props.subscription.version,
+ error_message: error?.data?.message,
} );
} );
};
return (