@automattic/jetpack-ai-client 0.14.6 → 0.16.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 +17 -0
- package/build/ask-question/sync.d.ts +2 -8
- package/build/ask-question/sync.js +20 -19
- package/build/hooks/use-image-generator/index.js +1 -1
- package/build/hooks/use-save-to-media-library/index.d.ts +12 -0
- package/build/hooks/use-save-to-media-library/index.js +74 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +5 -0
- package/build/libs/index.d.ts +1 -1
- package/build/libs/index.js +1 -1
- package/build/libs/markdown/index.d.ts +2 -2
- package/build/libs/markdown/index.js +2 -2
- package/build/libs/markdown/markdown-to-html.d.ts +8 -1
- package/build/libs/markdown/markdown-to-html.js +10 -1
- package/build/logo-generator/assets/icons/ai.d.ts +6 -0
- package/build/logo-generator/assets/icons/ai.js +8 -0
- package/build/logo-generator/assets/icons/check.d.ts +6 -0
- package/build/logo-generator/assets/icons/check.js +8 -0
- package/build/logo-generator/assets/icons/logo.d.ts +6 -0
- package/build/logo-generator/assets/icons/logo.js +8 -0
- package/build/logo-generator/assets/icons/media.d.ts +6 -0
- package/build/logo-generator/assets/icons/media.js +8 -0
- package/build/logo-generator/components/feature-fetch-failure-screen.d.ts +8 -0
- package/build/logo-generator/components/feature-fetch-failure-screen.js +10 -0
- package/build/logo-generator/components/first-load-screen.d.ts +5 -0
- package/build/logo-generator/components/first-load-screen.js +16 -0
- package/build/logo-generator/components/generator-modal.d.ts +7 -0
- package/build/logo-generator/components/generator-modal.js +177 -0
- package/build/logo-generator/components/history-carousel.d.ts +6 -0
- package/build/logo-generator/components/history-carousel.js +36 -0
- package/build/logo-generator/components/image-loader.d.ts +7 -0
- package/build/logo-generator/components/image-loader.js +12 -0
- package/build/logo-generator/components/logo-presenter.d.ts +4 -0
- package/build/logo-generator/components/logo-presenter.js +100 -0
- package/build/logo-generator/components/prompt.d.ts +5 -0
- package/build/logo-generator/components/prompt.js +96 -0
- package/build/logo-generator/components/upgrade-nudge.d.ts +2 -0
- package/build/logo-generator/components/upgrade-nudge.js +30 -0
- package/build/logo-generator/components/upgrade-screen.d.ts +9 -0
- package/build/logo-generator/components/upgrade-screen.js +24 -0
- package/build/logo-generator/components/visit-site-banner.d.ts +9 -0
- package/build/logo-generator/components/visit-site-banner.js +16 -0
- package/build/logo-generator/constants.d.ts +16 -0
- package/build/logo-generator/constants.js +19 -0
- package/build/logo-generator/hooks/use-checkout.d.ts +4 -0
- package/build/logo-generator/hooks/use-checkout.js +26 -0
- package/build/logo-generator/hooks/use-logo-generator.d.ts +46 -0
- package/build/logo-generator/hooks/use-logo-generator.js +286 -0
- package/build/logo-generator/hooks/use-request-errors.d.ts +16 -0
- package/build/logo-generator/hooks/use-request-errors.js +46 -0
- package/build/logo-generator/index.d.ts +1 -0
- package/build/logo-generator/index.js +1 -0
- package/build/logo-generator/lib/logo-storage.d.ts +58 -0
- package/build/logo-generator/lib/logo-storage.js +123 -0
- package/build/logo-generator/lib/media-exists.d.ts +12 -0
- package/build/logo-generator/lib/media-exists.js +33 -0
- package/build/logo-generator/lib/set-site-logo.d.ts +13 -0
- package/build/logo-generator/lib/set-site-logo.js +26 -0
- package/build/logo-generator/lib/wpcom-limited-request.d.ts +7 -0
- package/build/logo-generator/lib/wpcom-limited-request.js +25 -0
- package/build/logo-generator/store/actions.d.ts +105 -0
- package/build/logo-generator/store/actions.js +193 -0
- package/build/logo-generator/store/constants.d.ts +44 -0
- package/build/logo-generator/store/constants.js +44 -0
- package/build/logo-generator/store/index.d.ts +1 -0
- package/build/logo-generator/store/index.js +19 -0
- package/build/logo-generator/store/initial-state.d.ts +3 -0
- package/build/logo-generator/store/initial-state.js +40 -0
- package/build/logo-generator/store/reducer.d.ts +347 -0
- package/build/logo-generator/store/reducer.js +293 -0
- package/build/logo-generator/store/selectors.d.ts +119 -0
- package/build/logo-generator/store/selectors.js +173 -0
- package/build/logo-generator/store/types.d.ts +164 -0
- package/build/logo-generator/store/types.js +1 -0
- package/build/logo-generator/types.d.ts +84 -0
- package/build/logo-generator/types.js +1 -0
- package/build/types.d.ts +6 -0
- package/package.json +5 -3
- package/src/ask-question/sync.ts +22 -27
- package/src/hooks/use-image-generator/index.ts +1 -1
- package/src/hooks/use-save-to-media-library/index.ts +95 -0
- package/src/index.ts +6 -0
- package/src/libs/index.ts +1 -0
- package/src/libs/markdown/index.ts +2 -2
- package/src/libs/markdown/markdown-to-html.ts +20 -3
- package/src/logo-generator/assets/icons/ai.tsx +21 -0
- package/src/logo-generator/assets/icons/check.tsx +23 -0
- package/src/logo-generator/assets/icons/icons.scss +5 -0
- package/src/logo-generator/assets/icons/logo.tsx +23 -0
- package/src/logo-generator/assets/icons/media.tsx +24 -0
- package/src/logo-generator/assets/images/jetpack-logo.svg +4 -0
- package/src/logo-generator/assets/images/loader.gif +0 -0
- package/src/logo-generator/assets/index.d.ts +3 -0
- package/src/logo-generator/components/feature-fetch-failure-screen.tsx +35 -0
- package/src/logo-generator/components/first-load-screen.scss +12 -0
- package/src/logo-generator/components/first-load-screen.tsx +32 -0
- package/src/logo-generator/components/generator-modal.scss +92 -0
- package/src/logo-generator/components/generator-modal.tsx +280 -0
- package/src/logo-generator/components/history-carousel.scss +36 -0
- package/src/logo-generator/components/history-carousel.tsx +57 -0
- package/src/logo-generator/components/image-loader.tsx +22 -0
- package/src/logo-generator/components/logo-presenter.scss +116 -0
- package/src/logo-generator/components/logo-presenter.tsx +219 -0
- package/src/logo-generator/components/prompt.scss +102 -0
- package/src/logo-generator/components/prompt.tsx +211 -0
- package/src/logo-generator/components/upgrade-nudge.scss +43 -0
- package/src/logo-generator/components/upgrade-nudge.tsx +58 -0
- package/src/logo-generator/components/upgrade-screen.tsx +67 -0
- package/src/logo-generator/components/visit-site-banner.scss +29 -0
- package/src/logo-generator/components/visit-site-banner.tsx +54 -0
- package/src/logo-generator/constants.ts +22 -0
- package/src/logo-generator/hooks/use-checkout.ts +37 -0
- package/src/logo-generator/hooks/use-logo-generator.ts +389 -0
- package/src/logo-generator/hooks/use-request-errors.ts +70 -0
- package/src/logo-generator/index.ts +1 -0
- package/src/logo-generator/lib/logo-storage.ts +166 -0
- package/src/logo-generator/lib/media-exists.ts +42 -0
- package/src/logo-generator/lib/set-site-logo.ts +32 -0
- package/src/logo-generator/lib/wpcom-limited-request.ts +30 -0
- package/src/logo-generator/store/actions.ts +251 -0
- package/src/logo-generator/store/constants.ts +49 -0
- package/src/logo-generator/store/index.ts +25 -0
- package/src/logo-generator/store/initial-state.ts +43 -0
- package/src/logo-generator/store/reducer.ts +387 -0
- package/src/logo-generator/store/selectors.ts +201 -0
- package/src/logo-generator/store/types.ts +207 -0
- package/src/logo-generator/types.ts +99 -0
- package/src/types.ts +8 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types
|
|
3
|
+
*/
|
|
4
|
+
import { Logo } from '../store/types.js';
|
|
5
|
+
import { RemoveFromStorageProps, SaveToStorageProps, UpdateInStorageProps } from '../types.js';
|
|
6
|
+
import { mediaExists } from './media-exists.js';
|
|
7
|
+
|
|
8
|
+
const MAX_LOGOS = 10;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Add an entry to the site's logo history.
|
|
12
|
+
*
|
|
13
|
+
* @param {SaveToStorageProps} saveToStorageProps - The properties to save to storage
|
|
14
|
+
* @param {SaveToStorageProps.siteId} saveToStorageProps.siteId - The site ID
|
|
15
|
+
* @param {SaveToStorageProps.url} saveToStorageProps.url - The URL of the logo
|
|
16
|
+
* @param {SaveToStorageProps.description} saveToStorageProps.description - The description of the logo, based on the prompt used to generate it
|
|
17
|
+
* @param {SaveToStorageProps.mediaId} saveToStorageProps.mediaId - The media ID of the logo on the backend
|
|
18
|
+
*
|
|
19
|
+
* @returns {Logo} The logo that was saved
|
|
20
|
+
*/
|
|
21
|
+
export function stashLogo( { siteId, url, description, mediaId }: SaveToStorageProps ) {
|
|
22
|
+
const storedContent = getSiteLogoHistory( siteId );
|
|
23
|
+
|
|
24
|
+
const logo: Logo = {
|
|
25
|
+
url,
|
|
26
|
+
description,
|
|
27
|
+
mediaId,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
storedContent.push( logo );
|
|
31
|
+
|
|
32
|
+
localStorage.setItem(
|
|
33
|
+
`logo-history-${ siteId }`,
|
|
34
|
+
JSON.stringify( storedContent.slice( -MAX_LOGOS ) )
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return logo;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Update an entry in the site's logo history.
|
|
42
|
+
*
|
|
43
|
+
* @param {UpdateInStorageProps} updateInStorageProps - The properties to update in storage
|
|
44
|
+
* @param {UpdateInStorageProps.siteId} updateInStorageProps.siteId - The site ID
|
|
45
|
+
* @param {UpdateInStorageProps.url} updateInStorageProps.url - The URL of the logo to update
|
|
46
|
+
* @param {UpdateInStorageProps.newUrl} updateInStorageProps.newUrl - The new URL of the logo
|
|
47
|
+
* @param {UpdateInStorageProps.mediaId} updateInStorageProps.mediaId - The new media ID of the logo
|
|
48
|
+
* @returns {Logo} The logo that was updated
|
|
49
|
+
*/
|
|
50
|
+
export function updateLogo( { siteId, url, newUrl, mediaId }: UpdateInStorageProps ) {
|
|
51
|
+
const storedContent = getSiteLogoHistory( siteId );
|
|
52
|
+
|
|
53
|
+
const index = storedContent.findIndex( logo => logo.url === url );
|
|
54
|
+
|
|
55
|
+
if ( index > -1 ) {
|
|
56
|
+
storedContent[ index ].url = newUrl;
|
|
57
|
+
storedContent[ index ].mediaId = mediaId;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
localStorage.setItem(
|
|
61
|
+
`logo-history-${ siteId }`,
|
|
62
|
+
JSON.stringify( storedContent.slice( -MAX_LOGOS ) )
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return storedContent[ index ];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get the logo history for a site.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} siteId - The site ID to get the logo history for
|
|
72
|
+
* @returns {Logo[]} The logo history for the site
|
|
73
|
+
*/
|
|
74
|
+
export function getSiteLogoHistory( siteId: string ) {
|
|
75
|
+
const storedString = localStorage.getItem( `logo-history-${ siteId }` );
|
|
76
|
+
let storedContent: Logo[] = storedString ? JSON.parse( storedString ) : [];
|
|
77
|
+
|
|
78
|
+
// Ensure that the stored content is an array
|
|
79
|
+
if ( ! Array.isArray( storedContent ) ) {
|
|
80
|
+
storedContent = [];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Ensure a maximum of 10 logos are stored
|
|
84
|
+
storedContent = storedContent.slice( -MAX_LOGOS );
|
|
85
|
+
|
|
86
|
+
// Ensure that the stored content is an array of Logo objects
|
|
87
|
+
storedContent = storedContent
|
|
88
|
+
.filter( logo => {
|
|
89
|
+
return (
|
|
90
|
+
typeof logo === 'object' &&
|
|
91
|
+
typeof logo.url === 'string' &&
|
|
92
|
+
typeof logo.description === 'string'
|
|
93
|
+
);
|
|
94
|
+
} )
|
|
95
|
+
.map( logo => ( {
|
|
96
|
+
url: logo.url,
|
|
97
|
+
description: logo.description,
|
|
98
|
+
mediaId: logo.mediaId,
|
|
99
|
+
} ) );
|
|
100
|
+
|
|
101
|
+
return storedContent;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if the logo history for a site is empty.
|
|
106
|
+
*
|
|
107
|
+
* @param {string }siteId - The site ID to check the logo history for
|
|
108
|
+
* @returns {boolean} Whether the logo history for the site is empty
|
|
109
|
+
*/
|
|
110
|
+
export function isLogoHistoryEmpty( siteId: string ) {
|
|
111
|
+
const storedContent = getSiteLogoHistory( siteId );
|
|
112
|
+
|
|
113
|
+
return storedContent.length === 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Remove an entry from the site's logo history.
|
|
118
|
+
*
|
|
119
|
+
* @param {RemoveFromStorageProps} removeFromStorageProps - The properties to remove from storage
|
|
120
|
+
* @param {RemoveFromStorageProps.siteId} removeFromStorageProps.siteId - The site ID
|
|
121
|
+
* @param {RemoveFromStorageProps.mediaId} removeFromStorageProps.mediaId - The media ID of the logo to remove
|
|
122
|
+
* @returns {void}
|
|
123
|
+
*/
|
|
124
|
+
export function removeLogo( { siteId, mediaId }: RemoveFromStorageProps ) {
|
|
125
|
+
const storedContent = getSiteLogoHistory( siteId );
|
|
126
|
+
const index = storedContent.findIndex( logo => logo.mediaId === mediaId );
|
|
127
|
+
|
|
128
|
+
if ( index === -1 ) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
storedContent.splice( index, 1 );
|
|
133
|
+
localStorage.setItem( `logo-history-${ siteId }`, JSON.stringify( storedContent ) );
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Clear deleted media from the site's logo history, checking if the media still exists on the backend.
|
|
138
|
+
*
|
|
139
|
+
* @param {string} siteId - The site ID to clear deleted media for
|
|
140
|
+
* @returns {Promise<void>}
|
|
141
|
+
*/
|
|
142
|
+
export async function clearDeletedMedia( siteId: string ) {
|
|
143
|
+
const storedContent = getSiteLogoHistory( siteId );
|
|
144
|
+
|
|
145
|
+
const checks = storedContent
|
|
146
|
+
.filter( ( { mediaId } ) => mediaId !== undefined )
|
|
147
|
+
.map(
|
|
148
|
+
( { mediaId } ) =>
|
|
149
|
+
new Promise( ( resolve, reject ) => {
|
|
150
|
+
mediaExists( { siteId, mediaId } )
|
|
151
|
+
.then( exists => resolve( { mediaId, exists } ) )
|
|
152
|
+
.catch( error => reject( error ) );
|
|
153
|
+
} )
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const responses = ( await Promise.all( checks ) ) as {
|
|
158
|
+
mediaId: Logo[ 'mediaId' ];
|
|
159
|
+
exists: boolean;
|
|
160
|
+
}[];
|
|
161
|
+
|
|
162
|
+
responses
|
|
163
|
+
.filter( ( { exists } ) => ! exists )
|
|
164
|
+
.forEach( ( { mediaId } ) => removeLogo( { siteId, mediaId } ) );
|
|
165
|
+
} catch ( error ) {} // Assume that the media exists if there was a network error and do nothing to avoid data loss.
|
|
166
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import apiFetch from '../../api-fetch/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Types
|
|
7
|
+
*/
|
|
8
|
+
import type { CheckMediaProps } from '../types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Uses the media information to confirm it exists or not on the server.
|
|
12
|
+
*
|
|
13
|
+
* @param {CheckMediaProps} checkMediaProps - the media details to check
|
|
14
|
+
* @param {CheckMediaProps.mediaId} checkMediaProps.mediaId - the id of the media to check
|
|
15
|
+
* @returns {Promise<boolean>} - true if the media exists, false otherwise
|
|
16
|
+
*/
|
|
17
|
+
export async function mediaExists( { mediaId }: CheckMediaProps ): Promise< boolean > {
|
|
18
|
+
const id = Number( mediaId );
|
|
19
|
+
|
|
20
|
+
if ( Number.isNaN( id ) ) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Using apiFetch directly here because we don't want to limit the number of concurrent media checks
|
|
26
|
+
// We store at most 10 logos in the local storage, so the number of concurrent requests should be limited
|
|
27
|
+
await apiFetch( {
|
|
28
|
+
path: `/wp/v2/media/${ Number( mediaId ) }`,
|
|
29
|
+
method: 'GET',
|
|
30
|
+
} );
|
|
31
|
+
|
|
32
|
+
return true;
|
|
33
|
+
} catch ( error ) {
|
|
34
|
+
const status = ( error as { data?: { status?: number } } )?.data?.status;
|
|
35
|
+
|
|
36
|
+
if ( status === 404 ) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import wpcomLimitedRequest from './wpcom-limited-request.js';
|
|
5
|
+
/**
|
|
6
|
+
* Types
|
|
7
|
+
*/
|
|
8
|
+
import type { SetSiteLogoProps, SetSiteLogoResponseProps } from '../types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Set the site logo using a backend request.
|
|
12
|
+
*
|
|
13
|
+
* @param {SetSiteLogoProps} setSiteLogoProps - The properties to set the site logo
|
|
14
|
+
* @param {SetSiteLogoProps.siteId} setSiteLogoProps.siteId - The site ID
|
|
15
|
+
* @param {SetSiteLogoProps.imageId} setSiteLogoProps.imageId - The image ID to set as the site logo
|
|
16
|
+
* @returns {Promise<SetSiteLogoResponseProps>} The response from the request
|
|
17
|
+
*/
|
|
18
|
+
export async function setSiteLogo( { siteId, imageId }: SetSiteLogoProps ) {
|
|
19
|
+
const body = {
|
|
20
|
+
site_logo: imageId,
|
|
21
|
+
site_icon: imageId,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return wpcomLimitedRequest< SetSiteLogoResponseProps >( {
|
|
25
|
+
path: `/sites/${ String( siteId ) }/settings`,
|
|
26
|
+
apiVersion: 'v2',
|
|
27
|
+
apiNamespace: 'wp/v2',
|
|
28
|
+
body,
|
|
29
|
+
query: 'source=jetpack-ai',
|
|
30
|
+
method: 'POST',
|
|
31
|
+
} );
|
|
32
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import apiFetch from '../../api-fetch/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Types
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const MAX_CONCURRENT_REQUESTS = 5;
|
|
10
|
+
|
|
11
|
+
let concurrentCounter = 0;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Concurrency-limited request to wpcom-proxy-request.
|
|
15
|
+
* @param { object } params - The request params, as expected by apiFetch.
|
|
16
|
+
* @returns { Promise } The response.
|
|
17
|
+
* @throws { Error } If there are too many concurrent requests.
|
|
18
|
+
*/
|
|
19
|
+
export default async function wpcomLimitedRequest< T >( params: object ): Promise< T > {
|
|
20
|
+
concurrentCounter += 1;
|
|
21
|
+
|
|
22
|
+
if ( concurrentCounter > MAX_CONCURRENT_REQUESTS ) {
|
|
23
|
+
concurrentCounter -= 1;
|
|
24
|
+
throw new Error( 'Too many requests' );
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return apiFetch< T >( params ).finally( () => {
|
|
28
|
+
concurrentCounter -= 1;
|
|
29
|
+
} );
|
|
30
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { getSiteLogoHistory } from '../lib/logo-storage.js';
|
|
5
|
+
import wpcomLimitedRequest from '../lib/wpcom-limited-request.js';
|
|
6
|
+
/**
|
|
7
|
+
* Types & Constants
|
|
8
|
+
*/
|
|
9
|
+
import {
|
|
10
|
+
ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT,
|
|
11
|
+
ACTION_REQUEST_AI_ASSISTANT_FEATURE,
|
|
12
|
+
ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE,
|
|
13
|
+
ACTION_SET_SITE_DETAILS,
|
|
14
|
+
ACTION_STORE_AI_ASSISTANT_FEATURE,
|
|
15
|
+
ACTION_SET_TIER_PLANS_ENABLED,
|
|
16
|
+
ACTION_SET_SELECTED_LOGO_INDEX,
|
|
17
|
+
ACTION_ADD_LOGO_TO_HISTORY,
|
|
18
|
+
ACTION_SET_IS_SAVING_LOGO_TO_LIBRARY,
|
|
19
|
+
ACTION_SAVE_SELECTED_LOGO,
|
|
20
|
+
ACTION_SET_IS_REQUESTING_IMAGE,
|
|
21
|
+
ACTION_SET_IS_APPLYING_LOGO,
|
|
22
|
+
ACTION_SET_IS_ENHANCING_PROMPT,
|
|
23
|
+
ACTION_SET_SITE_HISTORY,
|
|
24
|
+
ACTION_SET_FEATURE_FETCH_ERROR,
|
|
25
|
+
ACTION_SET_FIRST_LOGO_PROMPT_FETCH_ERROR,
|
|
26
|
+
ACTION_SET_ENHANCE_PROMPT_FETCH_ERROR,
|
|
27
|
+
ACTION_SET_LOGO_FETCH_ERROR,
|
|
28
|
+
ACTION_SET_LOGO_UPDATE_ERROR,
|
|
29
|
+
ACTION_SET_SAVE_TO_LIBRARY_ERROR,
|
|
30
|
+
ACTION_SET_CONTEXT,
|
|
31
|
+
} from './constants.js';
|
|
32
|
+
import type {
|
|
33
|
+
AiFeatureProps,
|
|
34
|
+
AiAssistantFeatureEndpointResponseProps,
|
|
35
|
+
Logo,
|
|
36
|
+
RequestError,
|
|
37
|
+
} from './types.js';
|
|
38
|
+
import type { SiteDetails } from '../types.js';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Map the response from the `sites/$site/ai-assistant-feature`
|
|
42
|
+
* endpoint to the AI Assistant feature props.
|
|
43
|
+
* @param { AiAssistantFeatureEndpointResponseProps } response - The response from the endpoint.
|
|
44
|
+
* @returns { AiFeatureProps } The AI Assistant feature props.
|
|
45
|
+
*/
|
|
46
|
+
export function mapAiFeatureResponseToAiFeatureProps(
|
|
47
|
+
response: AiAssistantFeatureEndpointResponseProps
|
|
48
|
+
): AiFeatureProps {
|
|
49
|
+
return {
|
|
50
|
+
hasFeature: !! response[ 'has-feature' ],
|
|
51
|
+
isOverLimit: !! response[ 'is-over-limit' ],
|
|
52
|
+
requestsCount: response[ 'requests-count' ],
|
|
53
|
+
requestsLimit: response[ 'requests-limit' ],
|
|
54
|
+
requireUpgrade: !! response[ 'site-require-upgrade' ],
|
|
55
|
+
errorMessage: response[ 'error-message' ],
|
|
56
|
+
errorCode: response[ 'error-code' ],
|
|
57
|
+
upgradeType: response[ 'upgrade-type' ],
|
|
58
|
+
usagePeriod: {
|
|
59
|
+
currentStart: response[ 'usage-period' ]?.[ 'current-start' ],
|
|
60
|
+
nextStart: response[ 'usage-period' ]?.[ 'next-start' ],
|
|
61
|
+
requestsCount: response[ 'usage-period' ]?.[ 'requests-count' ] || 0,
|
|
62
|
+
},
|
|
63
|
+
currentTier: response[ 'current-tier' ],
|
|
64
|
+
nextTier: response[ 'next-tier' ],
|
|
65
|
+
tierPlansEnabled: !! response[ 'tier-plans-enabled' ],
|
|
66
|
+
costs: response.costs,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const actions = {
|
|
71
|
+
storeAiAssistantFeature( feature: AiFeatureProps ) {
|
|
72
|
+
return {
|
|
73
|
+
type: ACTION_STORE_AI_ASSISTANT_FEATURE,
|
|
74
|
+
feature,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Thunk action to fetch the AI Assistant feature from the API.
|
|
80
|
+
* @returns {Function} The thunk action.
|
|
81
|
+
*/
|
|
82
|
+
fetchAiAssistantFeature() {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
return async ( { dispatch }: { dispatch: any } ) => {
|
|
85
|
+
// Dispatch isFetching action.
|
|
86
|
+
dispatch( { type: ACTION_REQUEST_AI_ASSISTANT_FEATURE } );
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const response: AiAssistantFeatureEndpointResponseProps = await wpcomLimitedRequest( {
|
|
90
|
+
path: '/wpcom/v2/jetpack-ai/ai-assistant-feature',
|
|
91
|
+
query: 'force=wpcom',
|
|
92
|
+
} );
|
|
93
|
+
|
|
94
|
+
// Store the feature in the store.
|
|
95
|
+
dispatch(
|
|
96
|
+
actions.storeAiAssistantFeature( mapAiFeatureResponseToAiFeatureProps( response ) )
|
|
97
|
+
);
|
|
98
|
+
} catch ( err ) {
|
|
99
|
+
// Mark the fetch as failed.
|
|
100
|
+
dispatch( { type: ACTION_SET_FEATURE_FETCH_ERROR, error: err } );
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* This thunk action is used to increase
|
|
107
|
+
* the requests count for the current usage period.
|
|
108
|
+
* @param {number} count - The number of requests to increase. Default is 1.
|
|
109
|
+
* @returns {Function} The thunk action.
|
|
110
|
+
*/
|
|
111
|
+
increaseAiAssistantRequestsCount( count: number = 1 ) {
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
113
|
+
return ( { dispatch }: { dispatch: any } ) => {
|
|
114
|
+
dispatch( {
|
|
115
|
+
type: ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT,
|
|
116
|
+
count,
|
|
117
|
+
} );
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
setAiAssistantFeatureRequireUpgrade( requireUpgrade: boolean = true ) {
|
|
122
|
+
return {
|
|
123
|
+
type: ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE,
|
|
124
|
+
requireUpgrade,
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
setTierPlansEnabled( tierPlansEnabled: boolean = true ) {
|
|
129
|
+
return {
|
|
130
|
+
type: ACTION_SET_TIER_PLANS_ENABLED,
|
|
131
|
+
tierPlansEnabled,
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
setSiteDetails( siteDetails: SiteDetails ) {
|
|
136
|
+
return {
|
|
137
|
+
type: ACTION_SET_SITE_DETAILS,
|
|
138
|
+
siteDetails,
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
setSelectedLogoIndex( selectedLogoIndex: number ) {
|
|
143
|
+
return {
|
|
144
|
+
type: ACTION_SET_SELECTED_LOGO_INDEX,
|
|
145
|
+
selectedLogoIndex,
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
addLogoToHistory( logo: Logo ) {
|
|
150
|
+
return {
|
|
151
|
+
type: ACTION_ADD_LOGO_TO_HISTORY,
|
|
152
|
+
logo,
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
setIsSavingLogoToLibrary( isSavingLogoToLibrary: boolean ) {
|
|
157
|
+
return {
|
|
158
|
+
type: ACTION_SET_IS_SAVING_LOGO_TO_LIBRARY,
|
|
159
|
+
isSavingLogoToLibrary,
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
setIsApplyingLogo( isApplyingLogo: boolean ) {
|
|
164
|
+
return {
|
|
165
|
+
type: ACTION_SET_IS_APPLYING_LOGO,
|
|
166
|
+
isApplyingLogo,
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
updateSelectedLogo( mediaId: string, url: string ) {
|
|
171
|
+
return {
|
|
172
|
+
type: ACTION_SAVE_SELECTED_LOGO,
|
|
173
|
+
mediaId,
|
|
174
|
+
url,
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
setIsRequestingImage( isRequestingImage: boolean ) {
|
|
179
|
+
return {
|
|
180
|
+
type: ACTION_SET_IS_REQUESTING_IMAGE,
|
|
181
|
+
isRequestingImage,
|
|
182
|
+
};
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
setIsEnhancingPrompt( isEnhancingPrompt: boolean ) {
|
|
186
|
+
return {
|
|
187
|
+
type: ACTION_SET_IS_ENHANCING_PROMPT,
|
|
188
|
+
isEnhancingPrompt,
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
loadLogoHistory( siteId: string ) {
|
|
193
|
+
const history = getSiteLogoHistory( siteId );
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
type: ACTION_SET_SITE_HISTORY,
|
|
197
|
+
history,
|
|
198
|
+
};
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
setFeatureFetchError( error: RequestError ) {
|
|
202
|
+
return {
|
|
203
|
+
type: ACTION_SET_FEATURE_FETCH_ERROR,
|
|
204
|
+
error,
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
setFirstLogoPromptFetchError( error: RequestError ) {
|
|
209
|
+
return {
|
|
210
|
+
type: ACTION_SET_FIRST_LOGO_PROMPT_FETCH_ERROR,
|
|
211
|
+
error,
|
|
212
|
+
};
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
setEnhancePromptFetchError( error: RequestError ) {
|
|
216
|
+
return {
|
|
217
|
+
type: ACTION_SET_ENHANCE_PROMPT_FETCH_ERROR,
|
|
218
|
+
error,
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
setLogoFetchError( error: RequestError ) {
|
|
223
|
+
return {
|
|
224
|
+
type: ACTION_SET_LOGO_FETCH_ERROR,
|
|
225
|
+
error,
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
setSaveToLibraryError( error: RequestError ) {
|
|
230
|
+
return {
|
|
231
|
+
type: ACTION_SET_SAVE_TO_LIBRARY_ERROR,
|
|
232
|
+
error,
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
setLogoUpdateError( error: RequestError ) {
|
|
237
|
+
return {
|
|
238
|
+
type: ACTION_SET_LOGO_UPDATE_ERROR,
|
|
239
|
+
error,
|
|
240
|
+
};
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
setContext( context: string ) {
|
|
244
|
+
return {
|
|
245
|
+
type: ACTION_SET_CONTEXT,
|
|
246
|
+
context,
|
|
247
|
+
};
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
export default actions;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Assistant feature actions
|
|
3
|
+
*/
|
|
4
|
+
export const ACTION_STORE_AI_ASSISTANT_FEATURE = 'STORE_AI_ASSISTANT_FEATURE';
|
|
5
|
+
export const ACTION_REQUEST_AI_ASSISTANT_FEATURE = 'REQUEST_AI_ASSISTANT_FEATURE';
|
|
6
|
+
export const ACTION_INCREASE_AI_ASSISTANT_REQUESTS_COUNT = 'INCREASE_AI_ASSISTANT_REQUESTS_COUNT';
|
|
7
|
+
export const ACTION_SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE =
|
|
8
|
+
'SET_AI_ASSISTANT_FEATURE_REQUIRE_UPGRADE';
|
|
9
|
+
export const ACTION_SET_TIER_PLANS_ENABLED = 'SET_TIER_PLANS_ENABLED';
|
|
10
|
+
export const ACTION_SET_SITE_DETAILS = 'SET_SITE_DETAILS';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Endpoints
|
|
14
|
+
*/
|
|
15
|
+
export const ENDPOINT_AI_ASSISTANT_FEATURE = '/wpcom/v2/jetpack-ai/ai-assistant-feature';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* New AI Assistant feature async request
|
|
19
|
+
*/
|
|
20
|
+
export const FREE_PLAN_REQUESTS_LIMIT = 20;
|
|
21
|
+
export const UNLIMITED_PLAN_REQUESTS_LIMIT = 999999999;
|
|
22
|
+
export const ASYNC_REQUEST_COUNTDOWN_INIT_VALUE = 3;
|
|
23
|
+
export const NEW_ASYNC_REQUEST_TIMER_INTERVAL = 5000;
|
|
24
|
+
export const ACTION_DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN = 'DECREASE_NEW_ASYNC_REQUEST_COUNTDOWN';
|
|
25
|
+
export const ACTION_ENQUEUE_ASYNC_REQUEST = 'ENQUEUE_ASYNC_COUNTDOWN_REQUEST';
|
|
26
|
+
export const ACTION_DEQUEUE_ASYNC_REQUEST = 'DEQUEUE_ASYNC_COUNTDOWN_REQUEST';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Logo generator actions
|
|
30
|
+
*/
|
|
31
|
+
export const ACTION_SET_CONTEXT = 'SET_CONTEXT';
|
|
32
|
+
export const ACTION_SET_SELECTED_LOGO_INDEX = 'SET_SELECTED_LOGO_INDEX';
|
|
33
|
+
export const ACTION_ADD_LOGO_TO_HISTORY = 'ADD_LOGO_TO_HISTORY';
|
|
34
|
+
export const ACTION_SET_IS_SAVING_LOGO_TO_LIBRARY = 'SET_IS_SAVING_LOGO_TO_LIBRARY';
|
|
35
|
+
export const ACTION_SET_IS_APPLYING_LOGO = 'SET_IS_APPLYING_LOGO';
|
|
36
|
+
export const ACTION_SAVE_SELECTED_LOGO = 'SAVE_SELECTED_LOGO';
|
|
37
|
+
export const ACTION_SET_IS_REQUESTING_IMAGE = 'SET_IS_REQUESTING_IMAGE';
|
|
38
|
+
export const ACTION_SET_IS_ENHANCING_PROMPT = 'SET_IS_ENHANCING_PROMPT';
|
|
39
|
+
export const ACTION_SET_SITE_HISTORY = 'SET_SITE_HISTORY';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Logo generator error actions
|
|
43
|
+
*/
|
|
44
|
+
export const ACTION_SET_FEATURE_FETCH_ERROR = 'SET_FEATURE_FETCH_ERROR';
|
|
45
|
+
export const ACTION_SET_FIRST_LOGO_PROMPT_FETCH_ERROR = 'SET_FIRST_LOGO_PROMPT_FETCH_ERROR';
|
|
46
|
+
export const ACTION_SET_ENHANCE_PROMPT_FETCH_ERROR = 'SET_ENHANCE_PROMPT_FETCH_ERROR';
|
|
47
|
+
export const ACTION_SET_LOGO_FETCH_ERROR = 'SET_LOGO_FETCH_ERROR';
|
|
48
|
+
export const ACTION_SET_SAVE_TO_LIBRARY_ERROR = 'SET_SAVE_TO_LIBRARY_ERROR';
|
|
49
|
+
export const ACTION_SET_LOGO_UPDATE_ERROR = 'SET_LOGO_UPDATE_ERROR';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { createReduxStore, register } from '@wordpress/data';
|
|
5
|
+
/**
|
|
6
|
+
* Internal dependencies
|
|
7
|
+
*/
|
|
8
|
+
import actions from './actions.js';
|
|
9
|
+
import reducer from './reducer.js';
|
|
10
|
+
import selectors from './selectors.js';
|
|
11
|
+
|
|
12
|
+
export const STORE_NAME = 'jetpack-ai/logo-generator';
|
|
13
|
+
|
|
14
|
+
const jetpackAiLogoGeneratorStore = createReduxStore( STORE_NAME, {
|
|
15
|
+
// @ts-expect-error -- TSCONVERSION
|
|
16
|
+
__experimentalUseThunks: true,
|
|
17
|
+
|
|
18
|
+
actions,
|
|
19
|
+
|
|
20
|
+
reducer,
|
|
21
|
+
|
|
22
|
+
selectors,
|
|
23
|
+
} );
|
|
24
|
+
|
|
25
|
+
register( jetpackAiLogoGeneratorStore );
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types & Constants
|
|
3
|
+
*/
|
|
4
|
+
import { ASYNC_REQUEST_COUNTDOWN_INIT_VALUE, FREE_PLAN_REQUESTS_LIMIT } from './constants.js';
|
|
5
|
+
import { LogoGeneratorStateProp } from './types.js';
|
|
6
|
+
|
|
7
|
+
const INITIAL_STATE: LogoGeneratorStateProp = {
|
|
8
|
+
siteDetails: {},
|
|
9
|
+
features: {
|
|
10
|
+
aiAssistantFeature: {
|
|
11
|
+
hasFeature: true,
|
|
12
|
+
isOverLimit: false,
|
|
13
|
+
requestsCount: 0,
|
|
14
|
+
requestsLimit: FREE_PLAN_REQUESTS_LIMIT,
|
|
15
|
+
requireUpgrade: false,
|
|
16
|
+
errorMessage: '',
|
|
17
|
+
errorCode: '',
|
|
18
|
+
upgradeType: 'default',
|
|
19
|
+
currentTier: {
|
|
20
|
+
slug: 'ai-assistant-tier-free',
|
|
21
|
+
value: 0,
|
|
22
|
+
limit: 20,
|
|
23
|
+
},
|
|
24
|
+
usagePeriod: {
|
|
25
|
+
currentStart: '',
|
|
26
|
+
nextStart: '',
|
|
27
|
+
requestsCount: 0,
|
|
28
|
+
},
|
|
29
|
+
nextTier: null,
|
|
30
|
+
tierPlansEnabled: false,
|
|
31
|
+
_meta: {
|
|
32
|
+
isRequesting: false,
|
|
33
|
+
asyncRequestCountdown: ASYNC_REQUEST_COUNTDOWN_INIT_VALUE,
|
|
34
|
+
asyncRequestTimerId: 0,
|
|
35
|
+
isRequestingImage: false,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
history: [],
|
|
40
|
+
selectedLogoIndex: 0,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default INITIAL_STATE;
|