@automattic/jetpack-shared-extension-utils 2.0.0 → 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 +6 -0
- package/index.js +1 -1
- package/package.json +21 -20
- 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/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,11 @@ 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
|
+
|
|
8
13
|
## [2.0.0] - 2026-06-15
|
|
9
14
|
### Removed
|
|
10
15
|
- Remove `react-native` export condition. [#49526]
|
|
@@ -974,6 +979,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
974
979
|
### Changed
|
|
975
980
|
- Core: prepare utility for release
|
|
976
981
|
|
|
982
|
+
[2.0.1]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/2.0.0...2.0.1
|
|
977
983
|
[2.0.0]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/1.5.22...2.0.0
|
|
978
984
|
[1.5.22]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/1.5.21...1.5.22
|
|
979
985
|
[1.5.21]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/1.5.20...1.5.21
|
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": "2.0.
|
|
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": {
|
|
@@ -29,33 +29,34 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@automattic/color-studio": "4.1.0",
|
|
31
31
|
"@automattic/jetpack-analytics": "^1.0.15",
|
|
32
|
-
"@automattic/jetpack-base-styles": "^1.2.
|
|
33
|
-
"@automattic/jetpack-components": "^1.12.
|
|
34
|
-
"@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",
|
|
35
35
|
"@automattic/jetpack-script-data": "^0.6.4",
|
|
36
|
+
"@automattic/jetpack-shared-stores": "^0.1.0",
|
|
36
37
|
"@types/jest": "30.0.0",
|
|
37
|
-
"@wordpress/api-fetch": "7.48.
|
|
38
|
-
"@wordpress/block-editor": "15.21.
|
|
39
|
-
"@wordpress/components": "35.0.
|
|
40
|
-
"@wordpress/compose": "8.1.
|
|
41
|
-
"@wordpress/data": "10.48.
|
|
42
|
-
"@wordpress/dom-ready": "4.48.
|
|
43
|
-
"@wordpress/element": "8.0.
|
|
44
|
-
"@wordpress/hooks": "4.48.
|
|
45
|
-
"@wordpress/i18n": "6.21.
|
|
46
|
-
"@wordpress/plugins": "7.48.
|
|
47
|
-
"@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",
|
|
48
49
|
"@wordpress/ui": "0.13.0",
|
|
49
|
-
"@wordpress/url": "4.48.
|
|
50
|
+
"@wordpress/url": "4.48.1",
|
|
50
51
|
"clsx": "2.1.1",
|
|
51
52
|
"debug": "4.4.3"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"@automattic/jetpack-webpack-config": "workspace:*",
|
|
55
|
-
"@babel/core": "7.29.
|
|
56
|
-
"@babel/plugin-transform-react-jsx": "7.
|
|
57
|
-
"@babel/preset-react": "7.
|
|
58
|
-
"@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",
|
|
59
60
|
"@testing-library/dom": "10.4.1",
|
|
60
61
|
"@testing-library/react": "16.3.2",
|
|
61
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';
|
|
@@ -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
|
-
}
|