UNPKG

@twreporter/redux

Version:

redux actions and reducers for twreporter website

268 lines (257 loc) 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchAFullTopic = fetchAFullTopic; exports.fetchFeatureTopic = fetchFeatureTopic; exports.fetchTopics = fetchTopics; var _url2 = require("../utils/url"); var _apiConfig = _interopRequireDefault(require("../constants/api-config")); var _apiEndpoints = _interopRequireDefault(require("../constants/api-endpoints")); var _axios = _interopRequireDefault(require("axios")); var _errorActionCreators = _interopRequireDefault(require("../actions/error-action-creators")); var _pagination = _interopRequireDefault(require("../utils/pagination")); var _reduxStateFieldNames = _interopRequireDefault(require("../constants/redux-state-field-names")); var _actionTypes = _interopRequireDefault(require("../constants/action-types")); var _get = _interopRequireDefault(require("lodash/get")); var _isInteger = _interopRequireDefault(require("lodash/isInteger")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } // lodash var _ = { get: _get["default"], isInteger: _isInteger["default"] }; var pageToOffset = _pagination["default"].pageToOffset; /** * Fetch a full topic, whose assets like relateds, leading_video ...etc are all complete, * @param {string} slug - slug of topic * @param {number} [timeout=apiConfig.timeout] - request api timeout * @return {import('../typedef').Thunk} async action creator */ function fetchAFullTopic(slug) { var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _apiConfig["default"].timeout; return function (dispatch, getState) { var entities = _reduxStateFieldNames["default"].entities, topicsInEntities = _reduxStateFieldNames["default"].topicsInEntities; var state = getState(); var topicId = _.get(state, [entities, topicsInEntities, 'slugToId', slug], ''); var topic = _.get(state, [entities, topicsInEntities, 'byId', topicId], null); if (_.get(topic, 'full', false)) { var successAction = { type: _actionTypes["default"].selectedTopic.read.alreadyExists, payload: { topic: topic } }; dispatch(successAction); return Promise.resolve(successAction); } var apiOrigin = _.get(state, [_reduxStateFieldNames["default"].origins, 'api']); var path = "/v2/".concat(_apiEndpoints["default"].topics, "/").concat(slug); var params = { full: 'true' }; // Start to get topics dispatch({ type: _actionTypes["default"].selectedTopic.read.request, payload: { slug: slug } }); return _axios["default"].get((0, _url2.formURL)(apiOrigin, path, params), { timeout: timeout }).then(function (response) { var successAction = { type: _actionTypes["default"].selectedTopic.read.success, payload: { topic: _.get(response, 'data.data', {}) } }; dispatch(successAction); return successAction; })["catch"](function (error) { var failAction = _errorActionCreators["default"].axios(error, _actionTypes["default"].selectedTopic.read.failure); failAction.payload['slug'] = slug; dispatch(failAction); return Promise.reject(failAction); }); }; } /** * @param {Function} dispatch - Redux store dispatch function * @param {string} origin - URL origin * @param {string} path - URL path * @param {object} params - URL params * @param {string} successActionType * @param {number} timeout - request api timeout * @return {Promise} resolve with success action or reject with fail action */ function _fetchTopics(dispatch, origin, path, params, successActionType, timeout) { // Start to get topics var url = (0, _url2.formURL)(origin, path, params); dispatch({ type: _actionTypes["default"].topics.read.request, url: url }); return _axios["default"].get(url, { timeout: timeout }).then(function (response) { var meta = _.get(response, 'data.data.meta', {}); var total = meta.total, offset = meta.offset, limit = meta.limit; var successAction = { type: successActionType, payload: { items: _.get(response, 'data.data.records', []), total: total, limit: limit, offset: offset } }; dispatch(successAction); return successAction; })["catch"](function (error) { var failAction = _errorActionCreators["default"].axios(error, _actionTypes["default"].topics.read.failure); dispatch(failAction); return Promise.reject(failAction); }); } /** * Fetch topics(only containing meta properties), * and it will load more if (total > items you have currently). * * @param {number} [page=1] * @param {number} [nPerPage=5] * @param {number} [timeout=apiConfig.timeout] - request api timeout * @return {import('../typedef').Thunk} async action creator */ function fetchTopics() { var page = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; var nPerPage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5; var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _apiConfig["default"].timeout; return function (dispatch, getState) { /* If nPerPage number is invalid, return a Promise.reject(err) */ if (!_.isInteger(nPerPage) || nPerPage <= 0) { var failAction = _errorActionCreators["default"].preRequestValidation({ nPerPage: "value must be an interger larger than 0, but is ".concat(nPerPage) }, _actionTypes["default"].topics.read.failure); dispatch(failAction); return Promise.reject(failAction); } /* If page number is invalid, , return a Promise.reject(err) */ if (!_.isInteger(page) || page <= 0) { var _failAction = _errorActionCreators["default"].preRequestValidation({ page: "value must be an interger larger than 0, but is ".concat(page) }, _actionTypes["default"].topics.read.failure); dispatch(_failAction); return Promise.reject(_failAction); } /* construct request path */ var _pageToOffset = pageToOffset({ page: page, nPerPage: nPerPage }), limit = _pageToOffset.limit, offset = _pageToOffset.offset; var state = getState(); if (_.get(state, [_reduxStateFieldNames["default"].topicList, 'items', page, 'length'], 0) > 0) { var action = { type: _actionTypes["default"].topics.read.alreadyExists, payload: { page: page, nPerPage: nPerPage } }; dispatch(action); return Promise.resolve(action); } var apiOrigin = _.get(state, [_reduxStateFieldNames["default"].origins, 'api']); var path = "/v2/".concat(_apiEndpoints["default"].topics); var params = { limit: limit, offset: offset }; return _fetchTopics(dispatch, apiOrigin, path, params, _actionTypes["default"].topics.read.success, timeout); }; } /** * This function fetch the latest topic, and three related posts of that topic. * * @param {number} [timeout=apiConfig.timeout] - request api timeout * @return {import('../typedef').Thunk} async action creator */ function fetchFeatureTopic() { var timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _apiConfig["default"].timeout; return function (dispatch, getState) { var state = getState(); if (_.get(state, [_reduxStateFieldNames["default"].featureTopic, 'id'])) { var action = { type: _actionTypes["default"].featureTopic.read.alreadyExists }; dispatch(action); return Promise.resolve(action); } var apiOrigin = _.get(state, [_reduxStateFieldNames["default"].origins, 'api']); var url = (0, _url2.formURL)(apiOrigin, "/v2/".concat(_apiEndpoints["default"].topics), { limit: 1, offset: 0 }); // dispatch request action dispatch({ type: _actionTypes["default"].featureTopic.read.request }); return _axios["default"] // fetch the latest topic as feature topic .get(url, { timeout: timeout }).then(function (response) { var topic = _.get(response, 'data.data.records.0', {}); return topic; }) // fetch feature topic's latest three related posts .then(function (topic) { var allRelatedIds = _.get(topic, 'relateds', []); var threeRelatedIds = Array.isArray(allRelatedIds) ? allRelatedIds.slice(0, 3) : []; if (threeRelatedIds.length > 0) { var _url = (0, _url2.formURL)(apiOrigin, "/v2/".concat(_apiEndpoints["default"].posts), { id: threeRelatedIds }); return Promise.all([topic, _axios["default"].get(_url, { timeout: timeout }).then(function (res) { var relatedPosts = _.get(res, 'data.data.records', []); // Ensure the order of returned related posts is the same with topic landing page's order, // since API endpoint /v2/posts will sort the posts automatically by `published_date` in descending order. return relatedPosts.length < 2 ? relatedPosts : threeRelatedIds.map(function (id) { return relatedPosts.find(function (post) { return post.id === id; }); }); })]); } // return empty response return Promise.all([topic, []]); }) // dispatch success action .then(function (results) { var topic = results[0]; var lastThreeRelatedPosts = results[1]; var action = { type: _actionTypes["default"].featureTopic.read.success, payload: { topic: topic, lastThreeRelatedPosts: lastThreeRelatedPosts } }; dispatch(action); return Promise.resolve(action); }) // handle axios error response ["catch"](function (error) { var failAction = _errorActionCreators["default"].axios(error, _actionTypes["default"].featureTopic.read.failure); dispatch(failAction); return Promise.reject(failAction); }); }; }