@automattic/jetpack-shared-extension-utils 0.2.0 → 0.3.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
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.0] - 2022-03-23
9
+ ### Added
10
+ - Moved plan-utils.js file from plugin/jetpack to shared-extension-utils. Updated import references for the same
11
+
12
+ ### Changed
13
+ - Updated package dependencies
14
+
8
15
  ## [0.2.0] - 2022-03-15
9
16
  ### Added
10
17
  - Moved with-has-warning-is-interactive-class-names folder from jetpack plugin shared extensions
@@ -25,5 +32,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
25
32
  ### Changed
26
33
  - Core: prepare utility for release
27
34
 
35
+ [0.3.0]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/0.2.0...0.3.0
28
36
  [0.2.0]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/0.1.1...0.2.0
29
37
  [0.1.1]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/0.1.0...0.1.1
package/index.js CHANGED
@@ -4,3 +4,12 @@ export { isSimpleSite, isAtomicSite, isPrivateSite } from './src/site-type-utils
4
4
  export { default as getJetpackExtensionAvailability } from './src/get-jetpack-extension-availability';
5
5
  export { default as registerJetpackPlugin } from './src/register-jetpack-plugin';
6
6
  export { default as withHasWarningIsInteractiveClassNames } from './src/with-has-warning-is-interactive-class-names';
7
+ export {
8
+ getUpgradeUrl,
9
+ isUpgradable,
10
+ requiresPaidPlan,
11
+ getRequiredPlan,
12
+ isUpgradeNudgeEnabled,
13
+ isStillUsableWithFreePlan,
14
+ getUsableBlockProps,
15
+ } from './src/plan-utils';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/jetpack-shared-extension-utils",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Utility functions used by the block editor extensions",
5
5
  "homepage": "https://jetpack.com",
6
6
  "bugs": {
@@ -17,11 +17,14 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@wordpress/compose": "5.1.2",
20
- "@wordpress/plugins": "4.1.1"
20
+ "@wordpress/i18n": "4.3.0",
21
+ "@wordpress/plugins": "4.1.1",
22
+ "@wordpress/url": "3.4.0",
23
+ "lodash": "4.17.21"
21
24
  },
22
25
  "devDependencies": {
23
- "@babel/core": "7.16.0",
24
- "@babel/preset-react": "7.16.0",
26
+ "@babel/core": "7.17.8",
27
+ "@babel/preset-react": "7.16.7",
25
28
  "jetpack-js-test-runner": "workspace:*",
26
29
  "nyc": "15.1.0"
27
30
  },
@@ -0,0 +1,187 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { compact, get, startsWith, map, filter, head } from 'lodash';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { addQueryArgs } from '@wordpress/url';
10
+ import { __ } from '@wordpress/i18n';
11
+
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ import { isAtomicSite, isSimpleSite } from './site-type-utils';
16
+ import getJetpackData from './get-jetpack-data';
17
+ import getJetpackExtensionAvailability from './get-jetpack-extension-availability';
18
+ import getSiteFragment from './get-site-fragment';
19
+
20
+ /**
21
+ * Return the checkout URL to upgrade the site plan,
22
+ * depending on the plan, postId, and postType site values.
23
+ *
24
+ * @param {object} siteParams - Site params used to build the URL.
25
+ * @param {string} siteParams.planSlug - Plan slug.
26
+ * @param {object} siteParams.plan - An object with details about the plan.
27
+ * @param {number} siteParams.postId - Post id.
28
+ * @param {string} siteParams.postType - Post type.
29
+ * @returns {string} Upgrade URL.
30
+ */
31
+ export function getUpgradeUrl( { planSlug, plan, postId, postType } ) {
32
+ // WP.com plan objects have a dedicated `path_slug` field, Jetpack plan objects don't.
33
+ const planPathSlug = startsWith( planSlug, 'jetpack_' ) ? planSlug : get( plan, [ 'path_slug' ] );
34
+
35
+ // The full site editor has no set post type.
36
+ const redirect_to = ( undefined === postType
37
+ ? () => {
38
+ const queryParams = new URLSearchParams( window.location.search );
39
+
40
+ return addQueryArgs(
41
+ window.location.protocol +
42
+ `//${ getSiteFragment().replace( '::', '/' ) }/wp-admin/admin.php`,
43
+ {
44
+ page: 'gutenberg-edit-site',
45
+ postId: queryParams.get( 'postId' ),
46
+ postType: queryParams.get( 'postType' ),
47
+ plan_upgraded: 1,
48
+ }
49
+ );
50
+ }
51
+ : () => {
52
+ // The editor for CPTs has an `edit/` route fragment prefixed.
53
+ const postTypeEditorRoutePrefix = [ 'page', 'post' ].includes( postType ) ? '' : 'edit';
54
+
55
+ // Post-checkout: redirect back here.
56
+ return isSimpleSite()
57
+ ? addQueryArgs(
58
+ '/' +
59
+ compact( [ postTypeEditorRoutePrefix, postType, getSiteFragment(), postId ] ).join(
60
+ '/'
61
+ ),
62
+ {
63
+ plan_upgraded: 1,
64
+ }
65
+ )
66
+ : addQueryArgs(
67
+ window.location.protocol +
68
+ `//${ getSiteFragment().replace( '::', '/' ) }/wp-admin/post.php`,
69
+ {
70
+ action: 'edit',
71
+ post: postId,
72
+ plan_upgraded: 1,
73
+ }
74
+ );
75
+ } )();
76
+
77
+ // Redirect to calypso plans page for WoC sites.
78
+ if ( isAtomicSite() ) {
79
+ return addQueryArgs( `https://wordpress.com/plans/${ getSiteFragment() }`, {
80
+ redirect_to,
81
+ customerType: 'business',
82
+ } );
83
+ }
84
+
85
+ return (
86
+ planPathSlug &&
87
+ addQueryArgs( `https://wordpress.com/checkout/${ getSiteFragment() }/${ planPathSlug }`, {
88
+ redirect_to,
89
+ } )
90
+ );
91
+ }
92
+
93
+ /**
94
+ * Check if the block is upgradable, based on whether
95
+ * the block requires a paid plan.
96
+ *
97
+ * @param {string} name - Block name.
98
+ * @returns {boolean} True if the block is upgradable, false otherwise.
99
+ */
100
+ export function isUpgradable( name ) {
101
+ if ( ! name ) {
102
+ return false;
103
+ }
104
+
105
+ const blockName = /^jetpack\//.test( name ) ? name.substr( 8, name.length ) : name;
106
+ const { available, unavailableReason } = getJetpackExtensionAvailability( blockName );
107
+
108
+ return ! available && 'missing_plan' === unavailableReason;
109
+ }
110
+
111
+ /**
112
+ * Checks whether the block requires a paid plan or not.
113
+ *
114
+ * @param {string} unavailableReason - The reason why block is unavailable
115
+ * @param {object} details - The block details
116
+ * @returns {string|boolean} Either false if the block doesn't require a paid plan, or the actual plan name it requires.
117
+ */
118
+ export function requiresPaidPlan( unavailableReason, details ) {
119
+ if ( unavailableReason === 'missing_plan' ) {
120
+ return details.required_plan;
121
+ }
122
+ return false;
123
+ }
124
+
125
+ /**
126
+ * Returns the required plan slug for a passed block name.
127
+ *
128
+ * @param {string} name - Block name.
129
+ * @returns {string|boolean} Plan name if the block is upgradable, false otherwise.
130
+ */
131
+ export function getRequiredPlan( name ) {
132
+ if ( ! name ) {
133
+ return false;
134
+ }
135
+
136
+ const blockName = /^jetpack\//.test( name ) ? name.substr( 8, name.length ) : name;
137
+ const { details, unavailableReason } = getJetpackExtensionAvailability( blockName );
138
+
139
+ return requiresPaidPlan( unavailableReason, details );
140
+ }
141
+
142
+ /*
143
+ * Usable blocks list with a free plan.
144
+ * This array contains blocks that can be usable
145
+ * even with a free plan, as well as properties
146
+ * used to handle specific behaviour.
147
+ */
148
+ const usableBlockWithFreePlan = [
149
+ {
150
+ name: 'core/cover',
151
+ mediaPlaceholder: true,
152
+ mediaReplaceFlow: true,
153
+ fileType: 'video',
154
+ description: __( 'Upgrade your plan to use video covers', 'jetpack' ),
155
+ },
156
+ {
157
+ name: 'core/audio',
158
+ mediaPlaceholder: true,
159
+ mediaReplaceFlow: true,
160
+ fileType: 'audio',
161
+ description: __( 'Upgrade your plan to upload audio', 'jetpack' ),
162
+ },
163
+ ];
164
+
165
+ /**
166
+ * Return whether upgrade nudges are enabled or not.
167
+ *
168
+ * @returns {boolean} True if the Upgrade Nudge is enable. Otherwise, False.
169
+ */
170
+ export function isUpgradeNudgeEnabled() {
171
+ return get( getJetpackData(), 'jetpack.enable_upgrade_nudge', false );
172
+ }
173
+
174
+ /*
175
+ * Some blocks are still usable with a free plan.
176
+ * We can handle their dual behavior defining specifically
177
+ * when to show the upgrade banner
178
+ * through or the Paid Block context.
179
+ *
180
+ * @param {string} name - Block name to check.
181
+ * @returns {boolean} True is the block is usable with a Free plan. Otherwise, False.
182
+ */
183
+ export const isStillUsableWithFreePlan = name =>
184
+ map( usableBlockWithFreePlan, 'name' ).includes( name );
185
+
186
+ export const getUsableBlockProps = blockName =>
187
+ head( filter( usableBlockWithFreePlan, ( { name } ) => name === blockName ) );