Options improvement

* Added loading state

* Fixed bug where it does not search when the same keyword is used twice
This commit is contained in:
Moon 2021-03-23 22:54:19 -07:00
parent f997a7afc4
commit f0098cdbcb
6 changed files with 60 additions and 18 deletions

View File

@ -1,5 +1,6 @@
const TYPES = { const TYPES = {
SET_OPTIONS: 'SET_OPTIONS', SET_OPTIONS: 'SET_OPTIONS',
SET_IS_LOADING: 'SET_IS_LOADING',
DELETE_OPTION_BY_ID: 'DELETE_OPTION_BY_ID', DELETE_OPTION_BY_ID: 'DELETE_OPTION_BY_ID',
}; };

View File

@ -21,6 +21,13 @@ export function setOptions( options ) {
}; };
} }
export function setLoadingState( isLoading ) {
return {
type: TYPES.SET_IS_LOADING,
isLoading,
};
}
export function* deleteOptionById( optionId ) { export function* deleteOptionById( optionId ) {
try { try {
yield apiFetch( { yield apiFetch( {

View File

@ -5,16 +5,22 @@ import TYPES from './action-types';
const DEFAULT_STATE = { const DEFAULT_STATE = {
options: [], options: [],
isLoading: true,
}; };
const reducer = ( state = DEFAULT_STATE, action ) => { const reducer = ( state = DEFAULT_STATE, action ) => {
switch ( action.type ) { switch ( action.type ) {
case TYPES.SET_IS_LOADING:
return {
...state,
isLoading: action.isLoading,
};
case TYPES.SET_OPTIONS: case TYPES.SET_OPTIONS:
return { return {
...state, ...state,
options: action.options, options: action.options,
isLoading: false,
}; };
case TYPES.DELETE_OPTION_BY_ID: case TYPES.DELETE_OPTION_BY_ID:
return { return {
...state, ...state,

View File

@ -7,7 +7,7 @@ import { apiFetch } from '@wordpress/data-controls';
* Internal dependencies * Internal dependencies
*/ */
import { API_NAMESPACE } from './constants'; import { API_NAMESPACE } from './constants';
import { setOptions } from './actions'; import { setLoadingState, setOptions } from './actions';
export function* getOptions( search ) { export function* getOptions( search ) {
let path = `${ API_NAMESPACE }/options?`; let path = `${ API_NAMESPACE }/options?`;
@ -15,6 +15,8 @@ export function* getOptions( search ) {
path += `search=${ search }`; path += `search=${ search }`;
} }
yield setLoadingState( true );
try { try {
const response = yield apiFetch( { const response = yield apiFetch( {
path, path,

View File

@ -1,3 +1,7 @@
export function getOptions( state ) { export function getOptions( state ) {
return state.options; return state.options;
} }
export function isLoading( state ) {
return state.isLoading;
}

View File

@ -14,7 +14,8 @@ function Options( {
options, options,
getOptions, getOptions,
deleteOptionById, deleteOptionById,
invalidateResolutionForStoreSelector, isLoading,
invalidateResolution,
} ) { } ) {
const deleteOption = function ( optionId ) { const deleteOption = function ( optionId ) {
// eslint-disable-next-line no-alert // eslint-disable-next-line no-alert
@ -23,7 +24,27 @@ function Options( {
} }
}; };
const renderLoading = function () {
return (
<tr>
<td colSpan="4" align="center">
Loading...
</td>
</tr>
);
};
const renderTableData = function () { const renderTableData = function () {
if ( options.length === 0 ) {
return (
<tr>
<td colSpan="4" align="center">
No Options Found
</td>
</tr>
);
}
return options.map( ( option ) => { return options.map( ( option ) => {
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
const { option_id, option_name, autoload } = option; const { option_id, option_name, autoload } = option;
@ -53,14 +74,13 @@ function Options( {
const searchOption = function ( event ) { const searchOption = function ( event ) {
event.preventDefault(); event.preventDefault();
let keyword = event.target.search.value; const keyword = event.target.search.value;
if ( keyword === '' ) {
keyword = undefined;
}
getOptions( keyword );
// force invlidation of the cached selector resolvers // Invalidate resolution of the same selector + arg
invalidateResolutionForStoreSelector( 'getOptions' ); // so that entering the same keyword always works
invalidateResolution( STORE_KEY, 'getOptions', [ keyword ] );
getOptions( keyword );
}; };
return ( return (
@ -100,7 +120,9 @@ function Options( {
</td> </td>
</tr> </tr>
</thead> </thead>
<tbody>{ renderTableData() }</tbody> <tbody>
{ isLoading ? renderLoading() : renderTableData() }
</tbody>
</table> </table>
</div> </div>
); );
@ -108,15 +130,15 @@ function Options( {
export default compose( export default compose(
withSelect( ( select ) => { withSelect( ( select ) => {
const { getOptions } = select( STORE_KEY ); const { getOptions, isLoading } = select( STORE_KEY );
const options = getOptions(); const options = getOptions();
return { options, getOptions };
return { options, getOptions, isLoading: isLoading() };
} ), } ),
withDispatch( ( dispatch ) => { withDispatch( ( dispatch ) => {
const { const { deleteOptionById } = dispatch( STORE_KEY );
deleteOptionById, const { invalidateResolution } = dispatch( 'core/data' );
invalidateResolutionForStoreSelector,
} = dispatch( STORE_KEY ); return { deleteOptionById, invalidateResolution };
return { deleteOptionById, invalidateResolutionForStoreSelector };
} ) } )
)( Options ); )( Options );