@automattic/jetpack-connection 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ### This is a list detailing changes for the Jetpack RNA Connection Component releases.
4
4
 
5
+ ## [1.2.0] - 2025-06-05
6
+ ### Changed
7
+ - Connection: Display connection info on WoA sites [#43777]
8
+
9
+ ## [1.1.0] - 2025-06-04
10
+ ### Added
11
+ - Improve error handling for protected owner on WordPress.com. [#43593]
12
+
5
13
  ## [1.0.0] - 2025-06-03
6
14
  ### Changed
7
15
  - Update package dependencies. [#43718] [#43734]
@@ -1044,6 +1052,8 @@
1044
1052
  - `Main` and `ConnectUser` components added.
1045
1053
  - `JetpackRestApiClient` API client added.
1046
1054
 
1055
+ [1.2.0]: https://github.com/Automattic/jetpack-connection-js/compare/v1.1.0...v1.2.0
1056
+ [1.1.0]: https://github.com/Automattic/jetpack-connection-js/compare/v1.0.0...v1.1.0
1047
1057
  [1.0.0]: https://github.com/Automattic/jetpack-connection-js/compare/v0.39.18...v1.0.0
1048
1058
  [0.39.18]: https://github.com/Automattic/jetpack-connection-js/compare/v0.39.17...v0.39.18
1049
1059
  [0.39.17]: https://github.com/Automattic/jetpack-connection-js/compare/v0.39.16...v0.39.17
@@ -12,8 +12,13 @@ import styles from './styles.module.scss';
12
12
  * @return {React.Component} The `ConnectionErrorNotice` component.
13
13
  */
14
14
  const ConnectionErrorNotice = props => {
15
- const { message, isRestoringConnection, restoreConnectionCallback, restoreConnectionError } =
16
- props;
15
+ const {
16
+ message,
17
+ isRestoringConnection,
18
+ restoreConnectionCallback,
19
+ restoreConnectionError,
20
+ actions = [], // New prop for custom actions
21
+ } = props;
17
22
 
18
23
  const [ isBiggerThanMedium ] = useBreakpointMatch( [ 'md' ], [ '>' ] );
19
24
  const wrapperClassName =
@@ -73,6 +78,39 @@ const ConnectionErrorNotice = props => {
73
78
  </Notice>
74
79
  ) : null;
75
80
 
81
+ // Determine which actions to show
82
+ let actionButtons = [];
83
+
84
+ if ( actions.length > 0 ) {
85
+ // Use custom actions
86
+ actionButtons = actions.map( ( action, index ) => (
87
+ <a
88
+ key={ index }
89
+ onClick={ action.onClick }
90
+ onKeyDown={ action.onClick }
91
+ className={ `${ styles.button } ${ action.variant === 'primary' ? styles.primary : '' }` }
92
+ href="#"
93
+ >
94
+ { action.isLoading
95
+ ? action.loadingText || __( 'Loading…', 'jetpack-connection-js' )
96
+ : action.label }
97
+ </a>
98
+ ) );
99
+ } else if ( restoreConnectionCallback ) {
100
+ // Use default restore connection action for backward compatibility
101
+ actionButtons = [
102
+ <a
103
+ key="restore"
104
+ onClick={ restoreConnectionCallback }
105
+ onKeyDown={ restoreConnectionCallback }
106
+ className={ styles.button }
107
+ href="#"
108
+ >
109
+ { __( 'Restore Connection', 'jetpack-connection-js' ) }
110
+ </a>,
111
+ ];
112
+ }
113
+
76
114
  return (
77
115
  <>
78
116
  { errorRender }
@@ -81,16 +119,7 @@ const ConnectionErrorNotice = props => {
81
119
  { icon }
82
120
  { message }
83
121
  </div>
84
- { restoreConnectionCallback && (
85
- <a
86
- onClick={ restoreConnectionCallback }
87
- onKeyDown={ restoreConnectionCallback }
88
- className={ styles.button }
89
- href="#"
90
- >
91
- { __( 'Restore Connection', 'jetpack-connection-js' ) }
92
- </a>
93
- ) }
122
+ { actionButtons.length > 0 && <div className={ styles.actions }>{ actionButtons }</div> }
94
123
  </Notice>
95
124
  </>
96
125
  );
@@ -98,13 +127,23 @@ const ConnectionErrorNotice = props => {
98
127
 
99
128
  ConnectionErrorNotice.propTypes = {
100
129
  /** The notice message. */
101
- message: PropTypes.string.isRequired,
130
+ message: PropTypes.oneOfType( [ PropTypes.string, PropTypes.element ] ).isRequired,
102
131
  /** "Restore Connection" button callback. */
103
132
  restoreConnectionCallback: PropTypes.func,
104
133
  /** Whether connection restore is in progress. */
105
134
  isRestoringConnection: PropTypes.bool,
106
135
  /** The connection error text if there is one. */
107
136
  restoreConnectionError: PropTypes.string,
137
+ /** Array of custom action objects. */
138
+ actions: PropTypes.arrayOf(
139
+ PropTypes.shape( {
140
+ label: PropTypes.string.isRequired,
141
+ onClick: PropTypes.func.isRequired,
142
+ isLoading: PropTypes.bool,
143
+ loadingText: PropTypes.string,
144
+ variant: PropTypes.oneOf( [ 'primary', 'secondary' ] ),
145
+ } )
146
+ ),
108
147
  };
109
148
 
110
149
  export default ConnectionErrorNotice;
@@ -55,6 +55,16 @@
55
55
  margin-top: 24px;
56
56
  background: #000;
57
57
  border-radius: var( --jp-border-radius );
58
+
59
+ &.primary {
60
+ background: var( --jp-green-50 );
61
+ }
62
+ }
63
+
64
+ .actions {
65
+ display: flex;
66
+ gap: calc( var( --spacing-base ) * 2 ); // 16px
67
+ flex-wrap: wrap;
58
68
  }
59
69
 
60
70
  &.bigger-than-medium {
@@ -4,6 +4,7 @@
4
4
  import jetpackAnalytics from '@automattic/jetpack-analytics';
5
5
  import restApi from '@automattic/jetpack-api';
6
6
  import { Button, getRedirectUrl, Text } from '@automattic/jetpack-components';
7
+ import { isWoASite } from '@automattic/jetpack-script-data';
7
8
  import { ExternalLink, Modal } from '@wordpress/components';
8
9
  import { createInterpolateElement } from '@wordpress/element';
9
10
  import { __ } from '@wordpress/i18n';
@@ -204,7 +205,7 @@ const ManageConnectionDialog = props => {
204
205
  />
205
206
  </>
206
207
  ) }
207
- { isCurrentUserAdmin && (
208
+ { isCurrentUserAdmin && ! isWoASite() && (
208
209
  <ManageConnectionActionCard
209
210
  title={ __( 'Disconnect Jetpack', 'jetpack-connection-js' ) }
210
211
  onClick={ openDisconnectDialog }
@@ -1,10 +1,39 @@
1
+ import { __ } from '@wordpress/i18n';
1
2
  import ConnectionErrorNotice from '../../components/connection-error-notice';
2
3
  import useConnection from '../../components/use-connection';
3
4
  import useRestoreConnection from '../../hooks/use-restore-connection/index.jsx';
4
5
 
6
+ /**
7
+ * Helper function to generate user creation URL with email prepopulation
8
+ *
9
+ * @param {object} connectionError - The connection error object
10
+ * @param {string} baseUrl - Base admin URL (defaults to '/wp-admin/')
11
+ * @return {string} The complete URL for user creation with email parameters
12
+ */
13
+ export function getProtectedOwnerCreateAccountUrl( connectionError, baseUrl = '/wp-admin/' ) {
14
+ let redirectUrl = baseUrl + 'user-new.php';
15
+
16
+ // Add protected owner email if available for prepopulation
17
+ if ( connectionError?.error_data?.wpcom_user_email ) {
18
+ const params = new URLSearchParams( {
19
+ jetpack_protected_owner_email: connectionError.error_data.wpcom_user_email,
20
+ jetpack_create_missing_account: '1',
21
+ } );
22
+ redirectUrl += '?' + params.toString();
23
+ } else if ( connectionError?.error_data?.email ) {
24
+ const params = new URLSearchParams( {
25
+ jetpack_protected_owner_email: connectionError.error_data.email,
26
+ jetpack_create_missing_account: '1',
27
+ } );
28
+ redirectUrl += '?' + params.toString();
29
+ }
30
+
31
+ return redirectUrl;
32
+ }
33
+
5
34
  /**
6
35
  * Connection error notice hook.
7
- * Returns a ConnectionErrorNotice component and the conditional flag on whether
36
+ * Returns connection error data and conditional flag on whether
8
37
  * to render the component or not.
9
38
  *
10
39
  * @return {object} - The hook data.
@@ -12,27 +41,90 @@ import useRestoreConnection from '../../hooks/use-restore-connection/index.jsx';
12
41
  export default function useConnectionErrorNotice() {
13
42
  const { connectionErrors } = useConnection( {} );
14
43
  const connectionErrorList = Object.values( connectionErrors ).shift();
15
- const connectionErrorMessage =
44
+ const firstError =
16
45
  connectionErrorList &&
17
46
  Object.values( connectionErrorList ).length &&
18
- Object.values( connectionErrorList ).shift().error_message;
47
+ Object.values( connectionErrorList ).shift();
19
48
 
49
+ const connectionErrorMessage = firstError && firstError.error_message;
50
+
51
+ // Return all connection errors, including protected owner errors
20
52
  const hasConnectionError = Boolean( connectionErrorMessage );
21
53
 
22
- return { hasConnectionError, connectionErrorMessage };
54
+ return {
55
+ hasConnectionError,
56
+ connectionErrorMessage,
57
+ connectionError: firstError, // Full error object with error_type, etc.
58
+ connectionErrors, // All errors for advanced use cases
59
+ };
23
60
  }
24
61
 
25
- export const ConnectionError = () => {
26
- const { hasConnectionError, connectionErrorMessage } = useConnectionErrorNotice();
62
+ export const ConnectionError = ( {
63
+ onCreateMissingAccount = null, // Custom handler for protected owner errors
64
+ trackingCallback = null, // Custom tracking function
65
+ customActions = null, // Function that returns custom actions based on error
66
+ } = {} ) => {
67
+ const { hasConnectionError, connectionErrorMessage, connectionError } =
68
+ useConnectionErrorNotice();
27
69
  const { restoreConnection, isRestoringConnection, restoreConnectionError } =
28
70
  useRestoreConnection();
29
71
 
30
- return hasConnectionError ? (
72
+ if ( ! hasConnectionError ) {
73
+ return null;
74
+ }
75
+
76
+ // Determine error type
77
+ const isProtectedOwnerError = connectionError && connectionError.error_type === 'protected_owner';
78
+
79
+ // Build actions array based on error type
80
+ let actions = [];
81
+
82
+ if ( customActions ) {
83
+ // Use provided custom actions function
84
+ actions = customActions( connectionError, { restoreConnection, isRestoringConnection } );
85
+ } else if ( isProtectedOwnerError && onCreateMissingAccount ) {
86
+ // Handle protected owner error with custom handler
87
+ actions = [
88
+ {
89
+ label: __( 'Create missing account', 'jetpack-connection-js' ),
90
+ onClick: () => {
91
+ if ( trackingCallback ) {
92
+ trackingCallback( 'jetpack_connection_protected_owner_create_account_attempt', {} );
93
+ }
94
+ onCreateMissingAccount();
95
+ },
96
+ variant: 'primary',
97
+ },
98
+ ];
99
+ } else if ( ! isProtectedOwnerError ) {
100
+ // Standard connection error - use restore connection
101
+ actions = [
102
+ {
103
+ label: __( 'Restore Connection', 'jetpack-connection-js' ),
104
+ onClick: () => {
105
+ if ( trackingCallback ) {
106
+ trackingCallback( 'jetpack_connection_error_notice_reconnect_cta_click', {} );
107
+ }
108
+ restoreConnection();
109
+ },
110
+ isLoading: isRestoringConnection,
111
+ loadingText: __( 'Reconnecting Jetpack…', 'jetpack-connection-js' ),
112
+ },
113
+ ];
114
+ }
115
+
116
+ // For protected owner errors without custom handler, don't show the component
117
+ if ( isProtectedOwnerError && ! onCreateMissingAccount && ! customActions ) {
118
+ return null;
119
+ }
120
+
121
+ return (
31
122
  <ConnectionErrorNotice
32
123
  isRestoringConnection={ isRestoringConnection }
33
124
  restoreConnectionError={ restoreConnectionError }
34
- restoreConnectionCallback={ restoreConnection }
125
+ restoreConnectionCallback={ actions.length === 0 ? restoreConnection : null } // Fallback for backward compatibility
35
126
  message={ connectionErrorMessage }
127
+ actions={ actions }
36
128
  />
37
- ) : null;
129
+ );
38
130
  };
package/index.jsx CHANGED
@@ -49,4 +49,7 @@ export { STORE_ID as CONNECTION_STORE_ID } from './state/store';
49
49
  */
50
50
  export { default as useProductCheckoutWorkflow } from './hooks/use-product-checkout-workflow';
51
51
  export { default as useRestoreConnection } from './hooks/use-restore-connection';
52
- export { default as useConnectionErrorNotice } from './hooks/use-connection-error-notice';
52
+ export {
53
+ default as useConnectionErrorNotice,
54
+ getProtectedOwnerCreateAccountUrl,
55
+ } from './hooks/use-connection-error-notice';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/jetpack-connection",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Jetpack Connection Component",
5
5
  "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/connection/#readme",
6
6
  "bugs": {
@@ -16,7 +16,7 @@
16
16
  "dependencies": {
17
17
  "@automattic/jetpack-analytics": "^1.0.0",
18
18
  "@automattic/jetpack-api": "^1.0.0",
19
- "@automattic/jetpack-components": "^1.0.0",
19
+ "@automattic/jetpack-components": "^1.1.0",
20
20
  "@automattic/jetpack-config": "^1.0.0",
21
21
  "@automattic/jetpack-script-data": "^0.4.2",
22
22
  "@wordpress/base-styles": "6.0.0",