Files
2022-12-09 08:36:26 -06:00

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)