mirror of
				https://github.com/elyby/accounts-frontend.git
				synced 2025-05-31 14:11:58 +05:30 
			
		
		
		
	Блокировка формы во время обработки запроса
This commit is contained in:
		| @@ -25,6 +25,7 @@ class PanelTransition extends Component { | ||||
|         // context props | ||||
|         auth: PropTypes.shape({ | ||||
|             error: PropTypes.string, | ||||
|             isLoading: PropTypes.bool, | ||||
|             login: PropTypes.shape({ | ||||
|                 login: PropTypes.string, | ||||
|                 password: PropTypes.string | ||||
| @@ -142,7 +143,12 @@ class PanelTransition extends Component { | ||||
|                     }; | ||||
|  | ||||
|                     return ( | ||||
|                         <Form id={panelId} onSubmit={this.onFormSubmit} onInvalid={this.onFormInvalid}> | ||||
|                         <Form | ||||
|                             id={panelId} | ||||
|                             onSubmit={this.onFormSubmit} | ||||
|                             onInvalid={this.onFormInvalid} | ||||
|                             isLoading={this.props.auth.isLoading} | ||||
|                         > | ||||
|                             <Panel> | ||||
|                                 <PanelHeader> | ||||
|                                     {panels.map((config) => this.getHeader(config))} | ||||
|   | ||||
| @@ -8,7 +8,7 @@ export function login({login = '', password = '', rememberMe = false}) { | ||||
|     const LOGIN_REQUIRED = 'error.login_required'; | ||||
|     const ACTIVATION_REQUIRED = 'error.account_not_activated'; | ||||
|  | ||||
|     return (dispatch) => | ||||
|     return wrapInLoader((dispatch) => | ||||
|         request.post( | ||||
|             '/api/authentication/login', | ||||
|             {login, password, rememberMe} | ||||
| @@ -43,7 +43,7 @@ export function login({login = '', password = '', rememberMe = false}) { | ||||
|  | ||||
|             // TODO: log unexpected errors | ||||
|         }) | ||||
|         ; | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export function changePassword({ | ||||
| @@ -51,7 +51,7 @@ export function changePassword({ | ||||
|     newPassword = '', | ||||
|     newRePassword = '' | ||||
| }) { | ||||
|     return (dispatch) => | ||||
|     return wrapInLoader((dispatch) => | ||||
|         dispatch(changeUserPassword({password, newPassword, newRePassword})) | ||||
|             .catch((resp) => { | ||||
|                 if (resp.errors) { | ||||
| @@ -62,7 +62,7 @@ export function changePassword({ | ||||
|  | ||||
|                 // TODO: log unexpected errors | ||||
|             }) | ||||
|             ; | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export function register({ | ||||
| @@ -72,7 +72,7 @@ export function register({ | ||||
|     rePassword = '', | ||||
|     rulesAgreement = false | ||||
| }) { | ||||
|     return (dispatch) => | ||||
|     return wrapInLoader((dispatch) => | ||||
|         request.post( | ||||
|             '/api/signup', | ||||
|             {email, username, password, rePassword, rulesAgreement} | ||||
| @@ -94,11 +94,11 @@ export function register({ | ||||
|  | ||||
|             // TODO: log unexpected errors | ||||
|         }) | ||||
|         ; | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export function activate({key = ''}) { | ||||
|     return (dispatch) => | ||||
|     return wrapInLoader((dispatch) => | ||||
|         request.post( | ||||
|             '/api/signup/confirm', | ||||
|             {key} | ||||
| @@ -118,7 +118,7 @@ export function activate({key = ''}) { | ||||
|  | ||||
|             // TODO: log unexpected errors | ||||
|         }) | ||||
|         ; | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export const ERROR = 'error'; | ||||
| @@ -141,7 +141,7 @@ export function logout() { | ||||
| // TODO: move to oAuth actions? | ||||
| // test request: /oauth?client_id=ely&redirect_uri=http%3A%2F%2Fely.by&response_type=code&scope=minecraft_server_session | ||||
| export function oAuthValidate(oauth) { | ||||
|     return (dispatch) => | ||||
|     return wrapInLoader((dispatch) => | ||||
|         request.get( | ||||
|             '/api/oauth/validate', | ||||
|             getOAuthRequest(oauth) | ||||
| @@ -156,11 +156,12 @@ export function oAuthValidate(oauth) { | ||||
|             if (resp.statusCode === 401 && resp.error === 'accept_required') { | ||||
|                 alert('Accept required.'); | ||||
|             } | ||||
|         }); | ||||
|         }) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export function oAuthComplete(params = {}) { | ||||
|     return (dispatch, getState) => { | ||||
|     return wrapInLoader((dispatch, getState) => { | ||||
|         const oauth = getState().auth.oauth; | ||||
|         const query = request.buildQuery(getOAuthRequest(oauth)); | ||||
|  | ||||
| @@ -205,7 +206,7 @@ export function oAuthComplete(params = {}) { | ||||
|  | ||||
|             return resp; | ||||
|         }); | ||||
|     }; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function getOAuthRequest(oauth) { | ||||
| @@ -283,3 +284,29 @@ export function setScopes(scopes) { | ||||
|         payload: scopes | ||||
|     }; | ||||
| } | ||||
|  | ||||
|  | ||||
| export const SET_LOADING_STATE = 'set_loading_state'; | ||||
| export function setLoadingState(isLoading) { | ||||
|     return { | ||||
|         type: SET_LOADING_STATE, | ||||
|         payload: isLoading | ||||
|     }; | ||||
| } | ||||
|  | ||||
| function wrapInLoader(fn) { | ||||
|     return (dispatch, getState) => { | ||||
|         dispatch(setLoadingState(true)); | ||||
|         const endLoading = () => dispatch(setLoadingState(false)); | ||||
|  | ||||
|         return Reflect.apply(fn, null, [dispatch, getState]).then((resp) => { | ||||
|             endLoading(); | ||||
|  | ||||
|             return resp; | ||||
|         }, (resp) => { | ||||
|             endLoading(); | ||||
|  | ||||
|             return Promise.reject(resp); | ||||
|         }); | ||||
|     }; | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| import { combineReducers } from 'redux'; | ||||
|  | ||||
| import { ERROR, SET_CLIENT, SET_OAUTH, SET_OAUTH_RESULT, SET_SCOPES } from './actions'; | ||||
| import { ERROR, SET_CLIENT, SET_OAUTH, SET_OAUTH_RESULT, SET_SCOPES, SET_LOADING_STATE } from './actions'; | ||||
|  | ||||
| export default combineReducers({ | ||||
|     error, | ||||
|     isLoading, | ||||
|     client, | ||||
|     oauth, | ||||
|     scopes | ||||
| @@ -25,6 +26,20 @@ function error( | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| function isLoading( | ||||
|     state = false, | ||||
|     {type, payload = null} | ||||
| ) { | ||||
|     switch (type) { | ||||
|         case SET_LOADING_STATE: | ||||
|             return !!payload; | ||||
|  | ||||
|         default: | ||||
|             return state; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function client( | ||||
|     state = null, | ||||
|     {type, payload = {}} | ||||
|   | ||||
| @@ -102,6 +102,7 @@ export class Form extends Component { | ||||
|  | ||||
|     static propTypes = { | ||||
|         id: PropTypes.string, // and id, that uniquely identifies form contents | ||||
|         isLoading: PropTypes.bool, | ||||
|         onSubmit: PropTypes.func, | ||||
|         onInvalid: PropTypes.func, | ||||
|         children: PropTypes.oneOfType([ | ||||
| @@ -112,6 +113,7 @@ export class Form extends Component { | ||||
|  | ||||
|     static defaultProps = { | ||||
|         id: 'default', | ||||
|         isLoading: false, | ||||
|         onSubmit() {}, | ||||
|         onInvalid() {} | ||||
|     }; | ||||
| @@ -129,11 +131,14 @@ export class Form extends Component { | ||||
|     } | ||||
|  | ||||
|     render() { | ||||
|         const {isLoading} = this.props; | ||||
|  | ||||
|         return ( | ||||
|             <form | ||||
|                 className={classNames( | ||||
|                     styles.form, | ||||
|                     { | ||||
|                         [styles.isFormLoading]: isLoading, | ||||
|                         [styles.formTouched]: this.state.isTouched | ||||
|                     } | ||||
|                 )} | ||||
|   | ||||
| @@ -234,3 +234,17 @@ | ||||
|         border-color: $red; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .isFormLoading { | ||||
|     // TODO: надо бы разнести from и input на отдельные модули, | ||||
|     // так как в текущем контексте isLoading немного не логичен, | ||||
|     // пришлось юзать isFormLoading | ||||
|     * { | ||||
|         pointer-events: none; | ||||
|     } | ||||
|  | ||||
|     button { | ||||
|         background-image: url('images/loader_button.gif'); | ||||
|         background-position: center center; | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								src/components/ui/images/loader_button.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/components/ui/images/loader_button.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 317 B | 
		Reference in New Issue
	
	Block a user