Move login logic into a single folder

This commit is contained in:
Jerko Steiner 2019-01-20 00:48:22 +01:00
parent 4f17f8d6a9
commit 0fcd8cbb03
11 changed files with 78 additions and 91 deletions

View File

@ -2,4 +2,3 @@ export * from './ActionTypes'
export * from './IAction'
export * from './IErrorAction'
export * from './UnionType'
export * from './UserActions'

View File

@ -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),
}
}
}

View File

@ -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>

View 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),
}
}
}

View File

@ -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

View 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}
}
}

View File

@ -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>

View File

@ -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}
}
}

View File

@ -0,0 +1,3 @@
export type IStateSlicer<GlobalState, StateSlice>
= (state: GlobalState) => StateSlice

View File

@ -0,0 +1 @@
export * from './IStateSlicer'

View File

@ -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,
),
)
}