initial
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { createReduxStore, register } from '@wordpress/data';
|
||||
|
||||
// Per-user dismissed flag, persisted server-side so it follows the user across
|
||||
// devices/browsers. The initial value is preloaded into the page by PHP (see
|
||||
// _inc/content-guidelines-ai.php); dismissal is written via this REST route.
|
||||
const DISMISS_PATH = '/wpcom/v2/jetpack-ai/guidelines-banner-dismissed';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
loading: false,
|
||||
loadingSections: {},
|
||||
suggestions: {},
|
||||
bannerDismissed: !! window.jetpackContentGuidelinesAi?.bannerDismissed,
|
||||
};
|
||||
|
||||
const actions = {
|
||||
startLoading() {
|
||||
return { type: 'START_LOADING' };
|
||||
},
|
||||
stopLoading() {
|
||||
return { type: 'STOP_LOADING' };
|
||||
},
|
||||
setSuggestion( slug, text ) {
|
||||
return { type: 'SET_SUGGESTION', slug, text };
|
||||
},
|
||||
clearSuggestion( slug ) {
|
||||
return { type: 'CLEAR_SUGGESTION', slug };
|
||||
},
|
||||
startSectionLoading( slug ) {
|
||||
return { type: 'START_SECTION_LOADING', slug };
|
||||
},
|
||||
stopSectionLoading( slug ) {
|
||||
return { type: 'STOP_SECTION_LOADING', slug };
|
||||
},
|
||||
dismissBanner() {
|
||||
return ( { select, dispatch } ) => {
|
||||
// One-way flag — skip the write if already dismissed.
|
||||
if ( select.isBannerDismissed() ) {
|
||||
return;
|
||||
}
|
||||
// Optimistic: update state now, persist per-user in the background.
|
||||
// A failed write is ignored — re-syncs from the preloaded value on
|
||||
// the next page load.
|
||||
dispatch( { type: 'DISMISS_BANNER' } );
|
||||
apiFetch( {
|
||||
method: 'PUT',
|
||||
path: DISMISS_PATH,
|
||||
} ).catch( () => {} );
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
function reducer( state = DEFAULT_STATE, action ) {
|
||||
switch ( action.type ) {
|
||||
case 'START_LOADING':
|
||||
return { ...state, loading: true };
|
||||
case 'STOP_LOADING':
|
||||
return { ...state, loading: false };
|
||||
case 'SET_SUGGESTION':
|
||||
return {
|
||||
...state,
|
||||
suggestions: { ...state.suggestions, [ action.slug ]: action.text },
|
||||
};
|
||||
case 'CLEAR_SUGGESTION': {
|
||||
const suggestions = { ...state.suggestions };
|
||||
delete suggestions[ action.slug ];
|
||||
return { ...state, suggestions };
|
||||
}
|
||||
case 'DISMISS_BANNER':
|
||||
return { ...state, bannerDismissed: true };
|
||||
case 'START_SECTION_LOADING':
|
||||
return {
|
||||
...state,
|
||||
loadingSections: { ...state.loadingSections, [ action.slug ]: true },
|
||||
};
|
||||
case 'STOP_SECTION_LOADING': {
|
||||
const loadingSections = { ...state.loadingSections };
|
||||
delete loadingSections[ action.slug ];
|
||||
return { ...state, loadingSections };
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const selectors = {
|
||||
isLoading( state ) {
|
||||
return state.loading;
|
||||
},
|
||||
getSuggestion( state, slug ) {
|
||||
return state.suggestions[ slug ] || '';
|
||||
},
|
||||
hasSuggestion( state, slug ) {
|
||||
return !! state.suggestions[ slug ];
|
||||
},
|
||||
isSectionLoading( state, slug ) {
|
||||
return state.loading || !! state.loadingSections[ slug ];
|
||||
},
|
||||
isBannerDismissed( state ) {
|
||||
return state.bannerDismissed;
|
||||
},
|
||||
};
|
||||
|
||||
export const AI_STORE_NAME = 'jetpack/content-guidelines-ai';
|
||||
|
||||
const aiStore = createReduxStore( AI_STORE_NAME, {
|
||||
reducer,
|
||||
actions,
|
||||
selectors,
|
||||
} );
|
||||
|
||||
register( aiStore );
|
||||
Reference in New Issue
Block a user