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 = {
SET_OPTIONS: 'SET_OPTIONS',
SET_IS_LOADING: 'SET_IS_LOADING',
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 ) {
try {
yield apiFetch( {

View File

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

View File

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

View File

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

View File

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