From f87eb599ba643b940001d09c5f3313cabccf80cf Mon Sep 17 00:00:00 2001
From: Jason Moon
Date: Tue, 24 Mar 2020 17:24:48 -0600
Subject: [PATCH 1/6] Add handling for pricing and tier APIs
---
.../data/query-site-products/index.js | 20 ++++++
_inc/client/lib/plans/constants.js | 8 +++
_inc/client/plans/index.jsx | 2 +
_inc/client/plans/product-selector.jsx | 11 +++-
.../plans/single-product-search/index.jsx | 59 +++++++++++++----
_inc/client/rest-api/index.js | 7 +-
_inc/client/state/action-types.js | 4 ++
_inc/client/state/reducer.js | 2 +
_inc/client/state/site-products/actions.js | 31 +++++++++
_inc/client/state/site-products/index.js | 2 +
_inc/client/state/site-products/reducer.js | 58 +++++++++++++++++
_inc/lib/class.core-rest-api-endpoints.php | 10 +++
.../class.jetpack-core-api-site-endpoints.php | 65 ++++++++++++-------
13 files changed, 241 insertions(+), 38 deletions(-)
create mode 100644 _inc/client/components/data/query-site-products/index.js
create mode 100644 _inc/client/state/site-products/actions.js
create mode 100644 _inc/client/state/site-products/index.js
create mode 100644 _inc/client/state/site-products/reducer.js
diff --git a/_inc/client/components/data/query-site-products/index.js b/_inc/client/components/data/query-site-products/index.js
new file mode 100644
index 0000000000000..bc13c6bdb92a6
--- /dev/null
+++ b/_inc/client/components/data/query-site-products/index.js
@@ -0,0 +1,20 @@
+/**
+ * External dependencies
+ */
+import { useEffect } from 'react';
+import { connect } from 'react-redux';
+
+/**
+ * Internal dependencies
+ */
+import { fetchSiteProducts, isFetchingSiteProducts } from 'state/site-products';
+
+export function QuerySiteProducts( props ) {
+ useEffect( () => ! props.isFetchingSiteProducts && props.fetchSiteProducts(), [] );
+ return null;
+}
+
+export default connect(
+ state => ( { isFetchingSiteProducts: isFetchingSiteProducts( state ) } ),
+ dispatch => ( { fetchSiteProducts: () => dispatch( fetchSiteProducts() ) } )
+)( QuerySiteProducts );
diff --git a/_inc/client/lib/plans/constants.js b/_inc/client/lib/plans/constants.js
index 71043ddd9011b..f4a1ea6dfc0de 100644
--- a/_inc/client/lib/plans/constants.js
+++ b/_inc/client/lib/plans/constants.js
@@ -116,6 +116,14 @@ export const FEATURE_WORDADS_JETPACK = 'wordads-jetpack';
export const FEATURE_GOOGLE_ANALYTICS_JETPACK = 'google-analytics-jetpack';
export const FEATURE_SEARCH_JETPACK = 'search-jetpack';
+// Jetpack Search Tiers
+export const JETPACK_SEARCH_TIER_UP_TO_100_RECORDS = 'up_to_100_records';
+export const JETPACK_SEARCH_TIER_UP_TO_1K_RECORDS = 'up_to_1k_records';
+export const JETPACK_SEARCH_TIER_UP_TO_10K_RECORDS = 'up_to_10k_records';
+export const JETPACK_SEARCH_TIER_UP_TO_100K_RECORDS = 'up_to_100k_records';
+export const JETPACK_SEARCH_TIER_UP_TO_1M_RECORDS = 'up_to_1m_records';
+export const JETPACK_SEARCH_TIER_MORE_THAN_1M_RECORDS = 'more_than_1m_records';
+
export function isMonthly( plan ) {
return includes( JETPACK_MONTHLY_PLANS, plan );
}
diff --git a/_inc/client/plans/index.jsx b/_inc/client/plans/index.jsx
index 55e38ee694e6b..d413f91295718 100644
--- a/_inc/client/plans/index.jsx
+++ b/_inc/client/plans/index.jsx
@@ -7,6 +7,7 @@ import React, { Fragment } from 'react';
* Internal dependencies
*/
import QueryProducts from 'components/data/query-products';
+import QuerySiteProducts from 'components/data/query-site-products';
import QuerySite from 'components/data/query-site';
import PlanGrid from './plan-grid';
import ProductSelector from './product-selector';
@@ -16,6 +17,7 @@ export class Plans extends React.Component {
return (
+
diff --git a/_inc/client/plans/product-selector.jsx b/_inc/client/plans/product-selector.jsx
index f71b72baaafaa..af5689809de87 100644
--- a/_inc/client/plans/product-selector.jsx
+++ b/_inc/client/plans/product-selector.jsx
@@ -26,6 +26,7 @@ import {
import { getSiteRawUrl, getUpgradeUrl, isMultisite } from '../state/initial-state';
import { getProducts, isFetchingProducts } from '../state/products';
import './single-products.scss';
+import { isFetchingSiteProducts, getSiteProducts } from '../state/site-products';
class ProductSelector extends Component {
state = {
@@ -232,8 +233,9 @@ class ProductSelector extends Component {
renderSearchProduct() {
return (
);
@@ -250,6 +252,8 @@ class ProductSelector extends Component {
}
export default connect( state => {
+ const isFetchingData =
+ isFetchingSiteData( state ) || isFetchingProducts( state ) || ! getAvailablePlans( state );
return {
activeSitePurchases: getActiveSitePurchases( state ),
dailyBackupUpgradeUrl: getUpgradeUrl( state, 'jetpack-backup-daily' ),
@@ -258,9 +262,10 @@ export default connect( state => {
realtimeBackupUpgradeUrl: getUpgradeUrl( state, 'jetpack-backup-realtime' ),
searchUpgradeUrl: getUpgradeUrl( state, 'jetpack-search' ),
sitePlan: getSitePlan( state ),
+ siteProducts: getSiteProducts( state ),
siteRawlUrl: getSiteRawUrl( state ),
- isFetchingData:
- isFetchingSiteData( state ) || isFetchingProducts( state ) || ! getAvailablePlans( state ),
+ isFetchingData,
+ isFetchingDataForSearch: isFetchingData || isFetchingSiteProducts( state ),
backupInfoUrl: getUpgradeUrl( state, 'aag-backups' ), // Redirect to https://jetpack.com/upgrade/backup/
isInstantSearchEnabled: !! get( state, 'jetpack.initialState.isInstantSearchEnabled', false ),
};
diff --git a/_inc/client/plans/single-product-search/index.jsx b/_inc/client/plans/single-product-search/index.jsx
index ef809bf1deeb6..fb14c54b1df40 100644
--- a/_inc/client/plans/single-product-search/index.jsx
+++ b/_inc/client/plans/single-product-search/index.jsx
@@ -2,7 +2,7 @@
* External dependencies
*/
import React from 'react';
-import { translate as __ } from 'i18n-calypso';
+import { translate as __, numberFormat } from 'i18n-calypso';
import { get, noop } from 'lodash';
/**
@@ -10,13 +10,45 @@ import { get, noop } from 'lodash';
*/
import Button from 'components/button';
import PlanRadioButton from '../single-product-components/plan-radio-button';
+import {
+ JETPACK_SEARCH_TIER_UP_TO_100_RECORDS,
+ JETPACK_SEARCH_TIER_UP_TO_1K_RECORDS,
+ JETPACK_SEARCH_TIER_UP_TO_10K_RECORDS,
+ JETPACK_SEARCH_TIER_UP_TO_100K_RECORDS,
+ JETPACK_SEARCH_TIER_UP_TO_1M_RECORDS,
+ JETPACK_SEARCH_TIER_MORE_THAN_1M_RECORDS,
+} from '../../lib/plans/constants';
-const PLACEHOLDER_RECORD_COUNT = 53;
-const PLACEHOLDER_PRICE = 50;
-const PLACEHOLDER_LABEL = 'Tier 1: Up to 100 records';
+function getTierLabel( priceTierSlug, recordCount ) {
+ switch ( priceTierSlug ) {
+ case JETPACK_SEARCH_TIER_UP_TO_100_RECORDS:
+ return __( 'Tier 1: Up to 100 records' );
+ case JETPACK_SEARCH_TIER_UP_TO_1K_RECORDS:
+ return __( 'Tier 2: Up to 1,000 records' );
+ case JETPACK_SEARCH_TIER_UP_TO_10K_RECORDS:
+ return __( 'Tier 3: Up to 10,000 records' );
+ case JETPACK_SEARCH_TIER_UP_TO_100K_RECORDS:
+ return __( 'Tier 4: Up to 100,000 records' );
+ case JETPACK_SEARCH_TIER_UP_TO_1M_RECORDS:
+ return __( 'Tier 5: Up to 1,000,000 records' );
+ case JETPACK_SEARCH_TIER_MORE_THAN_1M_RECORDS:
+ // NOTE: 5 === number of defined tiers
+ const tierNumber = 5 + Math.floor( recordCount / 1000000 );
+ const tierMaximumRecords = 1000000 * Math.ceil( recordCount / 1000000 );
+ return __( 'Tier %(tierNumber)d: Up to %(tierMaximumRecords)s records', {
+ args: { tierNumber, tierMaximumRecords: numberFormat( tierMaximumRecords ) },
+ } );
+ default:
+ return null;
+ }
+}
+
+const BILLING_TIMEFRAME = 'yearly';
export default function SingleProductSearchCard( props ) {
- const currencyCode = get( props.products, 'jetpack_backup_daily.currency_code', '' );
+ const currencyCode = get( props.products, 'jetpack_search.currency_code', '' );
+ const yearlyPrice = get( props.products, 'jetpack_search.cost', '' );
+ const recordCount = get( props.siteProducts, 'jetpack_search.price_tier_usage_quantity', '0' );
return props.isFetching ? (
@@ -37,20 +69,23 @@ export default function SingleProductSearchCard( props ) {
{ __(
- 'Your current site record size: %d record',
- 'Your current site record size: %d records',
- { args: PLACEHOLDER_RECORD_COUNT, count: PLACEHOLDER_RECORD_COUNT }
+ 'Your current site record size: %s record',
+ 'Your current site record size: %s records',
+ { args: recordCount, count: recordCount }
) }
diff --git a/_inc/client/rest-api/index.js b/_inc/client/rest-api/index.js
index 0b12ab9b8cb05..4b3125f369bf4 100644
--- a/_inc/client/rest-api/index.js
+++ b/_inc/client/rest-api/index.js
@@ -31,7 +31,7 @@ function JetpackRestApiClient( root, nonce ) {
},
getParams = {
credentials: 'same-origin',
- headers: headers,
+ headers,
},
postParams = {
method: 'post',
@@ -219,6 +219,11 @@ function JetpackRestApiClient( root, nonce ) {
.then( parseJsonResponse )
.then( body => JSON.parse( body.data ) ),
+ fetchSiteProducts: () =>
+ getRequest( `${ apiRoot }jetpack/v4/site/products`, getParams )
+ .then( checkStatus )
+ .then( parseJsonResponse ),
+
fetchSitePurchases: () =>
getRequest( `${ apiRoot }jetpack/v4/site/purchases`, getParams )
.then( checkStatus )
diff --git a/_inc/client/state/action-types.js b/_inc/client/state/action-types.js
index 307a8d0f3e1a6..46e7ebb712870 100644
--- a/_inc/client/state/action-types.js
+++ b/_inc/client/state/action-types.js
@@ -76,6 +76,10 @@ export const JETPACK_PRODUCTS_FETCH = 'JETPACK_PRODUCTS_FETCH';
export const JETPACK_PRODUCTS_FETCH_RECEIVE = 'JETPACK_PRODUCTS_FETCH_RECEIVE';
export const JETPACK_PRODUCTS_FETCH_FAIL = 'JETPACK_PRODUCTS_FETCH_FAIL';
+export const JETPACK_SITE_PRODUCTS_FETCH = 'JETPACK_SITE_PRODUCTS_FETCH';
+export const JETPACK_SITE_PRODUCTS_FETCH_FAIL = 'JETPACK_SITE_PRODUCTS_FETCH_FAIL';
+export const JETPACK_SITE_PRODUCTS_FETCH_RECEIVE = 'JETPACK_SITE_PRODUCTS_FETCH_RECEIVE';
+
export const JETPACK_SETTINGS_FETCH = 'JETPACK_SETTINGS_FETCH';
export const JETPACK_SETTINGS_FETCH_RECEIVE = 'JETPACK_SETTINGS_FETCH_RECEIVE';
export const JETPACK_SETTINGS_FETCH_FAIL = 'JETPACK_SETTINGS_FETCH_FAIL';
diff --git a/_inc/client/state/reducer.js b/_inc/client/state/reducer.js
index 1005746b1e3a4..35c0efdfc00a4 100644
--- a/_inc/client/state/reducer.js
+++ b/_inc/client/state/reducer.js
@@ -22,6 +22,7 @@ import { reducer as rewind } from 'state/rewind/reducer';
import { reducer as search } from 'state/search/reducer';
import { reducer as settings } from 'state/settings/reducer';
import { reducer as siteData } from 'state/site/reducer';
+import { reducer as siteProducts } from 'state/site-products/reducer';
import { reducer as siteVerify } from 'state/site-verify/reducer';
import { reducer as disconnectSurvey } from 'state/disconnect-survey/reducer';
import { reducer as trackingSettings } from 'state/tracking/reducer';
@@ -42,6 +43,7 @@ const jetpackReducer = combineReducers( {
search,
settings,
siteData,
+ siteProducts,
siteVerify,
disconnectSurvey,
trackingSettings,
diff --git a/_inc/client/state/site-products/actions.js b/_inc/client/state/site-products/actions.js
new file mode 100644
index 0000000000000..6880673c373bb
--- /dev/null
+++ b/_inc/client/state/site-products/actions.js
@@ -0,0 +1,31 @@
+/**
+ * Internal dependencies
+ */
+import {
+ JETPACK_SITE_PRODUCTS_FETCH,
+ JETPACK_SITE_PRODUCTS_FETCH_FAIL,
+ JETPACK_SITE_PRODUCTS_FETCH_RECEIVE,
+} from 'state/action-types';
+import restApi from 'rest-api';
+
+export const fetchSiteProducts = () => {
+ return dispatch => {
+ dispatch( {
+ type: JETPACK_SITE_PRODUCTS_FETCH,
+ } );
+ return restApi
+ .fetchSiteProducts()
+ .then( response => {
+ dispatch( {
+ type: JETPACK_SITE_PRODUCTS_FETCH_RECEIVE,
+ siteProducts: response.data,
+ } );
+ } )
+ .catch( error => {
+ dispatch( {
+ type: JETPACK_SITE_PRODUCTS_FETCH_FAIL,
+ error,
+ } );
+ } );
+ };
+};
diff --git a/_inc/client/state/site-products/index.js b/_inc/client/state/site-products/index.js
new file mode 100644
index 0000000000000..5e3164b4c9f72
--- /dev/null
+++ b/_inc/client/state/site-products/index.js
@@ -0,0 +1,2 @@
+export * from './reducer';
+export * from './actions';
diff --git a/_inc/client/state/site-products/reducer.js b/_inc/client/state/site-products/reducer.js
new file mode 100644
index 0000000000000..174be6cfb7f2a
--- /dev/null
+++ b/_inc/client/state/site-products/reducer.js
@@ -0,0 +1,58 @@
+/**
+ * External dependencies
+ */
+import { combineReducers } from 'redux';
+
+/**
+ * Internal dependencies
+ */
+import {
+ JETPACK_SITE_PRODUCTS_FETCH,
+ JETPACK_SITE_PRODUCTS_FETCH_FAIL,
+ JETPACK_SITE_PRODUCTS_FETCH_RECEIVE,
+} from 'state/action-types';
+
+export const items = ( state = {}, action ) => {
+ switch ( action.type ) {
+ case JETPACK_SITE_PRODUCTS_FETCH_RECEIVE:
+ return action.siteProducts;
+ default:
+ return state;
+ }
+};
+
+export const requests = ( state = {}, action ) => {
+ switch ( action.type ) {
+ case JETPACK_SITE_PRODUCTS_FETCH:
+ return { ...state, isFetching: true };
+ case JETPACK_SITE_PRODUCTS_FETCH_RECEIVE:
+ case JETPACK_SITE_PRODUCTS_FETCH_FAIL:
+ return { ...state, isFetching: false };
+ default:
+ return state;
+ }
+};
+
+export const reducer = combineReducers( {
+ items,
+ requests,
+} );
+
+/**
+ * Returns true if currently requesting site products. Otherwise false.
+ *
+ * @param {Object} state Global state tree
+ * @return {Boolean} Whether site products are being requested
+ */
+export function isFetchingSiteProducts( state ) {
+ return !! state.jetpack.siteProducts.requests.isFetching;
+}
+
+/**
+ * Returns WP.com site products that are relevant to Jetpack.
+ * @param {Object} state Global state tree
+ * @return {Object} Site products
+ */
+export function getSiteProducts( state ) {
+ return state.jetpack.siteProducts.items;
+}
diff --git a/_inc/lib/class.core-rest-api-endpoints.php b/_inc/lib/class.core-rest-api-endpoints.php
index 2d655695727a9..62323dfa90597 100644
--- a/_inc/lib/class.core-rest-api-endpoints.php
+++ b/_inc/lib/class.core-rest-api-endpoints.php
@@ -212,6 +212,16 @@ public static function register_endpoints() {
'permission_callback' => array( $site_endpoint , 'can_request' ),
) );
+ register_rest_route(
+ 'jetpack/v4',
+ '/site/products',
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $site_endpoint, 'get_products' ),
+ 'permission_callback' => array( $site_endpoint, 'can_request' ),
+ )
+ );
+
// Get current site purchases.
register_rest_route(
'jetpack/v4',
diff --git a/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php b/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php
index c321f6ae37594..365692102d86e 100644
--- a/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php
+++ b/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php
@@ -11,7 +11,18 @@
* This is the endpoint class for `/site` endpoints.
*/
class Jetpack_Core_API_Site_Endpoint {
-
+ /**
+ * Returns commonly used WP_Error indicating failure to fetch data
+ *
+ * @return WP_Error that denotes our inability to fetch the requested data
+ */
+ private static function get_failed_fetch_error() {
+ return new WP_Error(
+ 'failed_to_fetch_data',
+ esc_html__( 'Unable to fetch the requested data.', 'jetpack' ),
+ array( 'status' => 500 )
+ );
+ }
/**
* Returns the result of `/sites/%s/features` endpoint call.
@@ -22,18 +33,13 @@ class Jetpack_Core_API_Site_Endpoint {
* of plan slugs that enable these features
*/
public static function get_features() {
-
// Make the API request.
$request = sprintf( '/sites/%d/features', Jetpack_Options::get_option( 'id' ) );
$response = Client::wpcom_json_api_request_as_blog( $request, '1.1' );
// Bail if there was an error or malformed response.
if ( is_wp_error( $response ) || ! is_array( $response ) || ! isset( $response['body'] ) ) {
- return new WP_Error(
- 'failed_to_fetch_data',
- esc_html__( 'Unable to fetch the requested data.', 'jetpack' ),
- array( 'status' => 500 )
- );
+ return self::get_failed_fetch_error();
}
// Decode the results.
@@ -41,11 +47,7 @@ public static function get_features() {
// Bail if there were no results or plan details returned.
if ( ! is_array( $results ) ) {
- return new WP_Error(
- 'failed_to_fetch_data',
- esc_html__( 'Unable to fetch the requested data.', 'jetpack' ),
- array( 'status' => 500 )
- );
+ return self::get_failed_fetch_error();
}
return rest_ensure_response(
@@ -70,11 +72,7 @@ public static function get_purchases() {
// Bail if there was an error or malformed response.
if ( is_wp_error( $response ) || ! is_array( $response ) || ! isset( $response['body'] ) ) {
- return new WP_Error(
- 'failed_to_fetch_data',
- esc_html__( 'Unable to fetch the requested data.', 'jetpack' ),
- array( 'status' => 500 )
- );
+ return self::get_failed_fetch_error();
}
// Decode the results.
@@ -82,11 +80,7 @@ public static function get_purchases() {
// Bail if there were no results or purchase details returned.
if ( ! is_array( $results ) ) {
- return new WP_Error(
- 'failed_to_fetch_data',
- esc_html__( 'Unable to fetch the requested data.', 'jetpack' ),
- array( 'status' => 500 )
- );
+ return self::get_failed_fetch_error();
}
return rest_ensure_response(
@@ -98,6 +92,33 @@ public static function get_purchases() {
);
}
+ /**
+ * Returns the result of `/sites/%d/products` endpoint call.
+ *
+ * @return array of site products.
+ */
+ public static function get_products() {
+ $url = sprintf( '/sites/%d/products?locale=%s&type=jetpack', Jetpack_Options::get_option( 'id' ), get_user_locale() );
+ $response = Client::wpcom_json_api_request_as_blog( $url, '1.1' );
+
+ if ( is_wp_error( $response ) || ! is_array( $response ) || ! isset( $response['body'] ) ) {
+ return self::get_failed_fetch_error();
+ }
+
+ $results = json_decode( wp_remote_retrieve_body( $response ), true );
+ if ( ! is_array( $results ) ) {
+ return self::get_failed_fetch_error();
+ }
+
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => esc_html__( 'Site products correctly received.', 'jetpack' ),
+ 'data' => $results,
+ )
+ );
+ }
+
/**
* Check that the current user has permissions to request information about this site.
*
From 33e1b3b11ecdabd4c1a64850748c009e76b64779 Mon Sep 17 00:00:00 2001
From: Jason Moon
Date: Wed, 25 Mar 2020 17:34:29 -0600
Subject: [PATCH 2/6] Remove tier numbers
---
.../client/plans/single-product-search/index.jsx | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/_inc/client/plans/single-product-search/index.jsx b/_inc/client/plans/single-product-search/index.jsx
index fb14c54b1df40..c59735123cba9 100644
--- a/_inc/client/plans/single-product-search/index.jsx
+++ b/_inc/client/plans/single-product-search/index.jsx
@@ -22,21 +22,19 @@ import {
function getTierLabel( priceTierSlug, recordCount ) {
switch ( priceTierSlug ) {
case JETPACK_SEARCH_TIER_UP_TO_100_RECORDS:
- return __( 'Tier 1: Up to 100 records' );
+ return __( 'Tier: Up to 100 records' );
case JETPACK_SEARCH_TIER_UP_TO_1K_RECORDS:
- return __( 'Tier 2: Up to 1,000 records' );
+ return __( 'Tier: Up to 1,000 records' );
case JETPACK_SEARCH_TIER_UP_TO_10K_RECORDS:
- return __( 'Tier 3: Up to 10,000 records' );
+ return __( 'Tier: Up to 10,000 records' );
case JETPACK_SEARCH_TIER_UP_TO_100K_RECORDS:
- return __( 'Tier 4: Up to 100,000 records' );
+ return __( 'Tier: Up to 100,000 records' );
case JETPACK_SEARCH_TIER_UP_TO_1M_RECORDS:
- return __( 'Tier 5: Up to 1,000,000 records' );
+ return __( 'Tier: Up to 1,000,000 records' );
case JETPACK_SEARCH_TIER_MORE_THAN_1M_RECORDS:
- // NOTE: 5 === number of defined tiers
- const tierNumber = 5 + Math.floor( recordCount / 1000000 );
const tierMaximumRecords = 1000000 * Math.ceil( recordCount / 1000000 );
- return __( 'Tier %(tierNumber)d: Up to %(tierMaximumRecords)s records', {
- args: { tierNumber, tierMaximumRecords: numberFormat( tierMaximumRecords ) },
+ return __( 'Tier: Up to %(tierMaximumRecords)s records', {
+ args: { tierMaximumRecords: numberFormat( tierMaximumRecords ) },
} );
default:
return null;
From 78ec1b883fc89b4241e01afd5419e239a0748f0a Mon Sep 17 00:00:00 2001
From: Jason Moon
Date: Wed, 25 Mar 2020 17:51:06 -0600
Subject: [PATCH 3/6] Add monthly and yearly pricing into search plan
---
_inc/client/plans/product-selector.jsx | 2 -
.../plans/single-product-search/index.jsx | 52 ++++++++++++++-----
2 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/_inc/client/plans/product-selector.jsx b/_inc/client/plans/product-selector.jsx
index af5689809de87..07a1fded0c60c 100644
--- a/_inc/client/plans/product-selector.jsx
+++ b/_inc/client/plans/product-selector.jsx
@@ -236,7 +236,6 @@ class ProductSelector extends Component {
isFetching={ this.props.isFetchingDataForSearch }
products={ this.props.products }
siteProducts={ this.props.siteProducts }
- searchUpgradeUrl={ this.props.searchUpgradeUrl }
/>
);
}
@@ -260,7 +259,6 @@ export default connect( state => {
multisite: isMultisite( state ),
products: getProducts( state ),
realtimeBackupUpgradeUrl: getUpgradeUrl( state, 'jetpack-backup-realtime' ),
- searchUpgradeUrl: getUpgradeUrl( state, 'jetpack-search' ),
sitePlan: getSitePlan( state ),
siteProducts: getSiteProducts( state ),
siteRawlUrl: getSiteRawUrl( state ),
diff --git a/_inc/client/plans/single-product-search/index.jsx b/_inc/client/plans/single-product-search/index.jsx
index c59735123cba9..966cf4618dde8 100644
--- a/_inc/client/plans/single-product-search/index.jsx
+++ b/_inc/client/plans/single-product-search/index.jsx
@@ -1,9 +1,10 @@
/**
* External dependencies
*/
-import React from 'react';
+import React, { useState } from 'react';
+import { connect } from 'react-redux';
import { translate as __, numberFormat } from 'i18n-calypso';
-import { get, noop } from 'lodash';
+import { get } from 'lodash';
/**
* Internal dependencies
@@ -18,6 +19,7 @@ import {
JETPACK_SEARCH_TIER_UP_TO_1M_RECORDS,
JETPACK_SEARCH_TIER_MORE_THAN_1M_RECORDS,
} from '../../lib/plans/constants';
+import { getUpgradeUrl } from '../../state/initial-state';
function getTierLabel( priceTierSlug, recordCount ) {
switch ( priceTierSlug ) {
@@ -41,10 +43,15 @@ function getTierLabel( priceTierSlug, recordCount ) {
}
}
-const BILLING_TIMEFRAME = 'yearly';
+function handleSelectedTimeframeChangeFactory( setTimeframe ) {
+ return event => setTimeframe( event.target.value );
+}
-export default function SingleProductSearchCard( props ) {
+export function SingleProductSearchCard( props ) {
+ const [ timeframe, setTimeframe ] = useState( 'yearly' );
+ const handleSelectedTimeframeChange = handleSelectedTimeframeChangeFactory( setTimeframe );
const currencyCode = get( props.products, 'jetpack_search.currency_code', '' );
+ const monthlyPrice = get( props.products, 'jetpack_search_monthly.cost', '' );
const yearlyPrice = get( props.products, 'jetpack_search.cost', '' );
const recordCount = get( props.siteProducts, 'jetpack_search.price_tier_usage_quantity', '0' );
@@ -71,23 +78,37 @@ export default function SingleProductSearchCard( props ) {
'Your current site record size: %s records',
{ args: recordCount, count: recordCount }
) }
+
+ { getTierLabel(
+ get( props.siteProducts, 'jetpack_search.price_tier_slug' ),
+ recordCount
+ ) }