import { RouterState } from "redux-first-history" ; import { Action as ReduxAction , combineReducers , Reducer } from "redux" ; import { DEFAULT_IDLE_TIMEOUT } from "./util/IdleDetector" ; interface LoadingState { [ loading ] : number ; } export interface IdleState { timeout : number ; state : "active" | "idle" ; } export interface State { loading : LoadingState ; router : RouterState ; app : object ; idle : IdleState ; } const SET_STATE_ACTION = "@@framework/setState" ; export interface Action < P > extends ReduxAction < string > { payload : P ; name ? : typeof SET_STATE_ACTION ; } interface SetStateActionPayload { module : string ; state : any ; } export function setStateAction ( module , state , type ) { return { type , name : SET_STATE_ACTION , payload : { module , state } , } ; } function setStateReducer ( state = { } , action ) { if ( action . name === SET_STATE_ACTION ) { const { module , state : moduleState } = action . payload as SetStateActionPayload ; return { ... state , [ module ] : moduleState } ; } return state ; } interface LoadingActionPayload { identifier : string ; show : boolean ; } export const LOADING_ACTION = "@@framework/loading" ; export function loadingAction ( show , identifier = "global" ) { return { type : LOADING_ACTION , payload : { identifier , show } , } ; } function loadingReducer ( state = { } , action ) { if ( action . type === LOADING_ACTION ) { const payload = action . payload as LoadingActionPayload ; const count = state [ payload . identifier ] || 0 ; return { ... state , [ payload . identifier ] : count + ( payload . show ? 1 : - 1 ) , } ; } return state ; } interface IdleStateActionPayload { state : "active" | "idle" ; } export const IDLE_STATE_ACTION = "@@framework/idle-state" ; export function idleStateActions ( state ) { return { type : IDLE_STATE_ACTION , payload : { state } , } ; } interface IdleTimeoutActionPayload { timeout : IdleState [ "timeout" ] ; } const IDLE_TIMEOUT_ACTION = "@@framework/idle-timeout" ; export function idleTimeoutActions ( timeout ) { return { type : IDLE_TIMEOUT_ACTION , payload : { timeout } , } ; } export function idleReducer ( state = { timeout : DEFAULT_IDLE_TIMEOUT , state : "active" } , action ) { if ( action . type === IDLE_STATE_ACTION ) { const payload = action . payload as IdleStateActionPayload ; return { ... state , state : payload . state } ; } else if ( action . type === IDLE_TIMEOUT_ACTION ) { const payload = action . payload as IdleTimeoutActionPayload ; return { ... state , timeout : payload . timeout } ; } else { return state ; } } export function rootReducer ( routerReducer ) { return combineReducers < State > ( { router : routerReducer , loading : loadingReducer , app : setStateReducer , idle : idleReducer , } ) ; } export function showLoading ( state , identifier = "global" ) { return state . loading [ identifier ] > 0 ; }