Move login logic into a single folder
This commit is contained in:
parent
4f17f8d6a9
commit
0fcd8cbb03
@ -2,4 +2,3 @@ export * from './ActionTypes'
|
||||
export * from './IAction'
|
||||
export * from './IErrorAction'
|
||||
export * from './UnionType'
|
||||
export * from './UserActions'
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
import {UserActions} from '../actions/UserActions'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators, Dispatch} from 'redux'
|
||||
import {IState} from '../reducers'
|
||||
// import {LoginForm} from '../components/LoginForm'
|
||||
import React from 'react'
|
||||
|
||||
export class LoginFormContainer {
|
||||
constructor(
|
||||
protected readonly Form: typeof React.PureComponent | typeof React.Component,
|
||||
protected readonly userActions: UserActions, // TODO interface
|
||||
) {}
|
||||
|
||||
connect() {
|
||||
return connect(this.mapStateToProps, this.mapDispatchToProps)()
|
||||
}
|
||||
|
||||
mapStateToProps = (state: IState) => {
|
||||
return {
|
||||
csrfToken: '', // TODO this should be read from the state too
|
||||
error: state.user.error,
|
||||
user: state.user.user,
|
||||
}
|
||||
}
|
||||
|
||||
mapDispatchToProps = (dispatch: Dispatch) => {
|
||||
return {
|
||||
logIn: bindActionCreators(this.userActions.logIn, dispatch),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,8 @@
|
||||
import {ActionTypes} from './ActionTypes'
|
||||
import {IAction, IErrorAction, ActionTypes} from '../actions'
|
||||
import {IAPIDef, ICredentials, IUser} from '@rondo/common'
|
||||
import {IAction} from './IAction'
|
||||
import {IErrorAction} from './IErrorAction'
|
||||
import {IHTTPClient} from '../http/IHTTPClient'
|
||||
|
||||
export enum UserActionKeys {
|
||||
export enum LoginActionKeys {
|
||||
USER_LOG_IN = 'USER_LOG_IN',
|
||||
USER_LOG_IN_PENDING = 'USER_LOG_IN_PENDING',
|
||||
USER_LOG_IN_REJECTED = 'USER_LOG_IN_REJECTED',
|
||||
@ -14,32 +12,32 @@ export enum UserActionKeys {
|
||||
USER_LOG_OUT_REJECTED = 'USER_LOG_OUT_REJECTED',
|
||||
}
|
||||
|
||||
export class UserActions {
|
||||
export class LoginActions {
|
||||
constructor(protected readonly http: IHTTPClient<IAPIDef>) {}
|
||||
|
||||
logIn =
|
||||
(credentials: ICredentials): IAction<IUser, UserActionKeys.USER_LOG_IN> => {
|
||||
logIn = (credentials: ICredentials)
|
||||
: IAction<IUser, LoginActionKeys.USER_LOG_IN> => {
|
||||
return {
|
||||
payload: this.http.post('/auth/login', credentials),
|
||||
type: UserActionKeys.USER_LOG_IN,
|
||||
type: LoginActionKeys.USER_LOG_IN,
|
||||
}
|
||||
}
|
||||
|
||||
logInError =
|
||||
(error: Error): IErrorAction<UserActionKeys.USER_LOG_IN_REJECTED> => {
|
||||
logInError = (error: Error)
|
||||
: IErrorAction<LoginActionKeys.USER_LOG_IN_REJECTED> => {
|
||||
return {
|
||||
error,
|
||||
type: UserActionKeys.USER_LOG_IN_REJECTED,
|
||||
type: LoginActionKeys.USER_LOG_IN_REJECTED,
|
||||
}
|
||||
}
|
||||
|
||||
logOut = (): IAction<unknown, UserActionKeys.USER_LOG_OUT> => {
|
||||
logOut = (): IAction<unknown, LoginActionKeys.USER_LOG_OUT> => {
|
||||
return {
|
||||
payload: this.http.get('/auth/logout'),
|
||||
type: UserActionKeys.USER_LOG_OUT,
|
||||
type: LoginActionKeys.USER_LOG_OUT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This makes it very easy to write reducer code.
|
||||
export type UserActionType = ActionTypes<UserActions>
|
||||
export type LoginActionType = ActionTypes<LoginActions>
|
||||
35
packages/client/src/login/LoginConnector.tsx
Normal file
35
packages/client/src/login/LoginConnector.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import {ILoginState} from './LoginReducer'
|
||||
import {LoginActions} from './LoginActions'
|
||||
import {LoginForm} from './LoginForm'
|
||||
import {bindActionCreators, Dispatch} from 'redux'
|
||||
import {connect} from 'react-redux'
|
||||
import {IStateSlicer} from '../redux'
|
||||
|
||||
export class LoginConnector<GlobalState> {
|
||||
constructor(
|
||||
protected readonly loginActions: LoginActions,
|
||||
protected readonly slice: IStateSlicer<GlobalState, ILoginState>,
|
||||
) {}
|
||||
|
||||
connect() {
|
||||
return connect(
|
||||
this.mapStateToProps,
|
||||
this.mapDispatchToProps,
|
||||
)(LoginForm)
|
||||
}
|
||||
|
||||
mapStateToProps = (globalState: GlobalState) => {
|
||||
const state = this.slice(globalState)
|
||||
return {
|
||||
csrfToken: '123', // TODO this should be read from the state too
|
||||
error: state.error,
|
||||
user: state.user,
|
||||
}
|
||||
}
|
||||
|
||||
mapDispatchToProps = (dispatch: Dispatch) => {
|
||||
return {
|
||||
onSubmit: bindActionCreators(this.loginActions.logIn, dispatch),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import {Input} from './Input'
|
||||
import {Input} from '../components/Input'
|
||||
import {ICredentials} from '@rondo/common'
|
||||
import {IState} from '../reducers'
|
||||
|
||||
export interface ILoginFormProps {
|
||||
error?: string
|
||||
26
packages/client/src/login/LoginReducer.ts
Normal file
26
packages/client/src/login/LoginReducer.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import {IUser} from '@rondo/common'
|
||||
import {LoginActionKeys, LoginActionType} from './LoginActions'
|
||||
|
||||
export interface ILoginState {
|
||||
readonly error?: string,
|
||||
readonly user?: IUser
|
||||
}
|
||||
|
||||
const defaultState: ILoginState = {
|
||||
error: undefined,
|
||||
user: undefined,
|
||||
}
|
||||
|
||||
export function Login(
|
||||
state = defaultState,
|
||||
action: LoginActionType,
|
||||
): ILoginState {
|
||||
switch (action.type) {
|
||||
case LoginActionKeys.USER_LOG_IN:
|
||||
return {...state, user: action.payload}
|
||||
case LoginActionKeys.USER_LOG_OUT:
|
||||
return {...state, user: undefined}
|
||||
case LoginActionKeys.USER_LOG_IN_REJECTED:
|
||||
return {...state, error: action.error.message}
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
export * from './user'
|
||||
|
||||
import {combineReducers} from 'redux'
|
||||
import * as user from './user'
|
||||
|
||||
export const reducers = combineReducers(user)
|
||||
export type IState = ReturnType<typeof reducers>
|
||||
@ -1,23 +0,0 @@
|
||||
import {IUser} from '@rondo/common'
|
||||
import {UserActionKeys, UserActionType} from '../actions/UserActions'
|
||||
|
||||
export interface IUserState {
|
||||
error?: string,
|
||||
user?: IUser
|
||||
}
|
||||
|
||||
const defaultState: IUserState = {
|
||||
error: undefined,
|
||||
user: undefined,
|
||||
}
|
||||
|
||||
export function user(state = defaultState, action: UserActionType): IUserState {
|
||||
switch (action.type) {
|
||||
case UserActionKeys.USER_LOG_IN:
|
||||
return {...state, user: action.payload}
|
||||
case UserActionKeys.USER_LOG_OUT:
|
||||
return {...state, user: undefined}
|
||||
case UserActionKeys.USER_LOG_IN_REJECTED:
|
||||
return {...state, error: action.error.message}
|
||||
}
|
||||
}
|
||||
3
packages/client/src/redux/IStateSlicer.ts
Normal file
3
packages/client/src/redux/IStateSlicer.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export type IStateSlicer<GlobalState, StateSlice>
|
||||
= (state: GlobalState) => StateSlice
|
||||
|
||||
1
packages/client/src/redux/index.ts
Normal file
1
packages/client/src/redux/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './IStateSlicer'
|
||||
@ -1,13 +0,0 @@
|
||||
import {PromiseMiddleware} from './middleware'
|
||||
import {applyMiddleware, createStore as create} from 'redux'
|
||||
import {reducers, IState} from './reducers'
|
||||
|
||||
export function createStore(state?: IState) {
|
||||
return create(
|
||||
reducers,
|
||||
state,
|
||||
applyMiddleware(
|
||||
new PromiseMiddleware().handle,
|
||||
),
|
||||
)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user