diff --git a/src/ts/@overflow/app/config/index.ts b/src/ts/@overflow/app/config/index.ts index 0aa617a..1197fdf 100644 --- a/src/ts/@overflow/app/config/index.ts +++ b/src/ts/@overflow/app/config/index.ts @@ -48,9 +48,12 @@ import NotificationReadAllUnconfirmedReducer from '@overflow/notification/redux/ import NotificationReadAllReducer from '@overflow/notification/redux/reducer/read_all'; import NotificationReadCountReducer from '@overflow/notification/redux/reducer/read_unconfirmed_count'; +import ForgotPassword from '@overflow/member/redux/reducer/forgotPassword'; + import AuthCrawlerRegistReducer from '@overflow/auth/redux/reducer/regist'; import AsyncRequest from '@overflow/app/redux/saga/AsyncRequest'; +import AsyncRestRequest from '@overflow/app/redux/saga/AsyncRestRequest'; // Container Configuration export interface ContainerConfig { @@ -121,9 +124,11 @@ const reduxConfig: ReduxConfig = { NotificationReadAllReducer, NotificationReadCountReducer, AuthCrawlerRegistReducer, + ForgotPassword, ], sagaWatchers: [ AsyncRequest, + AsyncRestRequest, ], }; diff --git a/src/ts/@overflow/app/redux/action/asyncRestRequestSending.ts b/src/ts/@overflow/app/redux/action/asyncRestRequestSending.ts new file mode 100644 index 0000000..73a5063 --- /dev/null +++ b/src/ts/@overflow/app/redux/action/asyncRestRequestSending.ts @@ -0,0 +1,18 @@ +import Action from '@overflow/commons/redux/Action'; +import AsyncRestRequestSendingPayload from '../payload/AsyncRestRequestSendingPayload'; + +// Action Type +export type SENDING = '@overflow/app/async/rest/SENDING'; +export const SENDING: SENDING = '@overflow/app/async/rest/SENDING'; + +// Action Creater +export type sending = (complete: boolean) => Action; + +export const sending: sending = (complete: boolean): Action => { + return { + type: SENDING, + payload: { + complete: complete, + }, + }; +}; diff --git a/src/ts/@overflow/app/redux/payload/AsyncRestRequestSendingPayload.ts b/src/ts/@overflow/app/redux/payload/AsyncRestRequestSendingPayload.ts new file mode 100644 index 0000000..1d3f20a --- /dev/null +++ b/src/ts/@overflow/app/redux/payload/AsyncRestRequestSendingPayload.ts @@ -0,0 +1,5 @@ +export interface AsyncRestRequestSendingPayload { + complete: boolean; +} + +export default AsyncRestRequestSendingPayload; diff --git a/src/ts/@overflow/app/redux/reducer/asyncRestRequestSending.ts b/src/ts/@overflow/app/redux/reducer/asyncRestRequestSending.ts new file mode 100644 index 0000000..3187373 --- /dev/null +++ b/src/ts/@overflow/app/redux/reducer/asyncRestRequestSending.ts @@ -0,0 +1,20 @@ +import Action from '@overflow/commons/redux/Action'; +import { ReducersMapObject } from 'redux'; +import AsyncRestRequestSendingPayload from '../payload/AsyncRestRequestSendingPayload'; + +import * as AsyncRestRequestSendingActions from '../action/asyncRestRequestSending'; + +import AsyncRestRequestSendingState, { + defaultState as AsyncRestRequestSendingDefaultState, +} from '../state/AsyncRestRequestSending'; + +const reducer: ReducersMapObject = { + [AsyncRestRequestSendingActions.SENDING]: (state: AsyncRestRequestSendingState = AsyncRestRequestSendingDefaultState, + action: Action): AsyncRestRequestSendingState => { + return { + complete: action.payload.complete, + }; + }, +}; + +export default reducer; diff --git a/src/ts/@overflow/app/redux/saga/AsyncRestRequest.ts b/src/ts/@overflow/app/redux/saga/AsyncRestRequest.ts new file mode 100644 index 0000000..e003058 --- /dev/null +++ b/src/ts/@overflow/app/redux/saga/AsyncRestRequest.ts @@ -0,0 +1,121 @@ +import { SagaIterator } from 'redux-saga'; +import { call, Effect, fork, put, takeEvery } from 'redux-saga/effects'; + +import Action from '@overflow/commons/redux/Action'; +import SagaWatcher from '@overflow/commons/redux/saga/SagaWatcher'; +import * as AsyncRestRequestActions from '@overflow/commons/redux/action/asyncRestRequest'; +import AsyncRestRequestPayload from '@overflow/commons/redux/payload/AsyncRestRequestPayload'; + + +import * as AppAsyncRestRequestSendingActions from '../action/asyncRestRequestSending'; + +export class AsyncRestRequest implements SagaWatcher { + // private _webSocketRPC: WebSocketRPC; + // + // public setWebSocketRPC(webSocketRPC: WebSocketRPC): void { + // this._webSocketRPC = webSocketRPC; + // } + + private * request(action: Action): SagaIterator { + const {entry, method, requestType, args} = action.payload; + console.log(JSON.stringify(args)); + + try { + yield put(AppAsyncRestRequestSendingActions.sending(false)); + + let result = yield call( + fetch, + 'http://192.168.1.103:19080/account/' + entry, + { + method: method, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(args), + }, + ); + + + // let result = yield call(this.fetchApi2, entry, method, args); + // let result = yield call({context: this, fn: this.fetchApi2}, entry, method, args); + + yield put(AsyncRestRequestActions.requestSuccess(requestType, result)); + } catch (e) { + yield put(AsyncRestRequestActions.requestFailure(requestType, e)); + } finally { + yield put(AppAsyncRestRequestSendingActions.sending(true)); + } + } + + public * watch(): SagaIterator { + yield takeEvery(AsyncRestRequestActions.REQUEST, this.request); + } + + public fetchApi2(uri: string, method:string, args:any): any { + return fetch( + 'http://192.168.1.103:19080/account/' + uri, { + method: method, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(args), + }, + ) + .then((response) => { + return (response.status === 200) ? response.json() : Promise.reject('logon'); + }); + // .catch(err => { + // Promise.reject(err); + // }); + } + + + public fetchApi(uri: string, method:string, args:any): Promise { + return fetch( + 'http://192.168.1.103:19080/account/' + uri, { + method: method, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(args), + }, + ); + // .then((response:any) => { + // console.log(response); + // return response; + // }) + // .then((json:any) => { + // return json; + // }) + // .catch(err => { + // return err; + // }); + } +// +// let d: any = await fetch('http://192.168.1.103:19080/account/forgot_password', { +// method: 'POST', +// headers: { +// // 'Content-Type': 'text/plain; charset=utf-8', +// 'Accept': 'application/json', +// 'Content-Type': 'application/json', +// }, +// body: JSON.stringify({ +// signinId: 'geek@loafle.com', +// }), +// +// }).then((respnse:any) => { +// console.log(respnse); +// return respnse.json(); +// }).then((resData:any) => { +// console.log('resdata' + resData); +// return resData; +// }).catch(err => { +// console.log('eee' + err); +// }); + +} + +export default AsyncRestRequest; diff --git a/src/ts/@overflow/app/redux/state/AsyncRestRequestSending.ts b/src/ts/@overflow/app/redux/state/AsyncRestRequestSending.ts new file mode 100644 index 0000000..6948d64 --- /dev/null +++ b/src/ts/@overflow/app/redux/state/AsyncRestRequestSending.ts @@ -0,0 +1,9 @@ +export interface State { + complete: boolean; +} + +export const defaultState: State = { + complete: false, +}; + +export default State; diff --git a/src/ts/@overflow/app/views/layout/AccountLayout.tsx b/src/ts/@overflow/app/views/layout/AccountLayout.tsx index 4106a9c..6ca8ad8 100644 --- a/src/ts/@overflow/app/views/layout/AccountLayout.tsx +++ b/src/ts/@overflow/app/views/layout/AccountLayout.tsx @@ -11,6 +11,7 @@ import SignIn from '../member/SignIn'; import SignUp from '../member/SignUp'; import PWConfirm from '../member/PWConfirm'; import Modify from '../member/Modify'; +import ResetPassword from '../member/ResetPassword'; export interface Props extends RouteComponentProps { } @@ -38,6 +39,7 @@ class AccountLayout extends React.Component { + diff --git a/src/ts/@overflow/app/views/member/ResetPassword.tsx b/src/ts/@overflow/app/views/member/ResetPassword.tsx new file mode 100644 index 0000000..ad2814d --- /dev/null +++ b/src/ts/@overflow/app/views/member/ResetPassword.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import { RouteComponentProps } from 'react-router'; +import ResetPasswordContainer from '@overflow/member/react/ResetPassword'; + +export interface Props { +} +export interface State { +} + +class ResetPassword extends React.Component, object> { + + public constructor(props?: RouteComponentProps, context?: State) { + super(props, context); + + } + + public render(): JSX.Element { + return ( + + ); + } + +} + + +export default ResetPassword; diff --git a/src/ts/@overflow/commons/redux/action/asyncRequest.ts b/src/ts/@overflow/commons/redux/action/asyncRequest.ts index 4d4648a..4ac194d 100644 --- a/src/ts/@overflow/commons/redux/action/asyncRequest.ts +++ b/src/ts/@overflow/commons/redux/action/asyncRequest.ts @@ -2,8 +2,8 @@ import Action from '@overflow/commons/redux/Action'; import AsyncRequestPayload from '../payload/AsyncRequestPayload'; // Action Type -export type REQUEST = '@overflow/commons/anync/REQUEST'; -export const REQUEST: REQUEST = '@overflow/commons/anync/REQUEST'; +export type REQUEST = '@overflow/commons/async/REQUEST'; +export const REQUEST: REQUEST = '@overflow/commons/async/REQUEST'; // Action Creater export type request = (service: string, method: string, requestType: string, ...args: any[]) => Action; diff --git a/src/ts/@overflow/commons/redux/action/asyncRestRequest.ts b/src/ts/@overflow/commons/redux/action/asyncRestRequest.ts new file mode 100644 index 0000000..6040f74 --- /dev/null +++ b/src/ts/@overflow/commons/redux/action/asyncRestRequest.ts @@ -0,0 +1,37 @@ +import Action from '@overflow/commons/redux/Action'; +import AsyncRestRequestPayload from '../payload/AsyncRestRequestPayload'; + +// Action Type +export type REQUEST = '@overflow/commons/async/rest/REQUEST'; +export const REQUEST: REQUEST = '@overflow/commons/async/rest/REQUEST'; + +// Action Creater +export type request = (entry: string, method: string, requestType: string, ...args: any[]) => Action; +export type requestSuccess = (requestType: string, result: any) => Action; +export type requestFailure = (requestType: string, error: any) => Action; + +export const request: request = (entry: string, method: string, requestType: string, ...args: any[]): Action => { + return { + type: REQUEST, + payload: { + entry: entry, + method: method, + requestType: requestType, + args: args, + }, + }; +}; + +export const requestSuccess: requestSuccess = (requestType: string, result: any): Action => { + return { + type: `${requestType}/SUCCESS`, + payload: result, + }; +}; + +export const requestFailure: requestFailure = (requestType: string, error: Error): Action => { + return { + type: `${requestType}/FAILURE`, + error: error, + }; +}; diff --git a/src/ts/@overflow/commons/redux/payload/AsyncRestRequestPayload.ts b/src/ts/@overflow/commons/redux/payload/AsyncRestRequestPayload.ts new file mode 100644 index 0000000..128c803 --- /dev/null +++ b/src/ts/@overflow/commons/redux/payload/AsyncRestRequestPayload.ts @@ -0,0 +1,10 @@ +import Action from '@overflow/commons/redux/Action'; + +interface AsyncRestRequestPayload { + entry: string; + method: string; + requestType: string; + args?: any[]; +} + +export default AsyncRestRequestPayload; diff --git a/src/ts/@overflow/member/react/ResetPassword.tsx b/src/ts/@overflow/member/react/ResetPassword.tsx new file mode 100644 index 0000000..877d44e --- /dev/null +++ b/src/ts/@overflow/member/react/ResetPassword.tsx @@ -0,0 +1,28 @@ +import { connect, Dispatch } from 'react-redux'; +import { + ResetPassword, + StateProps as ResetPasswordStateProps, + DispatchProps as ResetPasswordDispatchProps, + Props as ResetPasswordProps, +} from './components/ResetPassword'; +// import ResetPasswordState from '../redux/state/ResetPassword'; +// +// import * as ResetPasswordActions from '../redux/action/reset_password'; +// import { push as routerPush } from 'react-router-redux'; +// import * as asyncRequestActions from '@overflow/commons/redux/action/asyncRequest'; +export function mapStateToProps(state: any): ResetPasswordStateProps { + return { + + }; +} + +export function mapDispatchToProps(dispatch: Dispatch): ResetPasswordDispatchProps { + return { + // onConfirmPassword: (pass: string) => { + // dispatch(asyncRequestActions.request('MemberService', 'signin', ResetPasswordActions.REQUEST, 'overflow@loafle.com', pass)); + // }, + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(ResetPassword); + diff --git a/src/ts/@overflow/member/react/SignIn.tsx b/src/ts/@overflow/member/react/SignIn.tsx index 6fd9d42..bd4db79 100644 --- a/src/ts/@overflow/member/react/SignIn.tsx +++ b/src/ts/@overflow/member/react/SignIn.tsx @@ -8,8 +8,11 @@ import { import SignInState from '../redux/state/SignIn'; import * as signinActions from '../redux/action/signIn'; +import * as forgotPasswordAction from '../redux/action/forgot_password'; + import { push as routerPush } from 'react-router-redux'; import * as asyncRequestActions from '@overflow/commons/redux/action/asyncRequest'; +import * as asyncRestRequestAction from '@overflow/commons/redux/action/asyncRestRequest'; export function mapStateToProps(state: SignInState, ownProps?: SignInStateProps): SignInStateProps { console.log(state.error); @@ -28,6 +31,9 @@ export function mapDispatchToProps(dispatch: Dispatch, ownProps?: any): Sig onRedirectHome: () => { dispatch(routerPush('/')); }, + onForgotPassword: (email:string) => { + dispatch(asyncRestRequestAction.request('/forgot_password', 'POST', forgotPasswordAction.REQUEST, {signinId:email})); + }, }; } diff --git a/src/ts/@overflow/member/react/components/ResetPassword.tsx b/src/ts/@overflow/member/react/components/ResetPassword.tsx new file mode 100644 index 0000000..21f0ab5 --- /dev/null +++ b/src/ts/@overflow/member/react/components/ResetPassword.tsx @@ -0,0 +1,62 @@ +import *as React from 'react'; +import { + Input, + InputOnChangeData, + Button, + Form, + ButtonProps, +} from 'semantic-ui-react'; + +export interface StateProps { +} + +export interface DispatchProps { +} + +export type Props = StateProps & DispatchProps; + +export interface State { + pw: string; + pwConfirm: string; +} + +export class ResetPassword extends React.Component { + constructor(props: Props, context: State) { + super(props, context); + + this.state = { + pw:null, + pwConfirm:null, + }; + + } + + public render(): JSX.Element { + return ( +
+ , data: InputOnChangeData) => { + this.setState({ pw: data.value }); + }} /> + , data: InputOnChangeData) => { + this.setState({ pwConfirm: data.value }); + }} /> + + + + + + ); + } + + private PWConfirmClick(event: React.SyntheticEvent, data: ButtonProps):void { + if (this.state.pw !== this.state.pwConfirm) { + alert('Password Not Equal'); + return; + } + + // Todo Password Reset Fetch Communication + } +} + diff --git a/src/ts/@overflow/member/react/components/SignIn.tsx b/src/ts/@overflow/member/react/components/SignIn.tsx index ed1cffc..3c16b67 100644 --- a/src/ts/@overflow/member/react/components/SignIn.tsx +++ b/src/ts/@overflow/member/react/components/SignIn.tsx @@ -24,6 +24,7 @@ export interface StateProps { export interface DispatchProps { onSignIn?(signinId: string, signinPw: string ): void; + onForgotPassword?(email:string): void; onSignUp?(): void; onResetPassword?():void; onRedirectHome():void; @@ -81,7 +82,10 @@ export class SignIn extends React.Component { Enter email address - + , data: InputOnChangeData) => { + this.setState({ email: data.value }); + }} /> @@ -121,40 +125,41 @@ export class SignIn extends React.Component { sendComPopup: true, }); + this.props.onForgotPassword(this.state.email); // Todo Ajax - this.testhttp(); + // this.testhttp(); } - private async testhttp() { - // let httpc: httpm.HttpClient = new httpm.HttpClient('vsts-node-api'); - // let res:httpm.HttpClientResponse = await httpc.get('http://192.168.1.103:19080/forgot_password?'); - // let body: string = await res.readBody(); - // console.log(body, res.message); - - let d: any = await fetch('http://192.168.1.103:19080/account/forgot_password', { - method: 'POST', - headers: { - // 'Content-Type': 'text/plain; charset=utf-8', - 'Accept': 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - signinId: 'geek@loafle.com', - }), - - }).then((respnse:any) => { - console.log(respnse); - return respnse.json(); - }).then((resData:any) => { - console.log('resdata' + resData); - return resData; - }).catch(err => { - console.log('eee' + err); - }); - // let re: any = await d.json(); - - // console.log(d); - } + // private async testhttp() { + // // let httpc: httpm.HttpClient = new httpm.HttpClient('vsts-node-api'); + // // let res:httpm.HttpClientResponse = await httpc.get('http://192.168.1.103:19080/forgot_password?'); + // // let body: string = await res.readBody(); + // // console.log(body, res.message); + // + // let d: any = await fetch('http://192.168.1.103:19080/account/forgot_password', { + // method: 'POST', + // headers: { + // // 'Content-Type': 'text/plain; charset=utf-8', + // 'Accept': 'application/json', + // 'Content-Type': 'application/json', + // }, + // body: JSON.stringify({ + // signinId: 'geek@loafle.com', + // }), + // + // }).then((respnse:any) => { + // console.log(respnse); + // return respnse.json(); + // }).then((resData:any) => { + // console.log('resdata' + resData); + // return resData; + // }).catch(err => { + // console.log('eee' + err); + // }); + // // let re: any = await d.json(); + // + // // console.log(d); + // } private signInClick(event: React.SyntheticEvent, data: ButtonProps):void { this.props.onSignIn(this.state.email, this.state.pass); diff --git a/src/ts/@overflow/member/redux/action/forgot_password.ts b/src/ts/@overflow/member/redux/action/forgot_password.ts new file mode 100644 index 0000000..472e005 --- /dev/null +++ b/src/ts/@overflow/member/redux/action/forgot_password.ts @@ -0,0 +1,8 @@ +// Action Type +export type REQUEST = '@overflow/member/forgot_password/REQUEST'; +export type REQUEST_SUCCESS = '@overflow/member/forgot_password/REQUEST/SUCCESS'; +export type REQUEST_FAILURE = '@overflow/member/forgot_password/REQUEST/FAILURE'; + +export const REQUEST: REQUEST = '@overflow/member/forgot_password/REQUEST'; +export const REQUEST_SUCCESS: REQUEST_SUCCESS = '@overflow/member/forgot_password/REQUEST/SUCCESS'; +export const REQUEST_FAILURE: REQUEST_FAILURE = '@overflow/member/forgot_password/REQUEST/FAILURE'; \ No newline at end of file diff --git a/src/ts/@overflow/member/redux/payload/ForgotPassword.ts b/src/ts/@overflow/member/redux/payload/ForgotPassword.ts new file mode 100644 index 0000000..640610c --- /dev/null +++ b/src/ts/@overflow/member/redux/payload/ForgotPassword.ts @@ -0,0 +1,5 @@ +interface ForgotPasswordPayload { + email: string; +} + +export default ForgotPasswordPayload; diff --git a/src/ts/@overflow/member/redux/reducer/forgotPassword.ts b/src/ts/@overflow/member/redux/reducer/forgotPassword.ts new file mode 100644 index 0000000..7cf9d43 --- /dev/null +++ b/src/ts/@overflow/member/redux/reducer/forgotPassword.ts @@ -0,0 +1,26 @@ +import Action from '@overflow/commons/redux/Action'; +import { ReducersMapObject } from 'redux'; +import Member from '@overflow/member/api/model/Member'; + +import * as ForgotPasswordTypes from '../action/forgot_password'; +import ForgotPasswordState, { defaultState as forgotDefaultState } from '../state/ForgotPassword'; + +const reducer: ReducersMapObject = { + [ForgotPasswordTypes.REQUEST_SUCCESS]: (state: ForgotPasswordState = forgotDefaultState, action: Action): ForgotPasswordState => { + return { + ...state, + isSendMail: true, + }; + }, + [ForgotPasswordTypes.REQUEST_FAILURE]: (state: ForgotPasswordState = forgotDefaultState, action: Action): ForgotPasswordState => { + if (action.error.name === 'SignInPwNotMatchException') { + // + } + return { + ...state, + error: new Error('ForgotPassword Error'), + }; + }, +}; + +export default reducer; diff --git a/src/ts/@overflow/member/redux/state/ForgotPassword.ts b/src/ts/@overflow/member/redux/state/ForgotPassword.ts new file mode 100644 index 0000000..cb8fe00 --- /dev/null +++ b/src/ts/@overflow/member/redux/state/ForgotPassword.ts @@ -0,0 +1,12 @@ + +export interface State { + readonly isSendMail: boolean; + readonly error?: Error; +} + +export const defaultState: State = { + isSendMail: undefined, + error: undefined, +}; + +export default State;