From 01fd8c9873e0f58543d4e38bd1be54bc7639044d Mon Sep 17 00:00:00 2001
From: Dylan Munson <65001528+CodeyGuyDylan@users.noreply.github.com>
Date: Tue, 19 Nov 2024 13:04:07 -0700
Subject: [PATCH 1/2] Add/growth upsells to social and stats interstials
(#40236)
* Remove creator card and update checks for paid plans to include growth
* Add changelog
* Add growth upsell to stats and social interstitial
* changelog
* Remove unnecessary changes
* Add changelog
---
...th-upsells-to-social-and-stats-interstials | 4 +
.../components/components/icons/index.tsx | 13 ++
.../components/product-cards-section/all.ts | 1 +
.../product-cards-section/index.tsx | 9 +-
.../components/product-interstitial/index.jsx | 25 +--
.../my-jetpack/_inc/data/constants.ts | 1 +
...th-upsells-to-social-and-stats-interstials | 4 +
projects/packages/my-jetpack/global.d.ts | 3 +-
.../my-jetpack/src/class-products.php | 1 +
.../my-jetpack/src/products/class-growth.php | 209 ++++++++++++++++++
.../src/products/class-security.php | 11 +-
.../my-jetpack/src/products/class-social.php | 10 +
.../my-jetpack/src/products/class-stats.php | 10 +
13 files changed, 271 insertions(+), 30 deletions(-)
create mode 100644 projects/js-packages/components/changelog/add-growth-upsells-to-social-and-stats-interstials
create mode 100644 projects/packages/my-jetpack/changelog/add-growth-upsells-to-social-and-stats-interstials
create mode 100644 projects/packages/my-jetpack/src/products/class-growth.php
diff --git a/projects/js-packages/components/changelog/add-growth-upsells-to-social-and-stats-interstials b/projects/js-packages/components/changelog/add-growth-upsells-to-social-and-stats-interstials
new file mode 100644
index 0000000000000..dda6e2d1a89aa
--- /dev/null
+++ b/projects/js-packages/components/changelog/add-growth-upsells-to-social-and-stats-interstials
@@ -0,0 +1,4 @@
+Significance: patch
+Type: added
+
+Add Stats icon
diff --git a/projects/js-packages/components/components/icons/index.tsx b/projects/js-packages/components/components/icons/index.tsx
index a390b8a3a3f6f..892e03dee4997 100644
--- a/projects/js-packages/components/components/icons/index.tsx
+++ b/projects/js-packages/components/components/icons/index.tsx
@@ -234,6 +234,18 @@ export const AiIcon: React.FC< BaseIconProps > = ( {
);
};
+export const StatsIcon: React.FC< BaseIconProps > = ( { opacity = 1, size, color } ) => {
+ return (
+
+
+
+ );
+};
+
const jetpackIcons = {
'anti-spam': AntiSpamIcon,
backup: BackupIcon,
@@ -249,6 +261,7 @@ const jetpackIcons = {
jetpack: JetpackIcon,
share: ShareIcon,
ai: AiIcon,
+ stats: StatsIcon,
};
const iconsMap = {
diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/all.ts b/projects/packages/my-jetpack/_inc/components/product-cards-section/all.ts
index 10e29b7fbca76..880d6e7ea0a21 100644
--- a/projects/packages/my-jetpack/_inc/components/product-cards-section/all.ts
+++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/all.ts
@@ -28,4 +28,5 @@ export const JetpackModuleToProductCard: {
scan: null,
security: null,
creator: null,
+ growth: null,
};
diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx
index ff10798442fc2..855ba5e234b12 100644
--- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx
+++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx
@@ -26,7 +26,7 @@ type DisplayItemType = Record<
// We don't have a card for Security or Extras, and scan is displayed as protect.
// 'jetpack-ai' is the official slug for the AI module, so we also exclude 'ai'.
// The backend still supports the 'ai' slug, so it is part of the JetpackModule type.
- Exclude< JetpackModule, 'extras' | 'scan' | 'security' | 'ai' | 'creator' >,
+ Exclude< JetpackModule, 'extras' | 'scan' | 'security' | 'ai' | 'creator' | 'growth' >,
FC< { admin: boolean } >
>;
@@ -104,7 +104,12 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { noticeMessage }
const filterProducts = ( products: JetpackModule[] ) => {
return products.filter( product => {
- if ( product === 'scan' || product === 'security' || product === 'extras' ) {
+ if (
+ product === 'scan' ||
+ product === 'security' ||
+ product === 'growth' ||
+ product === 'extras'
+ ) {
return false;
}
return true;
diff --git a/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx b/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx
index 60cd848f1f817..a2da42c2af781 100644
--- a/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx
+++ b/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx
@@ -32,8 +32,6 @@ import boostImage from './boost.png';
import crmImage from './crm.png';
import extrasImage from './extras.png';
import searchImage from './search.png';
-import socialImage from './social.png';
-import statsImage from './stats.png';
import styles from './style.module.scss';
import videoPressImage from './videopress.png';
@@ -408,17 +406,7 @@ export function ScanInterstitial() {
* @return {object} SocialInterstitial react component.
*/
export function SocialInterstitial() {
- return (
-
-
-
- );
+ return ;
}
/**
@@ -462,15 +450,8 @@ export function StatsInterstitial() {
directCheckout={ true }
installsPlugin={ true }
ctaButtonLabel={ __( 'Get Stats', 'jetpack-my-jetpack' ) }
- >
-
-
+ bundle="growth"
+ />
);
}
diff --git a/projects/packages/my-jetpack/_inc/data/constants.ts b/projects/packages/my-jetpack/_inc/data/constants.ts
index c11217819409d..c55a4a6b24f61 100644
--- a/projects/packages/my-jetpack/_inc/data/constants.ts
+++ b/projects/packages/my-jetpack/_inc/data/constants.ts
@@ -51,4 +51,5 @@ export const PRODUCT_SLUGS = {
PROTECT: 'protect',
VIDEOPRESS: 'videopress',
STATS: 'stats',
+ GROWTH: 'growth',
} satisfies Record< string, JetpackModule >;
diff --git a/projects/packages/my-jetpack/changelog/add-growth-upsells-to-social-and-stats-interstials b/projects/packages/my-jetpack/changelog/add-growth-upsells-to-social-and-stats-interstials
new file mode 100644
index 0000000000000..5d0c9263fc127
--- /dev/null
+++ b/projects/packages/my-jetpack/changelog/add-growth-upsells-to-social-and-stats-interstials
@@ -0,0 +1,4 @@
+Significance: patch
+Type: added
+
+Add growth upsell to Stats and Social interstitials
diff --git a/projects/packages/my-jetpack/global.d.ts b/projects/packages/my-jetpack/global.d.ts
index 49d4563fabc82..ec2870487c89d 100644
--- a/projects/packages/my-jetpack/global.d.ts
+++ b/projects/packages/my-jetpack/global.d.ts
@@ -39,7 +39,8 @@ type JetpackModule =
| 'security'
| 'protect'
| 'videopress'
- | 'stats';
+ | 'stats'
+ | 'growth';
type ThreatItem = {
// Protect API properties (free plan)
diff --git a/projects/packages/my-jetpack/src/class-products.php b/projects/packages/my-jetpack/src/class-products.php
index dcd3fcc28b3cd..7d17c464804cd 100644
--- a/projects/packages/my-jetpack/src/class-products.php
+++ b/projects/packages/my-jetpack/src/class-products.php
@@ -120,6 +120,7 @@ public static function get_products_classes() {
'videopress' => Products\Videopress::class,
'stats' => Products\Stats::class,
'ai' => Products\Jetpack_Ai::class,
+ 'growth' => Products\Growth::class,
);
/**
diff --git a/projects/packages/my-jetpack/src/products/class-growth.php b/projects/packages/my-jetpack/src/products/class-growth.php
new file mode 100644
index 0000000000000..7478574449aa0
--- /dev/null
+++ b/projects/packages/my-jetpack/src/products/class-growth.php
@@ -0,0 +1,209 @@
+ true,
+ 'wpcom_product_slug' => $product_slug,
+ ),
+ Wpcom_Products::get_product_pricing( $product_slug )
+ );
+ }
+
+ /**
+ * Get the WPCOM product slug used to make the purchase
+ *
+ * @return string
+ */
+ public static function get_wpcom_product_slug() {
+ return 'jetpack_growth_yearly';
+ }
+
+ /**
+ * Checks whether the Jetpack module is active
+ *
+ * This is a bundle and not a product. We should not use this information for anything
+ *
+ * @return bool
+ */
+ public static function is_module_active() {
+ return false;
+ }
+
+ /**
+ * Activates the product by installing and activating its plugin
+ *
+ * @param WP_Error|bool $current_result Is the result of the top level activation actions. You probably won't do anything if it is an WP_Error.
+ * @return bool|\WP_Error
+ */
+ public static function do_product_specific_activation( $current_result ) {
+ $product_activation = parent::do_product_specific_activation( $current_result );
+
+ // A bundle is not a module. There's nothing in the plugin to be activated, so it's ok to fail to activate the module.
+ if ( is_wp_error( $product_activation ) && 'module_activation_failed' === $product_activation->get_error_code() ) {
+ return $product_activation;
+ }
+
+ // At this point, Jetpack plugin is installed. Let's activate each individual product.
+ $activation = Social::activate();
+ if ( is_wp_error( $activation ) ) {
+ return $activation;
+ }
+
+ $activation = Stats::activate();
+ if ( is_wp_error( $activation ) ) {
+ return $activation;
+ }
+
+ return $activation;
+ }
+
+ /**
+ * Checks whether the Product is active
+ *
+ * Growth is a bundle and not a module. Activation takes place on WPCOM. So lets consider it active if jetpack is active and has the plan.
+ *
+ * @return bool
+ */
+ public static function is_active() {
+ return static::is_jetpack_plugin_active() && static::has_required_plan();
+ }
+
+ /**
+ * Checks whether the current plan (or purchase) of the site already supports the product
+ *
+ * @return bool
+ */
+ public static function has_required_plan() {
+ $purchases_data = Wpcom_Products::get_site_current_purchases();
+ if ( is_wp_error( $purchases_data ) ) {
+ return false;
+ }
+ if ( is_array( $purchases_data ) && ! empty( $purchases_data ) ) {
+ foreach ( $purchases_data as $purchase ) {
+ if (
+ str_starts_with( $purchase->product_slug, 'jetpack_growth' ) ||
+ str_starts_with( $purchase->product_slug, 'jetpack_complete' )
+ ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether the product is a bundle
+ *
+ * @return bool
+ */
+ public static function is_bundle_product() {
+ return true;
+ }
+
+ /**
+ * Returns all products it contains.
+ *
+ * @return array Product slugs
+ */
+ public static function get_supported_products() {
+ return array( 'social', 'stats' );
+ }
+
+ /**
+ * Get the URL where the user manages the product
+ *
+ * @return string
+ */
+ public static function get_manage_url() {
+ return '';
+ }
+}
diff --git a/projects/packages/my-jetpack/src/products/class-security.php b/projects/packages/my-jetpack/src/products/class-security.php
index 866899cb81223..7e7005ea9d034 100644
--- a/projects/packages/my-jetpack/src/products/class-security.php
+++ b/projects/packages/my-jetpack/src/products/class-security.php
@@ -69,7 +69,7 @@ public static function get_long_description() {
/**
* Get the internationalized features list
*
- * @return array Boost features list
+ * @return array Security features list
*/
public static function get_features() {
return array(
@@ -81,17 +81,18 @@ public static function get_features() {
}
/**
- * Get the product princing details
+ * Get the product pricing details
*
* @return array Pricing details
*/
public static function get_pricing_for_ui() {
+ $product_slug = static::get_wpcom_product_slug();
return array_merge(
array(
'available' => true,
- 'wpcom_product_slug' => static::get_wpcom_product_slug(),
+ 'wpcom_product_slug' => $product_slug,
),
- Wpcom_Products::get_product_pricing( static::get_wpcom_product_slug() )
+ Wpcom_Products::get_product_pricing( $product_slug )
);
}
@@ -195,7 +196,7 @@ public static function is_bundle_product() {
/**
* Return all the products it contains.
*
- * @return Array Product slugs
+ * @return array Product slugs
*/
public static function get_supported_products() {
return array( 'backup', 'scan', 'anti-spam' );
diff --git a/projects/packages/my-jetpack/src/products/class-social.php b/projects/packages/my-jetpack/src/products/class-social.php
index 317eeaf303a01..ae1d3ee6f76c0 100644
--- a/projects/packages/my-jetpack/src/products/class-social.php
+++ b/projects/packages/my-jetpack/src/products/class-social.php
@@ -197,4 +197,14 @@ public static function get_manage_url() {
return admin_url( 'admin.php?page=jetpack#/settings?term=publicize' );
}
+
+ /**
+ * Return product bundles list
+ * that supports the product.
+ *
+ * @return boolean|array Products bundle list.
+ */
+ public static function is_upgradable_by_bundle() {
+ return array( 'growth' );
+ }
}
diff --git a/projects/packages/my-jetpack/src/products/class-stats.php b/projects/packages/my-jetpack/src/products/class-stats.php
index fa9aaf61f5561..c361bd6737f39 100644
--- a/projects/packages/my-jetpack/src/products/class-stats.php
+++ b/projects/packages/my-jetpack/src/products/class-stats.php
@@ -314,4 +314,14 @@ public static function get_purchase_url() {
public static function get_manage_url() {
return admin_url( 'admin.php?page=stats' );
}
+
+ /**
+ * Return product bundles list
+ * that supports the product.
+ *
+ * @return boolean|array Products bundle list.
+ */
+ public static function is_upgradable_by_bundle() {
+ return array( 'growth' );
+ }
}
From d438fb8556858eff768b2a10a7394bcc3c8b1e67 Mon Sep 17 00:00:00 2001
From: Calypso Bot
Date: Tue, 19 Nov 2024 21:39:53 +0100
Subject: [PATCH 2/2] Update dependency automattic/custom-fonts to v3.0.6
(#40261)
Co-authored-by: Renovate Bot
---
.../renovate-automattic-custom-fonts-3.x-lockfile | 4 ++++
projects/plugins/wpcomsh/composer.lock | 10 +++++-----
2 files changed, 9 insertions(+), 5 deletions(-)
create mode 100644 projects/plugins/wpcomsh/changelog/renovate-automattic-custom-fonts-3.x-lockfile
diff --git a/projects/plugins/wpcomsh/changelog/renovate-automattic-custom-fonts-3.x-lockfile b/projects/plugins/wpcomsh/changelog/renovate-automattic-custom-fonts-3.x-lockfile
new file mode 100644
index 0000000000000..c47cb18e82997
--- /dev/null
+++ b/projects/plugins/wpcomsh/changelog/renovate-automattic-custom-fonts-3.x-lockfile
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+
+Updated package dependencies.
diff --git a/projects/plugins/wpcomsh/composer.lock b/projects/plugins/wpcomsh/composer.lock
index 901e1573a5401..0803e22af3189 100644
--- a/projects/plugins/wpcomsh/composer.lock
+++ b/projects/plugins/wpcomsh/composer.lock
@@ -28,16 +28,16 @@
},
{
"name": "automattic/custom-fonts",
- "version": "v3.0.5",
+ "version": "v3.0.6",
"source": {
"type": "git",
"url": "https://github.com/Automattic/custom-fonts.git",
- "reference": "e9236c34a6ecbee3bb9d2bebe698f086dd339258"
+ "reference": "63d0a9251a252b74ab0862ac00f4d4d4c1d6b320"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Automattic/custom-fonts/zipball/e9236c34a6ecbee3bb9d2bebe698f086dd339258",
- "reference": "e9236c34a6ecbee3bb9d2bebe698f086dd339258",
+ "url": "https://api.github.com/repos/Automattic/custom-fonts/zipball/63d0a9251a252b74ab0862ac00f4d4d4c1d6b320",
+ "reference": "63d0a9251a252b74ab0862ac00f4d4d4c1d6b320",
"shasum": ""
},
"require-dev": {
@@ -49,7 +49,7 @@
"GPL-2.0-or-later"
],
"description": "A provider-agnostic WordPress plugin for changing theme fonts.",
- "time": "2024-06-26T18:47:13+00:00"
+ "time": "2024-11-19T20:05:23+00:00"
},
{
"name": "automattic/custom-fonts-typekit",