Skip to content

Instantly share code, notes, and snippets.

@rmorse
Created September 28, 2023 09:23
Show Gist options
  • Save rmorse/a39ed6816b531feb85908813723cdf81 to your computer and use it in GitHub Desktop.
Save rmorse/a39ed6816b531feb85908813723cdf81 to your computer and use it in GitHub Desktop.
/**
* WordPress dependencies
*/
import { createReduxStore, register, controls } from '@wordpress/data';
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
export const STORE_NAME = 'search-filter/settings';
const getUniqueKey = ( args ) => {
let queryString = '';
for ( const key in args ) {
let queryAdd = args[ key ];
if ( Array.isArray( args[ key ] ) ) {
queryAdd = args[ key ].join( '-' );
}
queryString += '_' + queryAdd;
}
return queryString;
};
const actions = {
clearSettingValue( settingRoute, args ) {
const uniqueKey = getUniqueKey( args );
return {
type: 'CLEAR_SETTING_VALUE',
settingRoute,
uniqueKey,
};
},
clearSettingData( settingRoute, args ) {
const uniqueKey = getUniqueKey( args );
return {
type: 'CLEAR_SETTING_DATA',
settingRoute,
uniqueKey,
};
},
setSettingOptions( settingRoute, args, data ) {
const uniqueKey = getUniqueKey( args );
return {
type: 'SET_SETTING_DATA',
settingRoute,
uniqueKey,
data,
};
},
fetchFromAPI( path ) {
return {
type: 'FETCH_FROM_API',
path,
};
},
postToAPI( path, data ) {
return {
type: 'POST_TO_API',
path,
data,
};
},
putToAPI( path, data ) {
return {
type: 'PUT_TO_API',
path,
data,
};
},
};
const DEFAULT_STATE = {};
const defaults = DEFAULT_STATE;
const settingStore = createReduxStore( STORE_NAME, {
reducer( state = DEFAULT_STATE, action ) {
switch ( action.type ) {
case 'SET_SETTING_DATA': {
const { settingRoute, uniqueKey, data } = action;
return {
...state,
[ settingRoute ]: {
...state[ settingRoute ],
[ uniqueKey ]: data,
},
};
}
case 'CLEAR_SETTING_VALUE': {
const { settingRoute, uniqueKey } = action;
const newState = { ...state };
const newRoute = { ...state[ settingRoute ] };
const settingData = { ...state[ settingRoute ][ uniqueKey ] };
if ( settingData?.value ) {
delete settingData.value;
}
newRoute[ uniqueKey ] = settingData;
newState[ settingRoute ] = newRoute;
return newState;
}
case 'CLEAR_SETTING_DATA': {
const { settingRoute, uniqueKey } = action;
const newState = { ...state };
if ( newState[ settingRoute ] ) {
newState[ settingRoute ][ uniqueKey ] = null;
}
return newState;
}
}
return state;
},
actions,
selectors: {
// This is a generic wrapper to handle multiple types of calls for data
// to populate some of our admin options - they are defined in our PHP
// settings object, so need to be mapped to the rest API accoringly
// What makes this different from using the built in rest api hooks,
// is we might often need to pass in the query settings (or similar)
// in order to know which options to retrieve
// EG - our taxonomy field can only show taxonomies that belong to
// the post types selected in the query settings
getSettingData( state, settingRoute, args ) {
const uniqueKey = getUniqueKey( args );
if ( state[ settingRoute ] ) {
if ( state[ settingRoute ][ uniqueKey ] ) {
return state[ settingRoute ][ uniqueKey ];
}
}
return null;
},
},
controls: {
FETCH_FROM_API( action ) {
return apiFetch( { path: action.path } );
},
POST_TO_API( action ) {
return apiFetch( {
path: action.path,
method: 'POST',
data: action.data,
} );
},
PUT_TO_API( action ) {
return apiFetch( {
path: action.path,
method: 'PUT',
data: action.data,
} );
},
},
resolvers: {
*getSettingData( settingRoute, args ) {
if ( settingRoute ) {
const path = addQueryArgs(
`/search-filter/v1${ settingRoute }`,
{
...args,
}
);
const optionsResult = yield actions.fetchFromAPI( path );
return actions.setSettingOptions(
settingRoute,
args,
optionsResult?.data
);
}
},
},
} );
register( settingStore );
export { defaults, settingStore };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment