300 lines
9.0 KiB
JavaScript
300 lines
9.0 KiB
JavaScript
import {createAction, handleActions} from 'redux-actions'
|
|
import {fromJS} from 'immutable'
|
|
import * as api from '../../../api/articlesApi'
|
|
import {addAlert} from '../common/alerts'
|
|
import {getSidebarCategories} from './sidebar'
|
|
import {thunkAction} from '../../utils/common'
|
|
import * as _ from 'lodash'
|
|
|
|
/**
|
|
*
|
|
* Constants
|
|
*/
|
|
const NS = '[Articles]'
|
|
const SHOW_DELETE_POPUP = `${NS} Show delete popup`
|
|
const HIDE_DELETE_POPUP = `${NS} Hide delete popup`
|
|
const SHOW_EMAIL_POPUP = `${NS} Show email popup`
|
|
const HIDE_EMAIL_POPUP = `${NS} Hide email popup`
|
|
const SHOW_COMMENT_POPUP = `${NS} Show comment popup`
|
|
const HIDE_COMMENT_POPUP = `${NS} Hide comment popup`
|
|
const SHOW_CLIP_POPUP = `${NS} Show clip popup`
|
|
const HIDE_CLIP_POPUP = `${NS} Hide clip popup`
|
|
const SHOW_EMAIL_CONFIRM_POPUP = `${NS} Show email confirm popup`
|
|
const HIDE_EMAIL_CONFIRM_POPUP = `${NS} Hide email confirm popup`
|
|
const SET_EMAIL_PARAMS = `${NS} Set email params`
|
|
|
|
//This actions, when fulfilled reduced in search.js! so export this
|
|
export const COMMENT_ARTICLE = `${NS} Comment article`
|
|
export const UPDATE_COMMENT = `${NS} Update comment`
|
|
export const DELETE_COMMENT = `${NS} Delete comment`
|
|
export const LOAD_MORE_COMMENTS = `${NS} Load more comments`
|
|
|
|
export const DELETE_ARTICLES_FROM_FEED = `${NS} Delete articles from feed`
|
|
export const DELETE_ARTICLES = `${NS} Delete articles from search results`
|
|
|
|
const EMAIL_ARTICLES = `${NS} Email articles`
|
|
const SEND_DOCUMENTS_BY_EMAIL = `${NS} Send documents by email`
|
|
const CLIP_ARTICLES = `${NS} Clip articles`
|
|
const GET_RECENT_CLIP_FEEDS = `${NS} Get recent clip feeds`
|
|
const READ_ARTICLE_LATER = `${NS} Read article later`
|
|
const LOAD_RECIPIENTS = `${NS} Load recipients`
|
|
|
|
const SHOW_SHARE_MENU = `${NS} Show share menu`
|
|
const HIDE_SHARE_MENU = `${NS} Hide share menu`
|
|
|
|
export const ARTICLE_COMMENTS_LIMIT = 100
|
|
|
|
/**
|
|
* Actions
|
|
*/
|
|
const showDeleteArticlesPopup = createAction(SHOW_DELETE_POPUP, articles => articles)
|
|
const showEmailArticlesPopup = createAction(SHOW_EMAIL_POPUP, articles => articles)
|
|
const showCommentArticlePopup = createAction(SHOW_COMMENT_POPUP, (article, comment) => ({article, comment}))
|
|
const showClipArticlesPopup = createAction(SHOW_CLIP_POPUP, articles => articles)
|
|
const showEmailConfirmPopup = createAction(SHOW_EMAIL_CONFIRM_POPUP)
|
|
const showShareMenu = createAction(SHOW_SHARE_MENU, article => article)
|
|
const hideDeleteArticlesPopup = createAction(HIDE_DELETE_POPUP)
|
|
const hideEmailArticlesPopup = createAction(HIDE_EMAIL_POPUP)
|
|
const hideCommentArticlePopup = createAction(HIDE_COMMENT_POPUP)
|
|
const hideClipArticlesPopup = createAction(HIDE_CLIP_POPUP)
|
|
const hideEmailConfirmPopup = createAction(HIDE_EMAIL_CONFIRM_POPUP)
|
|
const hideShareMenu = createAction(HIDE_SHARE_MENU)
|
|
|
|
const commentArticle = thunkAction(COMMENT_ARTICLE, (comment, articleId, {token, fulfilled}) => {
|
|
return api
|
|
.commentDocument(token, comment, articleId)
|
|
.then((comment) => {
|
|
fulfilled({comment, articleId})
|
|
})
|
|
})
|
|
|
|
const updateComment = thunkAction(UPDATE_COMMENT, (newComment, articleId, {getState, token, fulfilled}) => {
|
|
const commentToUpdate = getState().getIn(['appState', 'articles', 'commentPopup', 'comment']).toJS()
|
|
return api
|
|
.updateComment(token, newComment, commentToUpdate.id)
|
|
.then((comment) => {
|
|
fulfilled({comment, articleId})
|
|
})
|
|
})
|
|
|
|
const deleteComment = thunkAction(DELETE_COMMENT, (commentId, articleId, {token, fulfilled}) => {
|
|
return api
|
|
.deleteComment(token, undefined, commentId)
|
|
.then(() => {
|
|
fulfilled({commentId, articleId})
|
|
})
|
|
})
|
|
|
|
const loadMoreComments = thunkAction(LOAD_MORE_COMMENTS, (articleId, offset, {token, fulfilled}) => {
|
|
return api
|
|
.getComments(token, {offset: offset, limit: ARTICLE_COMMENTS_LIMIT}, articleId)
|
|
.then((response) => {
|
|
fulfilled({response, articleId})
|
|
})
|
|
})
|
|
|
|
const deleteArticles = createAction(DELETE_ARTICLES, ids => ids)
|
|
|
|
const deleteArticlesFromFeed = thunkAction(DELETE_ARTICLES_FROM_FEED, (ids, feedId, {token, dispatch, fulfilled}) => {
|
|
return api
|
|
.deleteDocumentsFromFeed(token, ids, feedId)
|
|
.then(() => {
|
|
dispatch(deleteArticles(ids))
|
|
fulfilled({ids, feedId})
|
|
dispatch(addAlert({
|
|
type: 'notice',
|
|
transKey: 'articleDeleted'
|
|
}))
|
|
})
|
|
})
|
|
|
|
const setEmailParams = createAction(SET_EMAIL_PARAMS, params => params)
|
|
|
|
const emailArticles = thunkAction(EMAIL_ARTICLES, (params, {dispatch}) => {
|
|
dispatch(setEmailParams(params))
|
|
if (params.subject) {
|
|
dispatch(sendDocumentsByEmail())
|
|
} else {
|
|
dispatch(showEmailConfirmPopup())
|
|
}
|
|
})
|
|
|
|
const sendDocumentsByEmail = thunkAction(SEND_DOCUMENTS_BY_EMAIL, ({token, getState, fulfilled, dispatch}) => {
|
|
const params = getState().getIn(['appState', 'articles', 'emailPopup', 'emailParams'])
|
|
return api
|
|
.sendDocumentsByEmail(token, params)
|
|
.then(() => {
|
|
dispatch(hideEmailArticlesPopup())
|
|
fulfilled()
|
|
})
|
|
})
|
|
|
|
const clipArticles = thunkAction(CLIP_ARTICLES, (feedId, {token, fulfilled, getState, dispatch}) => {
|
|
const articlesToClip = getState().getIn(['appState', 'articles', 'clipPopup', 'articles']).toJS()
|
|
const documentIds = articlesToClip.map((a) => a.id)
|
|
return api
|
|
.clipDocuments(token, documentIds, feedId)
|
|
.then(() => {
|
|
dispatch(addAlert([{type: 'notice', transKey: 'clipDocument'}]))
|
|
dispatch(hideClipArticlesPopup())
|
|
fulfilled()
|
|
})
|
|
})
|
|
|
|
const getRecentClipFeeds = thunkAction(GET_RECENT_CLIP_FEEDS, ({token, fulfilled}) => {
|
|
return api
|
|
.getRecentClipFeeds(token)
|
|
.then(fulfilled)
|
|
})
|
|
|
|
const readArticleLater = thunkAction(READ_ARTICLE_LATER, (article, {token, dispatch, fulfilled}) => {
|
|
return api
|
|
.readLater(token, undefined, article.id)
|
|
.then(() => {
|
|
dispatch(addAlert([{type: 'notice', transKey: 'clipDocument'}]))
|
|
dispatch(getSidebarCategories())
|
|
fulfilled()
|
|
})
|
|
})
|
|
|
|
const loadRecipients = thunkAction(LOAD_RECIPIENTS, ({getState, fulfilled}) => {
|
|
setTimeout(() => {
|
|
const user = getState().getIn(['common', 'auth', 'user'])
|
|
fulfilled([user.get('email')])
|
|
}, 100)
|
|
}, true)
|
|
|
|
export const actions = {
|
|
showDeleteArticlesPopup,
|
|
showCommentArticlePopup,
|
|
showEmailArticlesPopup,
|
|
showClipArticlesPopup,
|
|
showEmailConfirmPopup,
|
|
showShareMenu,
|
|
hideDeleteArticlesPopup,
|
|
hideCommentArticlePopup,
|
|
hideEmailArticlesPopup,
|
|
hideClipArticlesPopup,
|
|
hideEmailConfirmPopup,
|
|
hideShareMenu,
|
|
commentArticle,
|
|
updateComment,
|
|
deleteComment,
|
|
loadMoreComments,
|
|
deleteArticles,
|
|
deleteArticlesFromFeed,
|
|
emailArticles,
|
|
clipArticles,
|
|
getRecentClipFeeds,
|
|
readArticleLater,
|
|
loadRecipients,
|
|
sendDocumentsByEmail
|
|
}
|
|
|
|
/**
|
|
* State
|
|
*/
|
|
export const initialState = fromJS({
|
|
emailPopup: {
|
|
visible: false,
|
|
articles: [],
|
|
recipients: {
|
|
all: [],
|
|
pending: false
|
|
},
|
|
emailParams: null
|
|
},
|
|
deletePopup: {
|
|
visible: false,
|
|
articles: []
|
|
},
|
|
clipPopup: {
|
|
visible: false,
|
|
articles: []
|
|
},
|
|
commentPopup: {
|
|
visible: false,
|
|
article: null,
|
|
comment: null
|
|
},
|
|
emailConfirmPopup: {
|
|
visible: false
|
|
},
|
|
shareMenu: {
|
|
visible: false,
|
|
article: null
|
|
},
|
|
excludedArticles: [], //map of ids
|
|
recentClipFeeds: []
|
|
})
|
|
|
|
/**
|
|
* Reducers
|
|
*/
|
|
const hidePopup = (type) => (state) =>
|
|
state.mergeIn([type + 'Popup'], {visible: false, articles: []})
|
|
|
|
const showPopup = (type) => (state, {payload: articles}) =>
|
|
state.mergeIn([type + 'Popup'], {visible: true, articles: articles})
|
|
|
|
export default handleActions({
|
|
|
|
[SHOW_DELETE_POPUP]: showPopup('delete'),
|
|
[SHOW_EMAIL_POPUP]: showPopup('email'),
|
|
[SHOW_CLIP_POPUP]: showPopup('clip'),
|
|
[SHOW_EMAIL_CONFIRM_POPUP]: showPopup('emailConfirm'),
|
|
[HIDE_DELETE_POPUP]: hidePopup('delete'),
|
|
[HIDE_EMAIL_POPUP]: hidePopup('email'),
|
|
[HIDE_CLIP_POPUP]: hidePopup('clip'),
|
|
[HIDE_EMAIL_CONFIRM_POPUP]: hidePopup('emailConfirm'),
|
|
|
|
[SHOW_COMMENT_POPUP]: (state, {payload: {article, comment}}) => {
|
|
return state.mergeIn(['commentPopup'], {
|
|
visible: true,
|
|
article: article,
|
|
comment: comment
|
|
})
|
|
},
|
|
|
|
[HIDE_COMMENT_POPUP]: (state) => {
|
|
return state.mergeIn(['commentPopup'], {
|
|
visible: false,
|
|
article: null,
|
|
comment: null
|
|
})
|
|
},
|
|
|
|
[DELETE_ARTICLES]: (state, {payload: ids}) => {
|
|
const excludedArticles = state.get('excludedArticles')
|
|
const results = _.union(excludedArticles, ids)
|
|
return state.set('excludedArticles', results)
|
|
},
|
|
|
|
[`${GET_RECENT_CLIP_FEEDS} fulfilled`]: (state, {payload: recentClipFeeds}) => {
|
|
return state.set('recentClipFeeds', recentClipFeeds)
|
|
},
|
|
|
|
[SHOW_SHARE_MENU]: (state, {payload: article}) => {
|
|
return state.mergeIn(['shareMenu'], {
|
|
visible: true,
|
|
article
|
|
})
|
|
},
|
|
|
|
[HIDE_SHARE_MENU]: (state) => {
|
|
return state.setIn(['shareMenu', 'visible'], false)
|
|
},
|
|
|
|
[`${LOAD_RECIPIENTS} pending`]: (state, {payload: {isPending}}) => {
|
|
return state.setIn(['emailPopup', 'recipients', 'pending'], isPending)
|
|
},
|
|
|
|
[`${LOAD_RECIPIENTS} fulfilled`]: (state, {payload: emails}) => {
|
|
return state.setIn(['emailPopup', 'recipients', 'all'], emails)
|
|
},
|
|
|
|
[SET_EMAIL_PARAMS]: (state, {payload: params}) => state.setIn(['emailPopup', 'emailParams'], params)
|
|
|
|
}, initialState)
|
|
|