@automattic/jetpack-shared-extension-utils 1.5.22 → 2.0.1
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 +11 -0
- package/index.js +1 -1
- package/package.json +22 -24
- package/src/hooks/use-module-status/index.js +1 -1
- package/src/store/wordpress-com/index.ts +8 -106
- package/src/store/wordpress-com/types.ts +7 -160
- package/index.native.js +0 -3
- package/src/components/jetpack-editor-panel-logo/index.native.js +0 -4
- package/src/get-block-icon-from-metadata.native.js +0 -34
- package/src/get-host-app-namespace.native.js +0 -14
- package/src/icons.native.scss +0 -23
- package/src/modules-state/actions.js +0 -94
- package/src/modules-state/controls.js +0 -48
- package/src/modules-state/index.js +0 -30
- package/src/modules-state/reducer.js +0 -28
- package/src/modules-state/resolvers.js +0 -24
- package/src/modules-state/selectors.js +0 -13
- package/src/store/wordpress-com/actions.ts +0 -194
- package/src/store/wordpress-com/constants.ts +0 -31
- package/src/store/wordpress-com/reducer.ts +0 -224
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ 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
|
+
## [2.0.1] - 2026-06-22
|
|
9
|
+
### Changed
|
|
10
|
+
- Move the WordPress.com plans and Jetpack modules data stores to the new `jetpack-shared-stores` package. [#49494]
|
|
11
|
+
- Update package dependencies. [#49631] [#49691] [#49757]
|
|
12
|
+
|
|
13
|
+
## [2.0.0] - 2026-06-15
|
|
14
|
+
### Removed
|
|
15
|
+
- Remove `react-native` export condition. [#49526]
|
|
16
|
+
|
|
8
17
|
## [1.5.22] - 2026-06-09
|
|
9
18
|
### Changed
|
|
10
19
|
- Update package dependencies. [#49273]
|
|
@@ -970,6 +979,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
970
979
|
### Changed
|
|
971
980
|
- Core: prepare utility for release
|
|
972
981
|
|
|
982
|
+
[2.0.1]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/2.0.0...2.0.1
|
|
983
|
+
[2.0.0]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/1.5.22...2.0.0
|
|
973
984
|
[1.5.22]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/1.5.21...1.5.22
|
|
974
985
|
[1.5.21]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/1.5.20...1.5.21
|
|
975
986
|
[1.5.20]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/1.5.19...1.5.20
|
package/index.js
CHANGED
|
@@ -23,7 +23,7 @@ export { default as useRefInterval } from './src/hooks/use-ref-interval';
|
|
|
23
23
|
export { default as useModuleStatus } from './src/hooks/use-module-status';
|
|
24
24
|
export { getBlockIconComponent, getBlockIconProp } from './src/get-block-icon-from-metadata';
|
|
25
25
|
export { default as getJetpackBlocksVariation } from './src/get-jetpack-blocks-variation';
|
|
26
|
-
export
|
|
26
|
+
export { store, JETPACK_MODULES_STORE_ID } from '@automattic/jetpack-shared-stores';
|
|
27
27
|
export { default as isMyJetpackAvailable } from './src/is-my-jetpack-available';
|
|
28
28
|
export { default as hasFeatureFlag } from './src/has-feature-flag';
|
|
29
29
|
export * from './src/libs';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/jetpack-shared-extension-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Utility functions used by the block editor extensions",
|
|
5
5
|
"homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/shared-extension-utils/#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -13,10 +13,7 @@
|
|
|
13
13
|
"license": "GPL-2.0-or-later",
|
|
14
14
|
"author": "Automattic",
|
|
15
15
|
"exports": {
|
|
16
|
-
".":
|
|
17
|
-
"react-native": "./index.native.js",
|
|
18
|
-
"default": "./index.js"
|
|
19
|
-
},
|
|
16
|
+
".": "./index.js",
|
|
20
17
|
"./components": "./src/components/index.js",
|
|
21
18
|
"./components/wpcom-support-link": "./src/components/wpcom-support-link.jsx",
|
|
22
19
|
"./icons": "./src/icons.js",
|
|
@@ -32,33 +29,34 @@
|
|
|
32
29
|
"dependencies": {
|
|
33
30
|
"@automattic/color-studio": "4.1.0",
|
|
34
31
|
"@automattic/jetpack-analytics": "^1.0.15",
|
|
35
|
-
"@automattic/jetpack-base-styles": "^1.2.
|
|
36
|
-
"@automattic/jetpack-components": "^1.12.
|
|
37
|
-
"@automattic/jetpack-connection": "^1.4.
|
|
32
|
+
"@automattic/jetpack-base-styles": "^1.2.7",
|
|
33
|
+
"@automattic/jetpack-components": "^1.12.9",
|
|
34
|
+
"@automattic/jetpack-connection": "^1.4.62",
|
|
38
35
|
"@automattic/jetpack-script-data": "^0.6.4",
|
|
36
|
+
"@automattic/jetpack-shared-stores": "^0.1.0",
|
|
39
37
|
"@types/jest": "30.0.0",
|
|
40
|
-
"@wordpress/api-fetch": "7.48.
|
|
41
|
-
"@wordpress/block-editor": "15.21.
|
|
42
|
-
"@wordpress/components": "35.0.
|
|
43
|
-
"@wordpress/compose": "8.1.
|
|
44
|
-
"@wordpress/data": "10.48.
|
|
45
|
-
"@wordpress/dom-ready": "4.48.
|
|
46
|
-
"@wordpress/element": "8.0.
|
|
47
|
-
"@wordpress/hooks": "4.48.
|
|
48
|
-
"@wordpress/i18n": "6.21.
|
|
49
|
-
"@wordpress/plugins": "7.48.
|
|
50
|
-
"@wordpress/primitives": "4.48.
|
|
38
|
+
"@wordpress/api-fetch": "7.48.1",
|
|
39
|
+
"@wordpress/block-editor": "15.21.1",
|
|
40
|
+
"@wordpress/components": "35.0.1",
|
|
41
|
+
"@wordpress/compose": "8.1.1",
|
|
42
|
+
"@wordpress/data": "10.48.1",
|
|
43
|
+
"@wordpress/dom-ready": "4.48.1",
|
|
44
|
+
"@wordpress/element": "8.0.1",
|
|
45
|
+
"@wordpress/hooks": "4.48.1",
|
|
46
|
+
"@wordpress/i18n": "6.21.1",
|
|
47
|
+
"@wordpress/plugins": "7.48.1",
|
|
48
|
+
"@wordpress/primitives": "4.48.1",
|
|
51
49
|
"@wordpress/ui": "0.13.0",
|
|
52
|
-
"@wordpress/url": "4.48.
|
|
50
|
+
"@wordpress/url": "4.48.1",
|
|
53
51
|
"clsx": "2.1.1",
|
|
54
52
|
"debug": "4.4.3"
|
|
55
53
|
},
|
|
56
54
|
"devDependencies": {
|
|
57
55
|
"@automattic/jetpack-webpack-config": "workspace:*",
|
|
58
|
-
"@babel/core": "7.29.
|
|
59
|
-
"@babel/plugin-transform-react-jsx": "7.
|
|
60
|
-
"@babel/preset-react": "7.
|
|
61
|
-
"@babel/runtime": "7.29.
|
|
56
|
+
"@babel/core": "7.29.7",
|
|
57
|
+
"@babel/plugin-transform-react-jsx": "7.29.7",
|
|
58
|
+
"@babel/preset-react": "7.29.7",
|
|
59
|
+
"@babel/runtime": "7.29.7",
|
|
62
60
|
"@testing-library/dom": "10.4.1",
|
|
63
61
|
"@testing-library/react": "16.3.2",
|
|
64
62
|
"@testing-library/user-event": "14.6.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { JETPACK_MODULES_STORE_ID } from '@automattic/jetpack-shared-stores';
|
|
1
2
|
import { useDispatch, useSelect } from '@wordpress/data';
|
|
2
3
|
import { useMemo, useCallback } from '@wordpress/element';
|
|
3
|
-
import { JETPACK_MODULES_STORE_ID } from '../../modules-state';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @typedef {object} ModuleStatus
|
|
@@ -1,108 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Back-compat re-export.
|
|
3
|
+
*
|
|
4
|
+
* The `wordpress-com/plans` store moved to `@automattic/jetpack-shared-stores`
|
|
5
|
+
* so it can be externalized into a single bundle and registered only once.
|
|
6
|
+
* This shim preserves the historical `@automattic/jetpack-shared-extension-utils/store/wordpress-com`
|
|
7
|
+
* import path for existing consumers.
|
|
3
8
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Internal dependencies
|
|
7
|
-
*/
|
|
8
|
-
import actions from './actions.ts';
|
|
9
|
-
import reducer from './reducer.ts';
|
|
10
|
-
/**
|
|
11
|
-
* Types
|
|
12
|
-
*/
|
|
13
|
-
import type { AiFeatureProps, PlanStateProps } from './types.ts';
|
|
14
|
-
|
|
15
|
-
const store = 'wordpress-com/plans';
|
|
16
|
-
|
|
17
|
-
export const selectors = {
|
|
18
|
-
/*
|
|
19
|
-
* Return the plan with the given slug.
|
|
20
|
-
*
|
|
21
|
-
* @param {Object} state - The Plans state tree.
|
|
22
|
-
* @param {string} planSlug - The plan slug to find.
|
|
23
|
-
* @return {Object} The plan.
|
|
24
|
-
*/
|
|
25
|
-
getPlan( state: PlanStateProps, planSlug: string ) {
|
|
26
|
-
return state.plans.find( plan => plan.product_slug === planSlug );
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Return the AI Assistant feature.
|
|
31
|
-
*
|
|
32
|
-
* @param {PlanStateProps} state - The Plans state tree.
|
|
33
|
-
* @return {AiFeatureProps} The AI Assistant feature data.
|
|
34
|
-
*/
|
|
35
|
-
getAiAssistantFeature( state: PlanStateProps ): AiFeatureProps {
|
|
36
|
-
// Clean up the _meta property.
|
|
37
|
-
const data = { ...state.features.aiAssistant };
|
|
38
|
-
delete data._meta;
|
|
39
|
-
|
|
40
|
-
return data;
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Get the isRequesting flag for the AI Assistant feature.
|
|
45
|
-
*
|
|
46
|
-
* @param {PlanStateProps} state - The Plans state tree.
|
|
47
|
-
* @return {boolean} The isRequesting flag.
|
|
48
|
-
*/
|
|
49
|
-
getIsRequestingAiAssistantFeature( state: PlanStateProps ): boolean {
|
|
50
|
-
return state.features.aiAssistant?._meta?.isRequesting;
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
getAsyncRequestCountdownValue( state: PlanStateProps ): number {
|
|
54
|
-
return state.features.aiAssistant?._meta?.asyncRequestCountdown;
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
getAsyncRequestCountdownTimerId( state: PlanStateProps ): number {
|
|
58
|
-
return state.features.aiAssistant?._meta?.asyncRequestTimerId;
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export const wordpressPlansStore = createReduxStore( store, {
|
|
63
|
-
actions,
|
|
64
|
-
|
|
65
|
-
reducer,
|
|
66
|
-
|
|
67
|
-
selectors,
|
|
68
|
-
|
|
69
|
-
controls: {
|
|
70
|
-
FETCH_FROM_API( { url } ) {
|
|
71
|
-
// We cannot use `@wordpress/api-fetch` here since it unconditionally sends
|
|
72
|
-
// the `X-WP-Nonce` header, which is disallowed by WordPress.com.
|
|
73
|
-
// (To reproduce, note that you need to call `apiFetch` with `
|
|
74
|
-
// `{ credentials: 'same-origin', mode: 'cors' }`, since its defaults are
|
|
75
|
-
// different from `fetch`'s.)
|
|
76
|
-
return fetch( url ).then( response => response.json() );
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
resolvers: {
|
|
81
|
-
*getPlan() {
|
|
82
|
-
const url = 'https://public-api.wordpress.com/rest/v1.5/plans';
|
|
83
|
-
const plans = yield actions.fetchFromAPI( url );
|
|
84
|
-
return actions.setPlans( plans );
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
getAiAssistantFeature: ( state: PlanStateProps ) => {
|
|
88
|
-
if ( state?.features?.aiAssistant ) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return actions.fetchAiAssistantFeature();
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
} );
|
|
96
|
-
|
|
97
|
-
register( wordpressPlansStore );
|
|
98
|
-
|
|
99
|
-
// Types
|
|
100
|
-
|
|
101
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
|
-
type OmitFirstArg< F > = F extends ( _: any, ...args: infer P ) => infer R
|
|
103
|
-
? ( ...args: P ) => R
|
|
104
|
-
: never;
|
|
105
|
-
|
|
106
|
-
export type WordPressPlansSelectors = {
|
|
107
|
-
[ key in keyof typeof selectors ]: OmitFirstArg< ( typeof selectors )[ key ] >;
|
|
108
|
-
};
|
|
9
|
+
export { selectors, wordpressPlansStore } from '@automattic/jetpack-shared-stores';
|
|
10
|
+
export type * from '@automattic/jetpack-shared-stores';
|
|
@@ -1,161 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export type UpgradeTypeProp = 'vip' | 'default';
|
|
8
|
-
|
|
9
|
-
export type TierUnlimitedProps = {
|
|
10
|
-
slug: 'ai-assistant-tier-unlimited';
|
|
11
|
-
limit: 999999999 | 3000;
|
|
12
|
-
value: 1;
|
|
13
|
-
readableLimit: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type TierFreeProps = {
|
|
17
|
-
slug: 'ai-assistant-tier-free';
|
|
18
|
-
limit: 20;
|
|
19
|
-
value: 0;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type Tier100Props = {
|
|
23
|
-
slug: 'ai-assistant-tier-100';
|
|
24
|
-
limit: 100;
|
|
25
|
-
value: 100;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type Tier200Props = {
|
|
29
|
-
slug: 'ai-assistant-tier-200';
|
|
30
|
-
limit: 200;
|
|
31
|
-
value: 200;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type Tier500Props = {
|
|
35
|
-
slug: 'ai-assistant-tier-500';
|
|
36
|
-
limit: 500;
|
|
37
|
-
value: 500;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export type Tier750Props = {
|
|
41
|
-
slug: 'ai-assistant-tier-750';
|
|
42
|
-
limit: 750;
|
|
43
|
-
value: 750;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export type Tier1000Props = {
|
|
47
|
-
slug: 'ai-assistant-tier-1000';
|
|
48
|
-
limit: 1000;
|
|
49
|
-
value: 1000;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export type TierProp = {
|
|
53
|
-
slug: TierSlugProp;
|
|
54
|
-
limit: TierLimitProp;
|
|
55
|
-
value: TierValueProp;
|
|
56
|
-
readableLimit?: string;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export type TierLimitProp =
|
|
60
|
-
| TierUnlimitedProps[ 'limit' ]
|
|
61
|
-
| TierFreeProps[ 'limit' ]
|
|
62
|
-
| Tier100Props[ 'limit' ]
|
|
63
|
-
| Tier200Props[ 'limit' ]
|
|
64
|
-
| Tier500Props[ 'limit' ]
|
|
65
|
-
| Tier750Props[ 'limit' ]
|
|
66
|
-
| Tier1000Props[ 'limit' ];
|
|
67
|
-
|
|
68
|
-
export type TierSlugProp =
|
|
69
|
-
| TierUnlimitedProps[ 'slug' ]
|
|
70
|
-
| TierFreeProps[ 'slug' ]
|
|
71
|
-
| Tier100Props[ 'slug' ]
|
|
72
|
-
| Tier200Props[ 'slug' ]
|
|
73
|
-
| Tier500Props[ 'slug' ]
|
|
74
|
-
| Tier750Props[ 'slug' ]
|
|
75
|
-
| Tier1000Props[ 'slug' ];
|
|
76
|
-
|
|
77
|
-
export type TierValueProp =
|
|
78
|
-
| TierUnlimitedProps[ 'value' ]
|
|
79
|
-
| TierFreeProps[ 'value' ]
|
|
80
|
-
| Tier100Props[ 'value' ]
|
|
81
|
-
| Tier200Props[ 'value' ]
|
|
82
|
-
| Tier500Props[ 'value' ]
|
|
83
|
-
| Tier750Props[ 'value' ]
|
|
84
|
-
| Tier1000Props[ 'value' ];
|
|
85
|
-
|
|
86
|
-
export type FeatureControl = {
|
|
87
|
-
enabled: boolean;
|
|
88
|
-
'min-jetpack-version': string;
|
|
89
|
-
[ key: string ]: FeatureControl | boolean | string;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
export type FeaturesControl = { [ key: string ]: FeatureControl };
|
|
93
|
-
|
|
94
|
-
export type AiFeatureProps = {
|
|
95
|
-
hasFeature: boolean;
|
|
96
|
-
isOverLimit: boolean;
|
|
97
|
-
requestsCount: number;
|
|
98
|
-
requestsLimit: number;
|
|
99
|
-
requireUpgrade: boolean;
|
|
100
|
-
errorMessage?: string;
|
|
101
|
-
errorCode?: string;
|
|
102
|
-
upgradeType: UpgradeTypeProp;
|
|
103
|
-
currentTier?: TierProp;
|
|
104
|
-
usagePeriod?: {
|
|
105
|
-
currentStart: string;
|
|
106
|
-
nextStart: string;
|
|
107
|
-
requestsCount: number;
|
|
108
|
-
};
|
|
109
|
-
nextTier?: TierProp | null;
|
|
110
|
-
tierPlansEnabled?: boolean;
|
|
111
|
-
costs?: {
|
|
112
|
-
[ key: string ]: {
|
|
113
|
-
[ key: string ]: number;
|
|
114
|
-
};
|
|
115
|
-
};
|
|
116
|
-
featuresControl?: FeaturesControl;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// Type used in the `wordpress-com/plans` store.
|
|
120
|
-
export type AiFeatureStateProps = AiFeatureProps & {
|
|
121
|
-
_meta?: {
|
|
122
|
-
isRequesting: boolean;
|
|
123
|
-
asyncRequestCountdown: number;
|
|
124
|
-
asyncRequestTimerId: number;
|
|
125
|
-
};
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
export type PlanStateProps = {
|
|
129
|
-
plans: Array< Plan >;
|
|
130
|
-
features: {
|
|
131
|
-
aiAssistant?: AiFeatureStateProps;
|
|
132
|
-
};
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/*
|
|
136
|
-
* `sites/$site/ai-assistant-feature` endpoint response body props
|
|
1
|
+
/**
|
|
2
|
+
* Back-compat re-export.
|
|
3
|
+
*
|
|
4
|
+
* The `wordpress-com/plans` store types moved to `@automattic/jetpack-shared-stores`.
|
|
5
|
+
* This shim preserves the historical
|
|
6
|
+
* `@automattic/jetpack-shared-extension-utils/store/wordpress-com/types` import path.
|
|
137
7
|
*/
|
|
138
|
-
export type
|
|
139
|
-
'has-feature': boolean;
|
|
140
|
-
'is-over-limit': boolean;
|
|
141
|
-
'requests-count': number;
|
|
142
|
-
'requests-limit': number;
|
|
143
|
-
'usage-period': {
|
|
144
|
-
'current-start': string;
|
|
145
|
-
'next-start': string;
|
|
146
|
-
'requests-count': number;
|
|
147
|
-
};
|
|
148
|
-
'site-require-upgrade': boolean;
|
|
149
|
-
'error-message'?: string;
|
|
150
|
-
'error-code'?: string;
|
|
151
|
-
'upgrade-type': UpgradeTypeProp;
|
|
152
|
-
'current-tier': TierProp;
|
|
153
|
-
'tier-plans': Array< TierProp >;
|
|
154
|
-
'next-tier'?: TierProp | null;
|
|
155
|
-
costs?: {
|
|
156
|
-
[ key: string ]: {
|
|
157
|
-
[ key: string ]: number;
|
|
158
|
-
};
|
|
159
|
-
};
|
|
160
|
-
'features-control'?: FeaturesControl;
|
|
161
|
-
};
|
|
8
|
+
export type * from '@automattic/jetpack-shared-stores';
|
package/index.native.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { SvgXml } from '@wordpress/primitives';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Generate an icon as a React component from the SVG markup defined in a block.json metadata file.
|
|
5
|
-
* This prevents us from duplicating the markup in various places.
|
|
6
|
-
*
|
|
7
|
-
* Note: using an `img` tag and passing the SVG markup as a data URI doesn't allow us to
|
|
8
|
-
* dynamically set the icon color later on.
|
|
9
|
-
*
|
|
10
|
-
* @param {object} metadata - Block.json content
|
|
11
|
-
* @return {import('react').JSX.Element|string} Icon component
|
|
12
|
-
*/
|
|
13
|
-
export function getBlockIconComponent( metadata ) {
|
|
14
|
-
// If the SVG has been passed as a string, use SvgXml to correctly parse it.
|
|
15
|
-
if ( typeof metadata.icon === 'string' && metadata.icon.startsWith( '<svg' ) ) {
|
|
16
|
-
return <SvgXml xml={ metadata.icon } />;
|
|
17
|
-
}
|
|
18
|
-
return metadata.icon || '';
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* A block icon needs to be redefined on the front end as a React component, since a string - even
|
|
23
|
-
* SVG markup - is interpreted as a dashicon. This function returns the object that must be passed
|
|
24
|
-
* to the `icon` attribute when registering the block in the front end. It also sets the color
|
|
25
|
-
* of the icon.
|
|
26
|
-
*
|
|
27
|
-
* @param {object} metadata - Block.json content
|
|
28
|
-
* @return {object} Icon property for client registration
|
|
29
|
-
*/
|
|
30
|
-
export function getBlockIconProp( metadata ) {
|
|
31
|
-
return {
|
|
32
|
-
src: getBlockIconComponent( metadata ),
|
|
33
|
-
};
|
|
34
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WordPress dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { store as blockEditorStore } from '@wordpress/block-editor';
|
|
5
|
-
import { select } from '@wordpress/data';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Retrieves host app's namespace e.g. "WordPress" or "Jetpack".
|
|
9
|
-
*
|
|
10
|
-
* @return {string} hostAppNamespace The host app's namespace.
|
|
11
|
-
*/
|
|
12
|
-
export default function getHostAppNamespace() {
|
|
13
|
-
return select( blockEditorStore ).getSettings().hostAppNamespace;
|
|
14
|
-
}
|
package/src/icons.native.scss
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
.jetpack-gutenberg-social-icon {
|
|
2
|
-
fill: $gray-700;
|
|
3
|
-
|
|
4
|
-
&.is-facebook {
|
|
5
|
-
fill: var(--color-facebook);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
&.is-twitter {
|
|
9
|
-
fill: var(--color-twitter);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
&.is-linkedin {
|
|
13
|
-
fill: var(--color-linkedin);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
&.is-tumblr {
|
|
17
|
-
fill: var(--color-tumblr);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
&.is-google {
|
|
21
|
-
fill: var(--color-gplus);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { isSimpleSite } from '@automattic/jetpack-script-data';
|
|
2
|
-
import { select } from '@wordpress/data';
|
|
3
|
-
import {
|
|
4
|
-
fetchJetpackModules,
|
|
5
|
-
updateJetpackModuleStatus as updateJetpackModuleStatusControl,
|
|
6
|
-
} from './controls';
|
|
7
|
-
import { JETPACK_MODULES_STORE_ID } from '.';
|
|
8
|
-
|
|
9
|
-
export const SET_JETPACK_MODULES = 'SET_JETPACK_MODULES';
|
|
10
|
-
export const SET_MODULE_UPDATING = 'SET_MODULE_UPDATING';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Yield actions to update module status
|
|
14
|
-
*
|
|
15
|
-
* @param {object} settings - Jetpack module settings.
|
|
16
|
-
* @param {string} settings.name - Jetpack module name.
|
|
17
|
-
* @param {boolean} settings.active - If the module is active or not.
|
|
18
|
-
* @yield {object} - an action object.
|
|
19
|
-
* @return {object} - an action object.
|
|
20
|
-
*/
|
|
21
|
-
export function* updateJetpackModuleStatus( settings ) {
|
|
22
|
-
try {
|
|
23
|
-
yield setIsUpdating( settings.name, true );
|
|
24
|
-
yield updateJetpackModuleStatusControl( settings );
|
|
25
|
-
const data = yield fetchJetpackModules();
|
|
26
|
-
yield setJetpackModules( { data } );
|
|
27
|
-
return true;
|
|
28
|
-
} catch {
|
|
29
|
-
const oldSettings = select( JETPACK_MODULES_STORE_ID ).getJetpackModules();
|
|
30
|
-
yield setJetpackModules( oldSettings );
|
|
31
|
-
return false;
|
|
32
|
-
} finally {
|
|
33
|
-
yield setIsUpdating( settings.name, false );
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Yield actions to update module status
|
|
39
|
-
* @yield {object} - an action object.
|
|
40
|
-
* @return {boolean} - if operation is successful or not.
|
|
41
|
-
*/
|
|
42
|
-
export function* fetchModules() {
|
|
43
|
-
// We don't fetch modules for Simple Site and aknowledge that all modules are active
|
|
44
|
-
if ( isSimpleSite() ) {
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
yield setIsLoading( true );
|
|
49
|
-
const data = yield fetchJetpackModules();
|
|
50
|
-
yield setJetpackModules( { data } );
|
|
51
|
-
return true;
|
|
52
|
-
} catch {
|
|
53
|
-
const oldSettings = select( JETPACK_MODULES_STORE_ID ).getJetpackModules();
|
|
54
|
-
yield setJetpackModules( oldSettings );
|
|
55
|
-
return false;
|
|
56
|
-
} finally {
|
|
57
|
-
yield setIsLoading( false );
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Set modules as loading action
|
|
63
|
-
*
|
|
64
|
-
* @param {boolean} isLoading - If the modules are loading or not.
|
|
65
|
-
* @return {object} - an action object.
|
|
66
|
-
*/
|
|
67
|
-
export function setIsLoading( isLoading ) {
|
|
68
|
-
return setJetpackModules( { isLoading } );
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Set modules as updating action
|
|
73
|
-
*
|
|
74
|
-
* @param {string} name - Name of the module.
|
|
75
|
-
* @param {boolean} isUpdating - If the modules are updating or not.
|
|
76
|
-
* @return {object} - an action object.
|
|
77
|
-
*/
|
|
78
|
-
function setIsUpdating( name, isUpdating ) {
|
|
79
|
-
return { type: SET_MODULE_UPDATING, name, isUpdating };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Set Jetpack module action
|
|
84
|
-
*
|
|
85
|
-
* @param {object} options - Jetpack settings.
|
|
86
|
-
* @param {object} options.modules - Jetpack modules.
|
|
87
|
-
* @param {boolean} options.isLoading - If the modules are loading or not.
|
|
88
|
-
* @return {object} - an action object.
|
|
89
|
-
*/
|
|
90
|
-
export function setJetpackModules( options ) {
|
|
91
|
-
return { type: SET_JETPACK_MODULES, options };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export default { updateJetpackModuleStatus, setJetpackModules, fetchModules };
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import apiFetch from '@wordpress/api-fetch';
|
|
2
|
-
|
|
3
|
-
export const FETCH_JETPACK_MODULES = 'FETCH_JETPACK_MODULES';
|
|
4
|
-
export const UPDATE_JETPACK_MODULE_STATUS = 'UPDATE_JETPACK_MODULE_STATUS';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* fetchJetpackModules action
|
|
8
|
-
*
|
|
9
|
-
* @return {object} - an action object.
|
|
10
|
-
*/
|
|
11
|
-
export const fetchJetpackModules = () => {
|
|
12
|
-
return {
|
|
13
|
-
type: FETCH_JETPACK_MODULES,
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Updating single module status action
|
|
19
|
-
*
|
|
20
|
-
* @param settings - Jetpack module settings.
|
|
21
|
-
* @param {string} settings.name - Jetpack module name.
|
|
22
|
-
* @param {boolean} settings.active - If the module is active or not.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
export const updateJetpackModuleStatus = settings => {
|
|
26
|
-
return {
|
|
27
|
-
type: UPDATE_JETPACK_MODULE_STATUS,
|
|
28
|
-
settings,
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export default {
|
|
33
|
-
[ FETCH_JETPACK_MODULES ]: function () {
|
|
34
|
-
return apiFetch( {
|
|
35
|
-
path: `/jetpack/v4/module/all`,
|
|
36
|
-
method: 'GET',
|
|
37
|
-
} );
|
|
38
|
-
},
|
|
39
|
-
[ UPDATE_JETPACK_MODULE_STATUS ]: function ( { settings } ) {
|
|
40
|
-
return apiFetch( {
|
|
41
|
-
path: `/jetpack/v4/module/${ settings.name }/active`,
|
|
42
|
-
method: 'POST',
|
|
43
|
-
data: {
|
|
44
|
-
active: settings.active,
|
|
45
|
-
},
|
|
46
|
-
} );
|
|
47
|
-
},
|
|
48
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { createReduxStore, register, dispatch } from '@wordpress/data';
|
|
2
|
-
import actions from './actions';
|
|
3
|
-
import controls from './controls';
|
|
4
|
-
import reducer from './reducer';
|
|
5
|
-
import resolvers from './resolvers';
|
|
6
|
-
import selectors from './selectors';
|
|
7
|
-
|
|
8
|
-
export const JETPACK_MODULES_STORE_ID = 'jetpack-modules';
|
|
9
|
-
export const store = createReduxStore( JETPACK_MODULES_STORE_ID, {
|
|
10
|
-
reducer,
|
|
11
|
-
actions,
|
|
12
|
-
controls,
|
|
13
|
-
resolvers,
|
|
14
|
-
selectors,
|
|
15
|
-
} );
|
|
16
|
-
|
|
17
|
-
register( store );
|
|
18
|
-
|
|
19
|
-
const initialData =
|
|
20
|
-
window?.Initial_State?.getModules || // Jetpack Dashboard
|
|
21
|
-
window?.Jetpack_Editor_Initial_State?.modules || // Gutenberg
|
|
22
|
-
null;
|
|
23
|
-
|
|
24
|
-
// This is a temporary fix to have store filled properly.
|
|
25
|
-
// TODO: Create a proper solution after fixing initial issue (https://github.com/Automattic/jetpack/issues/34793).
|
|
26
|
-
if ( initialData !== null ) {
|
|
27
|
-
dispatch( JETPACK_MODULES_STORE_ID ).setJetpackModules( {
|
|
28
|
-
data: { ...initialData },
|
|
29
|
-
} );
|
|
30
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const defaultState = {
|
|
2
|
-
isLoading: false,
|
|
3
|
-
isUpdating: {},
|
|
4
|
-
data: {},
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
const setModulesData = ( state = defaultState, action ) => {
|
|
8
|
-
switch ( action.type ) {
|
|
9
|
-
case 'SET_JETPACK_MODULES':
|
|
10
|
-
return {
|
|
11
|
-
...state,
|
|
12
|
-
...action.options,
|
|
13
|
-
};
|
|
14
|
-
case 'SET_MODULE_UPDATING':
|
|
15
|
-
return {
|
|
16
|
-
...state,
|
|
17
|
-
...{
|
|
18
|
-
isUpdating: {
|
|
19
|
-
...state.isUpdating,
|
|
20
|
-
[ action.name ]: action.isUpdating,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
return state;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export default setModulesData;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { setIsLoading, setJetpackModules } from './actions';
|
|
2
|
-
import { fetchJetpackModules } from './controls';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Yield actions to get the Jetpack modules.
|
|
6
|
-
*
|
|
7
|
-
* @yield {object} - an action object.
|
|
8
|
-
* @return {object} - an action object.
|
|
9
|
-
*/
|
|
10
|
-
export function* getJetpackModules() {
|
|
11
|
-
try {
|
|
12
|
-
yield setIsLoading( true );
|
|
13
|
-
const data = yield fetchJetpackModules();
|
|
14
|
-
if ( data ) {
|
|
15
|
-
return setJetpackModules( { data } );
|
|
16
|
-
}
|
|
17
|
-
} catch ( e ) {
|
|
18
|
-
console.error( e ); // eslint-disable-line no-console
|
|
19
|
-
} finally {
|
|
20
|
-
yield setIsLoading( false );
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default { getJetpackModules };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { isSimpleSite } from '@automattic/jetpack-script-data';
|
|
2
|
-
|
|
3
|
-
const jetpackModulesSelectors = {
|
|
4
|
-
getJetpackModules: state => state.data,
|
|
5
|
-
// We consider simple sites to have all modules active
|
|
6
|
-
// TODO: we would remove this when wrapping logic with hooks
|
|
7
|
-
isModuleActive: ( state, moduleName ) =>
|
|
8
|
-
isSimpleSite() || ( state?.data?.[ moduleName ]?.activated ?? false ),
|
|
9
|
-
areModulesLoading: state => state.isLoading ?? false,
|
|
10
|
-
isModuleUpdating: ( state, moduleName ) => state?.isUpdating?.[ moduleName ] ?? false,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export default jetpackModulesSelectors;
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External dependencies
|
|
3
|
-
*/
|
|
4
|
-
import apiFetch from '@wordpress/api-fetch';
|
|
5
|
-
/**
|
|
6
|
-
* Types & Constants
|
|
7
|
-
*/
|
|
8
|
-
import {
|
|
9
|
-
ACTION_DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN,
|
|
10
|
-
ACTION_DEQUEUE_ASYNC_REQUEST,
|
|
11
|
-
ACTION_ENQUEUE_ASYNC_REQUEST,
|
|
12
|
-
ACTION_FETCH_FROM_API,
|
|
13
|
-
ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT,
|
|
14
|
-
ACTION_REQUEST_AI_ASSISTANT_FEATURE,
|
|
15
|
-
ACTION_SET_PLANS,
|
|
16
|
-
ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE,
|
|
17
|
-
ACTION_STORE_AI_ASSISTANT_FEATURE,
|
|
18
|
-
ENDPOINT_AI_ASSISTANT_FEATURE,
|
|
19
|
-
NEW_ASYNC_REQUEST_TIMER_INTERVAL,
|
|
20
|
-
ACTION_SET_TIER_PLANS_ENABLED,
|
|
21
|
-
} from './constants.ts';
|
|
22
|
-
import type { Plan, AiFeatureProps, SiteAIAssistantFeatureEndpointResponseProps } from './types.ts';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Map the response from the `sites/$site/ai-assistant-feature`
|
|
26
|
-
* endpoint to the AI Assistant feature props.
|
|
27
|
-
* @param { SiteAIAssistantFeatureEndpointResponseProps } response - The response from the endpoint.
|
|
28
|
-
* @return { AiFeatureProps } The AI Assistant feature props.
|
|
29
|
-
*/
|
|
30
|
-
export function mapAiFeatureResponseToAiFeatureProps(
|
|
31
|
-
response: SiteAIAssistantFeatureEndpointResponseProps
|
|
32
|
-
): AiFeatureProps {
|
|
33
|
-
return {
|
|
34
|
-
hasFeature: !! response[ 'has-feature' ],
|
|
35
|
-
isOverLimit: !! response[ 'is-over-limit' ],
|
|
36
|
-
requestsCount: response[ 'requests-count' ],
|
|
37
|
-
requestsLimit: response[ 'requests-limit' ],
|
|
38
|
-
requireUpgrade: !! response[ 'site-require-upgrade' ],
|
|
39
|
-
errorMessage: response[ 'error-message' ],
|
|
40
|
-
errorCode: response[ 'error-code' ],
|
|
41
|
-
upgradeType: response[ 'upgrade-type' ],
|
|
42
|
-
usagePeriod: {
|
|
43
|
-
currentStart: response[ 'usage-period' ]?.[ 'current-start' ],
|
|
44
|
-
nextStart: response[ 'usage-period' ]?.[ 'next-start' ],
|
|
45
|
-
requestsCount: response[ 'usage-period' ]?.[ 'requests-count' ] || 0,
|
|
46
|
-
},
|
|
47
|
-
currentTier: response[ 'current-tier' ],
|
|
48
|
-
nextTier: response[ 'next-tier' ],
|
|
49
|
-
tierPlansEnabled: !! response[ 'tier-plans-enabled' ],
|
|
50
|
-
costs: response.costs,
|
|
51
|
-
featuresControl: response[ 'features-control' ],
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const actions = {
|
|
56
|
-
setPlans( plans: Array< Plan > ) {
|
|
57
|
-
return {
|
|
58
|
-
type: ACTION_SET_PLANS,
|
|
59
|
-
plans,
|
|
60
|
-
};
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
fetchFromAPI( url: string ) {
|
|
64
|
-
return {
|
|
65
|
-
type: ACTION_FETCH_FROM_API,
|
|
66
|
-
url,
|
|
67
|
-
};
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
storeAiAssistantFeature( feature: AiFeatureProps ) {
|
|
71
|
-
return {
|
|
72
|
-
type: ACTION_STORE_AI_ASSISTANT_FEATURE,
|
|
73
|
-
feature,
|
|
74
|
-
};
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Thunk action to fetch the AI Assistant feature from the API.
|
|
79
|
-
*
|
|
80
|
-
* @return {Function} The thunk action.
|
|
81
|
-
*/
|
|
82
|
-
fetchAiAssistantFeature() {
|
|
83
|
-
return async ( { dispatch } ) => {
|
|
84
|
-
// Dispatch isFetching action.
|
|
85
|
-
dispatch( { type: ACTION_REQUEST_AI_ASSISTANT_FEATURE } );
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
const response: SiteAIAssistantFeatureEndpointResponseProps = await apiFetch( {
|
|
89
|
-
path: ENDPOINT_AI_ASSISTANT_FEATURE,
|
|
90
|
-
} );
|
|
91
|
-
|
|
92
|
-
// Store the feature in the store.
|
|
93
|
-
dispatch(
|
|
94
|
-
actions.storeAiAssistantFeature( mapAiFeatureResponseToAiFeatureProps( response ) )
|
|
95
|
-
);
|
|
96
|
-
} catch ( err ) {
|
|
97
|
-
// @todo: Handle error.
|
|
98
|
-
console.error( err ); // eslint-disable-line no-console
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* This thunk action is used to increase
|
|
105
|
-
* the requests count for the current usage period.
|
|
106
|
-
* @param {number} count - The number of requests to increase. Default is 1.
|
|
107
|
-
* @return {Function} The thunk action.
|
|
108
|
-
*/
|
|
109
|
-
increaseAiAssistantRequestsCount( count: number = 1 ) {
|
|
110
|
-
return ( { dispatch } ) => {
|
|
111
|
-
dispatch( {
|
|
112
|
-
type: ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT,
|
|
113
|
-
count,
|
|
114
|
-
} );
|
|
115
|
-
|
|
116
|
-
// Every time the requests count is increased, decrease the countdown
|
|
117
|
-
dispatch( actions.decreaseAsyncRequestCountdownValue() );
|
|
118
|
-
};
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* This thunk action is used to decrease
|
|
123
|
-
* the countdown value for the new async request.
|
|
124
|
-
* When the countdown reaches 0, enqueue a new async request.
|
|
125
|
-
*
|
|
126
|
-
* @return {Function} The thunk action.
|
|
127
|
-
*/
|
|
128
|
-
decreaseAsyncRequestCountdownValue() {
|
|
129
|
-
return async ( { dispatch, select } ) => {
|
|
130
|
-
dispatch( { type: ACTION_DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN } );
|
|
131
|
-
|
|
132
|
-
const asyncCoundown = select.getAsyncRequestCountdownValue();
|
|
133
|
-
if ( asyncCoundown <= 0 ) {
|
|
134
|
-
dispatch( actions.enqueueAiAssistantFeatureAsyncRequest() );
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* This thunk action is used to enqueue a new async request.
|
|
141
|
-
* If already exist an enqueue request, clear it and enqueue a new one.
|
|
142
|
-
*
|
|
143
|
-
* @return {Function} The thunk action.
|
|
144
|
-
*/
|
|
145
|
-
enqueueAiAssistantFeatureAsyncRequest() {
|
|
146
|
-
return ( { dispatch } ) => {
|
|
147
|
-
// Check if there is already a timer running
|
|
148
|
-
dispatch.dequeueAiAssistantFeatureAsyncRequest();
|
|
149
|
-
|
|
150
|
-
const contdownTimerId = setTimeout( () => {
|
|
151
|
-
dispatch( actions.fetchAiAssistantFeature() );
|
|
152
|
-
}, NEW_ASYNC_REQUEST_TIMER_INTERVAL ); // backend process requires a delay to be able to see the new value
|
|
153
|
-
|
|
154
|
-
dispatch( { type: ACTION_ENQUEUE_ASYNC_REQUEST, timerId: contdownTimerId } );
|
|
155
|
-
};
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* This thunk action is used to dequeue a new async request.
|
|
160
|
-
* It will clear the timer if there is one,
|
|
161
|
-
* canceling the enqueue async request.
|
|
162
|
-
*
|
|
163
|
-
* @return {Function} The thunk action.
|
|
164
|
-
*/
|
|
165
|
-
dequeueAiAssistantFeatureAsyncRequest() {
|
|
166
|
-
return ( { dispatch, select } ) => {
|
|
167
|
-
dispatch( { type: ACTION_DEQUEUE_ASYNC_REQUEST, timerId: 0 } );
|
|
168
|
-
|
|
169
|
-
const timerId = select.getAsyncRequestCountdownTimerId();
|
|
170
|
-
// If there is no timer, there is nothing to clear
|
|
171
|
-
if ( ! timerId ) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
window?.clearTimeout( timerId );
|
|
176
|
-
};
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
setAiAssistantFeatureRequireUpgrade( requireUpgrade: boolean = true ) {
|
|
180
|
-
return {
|
|
181
|
-
type: ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE,
|
|
182
|
-
requireUpgrade,
|
|
183
|
-
};
|
|
184
|
-
},
|
|
185
|
-
|
|
186
|
-
setTierPlansEnabled( tierPlansEnabled: boolean = true ) {
|
|
187
|
-
return {
|
|
188
|
-
type: ACTION_SET_TIER_PLANS_ENABLED,
|
|
189
|
-
tierPlansEnabled,
|
|
190
|
-
};
|
|
191
|
-
},
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
export default actions;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plans actions
|
|
3
|
-
*/
|
|
4
|
-
export const ACTION_SET_PLANS = 'SET_PLANS';
|
|
5
|
-
export const ACTION_FETCH_FROM_API = 'FETCH_FROM_API';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* AI Assistant feature Actions
|
|
9
|
-
*/
|
|
10
|
-
export const ACTION_STORE_AI_ASSISTANT_FEATURE = 'STORE_AI_ASSISTANT_FEATURE';
|
|
11
|
-
export const ACTION_REQUEST_AI_ASSISTANT_FEATURE = 'REQUEST_AI_ASSISTANT_FEATURE';
|
|
12
|
-
export const ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT = 'INCREASE_AI_ASSISTANT_REQUESTS_COUNT';
|
|
13
|
-
export const ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE =
|
|
14
|
-
'SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE';
|
|
15
|
-
export const ACTION_SET_TIER_PLANS_ENABLED = 'SET_TIER_PLANS_ENABLED';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Endpoints
|
|
19
|
-
*/
|
|
20
|
-
export const ENDPOINT_AI_ASSISTANT_FEATURE = '/wpcom/v2/jetpack-ai/ai-assistant-feature';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* New AI Assistant feature async request
|
|
24
|
-
*/
|
|
25
|
-
export const FREE_PLAN_REQUESTS_LIMIT = 20;
|
|
26
|
-
export const UNLIMITED_PLAN_REQUESTS_LIMIT = 3000;
|
|
27
|
-
export const ASYNC_REQUEST_COUNTDOWN_INIT_VALUE = 3;
|
|
28
|
-
export const NEW_ASYNC_REQUEST_TIMER_INTERVAL = 5000;
|
|
29
|
-
export const ACTION_DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN = 'DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN';
|
|
30
|
-
export const ACTION_ENQUEUE_ASYNC_REQUEST = 'ENQUEUE_ASYNC_COUNTDOWN_REQUEST';
|
|
31
|
-
export const ACTION_DEQUEUE_ASYNC_REQUEST = 'DEQUEUE_ASYNC_COUNTDOWN_REQUEST';
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Types & Constants
|
|
3
|
-
*/
|
|
4
|
-
import {
|
|
5
|
-
ACTION_DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN,
|
|
6
|
-
ACTION_ENQUEUE_ASYNC_REQUEST,
|
|
7
|
-
ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT,
|
|
8
|
-
ACTION_REQUEST_AI_ASSISTANT_FEATURE,
|
|
9
|
-
ACTION_SET_PLANS,
|
|
10
|
-
ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE,
|
|
11
|
-
ACTION_STORE_AI_ASSISTANT_FEATURE,
|
|
12
|
-
ASYNC_REQUEST_COUNTDOWN_INIT_VALUE,
|
|
13
|
-
FREE_PLAN_REQUESTS_LIMIT,
|
|
14
|
-
UNLIMITED_PLAN_REQUESTS_LIMIT,
|
|
15
|
-
ACTION_SET_TIER_PLANS_ENABLED,
|
|
16
|
-
} from './constants.ts';
|
|
17
|
-
import type { PlanStateProps, TierLimitProp } from './types.ts';
|
|
18
|
-
|
|
19
|
-
const INITIAL_STATE: PlanStateProps = {
|
|
20
|
-
plans: [],
|
|
21
|
-
features: {
|
|
22
|
-
aiAssistant: {
|
|
23
|
-
hasFeature: true,
|
|
24
|
-
isOverLimit: false,
|
|
25
|
-
requestsCount: 0,
|
|
26
|
-
requestsLimit: FREE_PLAN_REQUESTS_LIMIT,
|
|
27
|
-
requireUpgrade: false,
|
|
28
|
-
errorMessage: '',
|
|
29
|
-
errorCode: '',
|
|
30
|
-
upgradeType: 'default',
|
|
31
|
-
currentTier: {
|
|
32
|
-
slug: 'ai-assistant-tier-free',
|
|
33
|
-
value: 0,
|
|
34
|
-
limit: 20,
|
|
35
|
-
},
|
|
36
|
-
usagePeriod: {
|
|
37
|
-
currentStart: '',
|
|
38
|
-
nextStart: '',
|
|
39
|
-
requestsCount: 0,
|
|
40
|
-
},
|
|
41
|
-
nextTier: null,
|
|
42
|
-
tierPlansEnabled: false,
|
|
43
|
-
_meta: {
|
|
44
|
-
isRequesting: false,
|
|
45
|
-
asyncRequestCountdown: ASYNC_REQUEST_COUNTDOWN_INIT_VALUE,
|
|
46
|
-
asyncRequestTimerId: 0,
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* The reducer of the plan state
|
|
54
|
-
* @param {PlanStateProps} state - The plan state.
|
|
55
|
-
* @param {object} action - The action.
|
|
56
|
-
* @return {PlanStateProps} - The plan state.
|
|
57
|
-
*/
|
|
58
|
-
export default function reducer( state = INITIAL_STATE, action ) {
|
|
59
|
-
switch ( action.type ) {
|
|
60
|
-
case ACTION_SET_PLANS:
|
|
61
|
-
return {
|
|
62
|
-
...state,
|
|
63
|
-
plans: action.plans,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
case ACTION_REQUEST_AI_ASSISTANT_FEATURE:
|
|
67
|
-
return {
|
|
68
|
-
...state,
|
|
69
|
-
features: {
|
|
70
|
-
...state.features,
|
|
71
|
-
aiAssistant: {
|
|
72
|
-
...state.features.aiAssistant,
|
|
73
|
-
_meta: {
|
|
74
|
-
...state.features.aiAssistant._meta,
|
|
75
|
-
isRequesting: true,
|
|
76
|
-
asyncRequestCountdown: ASYNC_REQUEST_COUNTDOWN_INIT_VALUE, // restore the countdown
|
|
77
|
-
asyncRequestTimerId: 0, // reset the timer id
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
case ACTION_STORE_AI_ASSISTANT_FEATURE: {
|
|
84
|
-
return {
|
|
85
|
-
...state,
|
|
86
|
-
features: {
|
|
87
|
-
...state.features,
|
|
88
|
-
aiAssistant: {
|
|
89
|
-
...action.feature,
|
|
90
|
-
_meta: {
|
|
91
|
-
...state.features.aiAssistant._meta,
|
|
92
|
-
isRequesting: false,
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
case ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT: {
|
|
100
|
-
// Usage Period data
|
|
101
|
-
const usagePeriod = state.features.aiAssistant.usagePeriod || { requestsCount: 0 };
|
|
102
|
-
|
|
103
|
-
// Increase requests counters
|
|
104
|
-
const requestsCount = state.features.aiAssistant.requestsCount + action.count;
|
|
105
|
-
usagePeriod.requestsCount += action.count;
|
|
106
|
-
|
|
107
|
-
// Current tier value
|
|
108
|
-
const currentTierValue = state.features.aiAssistant.currentTier?.value;
|
|
109
|
-
|
|
110
|
-
const isFreeTierPlan =
|
|
111
|
-
( typeof currentTierValue === 'undefined' && ! state.features.aiAssistant.hasFeature ) ||
|
|
112
|
-
currentTierValue === 0;
|
|
113
|
-
|
|
114
|
-
const isUnlimitedTierPlan =
|
|
115
|
-
( typeof currentTierValue === 'undefined' && state.features.aiAssistant.hasFeature ) ||
|
|
116
|
-
currentTierValue === 1;
|
|
117
|
-
|
|
118
|
-
// Request limit defined with the current tier limit by default.
|
|
119
|
-
let requestsLimit = state.features.aiAssistant.currentTier?.limit;
|
|
120
|
-
|
|
121
|
-
if ( isUnlimitedTierPlan ) {
|
|
122
|
-
requestsLimit = UNLIMITED_PLAN_REQUESTS_LIMIT;
|
|
123
|
-
} else if ( isFreeTierPlan ) {
|
|
124
|
-
requestsLimit = state.features.aiAssistant.requestsLimit as TierLimitProp;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const currentCount = isFreeTierPlan
|
|
128
|
-
? requestsCount // Free tier plan counts all time requests
|
|
129
|
-
: state.features.aiAssistant.usagePeriod?.requestsCount; // Unlimited tier plan counts usage period requests
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Compute the AI Assistant Feature data optimistically,
|
|
133
|
-
* based on the Jetpack_AI_Helper::get_ai_assistance_feature() helper.
|
|
134
|
-
*
|
|
135
|
-
* @see _inc/lib/class-jetpack-ai-helper.php
|
|
136
|
-
*/
|
|
137
|
-
const isOverLimit = currentCount >= requestsLimit;
|
|
138
|
-
|
|
139
|
-
// highest tier holds a soft limit so requireUpgrade is false on that case (nextTier null means highest tier)
|
|
140
|
-
const requireUpgrade = isOverLimit && state.features.aiAssistant.nextTier !== null;
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
...state,
|
|
144
|
-
features: {
|
|
145
|
-
...state.features,
|
|
146
|
-
aiAssistant: {
|
|
147
|
-
...state.features.aiAssistant,
|
|
148
|
-
isOverLimit,
|
|
149
|
-
requestsCount,
|
|
150
|
-
requireUpgrade,
|
|
151
|
-
usagePeriod: { ...usagePeriod },
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
case ACTION_DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN: {
|
|
158
|
-
return {
|
|
159
|
-
...state,
|
|
160
|
-
features: {
|
|
161
|
-
...state.features,
|
|
162
|
-
aiAssistant: {
|
|
163
|
-
...state.features.aiAssistant,
|
|
164
|
-
_meta: {
|
|
165
|
-
...state.features.aiAssistant._meta,
|
|
166
|
-
asyncRequestCountdown: state.features.aiAssistant._meta.asyncRequestCountdown - 1,
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
case ACTION_ENQUEUE_ASYNC_REQUEST: {
|
|
174
|
-
return {
|
|
175
|
-
...state,
|
|
176
|
-
features: {
|
|
177
|
-
...state.features,
|
|
178
|
-
aiAssistant: {
|
|
179
|
-
...state.features.aiAssistant,
|
|
180
|
-
_meta: {
|
|
181
|
-
...state.features.aiAssistant._meta,
|
|
182
|
-
asyncRequestTimerId: action.timerId,
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
case ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE: {
|
|
190
|
-
/*
|
|
191
|
-
* If we require an upgrade, we are also over the limit;
|
|
192
|
-
* The opposite is not true, we can be over the limit without
|
|
193
|
-
* requiring an upgrade, for example when we are on the highest tier.
|
|
194
|
-
* In this case, we don't want to set isOverLimit to false.
|
|
195
|
-
*/
|
|
196
|
-
return {
|
|
197
|
-
...state,
|
|
198
|
-
features: {
|
|
199
|
-
...state.features,
|
|
200
|
-
aiAssistant: {
|
|
201
|
-
...state.features.aiAssistant,
|
|
202
|
-
requireUpgrade: action.requireUpgrade,
|
|
203
|
-
...( action.requireUpgrade ? { isOverLimit: true } : {} ),
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
case ACTION_SET_TIER_PLANS_ENABLED: {
|
|
210
|
-
return {
|
|
211
|
-
...state,
|
|
212
|
-
features: {
|
|
213
|
-
...state.features,
|
|
214
|
-
aiAssistant: {
|
|
215
|
-
...state.features.aiAssistant,
|
|
216
|
-
tierPlansEnabled: action.tierPlansEnabled,
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return state;
|
|
224
|
-
}
|