@twreporter/redux
Version:
redux actions and reducers for twreporter website
220 lines (212 loc) • 8.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.requestSearchAuthors = requestSearchAuthors;
exports.searchAuthors = searchAuthors;
exports.searchAuthorsIfNeeded = searchAuthorsIfNeeded;
var _articleSchema = require("../schemas/article-schema");
var _humps = require("humps");
var _authorsList = require("../constants/authors-list");
var _url = require("../utils/url");
var _normalizr = require("normalizr");
var _actionTypes = _interopRequireDefault(require("../constants/action-types"));
var _axios = _interopRequireDefault(require("axios"));
var _errorActionCreators = _interopRequireDefault(require("./error-action-creators"));
var _reduxStateFieldNames = _interopRequireDefault(require("../constants/redux-state-field-names"));
var _assign = _interopRequireDefault(require("lodash/assign"));
var _get = _interopRequireDefault(require("lodash/get"));
var _map = _interopRequireDefault(require("lodash/map"));
var _omit = _interopRequireDefault(require("lodash/omit"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// lodash
var _ = {
assign: _assign["default"],
get: _get["default"],
map: _map["default"],
omit: _omit["default"]
};
function requestSearchAuthors() {
var keywords = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
return {
type: keywords === '' ? _actionTypes["default"].LIST_ALL_AUTHORS_REQUEST : _actionTypes["default"].SEARCH_AUTHORS_REQUEST,
payload: {
keywords: keywords
}
};
}
/**
* NormalizedData
* @typedef {Object} NormalizedData
* @property {Object} entities
* @property {string[]} result
*/
/**
* ReceiveSearchAuthorsAction
*
* @typedef {Object} ReceiveSearchAuthorsAction
* @property {string} keywords
* @property {NormalizedData} normalizedData
* @property {number} currentPage
* @property {number} totalPages
* @property {number} receivedAt
*/
function searchAuthors(_ref) {
var keywords = _ref.keywords,
targetPage = _ref.targetPage,
returnDelay = _ref.returnDelay;
/**
* @param {Function} dispatch - Redux store dispatch function
* @param {Function} getState - Redux store getState function
* @return {Promise} resolve with success action or reject with fail action
*/
return function (dispatch, getState) {
// eslint-disable-line no-unused-vars
var searchParas = {
keywords: keywords,
limit: _authorsList.MAX_RESULTS_PER_FETCH,
offset: targetPage * _authorsList.MAX_RESULTS_PER_FETCH
};
var state = getState();
var apiOrigin = _.get(state, [_reduxStateFieldNames["default"].origins, 'api']);
var url = (0, _url.formURL)(apiOrigin, '/v2/authors', searchParas, false);
dispatch(requestSearchAuthors(keywords));
// Call our API server to fetch the data
return _axios["default"].get(url).then(function (_ref2) {
var data = _ref2.data;
var authors = _.get(data, 'data.records', {});
var offset = _.get(data, 'data.meta.offset', 0);
var limit = _.get(data, 'data.meta.limit', 24);
var total = _.get(data, 'data.meta.total', 0);
var receiveSearchAuthorsAction = {
type: keywords === '' ? _actionTypes["default"].LIST_ALL_AUTHORS_SUCCESS : _actionTypes["default"].SEARCH_AUTHORS_SUCCESS,
payload: {
keywords: keywords,
normalizedData: Array.isArray(authors) ? (0, _normalizr.normalize)((0, _humps.camelizeKeys)(authors), new _normalizr.schema.Array(_articleSchema.author)) : (0, _normalizr.normalize)((0, _humps.camelizeKeys)(authors), _articleSchema.author),
currentPage: Math.floor(offset / limit),
totalPages: Math.ceil(total / limit),
receivedAt: Date.now()
}
};
// delay for displaying loading spinner
function delayDispatch() {
return new Promise(function (resolve, reject) {
// eslint-disable-line no-unused-vars
setTimeout(function () {
resolve();
}, returnDelay);
});
}
if (returnDelay > 0) {
return delayDispatch().then(function () {
dispatch(receiveSearchAuthorsAction);
return receiveSearchAuthorsAction;
});
}
dispatch(receiveSearchAuthorsAction);
return receiveSearchAuthorsAction;
}, function (error) {
var type = keywords === '' ? _actionTypes["default"].LIST_ALL_AUTHORS_FAILURE : _actionTypes["default"].SEARCH_AUTHORS_FAILURE;
var failAction = _errorActionCreators["default"].axios(error, type);
failAction.payload.failedAt = Date.now();
dispatch(failAction);
return Promise.reject(failAction);
});
};
}
/*
Algolia set hitsPerPage limit up to 1000 items per search.
So if number of authors grows over 1000,
it will need to check hasMore as case lsat all authors.
*/
function searchAuthorsIfNeeded() {
var currentKeywords = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
/* --------- list all authors --------- */
if (currentKeywords === '') {
/**
* @param {Function} dispatch - Redux store dispatch function
* @param {Function} getState - Redux store getState function
* @return {Promise} resolve with success action or reject with fail action
*/
return function (dispatch, getState) {
var currentState = getState();
var authorsList = _.get(currentState, 'authorsList', {});
var isFetching = authorsList.isFetching,
currentPage = authorsList.currentPage,
hasMore = authorsList.hasMore;
if (currentPage < _authorsList.NUMBER_OF_FIRST_RESPONSE_PAGE) {
// If no data exists => fetch first page immediately
return dispatch(searchAuthors({
keywords: '',
targetPage: _authorsList.NUMBER_OF_FIRST_RESPONSE_PAGE,
returnDelay: 0
}));
}
if (!hasMore) {
var action = {
type: _actionTypes["default"].noMoreItemsToFetch,
payload: {
"function": searchAuthorsIfNeeded.name,
arguments: {
currentKeywords: currentKeywords
},
message: 'There is no more authors to search by current keywords.'
}
};
dispatch(action);
return Promise.resolve(action);
}
if (isFetching) {
var _action = {
type: _actionTypes["default"].lastActionIsStillProcessing,
payload: {
"function": searchAuthorsIfNeeded.name,
arguments: {
currentKeywords: currentKeywords
},
message: 'Request to search authors is still in progress.'
}
};
dispatch(_action);
return Promise.resolve(_action);
}
// If already have data AND not fetching AND has more => delay && next page
return dispatch(searchAuthors({
keywords: '',
targetPage: currentPage + 1,
returnDelay: _authorsList.RETURN_DELAY_TIME
}));
};
}
/* --------- searching authors --------- */
/**
* @param {Function} dispatch - Redux store dispatch function
* @param {Function} getState - Redux store getState function
* @return {Promise} resolve with success action or reject with fail action
*/
return function (dispatch, getState) {
var currentState = getState();
var authorsList = _.get(currentState, 'searchedAuthorsList', {});
var previousKeywords = _.get(authorsList, 'keywords');
if (currentKeywords !== previousKeywords) {
// Situation 1/2:If keywords are new => search
return dispatch(searchAuthors({
keywords: currentKeywords,
targetPage: _authorsList.NUMBER_OF_FIRST_RESPONSE_PAGE,
returnDelay: 0
}));
}
var action = {
type: _actionTypes["default"].dataAlreadyExists,
payload: {
"function": searchAuthorsIfNeeded.name,
arguments: {
currentKeywords: currentKeywords
},
message: 'Authors related to keywords already exists.'
}
};
dispatch(action);
return Promise.resolve(action); // Situation 2/2:If keywords are the same => do nothing
};
}