UNPKG

@twreporter/redux

Version:

redux actions and reducers for twreporter website

220 lines (212 loc) 8.18 kB
"use strict"; 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 }; }