openreplay/frontend/app/duck/funcTools/request/reducer.js
2021-05-01 15:12:01 +05:30

89 lines
2.8 KiB
JavaScript

import { List, Map } from 'immutable';
import { RequestType } from './types';
import { request, success, failure } from '../tools'; //
export const ROOT_KEY = '_';
const defaultReducer = (state = Map()) => state;
const simpleRequestInitialState = Map({
loading: false,
errors: null,
});
const getKeys = types => Object.keys(types).filter(key => key !== ROOT_KEY);
export function getRequestInitialState(types) {
if (typeof types === 'string' || Array.isArray(types)) {
return simpleRequestInitialState;
}
let initialState = Map();
if (types[ ROOT_KEY ]) {
initialState = getRequestInitialState(types[ ROOT_KEY ]);
}
return getKeys(types).reduce(
(accumState, key) => accumState.set(key, getRequestInitialState(types[ key ])),
initialState,
);
}
function createSimpleRequestReducer(types, reducer) {
const typesArray = Array.isArray(types) ? types : [ types ];
const requestEvents = typesArray.map(t => t.request || request(t)); // back compat.
const successEvents = typesArray.map(t => t.success || success(t));
const failureEvents = typesArray.map(t => t.failure || failure(t));
let loadingCounter = 0;
return (state, action = {}) => {
if (state === undefined) {
if (typeof reducer === "function") { // flow?
state = reducer(state, action).merge(simpleRequestInitialState);
} else {
state = simpleRequestInitialState;
}
}
if (requestEvents.includes(action.type)) {
loadingCounter += 1;
return state.set('loading', loadingCounter > 0).set('errors', null);
}
if (successEvents.includes(action.type)) {
loadingCounter -= 1;
return state.set('loading', loadingCounter > 0).set('errors', null);
}
if (failureEvents.includes(action.type)) {
loadingCounter -= 1;
return state.set('loading', loadingCounter > 0).set('errors', List(action.errors));
}
return state;
};
};
/**
* @types: RequestTypes - array or single
* or object like {'state1': RequestTypes, 'state2': [RequestTypes] ... }
* */
export function createRequestReducer(types, reducer = defaultReducer) {
if (typeof types === 'string' || types instanceof RequestType || Array.isArray(types)) {
return createSimpleRequestReducer(types);
}
const keys = getKeys(types);
const reducers = {};
keys.map((key) => { reducers[ key ] = createRequestReducer(types[ key ]); });
let rootReducer = typeof reducer === 'function' ? reducer : defaultReducer;
// TODO: remove ROOT_KEY logic
if (types[ ROOT_KEY ]) {
rootReducer = createRequestReducer(types[ ROOT_KEY ], rootReducer);
}
return (state, action = {}) => {
state = rootReducer(state, action);
keys.map((key) => {
state = state.update(key, subState => reducers[ key ](subState, action));
});
return state;
};
};