@automattic/jetpack-connection 0.33.3 → 0.33.4

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,10 @@
2
2
 
3
3
  ### This is a list detailing changes for the Jetpack RNA Connection Component releases.
4
4
 
5
+ ## [0.33.4] - 2024-03-25
6
+ ### Fixed
7
+ - Fix some redirect after purchase behavior when site is not connected [#36448]
8
+
5
9
  ## [0.33.3] - 2024-03-12
6
10
  ### Changed
7
11
  - Updated package dependencies. [#36325]
@@ -730,6 +734,7 @@
730
734
  - `Main` and `ConnectUser` components added.
731
735
  - `JetpackRestApiClient` API client added.
732
736
 
737
+ [0.33.4]: https://github.com/Automattic/jetpack-connection-js/compare/v0.33.3...v0.33.4
733
738
  [0.33.3]: https://github.com/Automattic/jetpack-connection-js/compare/v0.33.2...v0.33.3
734
739
  [0.33.2]: https://github.com/Automattic/jetpack-connection-js/compare/v0.33.1...v0.33.2
735
740
  [0.33.1]: https://github.com/Automattic/jetpack-connection-js/compare/v0.33.0...v0.33.1
@@ -0,0 +1,101 @@
1
+ import { __ } from '@wordpress/i18n';
2
+ import React from 'react';
3
+ import useConnection from '../../use-connection';
4
+ import ConnectScreenVisual from './visual';
5
+
6
+ export type Props = {
7
+ // API root
8
+ apiRoot: string;
9
+ // API nonce
10
+ apiNonce: string;
11
+ // Registration nonce
12
+ registrationNonce: string;
13
+ // The redirect admin UR
14
+ redirectUri: string;
15
+ // Additional page elements to show before the call to action
16
+ children: React.ReactNode;
17
+ // The Title
18
+ title?: string;
19
+ // The Connect Button label
20
+ buttonLabel?: string;
21
+ // The text read by screen readers when connecting
22
+ loadingLabel?: string;
23
+ // Where the connection request is coming from
24
+ from?: string;
25
+ // Whether to initiate the connection process automatically upon rendering the component
26
+ autoTrigger?: boolean;
27
+ // Images to display on the right side
28
+ images?: string[];
29
+ // The assets base URL
30
+ assetBaseUrl?: string;
31
+ // Whether to not require a user connection and just redirect after site connection
32
+ skipUserConnection?: boolean;
33
+ // Additional page elements to show after the call to action
34
+ footer?: React.ReactNode;
35
+ // The logo to display at the top of the component
36
+ logo?: React.ReactNode;
37
+ };
38
+
39
+ /*
40
+ * The Connection Screen component.
41
+ */
42
+ const ConnectScreen: React.FC< Props > = ( {
43
+ title,
44
+ buttonLabel,
45
+ loadingLabel,
46
+ apiRoot,
47
+ apiNonce,
48
+ registrationNonce,
49
+ from,
50
+ redirectUri,
51
+ images,
52
+ children,
53
+ assetBaseUrl,
54
+ autoTrigger,
55
+ footer,
56
+ skipUserConnection,
57
+ logo,
58
+ } ) => {
59
+ const {
60
+ handleRegisterSite,
61
+ siteIsRegistering,
62
+ userIsConnecting,
63
+ registrationError,
64
+ isOfflineMode,
65
+ } = useConnection( {
66
+ registrationNonce,
67
+ redirectUri,
68
+ apiRoot,
69
+ apiNonce,
70
+ autoTrigger,
71
+ from,
72
+ skipUserConnection,
73
+ } );
74
+
75
+ const displayButtonError = Boolean( registrationError );
76
+ const buttonIsLoading = siteIsRegistering || userIsConnecting;
77
+ const errorCode = registrationError?.response?.code;
78
+
79
+ return (
80
+ <ConnectScreenVisual
81
+ title={
82
+ title || __( 'Over 5 million WordPress sites are faster and more secure', 'jetpack' )
83
+ }
84
+ images={ images || [] }
85
+ assetBaseUrl={ assetBaseUrl }
86
+ buttonLabel={ buttonLabel || __( 'Set up Jetpack', 'jetpack' ) }
87
+ loadingLabel={ loadingLabel }
88
+ handleButtonClick={ handleRegisterSite }
89
+ displayButtonError={ displayButtonError }
90
+ errorCode={ errorCode }
91
+ buttonIsLoading={ buttonIsLoading }
92
+ footer={ footer }
93
+ isOfflineMode={ isOfflineMode }
94
+ logo={ logo }
95
+ >
96
+ { children }
97
+ </ConnectScreenVisual>
98
+ );
99
+ };
100
+
101
+ export default ConnectScreen;
@@ -0,0 +1,118 @@
1
+ import { ActionButton, TermsOfService } from '@automattic/jetpack-components';
2
+ import { getRedirectUrl } from '@automattic/jetpack-components';
3
+ import { createInterpolateElement } from '@wordpress/element';
4
+ import { __ } from '@wordpress/i18n';
5
+ import React from 'react';
6
+ import ConnectScreenLayout from '../layout';
7
+ import type { Props as ConnectScreenProps } from '../basic';
8
+ import type { WithRequired } from '../types';
9
+ import './style.scss';
10
+
11
+ type SharedProps = Pick<
12
+ ConnectScreenProps,
13
+ | 'title'
14
+ | 'children'
15
+ | 'assetBaseUrl'
16
+ | 'images'
17
+ | 'logo'
18
+ | 'footer'
19
+ | 'buttonLabel'
20
+ | 'loadingLabel'
21
+ >;
22
+ type OwnProps = {
23
+ // Whether the connection status is still loading
24
+ isLoading?: boolean;
25
+ // Callback to be called on button click
26
+ handleButtonClick?: ( e: MouseEvent ) => void;
27
+ // Whether the error message appears or not
28
+ displayButtonError?: boolean;
29
+ // The connection error code
30
+ errorCode?: string;
31
+ // Whether the button is loading or not
32
+ buttonIsLoading?: boolean;
33
+ // Whether the site is in offline mode
34
+ isOfflineMode?: boolean;
35
+ };
36
+
37
+ export type Props = WithRequired< SharedProps, 'buttonLabel' > & OwnProps;
38
+
39
+ const getErrorMessage = ( errorCode, isOfflineMode ) => {
40
+ // Explicit error code takes precedence over the offline mode.
41
+ switch ( errorCode ) {
42
+ case 'fail_domain_forbidden':
43
+ case 'fail_ip_forbidden':
44
+ case 'fail_domain_tld':
45
+ case 'fail_subdomain_wpcom':
46
+ case 'siteurl_private_ip':
47
+ return __(
48
+ 'Your site host is on a private network. Jetpack can only connect to public sites.',
49
+ 'jetpack'
50
+ );
51
+ }
52
+
53
+ if ( isOfflineMode ) {
54
+ return createInterpolateElement( __( 'Unavailable in <a>Offline Mode</a>', 'jetpack' ), {
55
+ a: (
56
+ <a
57
+ href={ getRedirectUrl( 'jetpack-support-development-mode' ) }
58
+ target="_blank"
59
+ rel="noopener noreferrer"
60
+ />
61
+ ),
62
+ } );
63
+ }
64
+ };
65
+
66
+ /*
67
+ * The Connection Screen Visual component.
68
+ */
69
+ const ConnectScreenVisual: React.FC< Props > = ( {
70
+ title,
71
+ images,
72
+ children,
73
+ assetBaseUrl,
74
+ isLoading,
75
+ buttonLabel,
76
+ handleButtonClick,
77
+ displayButtonError,
78
+ errorCode,
79
+ buttonIsLoading,
80
+ loadingLabel,
81
+ footer,
82
+ isOfflineMode,
83
+ logo,
84
+ } ) => (
85
+ <ConnectScreenLayout
86
+ title={ title }
87
+ assetBaseUrl={ assetBaseUrl }
88
+ images={ images }
89
+ className={
90
+ 'jp-connection__connect-screen' +
91
+ ( isLoading ? ' jp-connection__connect-screen__loading' : '' )
92
+ }
93
+ logo={ logo }
94
+ >
95
+ <div className="jp-connection__connect-screen__content">
96
+ { children }
97
+
98
+ <div className="jp-connection__connect-screen__tos">
99
+ <TermsOfService agreeButtonLabel={ buttonLabel } />
100
+ </div>
101
+ <ActionButton
102
+ label={ buttonLabel }
103
+ onClick={ handleButtonClick }
104
+ displayError={ displayButtonError || isOfflineMode }
105
+ errorMessage={ getErrorMessage( errorCode, isOfflineMode ) }
106
+ isLoading={ buttonIsLoading }
107
+ isDisabled={ isOfflineMode }
108
+ />
109
+ <span className="jp-connection__connect-screen__loading-message" role="status">
110
+ { buttonIsLoading ? loadingLabel || __( 'Loading', 'jetpack' ) : '' }
111
+ </span>
112
+
113
+ { footer && <div className="jp-connection__connect-screen__footer">{ footer }</div> }
114
+ </div>
115
+ </ConnectScreenLayout>
116
+ );
117
+
118
+ export default ConnectScreenVisual;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import type { Props as ConnectScreenProps } from '../basic';
3
+
4
+ export type Props = Pick< ConnectScreenProps, 'images' | 'assetBaseUrl' >;
5
+
6
+ /*
7
+ * The ImageSlider component.
8
+ */
9
+ const ImageSlider: React.FC< Props > = ( { images, assetBaseUrl = '' } ) => {
10
+ if ( ! images?.length ) {
11
+ return null;
12
+ }
13
+
14
+ const imagesHTML = images.map( ( image, index ) => (
15
+ <React.Fragment key={ index }>
16
+ <img src={ assetBaseUrl + image } alt="" />
17
+ </React.Fragment>
18
+ ) );
19
+
20
+ return <div className="jp-connection__connect-screen__image-slider">{ imagesHTML }</div>;
21
+ };
22
+
23
+ export default ImageSlider;
@@ -1,19 +1,36 @@
1
1
  import { JetpackLogo } from '@automattic/jetpack-components';
2
2
  import classNames from 'classnames';
3
- import PropTypes from 'prop-types';
4
3
  import React from 'react';
5
4
  import ImageSlider from './image-slider';
5
+ import type { Props as ConnectScreenProps } from '../basic';
6
+ import type { WithRequired } from '../types';
6
7
  import './style.scss';
7
8
 
8
- /**
9
+ type SharedProps = Pick<
10
+ ConnectScreenProps,
11
+ 'title' | 'children' | 'assetBaseUrl' | 'images' | 'logo'
12
+ >;
13
+ type OwnProps = {
14
+ // Class to be added to component
15
+ className?: string;
16
+ // Whether to apply RNA styles
17
+ rna?: boolean;
18
+ };
19
+
20
+ export type Props = WithRequired< SharedProps, 'title' > & OwnProps;
21
+
22
+ /*
9
23
  * The Connection Screen Layout component.
10
- *
11
- * @param {object} props -- The properties.
12
- * @returns {React.Component} The `ConnectScreenLayout` component.
13
24
  */
14
- const ConnectScreenLayout = props => {
15
- const { title, children, className, assetBaseUrl, images, logo, rna = false } = props;
16
-
25
+ const ConnectScreenLayout: React.FC< Props > = ( {
26
+ title,
27
+ children,
28
+ className,
29
+ assetBaseUrl,
30
+ images,
31
+ logo,
32
+ rna = false,
33
+ } ) => {
17
34
  const showImageSlider = images?.length;
18
35
 
19
36
  return (
@@ -49,17 +66,4 @@ const ConnectScreenLayout = props => {
49
66
  );
50
67
  };
51
68
 
52
- ConnectScreenLayout.propTypes = {
53
- /** The Title. */
54
- title: PropTypes.string,
55
- /** Class to be added to component. */
56
- className: PropTypes.string,
57
- /** Images to display on the right side. */
58
- images: PropTypes.arrayOf( PropTypes.string ),
59
- /** The assets base URL. */
60
- assetBaseUrl: PropTypes.string,
61
- /** The logo to display at the top of the component. */
62
- logo: PropTypes.element,
63
- };
64
-
65
69
  export default ConnectScreenLayout;
@@ -0,0 +1 @@
1
+ export type WithRequired< T, K extends keyof T > = T & { [ P in K ]-?: T[ P ] };
@@ -168,7 +168,9 @@ export default function useProductCheckoutWorkflow( {
168
168
  return handleAfterRegistration( redirect );
169
169
  }
170
170
 
171
- registerSite( { registrationNonce, redirectUri: redirectUrl } ).then( handleAfterRegistration );
171
+ registerSite( { registrationNonce, redirectUri: redirectUrl } ).then( () =>
172
+ handleAfterRegistration( redirect )
173
+ );
172
174
  };
173
175
 
174
176
  // Initialize/Setup the REST API.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/jetpack-connection",
3
- "version": "0.33.3",
3
+ "version": "0.33.4",
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": "^0.1.29",
18
18
  "@automattic/jetpack-api": "^0.17.2",
19
- "@automattic/jetpack-components": "^0.50.1",
19
+ "@automattic/jetpack-components": "^0.50.3",
20
20
  "@automattic/jetpack-config": "^0.1.24",
21
21
  "@wordpress/base-styles": "4.44.0",
22
22
  "@wordpress/browserslist-config": "5.36.0",
@@ -37,6 +37,7 @@
37
37
  "@testing-library/dom": "9.3.4",
38
38
  "@testing-library/react": "14.2.1",
39
39
  "@testing-library/user-event": "14.5.2",
40
+ "@types/react": "18.2.67",
40
41
  "jest": "29.7.0",
41
42
  "jest-environment-jsdom": "29.7.0",
42
43
  "react": "18.2.0",
@@ -1,110 +0,0 @@
1
- import { __ } from '@wordpress/i18n';
2
- import PropTypes from 'prop-types';
3
- import React from 'react';
4
- import useConnection from '../../use-connection';
5
- import ConnectScreenVisual from './visual';
6
-
7
- /**
8
- * The Connection Screen component.
9
- *
10
- * @param {object} props -- The properties.
11
- * @param {string?} props.title -- The Title.
12
- * @param {string?} props.buttonLabel -- The Connect Button label.
13
- * @param {string?} props.loadingLabel -- The text read by screen readers when connecting.
14
- * @param {string} props.apiRoot -- API root.
15
- * @param {string} props.apiNonce -- API nonce.
16
- * @param {string} props.registrationNonce -- Registration nonce.
17
- * @param {string?} props.from -- Where the connection request is coming from.
18
- * @param {string} props.redirectUri -- The redirect admin URI.
19
- * @param {string[]?} props.images -- Images to display on the right side.
20
- * @param {object[]} props.children -- Additional page elements to show before the call to action.
21
- * @param {string?} props.assetBaseUrl -- The assets base URL.
22
- * @param {object?} props.footer -- Additional page elements to show after the call to action.
23
- * @param {boolean?} props.skipUserConnection -- Whether to not require a user connection and just redirect after site connection.
24
- * @param {boolean?} props.autoTrigger -- Whether to initiate the connection process automatically upon rendering the component.
25
- * @param {object?} props.logo -- The logo to display at the top of the component.
26
- * @returns {React.Component} The `ConnectScreen` component.
27
- */
28
- const ConnectScreen = ( {
29
- title,
30
- buttonLabel,
31
- loadingLabel,
32
- apiRoot,
33
- apiNonce,
34
- registrationNonce,
35
- from,
36
- redirectUri,
37
- images,
38
- children,
39
- assetBaseUrl,
40
- autoTrigger,
41
- footer,
42
- skipUserConnection,
43
- logo,
44
- } ) => {
45
- const {
46
- handleRegisterSite,
47
- siteIsRegistering,
48
- userIsConnecting,
49
- registrationError,
50
- isOfflineMode,
51
- } = useConnection( {
52
- registrationNonce,
53
- redirectUri,
54
- apiRoot,
55
- apiNonce,
56
- autoTrigger,
57
- from,
58
- skipUserConnection,
59
- } );
60
-
61
- const displayButtonError = Boolean( registrationError );
62
- const buttonIsLoading = siteIsRegistering || userIsConnecting;
63
- const errorCode = registrationError?.response?.code;
64
-
65
- return (
66
- <ConnectScreenVisual
67
- title={ title }
68
- images={ images }
69
- assetBaseUrl={ assetBaseUrl }
70
- buttonLabel={ buttonLabel }
71
- loadingLabel={ loadingLabel }
72
- handleButtonClick={ handleRegisterSite }
73
- displayButtonError={ displayButtonError }
74
- errorCode={ errorCode }
75
- buttonIsLoading={ buttonIsLoading }
76
- footer={ footer }
77
- isOfflineMode={ isOfflineMode }
78
- logo={ logo }
79
- >
80
- { children }
81
- </ConnectScreenVisual>
82
- );
83
- };
84
-
85
- ConnectScreen.propTypes = {
86
- title: PropTypes.string,
87
- buttonLabel: PropTypes.string,
88
- loadingLabel: PropTypes.string,
89
- apiRoot: PropTypes.string.isRequired,
90
- apiNonce: PropTypes.string.isRequired,
91
- registrationNonce: PropTypes.string.isRequired,
92
- from: PropTypes.string,
93
- redirectUri: PropTypes.string.isRequired,
94
- autoTrigger: PropTypes.bool,
95
- images: PropTypes.arrayOf( PropTypes.string ),
96
- assetBaseUrl: PropTypes.string,
97
- skipUserConnection: PropTypes.bool,
98
- logo: PropTypes.element,
99
- };
100
-
101
- ConnectScreen.defaultProps = {
102
- title: __( 'Over 5 million WordPress sites are faster and more secure', 'jetpack' ),
103
- buttonLabel: __( 'Set up Jetpack', 'jetpack' ),
104
- images: [],
105
- redirectUri: null,
106
- autoTrigger: false,
107
- skipUserConnection: false,
108
- };
109
-
110
- export default ConnectScreen;
@@ -1,137 +0,0 @@
1
- import { ActionButton, getRedirectUrl, TermsOfService } from '@automattic/jetpack-components';
2
- import { createInterpolateElement } from '@wordpress/element';
3
- import { __ } from '@wordpress/i18n';
4
- import PropTypes from 'prop-types';
5
- import React from 'react';
6
- import ConnectScreenLayout from '../layout';
7
- import './style.scss';
8
-
9
- /**
10
- * The Connection Screen Visual component..
11
- *
12
- * @param {object} props -- The properties.
13
- * @returns {React.Component} The `ConnectScreenRequiredPlanVisual` component.
14
- */
15
- const ConnectScreenVisual = props => {
16
- const {
17
- title,
18
- images,
19
- children,
20
- assetBaseUrl,
21
- isLoading,
22
- buttonLabel,
23
- handleButtonClick,
24
- displayButtonError,
25
- errorCode,
26
- buttonIsLoading,
27
- loadingLabel,
28
- footer,
29
- isOfflineMode,
30
- logo,
31
- } = props;
32
-
33
- const getErrorMessage = () => {
34
- // Explicit error code takes precedence over the offline mode.
35
- switch ( errorCode ) {
36
- case 'fail_domain_forbidden':
37
- case 'fail_ip_forbidden':
38
- case 'fail_domain_tld':
39
- case 'fail_subdomain_wpcom':
40
- case 'siteurl_private_ip':
41
- return __(
42
- 'Your site host is on a private network. Jetpack can only connect to public sites.',
43
- 'jetpack'
44
- );
45
- }
46
-
47
- if ( isOfflineMode ) {
48
- return createInterpolateElement( __( 'Unavailable in <a>Offline Mode</a>', 'jetpack' ), {
49
- a: (
50
- <a
51
- href={ getRedirectUrl( 'jetpack-support-development-mode' ) }
52
- target="_blank"
53
- rel="noopener noreferrer"
54
- />
55
- ),
56
- } );
57
- }
58
- };
59
-
60
- const errorMessage = getErrorMessage( errorCode, isOfflineMode );
61
-
62
- return (
63
- <ConnectScreenLayout
64
- title={ title }
65
- assetBaseUrl={ assetBaseUrl }
66
- images={ images }
67
- className={
68
- 'jp-connection__connect-screen' +
69
- ( isLoading ? ' jp-connection__connect-screen__loading' : '' )
70
- }
71
- logo={ logo }
72
- >
73
- <div className="jp-connection__connect-screen__content">
74
- { children }
75
-
76
- <div className="jp-connection__connect-screen__tos">
77
- <TermsOfService agreeButtonLabel={ buttonLabel } />
78
- </div>
79
- <ActionButton
80
- label={ buttonLabel }
81
- onClick={ handleButtonClick }
82
- displayError={ displayButtonError || isOfflineMode }
83
- errorMessage={ errorMessage }
84
- isLoading={ buttonIsLoading }
85
- isDisabled={ isOfflineMode }
86
- />
87
- <span className="jp-connection__connect-screen__loading-message" role="status">
88
- { buttonIsLoading ? loadingLabel : '' }
89
- </span>
90
-
91
- { footer && <div className="jp-connection__connect-screen__footer">{ footer }</div> }
92
- </div>
93
- </ConnectScreenLayout>
94
- );
95
- };
96
-
97
- ConnectScreenVisual.propTypes = {
98
- /** The Title. */
99
- title: PropTypes.string,
100
- /** Images to display on the right side. */
101
- images: PropTypes.arrayOf( PropTypes.string ),
102
- /** The assets base URL. */
103
- assetBaseUrl: PropTypes.string,
104
- /** Whether the connection status is still loading. */
105
- isLoading: PropTypes.bool,
106
- /** Text label to be used into button. */
107
- buttonLabel: PropTypes.string.isRequired,
108
- /** Callback to be called on button click. */
109
- handleButtonClick: PropTypes.func,
110
- /** Whether the error message appears or not. */
111
- displayButtonError: PropTypes.bool,
112
- /** The connection error code. */
113
- errorCode: PropTypes.string,
114
- /** Whether the button is loading or not. */
115
- buttonIsLoading: PropTypes.bool,
116
- /** Text read by screen readers after the button is activated */
117
- loadingLabel: PropTypes.string,
118
- /** Node that will be rendered after ToS */
119
- footer: PropTypes.node,
120
- /** Whether the site is in offline mode. */
121
- isOfflineMode: PropTypes.bool,
122
- /** The logo to display at the top of the component. */
123
- logo: PropTypes.element,
124
- };
125
-
126
- ConnectScreenVisual.defaultProps = {
127
- isLoading: false,
128
- buttonIsLoading: false,
129
- loadingLabel: __( 'Loading', 'jetpack' ),
130
- displayButtonError: false,
131
- errorCode: null,
132
- handleButtonClick: () => {},
133
- footer: null,
134
- isOfflineMode: false,
135
- };
136
-
137
- export default ConnectScreenVisual;
@@ -1,37 +0,0 @@
1
- import PropTypes from 'prop-types';
2
- import React from 'react';
3
-
4
- /**
5
- * The ImageSlider component.
6
- *
7
- * @param {object} props -- The properties.
8
- * @param {Array} props.images -- Images to display on the right side.
9
- * @param {string} props.assetBaseUrl -- The assets base URL
10
- * @returns {React.Component} The `ImageSlider` component.
11
- */
12
- const ImageSlider = props => {
13
- const { images, assetBaseUrl } = props;
14
-
15
- if ( ! images.length ) {
16
- return null;
17
- }
18
-
19
- const imagesHTML = images.map( ( image, index ) => (
20
- <React.Fragment key={ index }>
21
- <img src={ assetBaseUrl + image } alt="" />
22
- </React.Fragment>
23
- ) );
24
-
25
- return <div className="jp-connection__connect-screen__image-slider">{ imagesHTML }</div>;
26
- };
27
-
28
- ImageSlider.propTypes = {
29
- images: PropTypes.arrayOf( PropTypes.string ).isRequired,
30
- assetBaseUrl: PropTypes.string,
31
- };
32
-
33
- ImageSlider.defaultProps = {
34
- assetBaseUrl: '',
35
- };
36
-
37
- export default ImageSlider;