UNPKG

twreporter-redux

Version:

redux actions and reducers for twreporter website

173 lines (149 loc) 5.07 kB
import apiEndpoints from '../constants/api-endpoints' import axios from 'axios' import fieldNames from '../constants/redux-state-fields' import formAPIURL from '../utils/form-api-url' import postStyles from '../constants/post-styles' import types from '../constants/action-types' // lodash import get from 'lodash/get' import merge from 'lodash/merge' const _ = { get, merge, } /* Fetch a full post, whose assets like relateds, leading_video ...etc are all complete, * @param {string} slug - slug of post */ export function fetchAFullPost(slug) { return (dispatch, getState) => { const state = getState() const post = _.get(state, `${fieldNames.entities}.${fieldNames.posts}.${slug}`, {}) if (_.get(post, 'full', false)) { return dispatch({ type: types.GET_A_FULL_POST, payload: post }) } const path = `${apiEndpoints.posts}/${slug}?full=true` const url = formAPIURL(path) // Start to get topics dispatch({ type: types.START_TO_GET_A_FULL_POST, url, }) return axios.get(url) .then((response) => { return dispatch({ type: types.GET_A_FULL_POST, payload: _.get(response, 'data.record', {}), }) }) .catch((error) => { // Error to get topics return dispatch({ type: types.ERROR_TO_GET_A_FULL_POST, error, }) }) } } /* * @param {function} dispatch - dispatch of redux * @param {string} path - uri * @param {string} successActionType - action type * @param {string} failureActionType - action type * @param {object} defaultPayload */ function _fetchPosts(dispatch, path, successActionType, failureActionType = types.ERROR_TO_GET_POSTS, defaultPayload = {}) { const url = formAPIURL(path) dispatch({ type: types.START_TO_GET_POSTS, url, }) return axios.get(url) .then((response) => { return dispatch({ type: successActionType, payload: _.merge({ items: _.get(response, 'data.records', []), total: _.get(response, 'data.meta.total', 0), }, defaultPayload), }) }) .catch((error) => { // Error to get topics return dispatch(_.merge({ type: failureActionType, error, }, defaultPayload)) }) } /* Fetch a listed posts(only containing meta properties), * such as the posts belonging to the same tag/category/topic. * @param {string} listID - id of the tag, category or topic * @param {string} listType - tags, categories or topics * @param {number} limit - the number of posts you want to get in one request */ export function fetchListedPosts(listID, listType, limit = 10) { return (dispatch, getState) => { const state = getState() const list = _.get(state, [fieldNames.lists, listID]) // if list is already existed and there is nothing more to load if (list && _.get(list, 'total', 0) <= _.get(list, 'items.length', 0)) { return Promise.resolve() } const where = { [listType]: { in: [listID], }, } const offset = _.get(list, 'items.length', 0) const path = `${apiEndpoints.posts}?where=${JSON.stringify(where)}&limit=${limit}&offset=${offset}` return _fetchPosts(dispatch, path, types.GET_LISTED_POSTS, types.ERROR_TO_GET_LISTED_POSTS, { listID }) } } /** Fetch those posts picked by editors */ export function fetchEditorPickedPosts() { return (dispatch, getState) => { const state = getState() const posts = _.get(state, `${fieldNames.indexPage}.${fieldNames.editorPicks}`, []) if (posts.length > 0) { return Promise.resolve() } const path = `${apiEndpoints.posts}?where={"is_featured":true}&limit=6` return _fetchPosts(dispatch, path, types.GET_EDITOR_PICKED_POSTS) } } /** * fetchPhotographyPostsOnIndexPage * This function will fetch 10 latest posts with photography style, * It's specifically made for index page */ export function fetchPhotographyPostsOnIndexPage() { return (dispatch, getState) => { const state = getState() const posts = _.get(state, `${fieldNames.indexPage}.${fieldNames.photos}`, []) if (Array.isArray(posts) && posts.length > 0) { return Promise.resolve() } const path = `${apiEndpoints.posts}?where={"style":"${postStyles.photography}"}&limit=10` return _fetchPosts(dispatch, path, types.GET_PHOTOGRAPHY_POSTS_FOR_INDEX_PAGE) } } /** * fetchInfographicPostsOnIndexPage * This function will fetch 10 latest posts with interactive style, * It's specifically made for index page */ export function fetchInfographicPostsOnIndexPage() { return (dispatch, getState) => { const state = getState() const posts = _.get(state, `${fieldNames.indexPage}.${fieldNames.infographics}`, []) if (Array.isArray(posts) && posts.length > 0) { return Promise.resolve() } const path = `${apiEndpoints.posts}?where={"style":"${postStyles.infographic}"}&limit=10` return _fetchPosts(dispatch, path, types.GET_INFOGRAPHIC_POSTS_FOR_INDEX_PAGE) } }