Files
frontend-app-discussions/src/discussions/post-comments/data/thunks.js

190 lines
5.0 KiB
JavaScript

/* eslint-disable import/prefer-default-export */
import { camelCaseObject } from '@edx/frontend-platform';
import { logError } from '@edx/frontend-platform/logging';
import { ContentActions, EndorsementStatus } from '../../../data/constants';
import { getHttpErrorStatus } from '../../utils';
import {
deleteComment, getCommentResponses, getThreadComments, postComment, updateComment,
} from './api';
import {
deleteCommentDenied,
deleteCommentFailed,
deleteCommentRequest,
deleteCommentSuccess,
fetchCommentResponsesDenied,
fetchCommentResponsesFailed,
fetchCommentResponsesRequest,
fetchCommentResponsesSuccess,
fetchCommentsDenied,
fetchCommentsFailed,
fetchCommentsRequest,
fetchCommentsSuccess,
postCommentDenied,
postCommentFailed,
postCommentRequest,
postCommentSuccess,
updateCommentDenied,
updateCommentFailed,
updateCommentRequest,
updateCommentsList,
updateCommentSuccess,
} from './slices';
/**
* Normalises comment data by mapping comments to ids, and grouping them by their
* parent thread and comment.
* @param data
* @returns {{commentsInComments: {}, pagination, commentsById: {}, commentsInThreads: {}}}
*/
function normaliseComments(data) {
const { pagination, results } = data;
const commentsInThreads = {};
const commentsInComments = {};
const commentsById = {};
const ids = [];
results.forEach(
comment => {
const { parentId, threadId, id } = comment;
ids.push(id);
if (parentId) {
if (!commentsInComments[parentId]) {
commentsInComments[parentId] = [];
}
if (!commentsInComments[parentId].includes(id)) {
commentsInComments[parentId].push(id);
}
} else {
if (!commentsInThreads[threadId]) {
commentsInThreads[threadId] = [];
}
if (!commentsInThreads[threadId].includes(id)) {
commentsInThreads[threadId].push(id);
}
}
commentsById[id] = comment;
},
);
return {
ids,
commentsInThreads,
commentsInComments,
commentsById,
pagination,
};
}
export function fetchThreadComments(
threadId,
{
page = 1,
reverseOrder,
endorsed = EndorsementStatus.DISCUSSION,
enableInContextSidebar,
} = {},
) {
return async (dispatch) => {
try {
dispatch(fetchCommentsRequest());
const data = await getThreadComments(threadId, {
page, reverseOrder, endorsed, enableInContextSidebar,
});
dispatch(fetchCommentsSuccess({
...normaliseComments(camelCaseObject(data)),
endorsed,
page,
threadId,
}));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(fetchCommentsDenied());
} else {
dispatch(fetchCommentsFailed());
}
logError(error);
}
};
}
export function fetchCommentResponses(commentId, { page = 1, reverseOrder = true } = {}) {
return async (dispatch) => {
try {
dispatch(fetchCommentResponsesRequest({ commentId }));
const data = await getCommentResponses(commentId, { page, reverseOrder });
dispatch(fetchCommentResponsesSuccess({
...normaliseComments(camelCaseObject(data)),
page,
commentId,
}));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(fetchCommentResponsesDenied());
} else {
dispatch(fetchCommentResponsesFailed());
}
logError(error);
}
};
}
export function editComment(commentId, comment, action = null) {
return async (dispatch) => {
try {
dispatch(updateCommentRequest({ commentId }));
const data = await updateComment(commentId, comment);
dispatch(updateCommentSuccess(camelCaseObject(data)));
if (action === ContentActions.ENDORSE) {
dispatch(updateCommentsList(camelCaseObject(data)));
}
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(updateCommentDenied());
} else {
dispatch(updateCommentFailed());
}
logError(error);
}
};
}
export function addComment(comment, threadId, parentId = null, enableInContextSidebar = false) {
return async (dispatch) => {
try {
dispatch(postCommentRequest({
comment,
threadId,
parentId,
}));
const data = await postComment(comment, threadId, parentId, enableInContextSidebar);
dispatch(postCommentSuccess(camelCaseObject(data)));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(postCommentDenied());
} else {
dispatch(postCommentFailed());
}
logError(error);
}
};
}
export function removeComment(commentId, threadId) {
return async (dispatch) => {
try {
dispatch(deleteCommentRequest({ commentId }));
await deleteComment(commentId);
dispatch(deleteCommentSuccess({
commentId,
threadId,
}));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(deleteCommentDenied());
} else {
dispatch(deleteCommentFailed());
}
logError(error);
}
};
}