feat: Created Course updates page (#581)

This commit is contained in:
vladislavkeblysh
2023-08-31 17:56:45 +03:00
committed by GitHub
parent 181f9c7a5f
commit ffae3bd868
61 changed files with 2241 additions and 8 deletions

View File

@@ -0,0 +1,84 @@
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
export const getCourseUpdatesApiUrl = (courseId) => `${getApiBaseUrl()}/course_info_update/${courseId}/`;
export const updateCourseUpdatesApiUrl = (courseId, updateId) => `${getApiBaseUrl()}/course_info_update/${courseId}/${updateId}`;
export const getCourseHandoutApiUrl = (courseId) => {
const formattedCourseId = courseId.split('course-v1:')[1];
return `${getApiBaseUrl()}/xblock/block-v1:${formattedCourseId}+type@course_info+block@handouts`;
};
/**
* Get course updates.
* @param {string} courseId
* @returns {Promise<Object>}
*/
export async function getCourseUpdates(courseId) {
const { data } = await getAuthenticatedHttpClient()
.get(getCourseUpdatesApiUrl(courseId));
return data;
}
/**
* Create new course update.
* @param {string} courseId
* @param {object} courseUpdate
* @returns {Promise<Object>}
*/
export async function createUpdate(courseId, courseUpdate) {
const { data } = await getAuthenticatedHttpClient()
.post(getCourseUpdatesApiUrl(courseId), courseUpdate);
return data;
}
/**
* Edit course update.
* @param {string} courseId
* @param {object} courseUpdate
* @returns {Promise<Object>}
*/
export async function editUpdate(courseId, courseUpdate) {
const { data } = await getAuthenticatedHttpClient()
.put(updateCourseUpdatesApiUrl(courseId, courseUpdate.id), courseUpdate);
return data;
}
/**
* Delete course update.
* @param {string} courseId
* @param {number} updateId
1 */
export async function deleteUpdate(courseId, updateId) {
const { data } = await getAuthenticatedHttpClient()
.delete(updateCourseUpdatesApiUrl(courseId, updateId));
return data;
}
/**
* Get course handouts.
* @param {string} courseId
* @returns {Promise<Object>}
*/
export async function getCourseHandouts(courseId) {
const { data } = await getAuthenticatedHttpClient()
.get(getCourseHandoutApiUrl(courseId));
return data;
}
/**
* Edit course handouts.
* @param {string} courseId
* @param {object} courseHandouts
* @returns {Promise<Object>}
*/
export async function editHandouts(courseId, courseHandouts) {
const { data } = await getAuthenticatedHttpClient()
.put(getCourseHandoutApiUrl(courseId), courseHandouts);
return data;
}

View File

@@ -0,0 +1,4 @@
export const getCourseUpdates = (state) => state.courseUpdates.courseUpdates;
export const getCourseHandouts = (state) => state.courseUpdates.courseHandouts;
export const getSavingStatuses = (state) => state.courseUpdates.savingStatuses;
export const getLoadingStatuses = (state) => state.courseUpdates.loadingStatuses;

View File

@@ -0,0 +1,72 @@
/* eslint-disable no-param-reassign */
import { createSlice } from '@reduxjs/toolkit';
import { sortBy } from 'lodash';
const initialState = {
courseUpdates: [],
courseHandouts: {},
savingStatuses: {
createCourseUpdateQuery: '',
editCourseUpdateQuery: '',
deleteCourseUpdateQuery: '',
editCourseHandoutsQuery: '',
},
loadingStatuses: {
fetchCourseUpdatesQuery: '',
fetchCourseHandoutsQuery: '',
},
};
const slice = createSlice({
name: 'courseUpdates',
initialState,
reducers: {
fetchCourseUpdatesSuccess: (state, { payload }) => {
state.courseUpdates = payload;
},
createCourseUpdate: (state, { payload }) => {
state.courseUpdates = [payload, ...state.courseUpdates];
},
editCourseUpdate: (state, { payload }) => {
state.courseUpdates = state.courseUpdates.map((courseUpdate) => {
if (courseUpdate.id === payload.id) {
return payload;
}
return courseUpdate;
});
},
deleteCourseUpdate: (state, { payload }) => {
state.courseUpdates = sortBy(payload, 'id').reverse();
},
fetchCourseHandoutsSuccess: (state, { payload }) => {
state.courseHandouts = payload;
},
editCourseHandouts: (state, { payload }) => {
state.courseHandouts = {
...state.courseHandouts,
...payload,
};
},
updateSavingStatuses: (state, { payload }) => {
state.savingStatuses = { ...state.savingStatuses, ...payload };
},
updateLoadingStatuses: (state, { payload }) => {
state.loadingStatuses = { ...state.loadingStatuses, ...payload };
},
},
});
export const {
fetchCourseUpdatesSuccess,
createCourseUpdate,
editCourseUpdate,
deleteCourseUpdate,
fetchCourseHandoutsSuccess,
editCourseHandouts,
updateSavingStatuses,
updateLoadingStatuses,
} = slice.actions;
export const {
reducer,
} = slice;

View File

@@ -0,0 +1,111 @@
import { NOTIFICATION_MESSAGES } from '../../constants';
import { RequestStatus } from '../../data/constants';
import { hideProcessingNotification, showProcessingNotification } from '../../generic/processing-notification/data/slice';
import {
getCourseUpdates,
getCourseHandouts,
createUpdate,
editUpdate,
deleteUpdate,
editHandouts,
} from './api';
import {
fetchCourseUpdatesSuccess,
createCourseUpdate,
editCourseUpdate,
deleteCourseUpdate,
fetchCourseHandoutsSuccess,
editCourseHandouts,
updateLoadingStatuses,
updateSavingStatuses,
} from './slice';
export function fetchCourseUpdatesQuery(courseId) {
return async (dispatch) => {
try {
dispatch(updateLoadingStatuses({ fetchCourseHandoutsQuery: RequestStatus.IN_PROGRESS }));
const courseUpdates = await getCourseUpdates(courseId);
dispatch(fetchCourseUpdatesSuccess(courseUpdates));
dispatch(updateLoadingStatuses({ fetchCourseHandoutsQuery: RequestStatus.SUCCESSFUL }));
} catch (error) {
dispatch(updateLoadingStatuses({ fetchCourseHandoutsQuery: RequestStatus.FAILED }));
}
};
}
export function createCourseUpdateQuery(courseId, data) {
return async (dispatch) => {
try {
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.PENDING }));
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.saving));
const courseUpdate = await createUpdate(courseId, data);
dispatch(createCourseUpdate(courseUpdate));
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.SUCCESSFUL }));
} catch (error) {
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.FAILED }));
}
};
}
export function editCourseUpdateQuery(courseId, data) {
return async (dispatch) => {
try {
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.PENDING }));
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.saving));
const courseUpdate = await editUpdate(courseId, data);
dispatch(editCourseUpdate(courseUpdate));
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.SUCCESSFUL }));
} catch (error) {
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.FAILED }));
}
};
}
export function deleteCourseUpdateQuery(courseId, updateId) {
return async (dispatch) => {
try {
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.PENDING }));
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.deleting));
const courseUpdates = await deleteUpdate(courseId, updateId);
dispatch(deleteCourseUpdate(courseUpdates));
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.SUCCESSFUL }));
} catch (error) {
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.FAILED }));
}
};
}
export function fetchCourseHandoutsQuery(courseId) {
return async (dispatch) => {
try {
dispatch(updateLoadingStatuses({ fetchCourseHandoutsQuery: RequestStatus.IN_PROGRESS }));
const courseHandouts = await getCourseHandouts(courseId);
dispatch(fetchCourseHandoutsSuccess(courseHandouts));
dispatch(updateLoadingStatuses({ fetchCourseHandoutsQuery: RequestStatus.SUCCESSFUL }));
} catch (error) {
dispatch(updateLoadingStatuses({ fetchCourseHandoutsQuery: RequestStatus.FAILED }));
}
};
}
export function editCourseHandoutsQuery(courseId, data) {
return async (dispatch) => {
try {
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.PENDING }));
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.saving));
const courseHandouts = await editHandouts(courseId, data);
dispatch(editCourseHandouts(courseHandouts));
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.SUCCESSFUL }));
} catch (error) {
dispatch(hideProcessingNotification());
dispatch(updateSavingStatuses({ createCourseUpdateQuery: RequestStatus.FAILED }));
}
};
}