Basic discussions forum framework
Adds the basic structure for the Discussions MFE around which future development will happen.
This commit is contained in:
31
src/discussions/comments/data/api.js
Normal file
31
src/discussions/comments/data/api.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { API_BASE_URL } from '../../../data/constants';
|
||||
|
||||
export async function getThreadComments(
|
||||
threadId, {
|
||||
commentId, page, pageSize, requestedFields,
|
||||
} = {},
|
||||
) {
|
||||
const url = new URL(`${API_BASE_URL}/api/discussion/v1/comments/`);
|
||||
const paramsMap = {
|
||||
thread_id: threadId,
|
||||
comment_id: commentId,
|
||||
page,
|
||||
page_size: pageSize,
|
||||
requested_fields: requestedFields,
|
||||
};
|
||||
Object.keys(paramsMap)
|
||||
.forEach(
|
||||
(param) => {
|
||||
const paramValue = paramsMap[param];
|
||||
if (paramValue) {
|
||||
url.searchParams.append(param, paramValue);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.get(url);
|
||||
return data;
|
||||
}
|
||||
1
src/discussions/comments/data/index.js
Normal file
1
src/discussions/comments/data/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export * from './slices';
|
||||
4
src/discussions/comments/data/selectors.js
Normal file
4
src/discussions/comments/data/selectors.js
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
export const selectTopicComments = topicId => state => state.comments.comments[topicId] || [];
|
||||
|
||||
export const courseTopicsStatus = state => state.comments.status;
|
||||
43
src/discussions/comments/data/slices.js
Normal file
43
src/discussions/comments/data/slices.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* eslint-disable no-param-reassign,import/prefer-default-export */
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { LoadingStatus } from '../../../data/constants';
|
||||
|
||||
const commentsSlice = createSlice({
|
||||
name: 'comments',
|
||||
initialState: {
|
||||
status: LoadingStatus.LOADING,
|
||||
page: null,
|
||||
comments: {
|
||||
// Map thread ids to comments
|
||||
},
|
||||
totalPages: null,
|
||||
totalThreads: null,
|
||||
},
|
||||
reducers: {
|
||||
fetchCommentsRequest: (state) => {
|
||||
state.status = LoadingStatus.LOADING;
|
||||
},
|
||||
fetchCommentsSuccess: (state, { payload }) => {
|
||||
const { data, topicId } = payload;
|
||||
state.status = LoadingStatus.LOADED;
|
||||
state.comments[topicId] = data.results;
|
||||
state.page = data.pagination.page;
|
||||
state.totalPages = data.pagination.num_pages;
|
||||
state.totalThreads = data.pagination.count;
|
||||
},
|
||||
fetchCommentsFailed: (state) => {
|
||||
state.status = LoadingStatus.FAILED;
|
||||
},
|
||||
fetchCommentsDenied: (state) => {
|
||||
state.status = LoadingStatus.DENIED;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
fetchCommentsRequest,
|
||||
fetchCommentsSuccess,
|
||||
fetchCommentsFailed,
|
||||
} = commentsSlice.actions;
|
||||
|
||||
export const commentsReducer = commentsSlice.reducer;
|
||||
17
src/discussions/comments/data/thunks.js
Normal file
17
src/discussions/comments/data/thunks.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { logError } from '@edx/frontend-platform/logging';
|
||||
import { getThreadComments } from './api';
|
||||
import { fetchCommentsFailed, fetchCommentsRequest, fetchCommentsSuccess } from './slices';
|
||||
|
||||
export function fetchTopicComments(topicId) {
|
||||
return async (dispatch) => {
|
||||
try {
|
||||
dispatch(fetchCommentsRequest({ topicId }));
|
||||
const data = await getThreadComments(topicId);
|
||||
dispatch(fetchCommentsSuccess({ topicId, data }));
|
||||
} catch (error) {
|
||||
dispatch(fetchCommentsFailed());
|
||||
logError(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user