Options improvement
* Added loading state * Fixed bug where it does not search when the same keyword is used twice
This commit is contained in:
parent
f997a7afc4
commit
f0098cdbcb
|
@ -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',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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( {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Reference in New Issue