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 './IAction'
|
||||||
export * from './IErrorAction'
|
export * from './IErrorAction'
|
||||||
export * from './UnionType'
|
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 {IAPIDef, ICredentials, IUser} from '@rondo/common'
|
||||||
import {IAction} from './IAction'
|
|
||||||
import {IErrorAction} from './IErrorAction'
|
|
||||||
import {IHTTPClient} from '../http/IHTTPClient'
|
import {IHTTPClient} from '../http/IHTTPClient'
|
||||||
|
|
||||||
export enum UserActionKeys {
|
export enum LoginActionKeys {
|
||||||
USER_LOG_IN = 'USER_LOG_IN',
|
USER_LOG_IN = 'USER_LOG_IN',
|
||||||
USER_LOG_IN_PENDING = 'USER_LOG_IN_PENDING',
|
USER_LOG_IN_PENDING = 'USER_LOG_IN_PENDING',
|
||||||
USER_LOG_IN_REJECTED = 'USER_LOG_IN_REJECTED',
|
USER_LOG_IN_REJECTED = 'USER_LOG_IN_REJECTED',
|
||||||
@ -14,32 +12,32 @@ export enum UserActionKeys {
|
|||||||
USER_LOG_OUT_REJECTED = 'USER_LOG_OUT_REJECTED',
|
USER_LOG_OUT_REJECTED = 'USER_LOG_OUT_REJECTED',
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserActions {
|
export class LoginActions {
|
||||||
constructor(protected readonly http: IHTTPClient<IAPIDef>) {}
|
constructor(protected readonly http: IHTTPClient<IAPIDef>) {}
|
||||||
|
|
||||||
logIn =
|
logIn = (credentials: ICredentials)
|
||||||
(credentials: ICredentials): IAction<IUser, UserActionKeys.USER_LOG_IN> => {
|
: IAction<IUser, LoginActionKeys.USER_LOG_IN> => {
|
||||||
return {
|
return {
|
||||||
payload: this.http.post('/auth/login', credentials),
|
payload: this.http.post('/auth/login', credentials),
|
||||||
type: UserActionKeys.USER_LOG_IN,
|
type: LoginActionKeys.USER_LOG_IN,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logInError =
|
logInError = (error: Error)
|
||||||
(error: Error): IErrorAction<UserActionKeys.USER_LOG_IN_REJECTED> => {
|
: IErrorAction<LoginActionKeys.USER_LOG_IN_REJECTED> => {
|
||||||
return {
|
return {
|
||||||
error,
|
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 {
|
return {
|
||||||
payload: this.http.get('/auth/logout'),
|
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.
|
// 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 React from 'react'
|
||||||
import {Input} from './Input'
|
import {Input} from '../components/Input'
|
||||||
import {ICredentials} from '@rondo/common'
|
import {ICredentials} from '@rondo/common'
|
||||||
import {IState} from '../reducers'
|
|
||||||
|
|
||||||
export interface ILoginFormProps {
|
export interface ILoginFormProps {
|
||||||
error?: string
|
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