diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1ded6421edce1..f6111e92e8f78 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1886,9 +1886,6 @@ importers:
'@wordpress/browserslist-config':
specifier: 6.7.0
version: 6.7.0
- core-js:
- specifier: 3.23.5
- version: 3.23.5
sass:
specifier: 1.64.1
version: 1.64.1
@@ -1927,9 +1924,6 @@ importers:
autoprefixer:
specifier: 10.4.14
version: 10.4.14(postcss@8.4.31)
- core-js:
- specifier: 3.23.5
- version: 3.23.5
glob:
specifier: 10.4.1
version: 10.4.1
@@ -2418,9 +2412,6 @@ importers:
autoprefixer:
specifier: 10.4.14
version: 10.4.14(postcss@8.4.31)
- core-js:
- specifier: 3.23.5
- version: 3.23.5
glob:
specifier: 10.4.1
version: 10.4.1
@@ -2785,8 +2776,8 @@ importers:
specifier: 7.6.0
version: 7.6.0
core-js:
- specifier: 3.23.5
- version: 3.23.5
+ specifier: 3.38.1
+ version: 3.38.1
jest:
specifier: 29.7.0
version: 29.7.0
@@ -3136,8 +3127,8 @@ importers:
specifier: 7.6.0
version: 7.6.0
core-js:
- specifier: 3.23.5
- version: 3.23.5
+ specifier: 3.38.1
+ version: 3.38.1
jest:
specifier: 29.7.0
version: 29.7.0
@@ -8943,9 +8934,6 @@ packages:
core-js-compat@3.38.1:
resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==}
- core-js@3.23.5:
- resolution: {integrity: sha512-7Vh11tujtAZy82da4duVreQysIoO2EvVrur7y6IzZkH1IHPSekuDi8Vuw1+YKjkbfWLRD7Nc9ICQ/sIUDutcyg==}
-
core-js@3.38.1:
resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==}
@@ -20834,8 +20822,6 @@ snapshots:
dependencies:
browserslist: 4.23.3
- core-js@3.23.5: {}
-
core-js@3.38.1: {}
cosmiconfig@7.1.0:
diff --git a/projects/js-packages/publicize-components/CHANGELOG.md b/projects/js-packages/publicize-components/CHANGELOG.md
index 3e2d193641976..00120d2df4155 100644
--- a/projects/js-packages/publicize-components/CHANGELOG.md
+++ b/projects/js-packages/publicize-components/CHANGELOG.md
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.71.0] - 2024-10-01
+### Added
+- Social: Added support for Bluesky [#39561]
+
## [0.70.1] - 2024-09-30
### Changed
- Update dependencies. [#39528]
@@ -948,6 +952,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Updated package dependencies. [#24470]
+[0.71.0]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.70.1...v0.71.0
[0.70.1]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.70.0...v0.70.1
[0.70.0]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.69.0...v0.70.0
[0.69.0]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.68.0...v0.69.0
diff --git a/projects/js-packages/publicize-components/changelog/add-bluesky-connection-ui b/projects/js-packages/publicize-components/changelog/add-bluesky-connection-ui
deleted file mode 100644
index f7abf12df99fb..0000000000000
--- a/projects/js-packages/publicize-components/changelog/add-bluesky-connection-ui
+++ /dev/null
@@ -1,4 +0,0 @@
-Significance: minor
-Type: added
-
-Social: Added support for Bluesky
diff --git a/projects/js-packages/publicize-components/package.json b/projects/js-packages/publicize-components/package.json
index 6aa9870bf19dc..a429123a8324c 100644
--- a/projects/js-packages/publicize-components/package.json
+++ b/projects/js-packages/publicize-components/package.json
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@automattic/jetpack-publicize-components",
- "version": "0.70.1",
+ "version": "0.71.0",
"description": "A library of JS components required by the Publicize editor plugin",
"homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/publicize-components/#readme",
"bugs": {
diff --git a/projects/packages/blaze/changelog/update-blaze-post-not-ready-behavior b/projects/packages/blaze/changelog/update-blaze-post-not-ready-behavior
new file mode 100644
index 0000000000000..2be9dad32f1db
--- /dev/null
+++ b/projects/packages/blaze/changelog/update-blaze-post-not-ready-behavior
@@ -0,0 +1,4 @@
+Significance: minor
+Type: changed
+
+Changes the error Blaze shows during sync to be a warning
diff --git a/projects/packages/blaze/src/class-dashboard-rest-controller.php b/projects/packages/blaze/src/class-dashboard-rest-controller.php
index 826b13a6d6dbd..de30672bf3e98 100644
--- a/projects/packages/blaze/src/class-dashboard-rest-controller.php
+++ b/projects/packages/blaze/src/class-dashboard-rest-controller.php
@@ -329,10 +329,6 @@ public function get_blaze_posts( $req ) {
return array();
}
- if ( ! $this->are_posts_ready() ) {
- return new WP_Error( 'posts_not_ready', 'Posts are not synced yet.' );
- }
-
// We don't use sub_path in the blaze posts, only query strings
if ( isset( $req['sub_path'] ) ) {
unset( $req['sub_path'] );
@@ -353,6 +349,24 @@ public function get_blaze_posts( $req ) {
$response['posts'] = $this->add_prices_in_posts( $response['posts'] );
}
+ $response = $this->add_warnings_to_posts_response( $response );
+
+ return $response;
+ }
+
+ /**
+ * Adds warning flags to the posts response.
+ *
+ * @param array $response The response object.
+ * @return array
+ */
+ private function add_warnings_to_posts_response( $response ) {
+ if ( ! $this->are_posts_ready() && is_array( $response ) ) {
+ $response['warnings'] = array_merge(
+ array( 'sync_in_progress' ),
+ $response['warnings'] ?? array()
+ );
+ }
return $response;
}
@@ -392,10 +406,6 @@ public function get_dsp_blaze_posts( $req ) {
return array();
}
- if ( ! $this->are_posts_ready() ) {
- return new WP_Error( 'posts_not_ready', 'Posts are not synced yet.' );
- }
-
// We don't use sub_path in the blaze posts, only query strings
if ( isset( $req['sub_path'] ) ) {
unset( $req['sub_path'] );
@@ -412,6 +422,8 @@ public function get_dsp_blaze_posts( $req ) {
$response['results'] = $this->add_prices_in_posts( $response['results'] );
}
+ $response = $this->add_warnings_to_posts_response( $response );
+
return $response;
}
diff --git a/projects/packages/calypsoify/changelog/renovate-core-js-3.x b/projects/packages/calypsoify/changelog/renovate-core-js-3.x
new file mode 100644
index 0000000000000..390dbc579d13c
--- /dev/null
+++ b/projects/packages/calypsoify/changelog/renovate-core-js-3.x
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+Comment: Remove unneeded `core-js` JS dep.
+
diff --git a/projects/packages/calypsoify/package.json b/projects/packages/calypsoify/package.json
index 78380b303665c..d83beee2bf25d 100644
--- a/projects/packages/calypsoify/package.json
+++ b/projects/packages/calypsoify/package.json
@@ -29,7 +29,6 @@
"devDependencies": {
"@automattic/jetpack-webpack-config": "workspace:*",
"@wordpress/browserslist-config": "6.7.0",
- "core-js": "3.23.5",
"sass": "1.64.1",
"sass-loader": "12.4.0",
"webpack": "5.94.0",
diff --git a/projects/packages/classic-theme-helper/changelog/renovate-core-js-3.x b/projects/packages/classic-theme-helper/changelog/renovate-core-js-3.x
new file mode 100644
index 0000000000000..390dbc579d13c
--- /dev/null
+++ b/projects/packages/classic-theme-helper/changelog/renovate-core-js-3.x
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+Comment: Remove unneeded `core-js` JS dep.
+
diff --git a/projects/packages/classic-theme-helper/package.json b/projects/packages/classic-theme-helper/package.json
index 0ff5cd083be86..bda3fe63aa8fe 100644
--- a/projects/packages/classic-theme-helper/package.json
+++ b/projects/packages/classic-theme-helper/package.json
@@ -31,7 +31,6 @@
"@wordpress/browserslist-config": "6.7.0",
"@wordpress/dependency-extraction-webpack-plugin": "6.7.0",
"autoprefixer": "10.4.14",
- "core-js": "3.23.5",
"glob": "10.4.1",
"postcss": "8.4.31",
"postcss-loader": "6.2.0",
diff --git a/projects/packages/masterbar/changelog/fix-submenu-jetpack-null b/projects/packages/masterbar/changelog/fix-submenu-jetpack-null
new file mode 100644
index 0000000000000..6519110c5c524
--- /dev/null
+++ b/projects/packages/masterbar/changelog/fix-submenu-jetpack-null
@@ -0,0 +1,5 @@
+Significance: patch
+Type: fixed
+Comment: Fix for WP.com sites
+
+
diff --git a/projects/packages/masterbar/changelog/renovate-core-js-3.x b/projects/packages/masterbar/changelog/renovate-core-js-3.x
new file mode 100644
index 0000000000000..390dbc579d13c
--- /dev/null
+++ b/projects/packages/masterbar/changelog/renovate-core-js-3.x
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+Comment: Remove unneeded `core-js` JS dep.
+
diff --git a/projects/packages/masterbar/package.json b/projects/packages/masterbar/package.json
index b79156aedeacf..938a8ca607c2b 100644
--- a/projects/packages/masterbar/package.json
+++ b/projects/packages/masterbar/package.json
@@ -36,7 +36,6 @@
"@wordpress/browserslist-config": "6.7.0",
"@wordpress/dependency-extraction-webpack-plugin": "6.7.0",
"autoprefixer": "10.4.14",
- "core-js": "3.23.5",
"glob": "10.4.1",
"postcss": "8.4.31",
"postcss-loader": "6.2.0",
diff --git a/projects/packages/masterbar/src/admin-menu/class-atomic-admin-menu.php b/projects/packages/masterbar/src/admin-menu/class-atomic-admin-menu.php
index 7b81df2be6ee3..4a22f09c7d1af 100644
--- a/projects/packages/masterbar/src/admin-menu/class-atomic-admin-menu.php
+++ b/projects/packages/masterbar/src/admin-menu/class-atomic-admin-menu.php
@@ -328,11 +328,15 @@ public function add_jetpack_menu() {
parent::add_jetpack_menu();
}
+ $scan_position = $this->get_submenu_item_count( 'jetpack' ) - 1;
+
global $submenu;
- $backup_submenu_label = __( 'Backup', 'jetpack-masterbar' );
- $submenu_labels = array_column( $submenu['jetpack'], 3 );
- $backup_position = array_search( $backup_submenu_label, $submenu_labels, true );
- $scan_position = $backup_position !== false ? $backup_position + 1 : $this->get_submenu_item_count( 'jetpack' ) - 1;
+ if ( isset( $submenu['jetpack'] ) ) {
+ $backup_submenu_label = __( 'Backup', 'jetpack-masterbar' );
+ $submenu_labels = array_column( $submenu['jetpack'], 3 );
+ $backup_position = array_search( $backup_submenu_label, $submenu_labels, true );
+ $scan_position = $backup_position !== false ? $backup_position + 1 : $this->get_submenu_item_count( 'jetpack' ) - 1;
+ }
// @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- Core should ideally document null for no-callback arg. https://core.trac.wordpress.org/ticket/52539.
add_submenu_page( 'jetpack', esc_attr__( 'Scan', 'jetpack-masterbar' ), __( 'Scan', 'jetpack-masterbar' ), 'manage_options', 'https://wordpress.com/scan/history/' . $this->domain, null, $scan_position );
diff --git a/projects/packages/publicize/changelog/fix-social-bluesky-does-not-show-up-on-load b/projects/packages/publicize/changelog/fix-social-bluesky-does-not-show-up-on-load
new file mode 100644
index 0000000000000..3258f9cb1a7c6
--- /dev/null
+++ b/projects/packages/publicize/changelog/fix-social-bluesky-does-not-show-up-on-load
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fixed
+
+Social: Fixed Bluesky not showing up on page load
diff --git a/projects/packages/publicize/src/class-publicize.php b/projects/packages/publicize/src/class-publicize.php
index 715d6cd3f8495..b1e59b1582bc4 100644
--- a/projects/packages/publicize/src/class-publicize.php
+++ b/projects/packages/publicize/src/class-publicize.php
@@ -566,6 +566,7 @@ public function get_services( $filter = 'all', $_blog_id = false, $_user_id = fa
'instagram-business' => array(),
'nextdoor' => array(),
'threads' => array(),
+ 'bluesky' => array(),
);
if ( 'all' === $filter ) {
diff --git a/projects/plugins/social/changelog/renovate-js-unit-testing-packages b/projects/packages/search/changelog/renovate-core-js-3.x
similarity index 100%
rename from projects/plugins/social/changelog/renovate-js-unit-testing-packages
rename to projects/packages/search/changelog/renovate-core-js-3.x
diff --git a/projects/packages/search/package.json b/projects/packages/search/package.json
index d406808196f30..33e056c37e893 100644
--- a/projects/packages/search/package.json
+++ b/projects/packages/search/package.json
@@ -81,7 +81,7 @@
"autoprefixer": "10.4.14",
"babel-jest": "29.4.3",
"concurrently": "7.6.0",
- "core-js": "3.23.5",
+ "core-js": "3.38.1",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"postcss": "8.4.31",
diff --git a/projects/plugins/social/changelog/renovate-lock-file-maintenance b/projects/packages/wordads/changelog/renovate-core-js-3.x
similarity index 100%
rename from projects/plugins/social/changelog/renovate-lock-file-maintenance
rename to projects/packages/wordads/changelog/renovate-core-js-3.x
diff --git a/projects/packages/wordads/package.json b/projects/packages/wordads/package.json
index 6e7dd857ea24d..dcc9a688a495a 100644
--- a/projects/packages/wordads/package.json
+++ b/projects/packages/wordads/package.json
@@ -74,7 +74,7 @@
"@wordpress/dependency-extraction-webpack-plugin": "6.7.0",
"babel-jest": "29.4.3",
"concurrently": "7.6.0",
- "core-js": "3.23.5",
+ "core-js": "3.38.1",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"prettier": "npm:wp-prettier@3.0.3",
diff --git a/projects/plugins/jetpack/_inc/client/at-a-glance/connections.jsx b/projects/plugins/jetpack/_inc/client/at-a-glance/connections.jsx
index 812d536a8e5d1..75b497f5429fa 100644
--- a/projects/plugins/jetpack/_inc/client/at-a-glance/connections.jsx
+++ b/projects/plugins/jetpack/_inc/client/at-a-glance/connections.jsx
@@ -71,7 +71,6 @@ export class DashConnections extends Component {
) }
- { __( 'Your site is connected to WordPress.com.', 'jetpack' ) }
{ this.props.isConnectionOwner && (
{ __( 'You are the Jetpack owner.', 'jetpack' ) }
@@ -100,7 +99,7 @@ export class DashConnections extends Component {
*/
userConnection() {
const maybeShowLinkUnlinkBtn = this.props.isConnectionOwner ? null : (
-
+
);
let cardContent = '';
@@ -131,14 +130,7 @@ export class DashConnections extends Component {
}
if ( ! this.props.isLinked ) {
- cardContent = (
-
-
- { __( 'Get the most out of Jetpack.', 'jetpack' ) }
-
-
{ maybeShowLinkUnlinkBtn }
-
- );
+ cardContent = { maybeShowLinkUnlinkBtn }
;
} else if ( this.props.isFetchingUserData ) {
cardContent = __( 'Loading…', 'jetpack' );
} else if ( ! this.props.wpComConnectedUser?.email ) {
diff --git a/projects/plugins/jetpack/_inc/client/at-a-glance/monitor.jsx b/projects/plugins/jetpack/_inc/client/at-a-glance/monitor.jsx
index 077da4c240e10..fbb2b5a1e08fd 100644
--- a/projects/plugins/jetpack/_inc/client/at-a-glance/monitor.jsx
+++ b/projects/plugins/jetpack/_inc/client/at-a-glance/monitor.jsx
@@ -3,9 +3,10 @@ import { createInterpolateElement } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import Button from 'components/button';
import DashItem from 'components/dash-item';
+import JetpackBanner from 'components/jetpack-banner';
import analytics from 'lib/analytics';
import PropTypes from 'prop-types';
-import React, { Component } from 'react';
+import { Component } from 'react';
import { connect } from 'react-redux';
import { isOfflineMode, hasConnectedOwner, connectUser } from 'state/connection';
import { isModuleAvailable } from 'state/modules';
@@ -78,26 +79,29 @@ class DashMonitor extends Component {
support={ support }
className="jp-dash-item__is-inactive"
noToggle={ ! this.props.hasConnectedOwner }
+ overrideContent={
+ ( ! this.props.hasConnectedOwner && ! this.props.isOfflineMode && (
+
+ ) ) ||
+ null
+ }
>
{ this.props.isOfflineMode
? __( 'Unavailable in Offline Mode.', 'jetpack' )
: activateMessage }
-
- { ! this.props.isOfflineMode && ! this.props.hasConnectedOwner && (
-
- { createInterpolateElement(
- __(
- ' account to use this feature.',
- 'jetpack'
- ),
- {
- Button: ,
- }
- ) }
-
- ) }
);
}
diff --git a/projects/plugins/jetpack/_inc/client/at-a-glance/style.scss b/projects/plugins/jetpack/_inc/client/at-a-glance/style.scss
index c02e78ef720a4..5e5a65517d19b 100644
--- a/projects/plugins/jetpack/_inc/client/at-a-glance/style.scss
+++ b/projects/plugins/jetpack/_inc/client/at-a-glance/style.scss
@@ -717,3 +717,37 @@ a.jp-dash-item__manage-in-wpcom,
border-top: 1px solid $gray-5;
}
}
+
+.jp-dash-item.jp-connection-type {
+ border: 1px solid transparent;
+ border-radius: 4px;
+
+ .jp-dash-item__card {
+ padding: 16px 16px 16px 24px;
+ }
+
+ .jp-dash-item__content {
+ display: block;
+ }
+
+ .jp-connection-settings__text {
+ flex-grow: 1;
+ }
+
+ .jp-dash-item__content,
+ .jp-connection-settings__text {
+ align-self: center;
+ }
+
+ .dops-banner {
+ padding: 0;
+
+ &__title {
+ padding: 0 0.5rem 0 0;
+ }
+ }
+
+ .dops-banner.dops-card {
+ display: block;
+ }
+}
diff --git a/projects/plugins/jetpack/_inc/client/at-a-glance/test/component.js b/projects/plugins/jetpack/_inc/client/at-a-glance/test/component.js
index e23415045ce73..804f931ca4f8b 100644
--- a/projects/plugins/jetpack/_inc/client/at-a-glance/test/component.js
+++ b/projects/plugins/jetpack/_inc/client/at-a-glance/test/component.js
@@ -84,7 +84,7 @@ describe( 'Connections', () => {
it( 'shows a disconnection link', () => {
render( , { initialState: buildInitialState() } );
expect(
- withinCard( 'Site connection' ).getByRole( 'button', { name: 'Manage site connection' } )
+ withinCard( 'Site connection' ).getByRole( 'button', { name: 'Manage' } )
).toBeInTheDocument();
} );
@@ -128,8 +128,8 @@ describe( 'Connections', () => {
initialState: buildInitialState( { userIsLinked: false } ),
} );
expect(
- withinCard( 'Account connection' ).getByRole( 'link', {
- name: 'Connect your WordPress.com account',
+ withinCard( 'Account connection' ).getByRole( 'button', {
+ name: 'Connect',
} )
).toBeInTheDocument();
} );
diff --git a/projects/plugins/jetpack/_inc/client/components/connect-button/index.jsx b/projects/plugins/jetpack/_inc/client/components/connect-button/index.jsx
index 8192e4a424c84..858e6a48ffcaf 100644
--- a/projects/plugins/jetpack/_inc/client/components/connect-button/index.jsx
+++ b/projects/plugins/jetpack/_inc/client/components/connect-button/index.jsx
@@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n';
import { getFragment } from '@wordpress/url';
import Button from 'components/button';
import QuerySiteBenefits from 'components/data/query-site-benefits';
+import JetpackBanner from 'components/jetpack-banner';
import analytics from 'lib/analytics';
import PropTypes from 'prop-types';
import React from 'react';
@@ -47,6 +48,7 @@ export class ConnectButton extends React.Component {
connectUser: PropTypes.bool,
from: PropTypes.string,
asLink: PropTypes.bool,
+ asBanner: PropTypes.bool,
connectLegend: PropTypes.string,
connectInPlace: PropTypes.bool,
customConnect: PropTypes.func,
@@ -74,8 +76,11 @@ export class ConnectButton extends React.Component {
}
handleOpenModal = e => {
+ if ( e ) {
+ e.preventDefault();
+ }
+
analytics.tracks.recordJetpackClick( 'manage_site_connection' );
- e.preventDefault();
this.toggleVisibility();
};
@@ -89,7 +94,9 @@ export class ConnectButton extends React.Component {
};
loadConnectionScreen = e => {
- e.preventDefault();
+ if ( e ) {
+ e.preventDefault();
+ }
// If the iframe is already loaded or we don't have a connectUrl yet, return.
if ( this.props.isAuthorizing || this.props.fetchingConnectUrl ) {
return;
@@ -131,6 +138,23 @@ export class ConnectButton extends React.Component {
);
}
+ if ( this.props.asBanner ) {
+ return (
+
+ );
+ }
+
let connectUrl = this.props.connectUrl;
if ( this.props.from ) {
connectUrl += `&from=${ this.props.from }`;
@@ -162,15 +186,15 @@ export class ConnectButton extends React.Component {
if ( this.props.isSiteConnected ) {
return (
-
- { this.props.connectLegend || __( 'Manage site connection', 'jetpack' ) }
-
+ eventFeature="manage-site-connection"
+ path="dashboard"
+ eventProps={ { type: 'manage' } }
+ />
);
}
diff --git a/projects/plugins/jetpack/_inc/client/components/connect-button/test/component.js b/projects/plugins/jetpack/_inc/client/components/connect-button/test/component.js
index 63fa59414fbce..5a04f18247650 100644
--- a/projects/plugins/jetpack/_inc/client/components/connect-button/test/component.js
+++ b/projects/plugins/jetpack/_inc/client/components/connect-button/test/component.js
@@ -1,8 +1,8 @@
import { jest } from '@jest/globals';
import userEvent from '@testing-library/user-event';
-import React from 'react';
import { render, screen } from 'test/test-utils';
import { ConnectButton } from '../index';
+import { buildInitialState } from './fixtures';
// Mock components that do fetches in the background. We supply needed state directly.
jest.mock( 'components/data/query-site-benefits', () => ( {
@@ -25,30 +25,15 @@ describe( 'ConnectButton', () => {
asLink: false,
connectInPlace: false,
doNotUseConnectionIframe: false,
+ asBanner: true,
};
describe( 'Initially', () => {
it( 'renders a button to connect or link', () => {
- render( );
- expect(
- screen.getByRole( 'link', { name: 'Connect your WordPress.com account' } )
- ).toBeInTheDocument();
- } );
-
- it( 'disables the button while fetching the connect URL', () => {
- render( );
- expect( screen.getByRole( 'link', { name: 'Connect your WordPress.com account' } ) )
- // eslint-disable-next-line jest-dom/prefer-enabled-disabled -- `.toBeDisabled()` doesn't work on links.
- .toHaveAttribute( 'disabled' );
- } );
- } );
-
- describe( 'When it is used to link a user', () => {
- it( 'has a link to jetpack.wordpress.com', () => {
- render( );
- expect(
- screen.getByRole( 'link', { name: 'Connect your WordPress.com account' } )
- ).toHaveAttribute( 'href', 'https://jetpack.wordpress.com/jetpack.authorize/1/' );
+ render( , {
+ initialState: buildInitialState(),
+ } );
+ expect( screen.getByRole( 'button', { name: 'Connect' } ) ).toBeInTheDocument();
} );
} );
@@ -62,15 +47,15 @@ describe( 'ConnectButton', () => {
};
it( 'has a link to jetpack.wordpress.com', () => {
- render( );
- expect(
- screen.getByRole( 'link', { name: 'Link your account to WordPress.com' } )
- ).toHaveAttribute( 'href', 'https://jetpack.wordpress.com/jetpack.authorize/1/' );
+ render( , {
+ initialState: buildInitialState(),
+ } );
+ expect( screen.getByRole( 'button', { name: 'Connect' } ) ).toBeInTheDocument();
} );
it( 'when clicked, loadConnectionScreen() is called once', async () => {
const user = userEvent.setup();
- const loadConnectionScreen = jest.fn( e => e.preventDefault() );
+ const loadConnectionScreen = jest.fn();
class ConnectButtonMock extends ConnectButton {
constructor( props ) {
@@ -79,10 +64,10 @@ describe( 'ConnectButton', () => {
}
}
- render( );
- await user.click(
- screen.getByRole( 'link', { name: 'Link your account to WordPress.com' } )
- );
+ render( , {
+ initialState: buildInitialState(),
+ } );
+ await user.click( screen.getByRole( 'button', { name: 'Connect' } ) );
expect( loadConnectionScreen ).toHaveBeenCalledTimes( 1 );
} );
} );
@@ -96,7 +81,9 @@ describe( 'ConnectButton', () => {
};
it( 'does not link to a URL', () => {
- render( );
+ render( , {
+ initialState: buildInitialState(),
+ } );
expect(
screen.getByRole( 'button', { name: 'Unlink your account from WordPress.com' } )
).not.toHaveAttribute( 'href' );
@@ -152,7 +139,9 @@ describe( 'ConnectButton', () => {
};
it( 'does not link to a URL', () => {
- render( );
+ render( , {
+ initialState: buildInitialState(),
+ } );
expect(
screen.getByRole( 'button', { name: 'Disconnect your site from WordPress.com' } )
).not.toHaveAttribute( 'href' );
@@ -160,7 +149,7 @@ describe( 'ConnectButton', () => {
it( 'when clicked, handleOpenModal() is called once', async () => {
const user = userEvent.setup();
- const handleOpenModal = jest.fn( e => e.preventDefault() );
+ const handleOpenModal = jest.fn();
class ConnectButtonMock extends ConnectButton {
constructor( props ) {
@@ -169,7 +158,9 @@ describe( 'ConnectButton', () => {
}
}
- render( );
+ render( , {
+ initialState: buildInitialState(),
+ } );
await user.click(
screen.getByRole( 'button', { name: 'Disconnect your site from WordPress.com' } )
);
diff --git a/projects/plugins/jetpack/_inc/client/components/connect-button/test/fixtures.js b/projects/plugins/jetpack/_inc/client/components/connect-button/test/fixtures.js
new file mode 100644
index 0000000000000..2ffddcfba3695
--- /dev/null
+++ b/projects/plugins/jetpack/_inc/client/components/connect-button/test/fixtures.js
@@ -0,0 +1,27 @@
+/**
+ * Build an object that can be used as a Redux store initial state.
+ *
+ * @return {object} – initial Redux state
+ */
+export function buildInitialState() {
+ return {
+ jetpack: {
+ initialState: {
+ userData: {
+ currentUser: {
+ permissions: {
+ manage_modules: true,
+ },
+ },
+ },
+ },
+ connection: {
+ user: {
+ currentUser: {
+ isConnected: true,
+ },
+ },
+ },
+ },
+ };
+}
diff --git a/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx b/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx
index 1e6a8d6835312..40bc7a8ca301a 100644
--- a/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx
+++ b/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx
@@ -13,7 +13,13 @@ import {
FEATURE_SPAM_AKISMET_PLUS,
FEATURE_SEARCH_JETPACK,
FEATURE_SIMPLE_PAYMENTS_JETPACK,
+ FEATURE_DOWNTIME_MONITORING_JETPACK,
+ FEATURE_SSO,
+ FEATURE_JETPACK_SOCIAL,
+ FEATURE_POST_BY_EMAIL,
getJetpackProductUpsellByFeature,
+ FEATURE_JETPACK_BLAZE,
+ FEATURE_JETPACK_EARN,
} from 'lib/plans/constants';
import { get, includes } from 'lodash';
import ProStatus from 'pro-status';
@@ -22,19 +28,20 @@ import {
isSearchNewPricingLaunched202208,
} from 'product-descriptions/utils';
import PropTypes from 'prop-types';
-import React from 'react';
import { connect } from 'react-redux';
import { isAkismetKeyValid, isCheckingAkismetKey, getVaultPressData } from 'state/at-a-glance';
import {
hasConnectedOwner as hasConnectedOwnerSelector,
isOfflineMode,
connectUser,
+ isUnavailableInOfflineMode,
} from 'state/connection';
import {
getSiteAdminUrl,
getUpgradeUrl,
isMultisite,
userCanManageModules,
+ shouldInitializeBlaze,
} from 'state/initial-state';
import { getModuleOverride, getModule } from 'state/modules';
import { siteHasFeature, isFetchingSiteData } from 'state/site';
@@ -223,6 +230,113 @@ export const SettingsCard = inprops => {
/>
);
+ case FEATURE_DOWNTIME_MONITORING_JETPACK:
+ if ( props.hasConnectedOwner || props.inOfflineMode ) {
+ return '';
+ }
+
+ return (
+
+ );
+
+ case FEATURE_SSO:
+ if ( props.hasConnectedOwner || props.inOfflineMode ) {
+ return '';
+ }
+
+ return (
+
+ );
+
+ case FEATURE_POST_BY_EMAIL:
+ if ( props.hasConnectedOwner || props.isUnavailableInOfflineMode( 'post-by-email' ) ) {
+ return '';
+ }
+
+ return (
+
+ );
+
+ case FEATURE_JETPACK_SOCIAL:
+ if ( props.hasConnectedOwner || props.inOfflineMode ) {
+ return '';
+ }
+
+ return (
+
+ );
+
+ case FEATURE_JETPACK_BLAZE:
+ if ( props.blazeAvailable.can_init || props.inOfflineMode ) {
+ return '';
+ }
+
+ return (
+
+ );
+
+ case FEATURE_JETPACK_EARN:
+ return (
+
+ );
+
case FEATURE_GOOGLE_ANALYTICS_JETPACK:
if ( props.hasGoogleAnalytics ) {
return '';
@@ -478,6 +592,8 @@ export default connect(
hasSimplePayments: siteHasFeature( state, 'simple-payments' ),
hasVideoPress: siteHasFeature( state, 'videopress' ),
hasWordAds: siteHasFeature( state, 'wordads' ),
+ isUnavailableInOfflineMode: module_name => isUnavailableInOfflineMode( state, module_name ),
+ blazeAvailable: shouldInitializeBlaze( state ),
};
},
dispatch => ( {
diff --git a/projects/plugins/jetpack/_inc/client/earn/index.jsx b/projects/plugins/jetpack/_inc/client/earn/index.jsx
index 91651ad7ed4a0..6662ea0bd1bf2 100644
--- a/projects/plugins/jetpack/_inc/client/earn/index.jsx
+++ b/projects/plugins/jetpack/_inc/client/earn/index.jsx
@@ -2,7 +2,6 @@ import { getRedirectUrl } from '@automattic/jetpack-components';
import { useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import Card from 'components/card';
-import ConnectUserBar from 'components/connect-user-bar';
import QuerySite from 'components/data/query-site';
import SettingsCard from 'components/settings-card';
import SettingsGroup from 'components/settings-group';
@@ -81,8 +80,16 @@ function EarnFeatureButton( props ) {
* @return {React.Component} Earn settings component.
*/
function Earn( props ) {
- const { active, hasConnectedOwner, isModuleFound, isOffline, searchTerm, siteRawUrl, blogID } =
- props;
+ const {
+ active,
+ hasConnectedOwner,
+ isModuleFound,
+ isOffline,
+ searchTerm,
+ siteRawUrl,
+ blogID,
+ feature,
+ } = props;
if ( ! searchTerm && ! active ) {
return null;
@@ -112,13 +119,8 @@ function Earn( props ) {
hideButton
module="earn"
header={ __( 'Collect payments', 'jetpack' ) }
- >
-
-
+ feature={ feature }
+ />
);
}
diff --git a/projects/plugins/jetpack/_inc/client/lib/plans/constants.js b/projects/plugins/jetpack/_inc/client/lib/plans/constants.js
index 8112965e3ae8e..995306b550c74 100644
--- a/projects/plugins/jetpack/_inc/client/lib/plans/constants.js
+++ b/projects/plugins/jetpack/_inc/client/lib/plans/constants.js
@@ -400,22 +400,33 @@ export const FEATURE_JETPACK_AI = 'ai-jetpack';
export const FEATURE_JETPACK_CRM = 'crm-jetpack';
export const FEATURE_JETPACK_BOOST = 'boost-jetpack';
export const FEATURE_SIMPLE_PAYMENTS_JETPACK = 'simple-payments-jetpack';
+export const FEATURE_DOWNTIME_MONITORING_JETPACK = 'downtime-monitoring-jetpack';
+export const FEATURE_SSO = 'sso-jetpack';
+export const FEATURE_POST_BY_EMAIL = 'post-by-email-jetpack';
+export const FEATURE_JETPACK_SOCIAL = 'social-jetpack';
+export const FEATURE_JETPACK_BLAZE = 'blaze-jetpack';
+export const FEATURE_JETPACK_EARN = 'earn-jetpack';
// Upsells
export const JETPACK_FEATURE_PRODUCT_UPSELL_MAP = {
+ [ FEATURE_DOWNTIME_MONITORING_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
+ [ FEATURE_GOOGLE_ANALYTICS_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
+ [ FEATURE_JETPACK_AI ]: PLAN_JETPACK_AI_YEARLY,
+ [ FEATURE_JETPACK_BOOST ]: PLAN_JETPACK_BOOST,
+ [ FEATURE_JETPACK_BLAZE ]: PLAN_JETPACK_FREE,
+ [ FEATURE_JETPACK_EARN ]: PLAN_JETPACK_FREE,
+ [ FEATURE_JETPACK_SOCIAL ]: PLAN_JETPACK_SOCIAL_V1,
+ [ FEATURE_POST_BY_EMAIL ]: PLAN_JETPACK_FREE,
[ FEATURE_PRIORITY_SUPPORT_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
[ FEATURE_SEARCH_JETPACK ]: PLAN_JETPACK_SEARCH,
[ FEATURE_SECURITY_SCANNING_JETPACK ]: PLAN_JETPACK_SCAN,
+ [ FEATURE_SIMPLE_PAYMENTS_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
[ FEATURE_SITE_BACKUPS_JETPACK ]: PLAN_JETPACK_BACKUP_T1_YEARLY,
[ FEATURE_SPAM_AKISMET_PLUS ]: PLAN_JETPACK_ANTI_SPAM,
+ [ FEATURE_SSO ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
[ FEATURE_VIDEO_HOSTING_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
- [ FEATURE_WORDADS_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
- [ FEATURE_GOOGLE_ANALYTICS_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
- [ FEATURE_SPAM_AKISMET_PLUS ]: PLAN_JETPACK_ANTI_SPAM,
[ FEATURE_VIDEOPRESS ]: PLAN_JETPACK_VIDEOPRESS,
- [ FEATURE_SIMPLE_PAYMENTS_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
- [ FEATURE_JETPACK_AI ]: PLAN_JETPACK_AI_YEARLY,
- [ FEATURE_JETPACK_BOOST ]: PLAN_JETPACK_BOOST,
+ [ FEATURE_WORDADS_JETPACK ]: PLAN_JETPACK_SECURITY_T1_YEARLY,
};
/**
diff --git a/projects/plugins/jetpack/_inc/client/security/monitor.jsx b/projects/plugins/jetpack/_inc/client/security/monitor.jsx
index 6a72d8085f53c..c0bda41fdb64b 100644
--- a/projects/plugins/jetpack/_inc/client/security/monitor.jsx
+++ b/projects/plugins/jetpack/_inc/client/security/monitor.jsx
@@ -2,13 +2,13 @@ import { getRedirectUrl } from '@automattic/jetpack-components';
import { ExternalLink } from '@wordpress/components';
import { createInterpolateElement } from '@wordpress/element';
import { __, _x } from '@wordpress/i18n';
-import ConnectUserBar from 'components/connect-user-bar';
import { withModuleSettingsFormHelpers } from 'components/module-settings/with-module-settings-form-helpers';
import { ModuleToggle } from 'components/module-toggle';
import SettingsCard from 'components/settings-card';
import SettingsGroup from 'components/settings-group';
import analytics from 'lib/analytics';
-import React, { Component } from 'react';
+import { Component } from 'react';
+import { FEATURE_DOWNTIME_MONITORING_JETPACK } from '../lib/plans/constants';
export const Monitor = withModuleSettingsFormHelpers(
class extends Component {
@@ -18,7 +18,6 @@ export const Monitor = withModuleSettingsFormHelpers(
render() {
const hasConnectedOwner = this.props.hasConnectedOwner,
- isOfflineMode = this.props.isOfflineMode,
isMonitorActive = this.props.getOptionValue( 'monitor' ),
unavailableInOfflineMode = this.props.isUnavailableInOfflineMode( 'monitor' );
return (
@@ -27,6 +26,7 @@ export const Monitor = withModuleSettingsFormHelpers(
hideButton
module="monitor"
header={ _x( 'Downtime monitoring', 'Settings header', 'jetpack' ) }
+ feature={ FEATURE_DOWNTIME_MONITORING_JETPACK }
>
-
- { ! hasConnectedOwner && ! isOfflineMode && (
-
- ) }
);
}
diff --git a/projects/plugins/jetpack/_inc/client/security/sso.jsx b/projects/plugins/jetpack/_inc/client/security/sso.jsx
index 55d31668c31da..c613373b5c187 100644
--- a/projects/plugins/jetpack/_inc/client/security/sso.jsx
+++ b/projects/plugins/jetpack/_inc/client/security/sso.jsx
@@ -3,7 +3,6 @@ import { useConnection } from '@automattic/jetpack-connection';
import { Button, ExternalLink } from '@wordpress/components';
import { createInterpolateElement } from '@wordpress/element';
import { __, _x } from '@wordpress/i18n';
-import ConnectUserBar from 'components/connect-user-bar';
import { FormFieldset } from 'components/forms';
import { withModuleSettingsFormHelpers } from 'components/module-settings/with-module-settings-form-helpers';
import { ModuleToggle } from 'components/module-toggle';
@@ -12,6 +11,7 @@ import SettingsGroup from 'components/settings-group';
import cookie from 'cookie';
import { useState, Component } from 'react';
import ReactDOM from 'react-dom';
+import { FEATURE_SSO } from '../lib/plans/constants';
const SSOSurveyNotice = () => {
const { userConnectionData } = useConnection();
@@ -140,6 +140,7 @@ export const SSO = withModuleSettingsFormHelpers(
hideButton
module="sso"
header={ _x( 'WordPress.com login', 'Settings header, noun.', 'jetpack' ) }
+ feature={ FEATURE_SSO }
>
-
- { ! this.props.hasConnectedOwner && ! this.props.isOfflineMode && (
-
- ) }
{ this.state.showSSODisableModal &&
ReactDOM.createPortal( , document.body ) }
diff --git a/projects/plugins/jetpack/_inc/client/settings/index.jsx b/projects/plugins/jetpack/_inc/client/settings/index.jsx
index 481e195e98c15..76c4a77f6e872 100644
--- a/projects/plugins/jetpack/_inc/client/settings/index.jsx
+++ b/projects/plugins/jetpack/_inc/client/settings/index.jsx
@@ -14,6 +14,7 @@ import Sharing from 'sharing';
import { isModuleActivated as isModuleActivatedSelector } from 'state/modules';
import Traffic from 'traffic';
import Writing from 'writing';
+import { FEATURE_JETPACK_EARN } from '../lib/plans/constants';
class Settings extends React.Component {
static displayName = 'SearchableSettings';
@@ -66,7 +67,12 @@ class Settings extends React.Component {
active={ '/newsletter' === pathname }
{ ...commonProps }
/>
-
+
{ userCanManageModules && (
) }
-
- { ! isLinked && ! isOfflineMode && (
-
- ) }
-
{ isActive && ! useAdminUiV1 && configCard() }
);
diff --git a/projects/plugins/jetpack/_inc/client/traffic/blaze.jsx b/projects/plugins/jetpack/_inc/client/traffic/blaze.jsx
index 5b119694d05cf..d58324561cd3a 100644
--- a/projects/plugins/jetpack/_inc/client/traffic/blaze.jsx
+++ b/projects/plugins/jetpack/_inc/client/traffic/blaze.jsx
@@ -1,7 +1,6 @@
import { getRedirectUrl, ToggleControl } from '@automattic/jetpack-components';
import { __ } from '@wordpress/i18n';
import Card from 'components/card';
-import ConnectUserBar from 'components/connect-user-bar';
import { withModuleSettingsFormHelpers } from 'components/module-settings/with-module-settings-form-helpers';
import { ModuleToggle } from 'components/module-toggle';
import SettingsCard from 'components/settings-card';
@@ -15,6 +14,7 @@ import {
shouldInitializeBlaze,
} from 'state/initial-state';
import { getModule } from 'state/modules';
+import { FEATURE_JETPACK_BLAZE } from '../lib/plans/constants';
const trackDashboardClick = () => {
analytics.tracks.recordJetpackClick( 'blaze-dashboard' );
@@ -102,7 +102,13 @@ function Blaze( props ) {
};
return (
-
+
{ canInit && blazeActive && ! isOfflineMode && blazeDashboardLink() }
- { ! canInit && reason === 'user_not_connected' && ! isOfflineMode && (
-
- ) }
);
}
diff --git a/projects/plugins/jetpack/_inc/client/writing/post-by-email.jsx b/projects/plugins/jetpack/_inc/client/writing/post-by-email.jsx
index 152b83e58a29b..7224dd4006e3f 100644
--- a/projects/plugins/jetpack/_inc/client/writing/post-by-email.jsx
+++ b/projects/plugins/jetpack/_inc/client/writing/post-by-email.jsx
@@ -2,7 +2,6 @@ import { getRedirectUrl } from '@automattic/jetpack-components';
import { __, _x } from '@wordpress/i18n';
import Button from 'components/button';
import ClipboardButtonInput from 'components/clipboard-button-input';
-import ConnectUserBar from 'components/connect-user-bar';
import { FormFieldset, FormLegend, FormLabel } from 'components/forms';
import { withModuleSettingsFormHelpers } from 'components/module-settings/with-module-settings-form-helpers';
import { ModuleToggle } from 'components/module-toggle';
@@ -13,6 +12,7 @@ import React from 'react';
import { connect } from 'react-redux';
import { getModule } from 'state/modules';
import { isModuleFound as _isModuleFound } from 'state/search';
+import { FEATURE_POST_BY_EMAIL } from '../lib/plans/constants';
class PostByEmail extends React.Component {
regeneratePostByEmailAddress = event => {
@@ -44,7 +44,12 @@ class PostByEmail extends React.Component {
emailAddress = this.address();
return (
-
+
-
- { ! this.props.isUnavailableInOfflineMode( 'post-by-email' ) && ! this.props.isLinked && (
-
- ) }
);
}
diff --git a/projects/plugins/jetpack/changelog/update-at-a-glance-unify-connection-ctas b/projects/plugins/jetpack/changelog/update-at-a-glance-unify-connection-ctas
new file mode 100644
index 0000000000000..af2f73b816a2b
--- /dev/null
+++ b/projects/plugins/jetpack/changelog/update-at-a-glance-unify-connection-ctas
@@ -0,0 +1,4 @@
+Significance: patch
+Type: other
+
+Unify connection related CTAs on At A Glance
diff --git a/projects/plugins/jetpack/changelog/update-email-preview-error-styles b/projects/plugins/jetpack/changelog/update-email-preview-error-styles
new file mode 100644
index 0000000000000..e97bcd728ea1f
--- /dev/null
+++ b/projects/plugins/jetpack/changelog/update-email-preview-error-styles
@@ -0,0 +1,4 @@
+Significance: minor
+Type: other
+
+Email preview modal: visually improved error state
diff --git a/projects/plugins/jetpack/changelog/update-jetpack-settings-connection-nudges b/projects/plugins/jetpack/changelog/update-jetpack-settings-connection-nudges
new file mode 100644
index 0000000000000..394cbd36b3139
--- /dev/null
+++ b/projects/plugins/jetpack/changelog/update-jetpack-settings-connection-nudges
@@ -0,0 +1,4 @@
+Significance: patch
+Type: other
+
+Unify connection nudge design on Jetpack Settings
diff --git a/projects/plugins/jetpack/extensions/blocks/subscriptions/email-preview.js b/projects/plugins/jetpack/extensions/blocks/subscriptions/email-preview.js
index d852046b60f9a..7243d87868f88 100644
--- a/projects/plugins/jetpack/extensions/blocks/subscriptions/email-preview.js
+++ b/projects/plugins/jetpack/extensions/blocks/subscriptions/email-preview.js
@@ -1,4 +1,4 @@
-import { useBreakpointMatch } from '@automattic/jetpack-components';
+import { getRedirectUrl, useBreakpointMatch } from '@automattic/jetpack-components';
import { useAnalytics } from '@automattic/jetpack-shared-extension-utils';
import apiFetch from '@wordpress/api-fetch';
import {
@@ -13,12 +13,13 @@ import {
__experimentalToggleGroupControlOption as ToggleGroupControlOption, // eslint-disable-line @wordpress/no-unsafe-wp-apis
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, // eslint-disable-line @wordpress/no-unsafe-wp-apis
Spinner,
+ ExternalLink,
} from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
-import { useState, useCallback, useEffect } from '@wordpress/element';
+import { useState, useCallback, useEffect, createInterpolateElement } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
-import { desktop, mobile, tablet, check, people, currencyDollar } from '@wordpress/icons';
+import { desktop, mobile, tablet, check, people, currencyDollar, warning } from '@wordpress/icons';
import './email-preview.scss';
import { accessOptions } from '../../shared/memberships/constants';
import { useAccessLevel } from '../../shared/memberships/edit';
@@ -226,6 +227,8 @@ const PreviewControls = ( {
export function NewsletterPreviewModal( { isOpen, onClose, postId } ) {
const [ isLoading, setIsLoading ] = useState( true );
+ const [ isError, setError ] = useState( false );
+ const [ refetchedOnError, setRefetchedOnError ] = useState( false );
const [ previewCache, setPreviewCache ] = useState( {} );
const [ selectedAccess, setSelectedAccess ] = useState( accessOptions.subscribers.key );
const [ selectedDevice, setSelectedDevice ] = useState( 'desktop' );
@@ -238,6 +241,7 @@ export function NewsletterPreviewModal( { isOpen, onClose, postId } ) {
}
setIsLoading( true );
+ setError( false );
try {
const response = await apiFetch( {
@@ -253,19 +257,14 @@ export function NewsletterPreviewModal( { isOpen, onClose, postId } ) {
} else {
throw new Error( 'Invalid response format' );
}
- } catch ( error ) {
- setPreviewCache( prevCache => ( {
- ...prevCache,
- [ accessLevel ]: `${ __(
- 'Error loading preview',
- 'jetpack'
- ) }`,
- } ) );
+ } catch {
+ tracks.recordEvent( 'jetpack_newsletter_preview_modal_error' );
+ setError( true );
} finally {
setIsLoading( false );
}
},
- [ postId ]
+ [ postId, tracks ]
);
useEffect( () => {
@@ -312,14 +311,46 @@ export function NewsletterPreviewModal( { isOpen, onClose, postId } ) {
justifyContent: 'center',
alignItems: 'center',
height: 'calc(100vh - 190px)',
- backgroundColor: '#ddd',
+ backgroundColor: isError ? '#fff' : '#ddd',
paddingTop: selectedDevice !== 'desktop' ? '36px' : '0',
transition: 'padding 0.3s ease-in-out',
} }
>
- { isLoading ? (
-
- ) : (
+ { isLoading && }
+ { isError && (
+
+
+ { __( 'Oops, something went wrong showing the preview…', 'jetpack' ) }
+
+ { refetchedOnError && (
+
+ { createInterpolateElement(
+ __(
+ 'If the issue persists, please contact support.',
+ 'jetpack'
+ ),
+ {
+ supportLink: ,
+ }
+ ) }
+
+ ) }
+
+ ) }
+ { ! isLoading && ! isError && (