chore: removed eslint-disable statements (#658)

* chore: removed eslint-disable statements

* refactor: removed unnecessary files and unintentional eslint-disable statements

* refactor: removed eslint import/no-cycle error

* fix: failing testcase

* style: removed comments

* fix: failing testcase

---------

Co-authored-by: sohailfatima <23100065@lums.edu.pk>
Co-authored-by: Fatima Sohail <68312464+sohailfatima@users.noreply.github.com>
This commit is contained in:
ayesha waris
2024-01-31 16:54:03 +05:00
committed by GitHub
parent 88a985da35
commit f69b2c118f
159 changed files with 1151 additions and 1077 deletions

View File

@@ -5,10 +5,10 @@ module.exports = createConfig('jest', {
// If you want to add config BEFORE jest loads, use setupFiles instead.
setupFiles: ['<rootDir>/.env.test'],
setupFilesAfterEnv: [
'<rootDir>/src/setupTest.js',
'<rootDir>/src/setupTest.jsx',
],
coveragePathIgnorePatterns: [
'src/setupTest.js',
'src/setupTest.jsx',
'src/i18n',
],
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable react/forbid-prop-types */
import React, { useCallback, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
@@ -15,7 +14,7 @@ import {
PostsStatusFilter, RequestStatus,
ThreadOrdering, ThreadType,
} from '../data/constants';
import { selectCourseCohorts } from '../discussions/cohorts/data/selectors';
import selectCourseCohorts from '../discussions/cohorts/data/selectors';
import messages from '../discussions/posts/post-filter-bar/messages';
import { ActionItem } from '../discussions/posts/post-filter-bar/PostFilterBar';
@@ -194,8 +193,16 @@ const FilterBar = ({
FilterBar.propTypes = {
intl: intlShape.isRequired,
filters: PropTypes.array.isRequired,
selectedFilters: PropTypes.object.isRequired,
filters: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
filters: PropTypes.arrayOf(PropTypes.string),
})).isRequired,
selectedFilters: PropTypes.shape({
postType: ThreadType,
status: PostsStatusFilter,
orderBy: ThreadOrdering,
cohort: PropTypes.string,
}).isRequired,
onFilterChange: PropTypes.func.isRequired,
showCohortsFilter: PropTypes.bool,
};

View File

@@ -6,7 +6,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { fetchTab } from './data/thunks';
import fetchTab from './data/thunks';
import Tabs from './tabs/Tabs';
import messages from './messages';

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { camelCaseObject } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

View File

@@ -5,9 +5,9 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import executeThunk from '../../../test-utils';
import { getCourseMetadataApiUrl } from './api';
import { fetchTab } from './thunks';
import fetchTab from './thunks';
import './__factories__';

View File

@@ -1,3 +1,3 @@
/* eslint-disable import/prefer-default-export */
const selectCourseTabs = state => state.courseTabs;
export const selectCourseTabs = state => state.courseTabs;
export default selectCourseTabs;

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign */
import { createSlice } from '@reduxjs/toolkit';
export const LOADING = 'loading';
@@ -17,27 +16,39 @@ const slice = createSlice({
org: null,
},
reducers: {
fetchTabDenied: (state, { payload }) => {
state.courseId = payload.courseId;
state.courseStatus = DENIED;
},
fetchTabFailure: (state, { payload }) => {
state.courseId = payload.courseId;
state.courseStatus = FAILED;
},
fetchTabRequest: (state, { payload }) => {
state.courseId = payload.courseId;
state.courseStatus = LOADING;
},
fetchTabSuccess: (state, { payload }) => {
state.courseId = payload.courseId;
state.targetUserId = payload.targetUserId;
state.tabs = payload.tabs;
state.courseStatus = LOADED;
state.courseTitle = payload.courseTitle;
state.courseNumber = payload.courseNumber;
state.org = payload.org;
},
fetchTabDenied: (state, { payload }) => (
{
...state,
courseId: payload.courseId,
courseStatus: DENIED,
}
),
fetchTabFailure: (state, { payload }) => (
{
...state,
courseId: payload.courseId,
courseStatus: FAILED,
}
),
fetchTabRequest: (state, { payload }) => (
{
...state,
courseId: payload.courseId,
courseStatus: LOADING,
}
),
fetchTabSuccess: (state, { payload }) => (
{
...state,
courseId: payload.courseId,
targetUserId: payload.targetUserId,
tabs: payload.tabs,
courseStatus: LOADED,
courseTitle: payload.courseTitle,
courseNumber: payload.courseNumber,
org: payload.org,
}
),
},
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export, no-unused-expressions */
import { logError } from '@edx/frontend-platform/logging';
import { getHttpErrorStatus } from '../../../discussions/utils';
@@ -10,7 +9,7 @@ import {
fetchTabSuccess,
} from './slice';
export function fetchTab(courseId, rootSlug) {
export default function fetchTab(courseId, rootSlug) {
return async (dispatch) => {
dispatch(fetchTabRequest({ courseId }));
try {

View File

@@ -1,2 +0,0 @@
/* eslint-disable import/prefer-default-export */
export { default as CourseTabsNavigation } from './CourseTabsNavigation';

View File

@@ -9,7 +9,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { Icon, SearchField } from '@edx/paragon';
import { Search as SearchIcon } from '@edx/paragon/icons';
import { DiscussionContext } from '../discussions/common/context';
import DiscussionContext from '../discussions/common/context';
import { setUsernameSearch } from '../discussions/learners/data';
import { setSearchQuery } from '../discussions/posts/data';
import postsMessages from '../discussions/posts/post-actions-bar/messages';

View File

@@ -1,21 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function InsertLink() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"
clipRule="evenodd"
/>
</svg>
);
}

View File

@@ -1,27 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function Issue() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="28"
height="28"
fill="none"
viewBox="0 0 28 28"
>
<path
fill="#F2F0EF"
d="M0 14C0 6.268 6.268 0 14 0s14 6.268 14 14-6.268 14-14 14S0 21.732 0 14z"
/>
<path
fill="#2D494E"
d="M14 2.333C7.56 2.333 2.333 7.56 2.333 14c0 6.44 5.227 11.667 11.667 11.667 6.44 0 11.667-5.227 11.667-11.667C25.667 7.56 20.44 2.334 14 2.334z"
/>
<path
fill="#fff"
d="M12.833 22.167h2.334v-2.334h-2.334v2.334zM16.532 14.198l1.05-1.073a3.713 3.713 0 001.085-2.625A4.665 4.665 0 0014 5.833 4.665 4.665 0 009.333 10.5h2.334A2.34 2.34 0 0114 8.167a2.34 2.34 0 012.333 2.333c0 .642-.256 1.225-.688 1.645l-1.447 1.47a4.696 4.696 0 00-1.365 3.302v.583h2.334c0-1.75.525-2.45 1.365-3.302z"
/>
</svg>
);
}

View File

@@ -1,19 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function People() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="none"
viewBox="0 0 16 16"
>
<path
fill="#707070"
d="M11.072 7.332a1.992 1.992 0 001.993-2 1.997 1.997 0 10-3.993 0c0 1.107.893 2 2 2zm-5.334 0a1.992 1.992 0 001.994-2 1.997 1.997 0 10-3.993 0c0 1.107.893 2 2 2zm0 1.333c-1.553 0-4.666.78-4.666 2.334v1.666h9.333V11c0-1.554-3.113-2.334-4.667-2.334zm5.334 0c-.194 0-.414.014-.647.034.773.56 1.313 1.313 1.313 2.3v1.666h4V11c0-1.554-3.113-2.334-4.666-2.334z"
/>
</svg>
);
}

View File

@@ -1,21 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function PushPin() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M16 9V4H18V2H6V4H8V9C8 10.66 6.66 12 5 12V14H10.97V21L11.97 22L12.97 21V14H19V12C17.34 12 16 10.66 16 9Z"
clipRule="evenodd"
/>
</svg>
);
}

View File

@@ -1,27 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function Question() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="28"
height="28"
fill="none"
viewBox="0 0 28 28"
>
<path
fill="#fff"
d="M0 14.001c0-7.732 6.268-14 14-14s14 6.268 14 14-6.268 14-14 14-14-6.268-14-14z"
/>
<path
fill="#2D494E"
d="M14 2.334c-6.44 0-11.667 5.227-11.667 11.667 0 6.44 5.227 11.667 11.667 11.667 6.44 0 11.666-5.227 11.666-11.667 0-6.44-5.226-11.667-11.666-11.667z"
/>
<path
fill="#fff"
d="M12.833 22.168h2.333v-2.334h-2.333v2.334zM16.531 14.2l1.05-1.074a3.712 3.712 0 001.085-2.625A4.665 4.665 0 0014 5.834a4.665 4.665 0 00-4.667 4.667h2.333A2.34 2.34 0 0114 8.168a2.34 2.34 0 012.333 2.333c0 .642-.257 1.225-.688 1.645l-1.447 1.47a4.696 4.696 0 00-1.365 3.302v.583h2.333c0-1.75.525-2.45 1.365-3.302z"
/>
</svg>
);
}

View File

@@ -1,19 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function QuestionAnswer() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="21"
height="20"
fill="none"
viewBox="0 0 21 20"
>
<path
fill="currentColor"
d="M18.737 5h-2.5v7.5H5.404V15h10l3.333 3.333V5zm-4.166 5.833V1.667H2.07v12.5l3.333-3.334h9.166z"
/>
</svg>
);
}

View File

@@ -1,19 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function QuestionAnswerOutline() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="none"
viewBox="0 0 20 20"
>
<path
fill="currentColor"
d="M12.6 3.267v6.067H4.08l-.512.512-.502.502v-7.08H12.6zm.867-1.733H2.198a.87.87 0 00-.867.867v12.134L4.8 11.068h8.668a.87.87 0 00.866-.867v-7.8a.87.87 0 00-.867-.867zM17.8 5h-1.733v7.8H4.799v1.734c0 .476.39.867.867.867H15.2l3.467 3.466v-13A.87.87 0 0017.8 5z"
/>
</svg>
);
}

View File

@@ -1,19 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function StarFilled() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="21"
height="20"
fill="none"
viewBox="0 0 21 20"
>
<path
fill="currentColor"
d="M10.404 14.392l5.15 3.108-1.367-5.858 4.55-3.942-5.991-.508-2.342-5.525-2.342 5.525L2.07 7.7l4.55 3.942L5.254 17.5l5.15-3.108z"
/>
</svg>
);
}

View File

@@ -1,19 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function StarOutline() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="none"
viewBox="0 0 20 20"
>
<path
fill="currentColor"
d="M18.737 7.7l-5.991-.517-2.342-5.516-2.342 5.525L2.07 7.7l4.55 3.942L5.254 17.5l5.15-3.108 5.15 3.108-1.359-5.858L18.737 7.7zm-8.333 5.133L7.27 14.725l.834-3.567-2.767-2.4 3.65-.316 1.417-3.359 1.425 3.367 3.65.317-2.767 2.4.834 3.566-3.142-1.9z"
/>
</svg>
);
}

View File

@@ -1,19 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function ThumbUpFilled() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="21"
height="20"
fill="none"
viewBox="0 0 21 20"
>
<path
fill="currentColor"
d="M12.212.833L6.237 6.817V17.5h10.258l3.075-7.167V6.667h-6.925l.934-4.484-1.367-1.35zM1.237 7.5H4.57v10H1.237v-10z"
/>
</svg>
);
}

View File

@@ -1,22 +0,0 @@
import React from 'react';
// eslint-disable-next-line react/function-component-definition
export default function ThumbUpOutline() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="none"
viewBox="0 0 20 20"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M19.57 6.667v3.666L16.495 17.5H6.238V6.817L12.212.833l1.367 1.35-.934 4.484h6.925zm-11.666.841v8.325h7.492l2.508-5.841V8.333h-7.309l.925-4.45-3.616 3.625z"
clipRule="evenodd"
/>
<path fill="currentColor" d="M4.57 17.5H1.237v-10H4.57v10z" />
</svg>
);
}

View File

@@ -1,11 +0,0 @@
export { default as InsertLink } from './InsertLink';
export { default as Issue } from './Issue';
export { default as People } from './People';
export { default as PushPin } from './PushPin';
export { default as Question } from './Question';
export { default as QuestionAnswer } from './QuestionAnswer';
export { default as QuestionAnswerOutline } from './QuestionAnswerOutline';
export { default as StarFilled } from './StarFilled';
export { default as StarOutline } from './StarOutline';
export { default as ThumbUpFilled } from './ThumbUpFilled';
export { default as ThumbUpOutline } from './ThumbUpOutline';

View File

@@ -1,7 +1,5 @@
/* eslint-disable import/prefer-default-export */
// Course Blocks API response for the demo course.
export const getBlocksAPIResponse = (newProvider = false) => {
const getBlocksAPIResponse = (newProvider = false) => {
const response = {
root: 'block-v1:edX+DemoX+Demo_Course+type@course+block@course',
blocks: {
@@ -936,3 +934,5 @@ export const getBlocksAPIResponse = (newProvider = false) => {
}
return response;
};
export default getBlocksAPIResponse;

View File

@@ -1 +0,0 @@
export * from './blocks';

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { getApiBaseUrl } from './constants';

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { useState } from 'react';
import { useDispatch } from 'react-redux';
@@ -15,7 +14,7 @@ import { useDispatch } from 'react-redux';
*
* @return {(boolean|(function(*=): Promise<void>)|*)[]}
*/
export function useDispatchWithState() {
export default function useDispatchWithState() {
const dispatch = useDispatch();
const [isDispatching, setDispatching] = useState(false);

View File

@@ -5,11 +5,11 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../store';
import { executeThunk } from '../test-utils';
import { getBlocksAPIResponse } from './__factories__';
import executeThunk from '../test-utils';
import getBlocksAPIResponse from './__factories__/blocks';
import { getBlocksAPIURL } from './api';
import { RequestStatus } from './constants';
import { fetchCourseBlocks } from './thunks';
import fetchCourseBlocks from './thunks';
const blocksAPIURL = getBlocksAPIURL();
const courseId = 'course-v1:edX+DemoX+Demo_Course';

View File

@@ -1,5 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { createSelector } from '@reduxjs/toolkit';
import { selectDiscussionProvider, selectGroupAtSubsection } from '../discussions/data/selectors';

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign,import/prefer-default-export */
import { createSlice } from '@reduxjs/toolkit';
import { RequestStatus } from './constants';
@@ -16,19 +15,33 @@ const blocksSlice = createSlice({
blocks: {},
},
reducers: {
fetchCourseBlocksRequest: (state) => {
state.status = RequestStatus.IN_PROGRESS;
},
fetchCourseBlocksSuccess: (state, { payload }) => {
state.status = RequestStatus.SUCCESSFUL;
Object.assign(state, payload);
},
fetchCourseBlocksFailed: (state) => {
state.status = RequestStatus.FAILED;
},
fetchCourseBlocksDenied: (state) => {
state.status = RequestStatus.DENIED;
},
fetchCourseBlocksRequest: (state) => (
{
...state,
status: RequestStatus.IN_PROGRESS,
}
),
fetchCourseBlocksSuccess: (state, { payload }) => (
{
...state,
status: RequestStatus.SUCCESSFUL,
topics: payload.topics,
chapters: payload.chapters,
blocks: payload.blocks,
}
),
fetchCourseBlocksFailed: (state) => (
{
...state,
status: RequestStatus.FAILED,
}
),
fetchCourseBlocksDenied: (state) => (
{
...state,
status: RequestStatus.DENIED,
}
),
},
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export, no-unused-expressions */
import { camelCaseObject } from '@edx/frontend-platform';
import { logError } from '@edx/frontend-platform/logging';
@@ -88,7 +87,7 @@ function normaliseCourseBlocks({
};
}
export function fetchCourseBlocks(courseId, username) {
export default function fetchCourseBlocks(courseId, username) {
return async (dispatch) => {
try {
dispatch(fetchCourseBlocksRequest({ courseId }));

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { ensureConfig, getConfig, snakeCaseObject } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

View File

@@ -5,9 +5,9 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import executeThunk from '../../../test-utils';
import { getCohortsApiUrl } from './api';
import { fetchCourseCohorts } from './thunks';
import fetchCourseCohorts from './thunks';
import './__factories__';

View File

@@ -1,3 +1,3 @@
/* eslint-disable import/prefer-default-export */
const selectCourseCohorts = state => state.cohorts.cohorts;
export const selectCourseCohorts = state => state.cohorts.cohorts;
export default selectCourseCohorts;

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign,import/prefer-default-export */
import { createSlice } from '@reduxjs/toolkit';
import { RequestStatus } from '../../../data/constants';
@@ -10,17 +9,26 @@ const cohortsSlice = createSlice({
cohorts: [],
},
reducers: {
fetchCohortsRequest: (state) => {
state.status = RequestStatus.IN_PROGRESS;
state.cohorts = [];
},
fetchCohortsSuccess: (state, { payload }) => {
state.status = RequestStatus.SUCCESSFUL;
state.cohorts = payload;
},
fetchCohortsFailed: (state) => {
state.status = RequestStatus.FAILED;
},
fetchCohortsRequest: (state) => (
{
...state,
status: RequestStatus.IN_PROGRESS,
cohorts: [],
}
),
fetchCohortsSuccess: (state, { payload }) => (
{
...state,
status: RequestStatus.SUCCESSFUL,
cohorts: payload,
}
),
fetchCohortsFailed: (state) => (
{
...state,
status: RequestStatus.FAILED,
}
),
},
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { camelCaseObject } from '@edx/frontend-platform';
import { logError } from '@edx/frontend-platform/logging';
@@ -11,7 +10,7 @@ import {
fetchCohortsSuccess,
} from './slices';
export function fetchCourseCohorts(courseId) {
export default function fetchCourseCohorts(courseId) {
return async (dispatch) => {
try {
dispatch(fetchCohortsRequest());

View File

@@ -12,13 +12,13 @@ import { AppProvider } from '@edx/frontend-platform/react';
import { ContentActions } from '../../data/constants';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import { getCourseConfigApiUrl } from '../data/api';
import { fetchCourseConfig } from '../data/thunks';
import fetchCourseConfig from '../data/thunks';
import messages from '../messages';
import { getCommentsApiUrl } from '../post-comments/data/api';
import { addComment, fetchThreadComments } from '../post-comments/data/thunks';
import { PostCommentsContext } from '../post-comments/postCommentsContext';
import PostCommentsContext from '../post-comments/postCommentsContext';
import { getThreadsApiUrl } from '../posts/data/api';
import { fetchThread } from '../posts/data/thunks';
import { ACTIONS_LIST } from '../utils';

View File

@@ -9,7 +9,7 @@ import { ThreadType } from '../../data/constants';
import { initializeStore } from '../../store';
import messages from '../post-comments/messages';
import AlertBanner from './AlertBanner';
import { DiscussionContext } from './context';
import DiscussionContext from './context';
import '../post-comments/data/__factories__';
import '../posts/data/__factories__';

View File

@@ -11,7 +11,7 @@ import { Institution, School } from '@edx/paragon/icons';
import { Routes } from '../../data/constants';
import messages from '../messages';
import { DiscussionContext } from './context';
import DiscussionContext from './context';
import timeLocale from './time-locale';
const AuthorLabel = ({

View File

@@ -9,11 +9,11 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import { getCourseConfigApiUrl } from '../data/api';
import { fetchCourseConfig } from '../data/thunks';
import fetchCourseConfig from '../data/thunks';
import AuthorLabel from './AuthorLabel';
import { DiscussionContext } from './context';
import DiscussionContext from './context';
const courseId = 'course-v1:edX+DemoX+Demo_Course';
const courseConfigApiUrl = getCourseConfigApiUrl();

View File

@@ -9,7 +9,7 @@ import { CheckCircle, Verified } from '@edx/paragon/icons';
import { ThreadType } from '../../data/constants';
import messages from '../post-comments/messages';
import { PostCommentsContext } from '../post-comments/postCommentsContext';
import PostCommentsContext from '../post-comments/postCommentsContext';
import AuthorLabel from './AuthorLabel';
import timeLocale from './time-locale';

View File

@@ -8,8 +8,8 @@ import { AppProvider } from '@edx/frontend-platform/react';
import { ThreadType } from '../../data/constants';
import { initializeStore } from '../../store';
import messages from '../post-comments/messages';
import { PostCommentsContext } from '../post-comments/postCommentsContext';
import { DiscussionContext } from './context';
import PostCommentsContext from '../post-comments/postCommentsContext';
import DiscussionContext from './context';
import EndorsedAlertBanner from './EndorsedAlertBanner';
import '../post-comments/data/__factories__';

View File

@@ -7,14 +7,15 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import {
Button, Icon, IconButton, OverlayTrigger, Tooltip,
} from '@edx/paragon';
import {
StarFilled, StarOutline, ThumbUpFilled, ThumbUpOutline,
} from '../../components/icons';
} from '@edx/paragon/icons';
import { ThreadType } from '../../data/constants';
import { useUserPostingEnabled } from '../data/hooks';
import { PostCommentsContext } from '../post-comments/postCommentsContext';
import PostCommentsContext from '../post-comments/postCommentsContext';
import ActionsDropdown from './ActionsDropdown';
import { DiscussionContext } from './context';
import DiscussionContext from './context';
const HoverCard = ({
id,
@@ -127,8 +128,22 @@ HoverCard.propTypes = {
addResponseCommentButtonMessage: PropTypes.string.isRequired,
onLike: PropTypes.func.isRequired,
voted: PropTypes.bool.isRequired,
// eslint-disable-next-line react/forbid-prop-types
endorseIcons: PropTypes.objectOf(PropTypes.any),
endorseIcons: PropTypes.objectOf(PropTypes.shape(
{
id: PropTypes.string,
action: PropTypes.string,
icon: PropTypes.element,
label: {
id: PropTypes.string,
defaultMessage: PropTypes.string,
description: PropTypes.string,
},
conditions: {
endorsed: PropTypes.bool,
postType: ThreadType,
},
},
)),
onFollow: PropTypes.func,
following: PropTypes.bool,
};

View File

@@ -11,15 +11,15 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import { getCourseConfigApiUrl } from '../data/api';
import { fetchCourseConfig } from '../data/thunks';
import fetchCourseConfig from '../data/thunks';
import DiscussionContent from '../discussions-home/DiscussionContent';
import { getCommentsApiUrl } from '../post-comments/data/api';
import { fetchCommentResponses } from '../post-comments/data/thunks';
import { getThreadsApiUrl } from '../posts/data/api';
import { fetchThreads } from '../posts/data/thunks';
import { DiscussionContext } from './context';
import DiscussionContext from './context';
import '../posts/data/__factories__';
import '../post-comments/data/__factories__';

View File

@@ -1,7 +1,6 @@
/* eslint-disable import/prefer-default-export */
import React from 'react';
export const DiscussionContext = React.createContext({
const DiscussionContext = React.createContext({
page: null,
courseId: null,
postId: null,
@@ -10,3 +9,5 @@ export const DiscussionContext = React.createContext({
category: null,
learnerUsername: null,
});
export default DiscussionContext;

View File

@@ -1,5 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { ensureConfig, getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

View File

@@ -15,13 +15,13 @@ import { breakpoints, useWindowSize } from '@edx/paragon';
import { RequestStatus, Routes } from '../../data/constants';
import { selectTopicsUnderCategory } from '../../data/selectors';
import { fetchCourseBlocks } from '../../data/thunks';
import { DiscussionContext } from '../common/context';
import fetchCourseBlocks from '../../data/thunks';
import DiscussionContext from '../common/context';
import { clearRedirect } from '../posts/data';
import { threadsLoadingStatus } from '../posts/data/selectors';
import { selectTopics } from '../topics/data/selectors';
import tourCheckpoints from '../tours/constants';
import { selectTours } from '../tours/data/selectors';
import selectTours from '../tours/data/selectors';
import { updateTourShowStatus } from '../tours/data/thunks';
import messages from '../tours/messages';
import { discussionsPath } from '../utils';
@@ -36,7 +36,7 @@ import {
selectUserIsGroupTa,
selectUserIsStaff,
} from './selectors';
import { fetchCourseConfig } from './thunks';
import fetchCourseConfig from './thunks';
export function useTotalTopicThreadCount() {
const topics = useSelector(selectTopics);

View File

@@ -8,11 +8,11 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import { DiscussionContext } from '../common/context';
import executeThunk from '../../test-utils';
import DiscussionContext from '../common/context';
import { getCourseConfigApiUrl } from './api';
import { useCurrentDiscussionTopic, useUserPostingEnabled } from './hooks';
import { fetchCourseConfig } from './thunks';
import fetchCourseConfig from './thunks';
const courseId = 'course-v1:edX+TestX+Test_Course';
const courseConfigApiUrl = getCourseConfigApiUrl();

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { PostsStatusFilter, ThreadType } from '../../data/constants';
export const selectAnonymousPostingConfig = state => ({

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign,import/prefer-default-export */
import { createSlice } from '@reduxjs/toolkit';
import { RequestStatus } from '../../data/constants';
@@ -28,19 +27,29 @@ const configSlice = createSlice({
enableInContext: false,
},
reducers: {
fetchConfigRequest: (state) => {
state.status = RequestStatus.IN_PROGRESS;
},
fetchConfigRequest: (state) => (
{
...state,
status: RequestStatus.IN_PROGRESS,
}
),
fetchConfigSuccess: (state, { payload }) => {
state.status = RequestStatus.SUCCESSFUL;
Object.assign(state, payload);
},
fetchConfigFailed: (state) => {
state.status = RequestStatus.FAILED;
},
fetchConfigDenied: (state) => {
state.status = RequestStatus.DENIED;
const newState = Object.assign(state, payload);
newState.status = RequestStatus.SUCCESSFUL;
return newState;
},
fetchConfigFailed: (state) => (
{
...state,
status: RequestStatus.FAILED,
}
),
fetchConfigDenied: (state) => (
{
...state,
status: RequestStatus.DENIED,
}
),
},
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { camelCaseObject } from '@edx/frontend-platform';
import { logError } from '@edx/frontend-platform/logging';
@@ -19,7 +18,7 @@ import {
* @param {string} courseId The course ID for the course to fetch config for.
* @returns {(function(*): Promise<void>)|*}
*/
export function fetchCourseConfig(courseId) {
export default function fetchCourseConfig(courseId) {
return async (dispatch) => {
try {
let learnerSort = LearnersOrdering.BY_LAST_ACTIVITY;

View File

@@ -13,7 +13,7 @@ import { useWindowSize } from '@edx/paragon';
import Spinner from '../../components/Spinner';
import { RequestStatus, Routes as ROUTES } from '../../data/constants';
import { DiscussionContext } from '../common/context';
import DiscussionContext from '../common/context';
import { useContainerSize, useIsOnDesktop, useIsOnXLDesktop } from '../data/hooks';
import { selectConfigLoadingStatus, selectEnableInContext } from '../data/selectors';

View File

@@ -11,7 +11,7 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { DiscussionContext } from '../common/context';
import DiscussionContext from '../common/context';
import { fetchConfigSuccess } from '../data/slices';
import { getThreadsApiUrl } from '../posts/data/api';
import DiscussionSidebar from './DiscussionSidebar';

View File

@@ -1,5 +1,6 @@
/* eslint-disable react/jsx-no-constructed-context-values */
import React, { lazy, Suspense, useRef } from 'react';
import React, {
lazy, Suspense, useMemo, useRef,
} from 'react';
import classNames from 'classnames';
import { useSelector } from 'react-redux';
@@ -10,14 +11,15 @@ import {
import { LearningHeader as Header } from '@edx/frontend-component-header';
import { Spinner } from '../../components';
import { selectCourseTabs } from '../../components/NavigationBar/data/selectors';
import selectCourseTabs from '../../components/NavigationBar/data/selectors';
import { ALL_ROUTES, DiscussionProvider, Routes as ROUTES } from '../../data/constants';
import { DiscussionContext } from '../common/context';
import DiscussionContext from '../common/context';
import {
useCourseDiscussionData, useIsOnDesktop, useRedirectToThread, useSidebarVisible,
} from '../data/hooks';
import { selectDiscussionProvider, selectEnableInContext } from '../data/selectors';
import { EmptyLearners, EmptyPosts, EmptyTopics } from '../empty-posts';
import { EmptyLearners, EmptyTopics } from '../empty-posts';
import EmptyPosts from '../empty-posts/EmptyPosts';
import { EmptyTopic as InContextEmptyTopics } from '../in-context-topics/components';
import messages from '../messages';
import { selectPostEditorVisible } from '../posts/data/selectors';
@@ -60,18 +62,19 @@ const DiscussionsHome = () => {
const displayContentArea = (postId || postEditorVisible || (learnerUsername && postId));
if (displayContentArea) { displaySidebar = isOnDesktop; }
const discussionContextValue = useMemo(() => ({
page,
courseId,
postId,
topicId,
enableInContextSidebar,
category,
learnerUsername,
}));
return (
<Suspense fallback={(<Spinner />)}>
<DiscussionContext.Provider value={{
page,
courseId,
postId,
topicId,
enableInContextSidebar,
category,
learnerUsername,
}}
>
<DiscussionContext.Provider value={discussionContextValue}>
{!enableInContextSidebar && (
<Header courseOrg={org} courseNumber={courseNumber} courseTitle={courseTitle} />
)}

View File

@@ -13,18 +13,18 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { getCourseMetadataApiUrl } from '../../components/NavigationBar/data/api';
import { fetchTab } from '../../components/NavigationBar/data/thunks';
import fetchTab from '../../components/NavigationBar/data/thunks';
import { getApiBaseUrl } from '../../data/constants';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import { getCourseConfigApiUrl, getDiscussionsConfigUrl } from '../data/api';
import { fetchCourseConfig } from '../data/thunks';
import fetchCourseConfig from '../data/thunks';
import { getCourseTopicsApiUrl } from '../in-context-topics/data/api';
import { fetchCourseTopicsV3 } from '../in-context-topics/data/thunks';
import fetchCourseTopicsV3 from '../in-context-topics/data/thunks';
import navigationBarMessages from '../navigation/navigation-bar/messages';
import { getThreadsApiUrl } from '../posts/data/api';
import { fetchThreads } from '../posts/data/thunks';
import { fetchCourseTopics } from '../topics/data/thunks';
import fetchCourseTopics from '../topics/data/thunks';
import DiscussionsHome from './DiscussionsHome';
import '../posts/data/__factories__/threads.factory';

View File

@@ -5,7 +5,7 @@ import { initializeMockApp } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { DiscussionContext } from '../common/context';
import DiscussionContext from '../common/context';
import { fetchConfigSuccess } from '../data/slices';
import messages from '../messages';
import DiscussionsRestrictionBanner from './DiscussionsRestrictionBanner';

View File

@@ -1,2 +0,0 @@
/* eslint-disable import/prefer-default-export */
export { default as DiscussionsHome } from './DiscussionsHome';

View File

@@ -8,8 +8,8 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { useIsOnDesktop } from '../data/hooks';
import { selectAreThreadsFiltered, selectPostThreadCount } from '../data/selectors';
import messages from '../messages';
// eslint-disable-next-line import/no-cycle
import { messages as postMessages, showPostEditor } from '../posts';
import { showPostEditor } from '../posts/data';
import postMessages from '../posts/post-actions-bar/messages';
import EmptyPage from './EmptyPage';
const EmptyPosts = ({ subTitleMessage }) => {

View File

@@ -10,7 +10,7 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import messages from '../messages';
import { getThreadsApiUrl } from '../posts/data/api';
import { fetchThreads } from '../posts/data/thunks';

View File

@@ -8,8 +8,8 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { useIsOnDesktop, useTotalTopicThreadCount } from '../data/hooks';
import { selectTopicThreadCount } from '../data/selectors';
import messages from '../messages';
// eslint-disable-next-line import/no-cycle
import { messages as postMessages, showPostEditor } from '../posts';
import { showPostEditor } from '../posts/data';
import postMessages from '../posts/post-actions-bar/messages';
import EmptyPage from './EmptyPage';
const EmptyTopics = () => {

View File

@@ -11,9 +11,9 @@ import { AppProvider } from '@edx/frontend-platform/react';
import { getApiBaseUrl, Routes as ROUTES } from '../../data/constants';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import messages from '../messages';
import { fetchCourseTopics } from '../topics/data/thunks';
import fetchCourseTopics from '../topics/data/thunks';
import EmptyTopics from './EmptyTopics';
import '../topics/data/__factories__';

View File

@@ -1,5 +1,3 @@
export { default as EmptyLearners } from './EmptyLearners';
export { default as EmptyPage } from './EmptyPage';
// eslint-disable-next-line import/no-cycle
export { default as EmptyPosts } from './EmptyPosts';
export { default as EmptyTopics } from './EmptyTopics';

View File

@@ -9,7 +9,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { Spinner } from '@edx/paragon';
import { RequestStatus, Routes } from '../../data/constants';
import { DiscussionContext } from '../common/context';
import DiscussionContext from '../common/context';
import { selectDiscussionProvider } from '../data/selectors';
import { selectTopicThreadsIds } from '../posts/data/selectors';
import PostsList from '../posts/PostsList';
@@ -18,7 +18,7 @@ import {
selectArchivedTopic, selectLoadingStatus, selectNonCoursewareTopics,
selectSubsection, selectSubsectionUnits, selectUnits,
} from './data/selectors';
import { fetchCourseTopicsV3 } from './data/thunks';
import fetchCourseTopicsV3 from './data/thunks';
import { BackButton, NoResults } from './components';
import messages from './messages';
import { Topic } from './topic';

View File

@@ -16,13 +16,13 @@ import { AppProvider } from '@edx/frontend-platform/react';
import { PostActionsBar } from '../../components';
import { Routes as ROUTES } from '../../data/constants';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import { DiscussionContext } from '../common/context';
import executeThunk from '../../test-utils';
import DiscussionContext from '../common/context';
import { getThreadsApiUrl } from '../posts/data/api';
import { fetchThreads } from '../posts/data/thunks';
import { getCourseTopicsApiUrl } from './data/api';
import { selectCoursewareTopics } from './data/selectors';
import { fetchCourseTopicsV3 } from './data/thunks';
import fetchCourseTopicsV3 from './data/thunks';
import TopicPostsView from './TopicPostsView';
import TopicsView from './TopicsView';

View File

@@ -10,7 +10,7 @@ import { Spinner } from '@edx/paragon';
import SearchInfo from '../../components/SearchInfo';
import { RequestStatus } from '../../data/constants';
import { DiscussionContext } from '../common/context';
import DiscussionContext from '../common/context';
import { selectAreThreadsFiltered, selectDiscussionProvider } from '../data/selectors';
import { clearFilter, clearSort } from '../posts/data/slices';
import NoResults from '../posts/NoResults';
@@ -20,7 +20,7 @@ import {
selectNonCoursewareTopics, selectTopicFilter, selectTopics,
} from './data/selectors';
import { setFilter } from './data/slices';
import { fetchCourseTopicsV3 } from './data/thunks';
import fetchCourseTopicsV3 from './data/thunks';
import { ArchivedBaseGroup, SectionBaseGroup, Topic } from './topic';
const TopicsList = () => {

View File

@@ -15,11 +15,11 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import { DiscussionContext } from '../common/context';
import executeThunk from '../../test-utils';
import DiscussionContext from '../common/context';
import { getCourseTopicsApiUrl } from './data/api';
import { selectCoursewareTopics, selectNonCoursewareTopics } from './data/selectors';
import { fetchCourseTopicsV3 } from './data/thunks';
import fetchCourseTopicsV3 from './data/thunks';
import TopicPostsView from './TopicPostsView';
import TopicsView from './TopicsView';

View File

@@ -5,7 +5,7 @@ import { useParams } from 'react-router-dom';
import { useIntl } from '@edx/frontend-platform/i18n';
import { DiscussionContext } from '../../common/context';
import DiscussionContext from '../../common/context';
import { useIsOnDesktop } from '../../data/hooks';
import { selectPostThreadCount } from '../../data/selectors';
import EmptyPage from '../../empty-posts/EmptyPage';

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
export { default as BackButton } from './BackButton';
export { default as EmptyTopic } from './EmptyTopics';
export { default as NoResults } from './NoResults';

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { camelCaseObject } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

View File

@@ -5,9 +5,9 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import executeThunk from '../../../test-utils';
import { getCourseTopicsApiUrl, getCourseTopicsV3 } from './api';
import { fetchCourseTopicsV3 } from './thunks';
import fetchCourseTopicsV3 from './thunks';
import './__factories__';

View File

@@ -5,9 +5,9 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import executeThunk from '../../../test-utils';
import { getCourseTopicsApiUrl } from './api';
import { fetchCourseTopicsV3 } from './thunks';
import fetchCourseTopicsV3 from './thunks';
import './__factories__';

View File

@@ -5,7 +5,7 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import executeThunk from '../../../test-utils';
import { getCourseTopicsApiUrl } from './api';
import {
selectArchivedTopic,
@@ -20,7 +20,7 @@ import {
selectTotalTopicsThreadsCount,
selectUnits,
} from './selectors';
import { fetchCourseTopicsV3 } from './thunks';
import fetchCourseTopicsV3 from './thunks';
import './__factories__';

View File

@@ -1,5 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { createSelector } from '@reduxjs/toolkit';
export const selectTopicFilter = state => state.inContextTopics.filter.trim().toLowerCase();

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign,import/prefer-default-export */
import { createSlice } from '@reduxjs/toolkit';
import { RequestStatus } from '../../../data/constants';
@@ -16,27 +15,42 @@ const topicsSlice = createSlice({
filter: '',
},
reducers: {
fetchCourseTopicsRequest: (state) => {
state.status = RequestStatus.IN_PROGRESS;
},
fetchCourseTopicsSuccess: (state, { payload }) => {
state.status = RequestStatus.SUCCESSFUL;
state.topics = payload.topics;
state.coursewareTopics = payload.coursewareTopics;
state.nonCoursewareTopics = payload.nonCoursewareTopics;
state.nonCoursewareIds = payload.nonCoursewareIds;
state.units = payload.units;
state.archivedTopics = payload.archivedTopics;
},
fetchCourseTopicsFailed: (state) => {
state.status = RequestStatus.FAILED;
},
fetchCourseTopicsDenied: (state) => {
state.status = RequestStatus.DENIED;
},
setFilter: (state, { payload }) => {
state.filter = payload;
},
fetchCourseTopicsRequest: (state) => (
{
...state,
status: RequestStatus.IN_PROGRESS,
}
),
fetchCourseTopicsSuccess: (state, { payload }) => (
{
...state,
status: RequestStatus.SUCCESSFUL,
topics: payload.topics,
coursewareTopics: payload.coursewareTopics,
nonCoursewareTopics: payload.nonCoursewareTopics,
nonCoursewareIds: payload.nonCoursewareIds,
units: payload.units,
archivedTopics: payload.archivedTopics,
}
),
fetchCourseTopicsFailed: (state) => (
{
...state,
status: RequestStatus.FAILED,
}
),
fetchCourseTopicsDenied: (state) => (
{
...state,
status: RequestStatus.DENIED,
}
),
setFilter: (state, { payload }) => (
{
...state,
filter: payload,
}
),
},
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { reduce } from 'lodash';
import { logError } from '@edx/frontend-platform/logging';
@@ -53,7 +52,7 @@ function normalizeTopicsV3(topics) {
};
}
export function fetchCourseTopicsV3(courseId) {
export default function fetchCourseTopicsV3(courseId) {
return async (dispatch) => {
try {
dispatch(fetchCourseTopicsRequest({ courseId }));

View File

@@ -1,3 +1,2 @@
/* eslint-disable import/prefer-default-export */
export { default as TopicPostsView } from './TopicPostsView';
export { default as TopicsView } from './TopicsView';

View File

@@ -6,7 +6,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { Icon, SearchField } from '@edx/paragon';
import { Search as SearchIcon } from '@edx/paragon/icons';
import { DiscussionContext } from '../../common/context';
import DiscussionContext from '../../common/context';
import postsMessages from '../../posts/post-actions-bar/messages';
import { setFilter as setTopicFilter } from '../data/slices';

View File

@@ -1,3 +1,2 @@
/* eslint-disable import/prefer-default-export */
export { default as TopicSearchBar } from './TopicSearchBar';
export { default as TopicSearchResultBar } from './TopicSearchResultBar';

View File

@@ -1,19 +1,13 @@
/* eslint-disable react/prop-types */
/* eslint-disable no-unused-vars, react/forbid-prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useSelector } from 'react-redux';
import { Link, useParams } from 'react-router-dom';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Icon, OverlayTrigger, Tooltip } from '@edx/paragon';
import { HelpOutline, PostOutline, Report } from '@edx/paragon/icons';
import TopicStats from '../../../components/TopicStats';
import { Routes } from '../../../data/constants';
import { selectUserHasModerationPrivileges, selectUserIsGroupTa } from '../../data/selectors';
import { discussionsPath } from '../../utils';
import messages from '../messages';
@@ -24,10 +18,6 @@ const Topic = ({
}) => {
const intl = useIntl();
const { courseId } = useParams();
const userHasModerationPrivileges = useSelector(selectUserHasModerationPrivileges);
const userIsGroupTa = useSelector(selectUserIsGroupTa);
const { inactiveFlags, activeFlags } = topic;
const canSeeReportedStats = (activeFlags || inactiveFlags) && (userHasModerationPrivileges || userIsGroupTa);
const isSelected = (id) => window.location.pathname.includes(id);
const topicUrl = discussionsPath(Routes.TOPICS.TOPIC, {
courseId,
@@ -72,7 +62,8 @@ export const topicShape = PropTypes.shape({
id: PropTypes.string,
usage_key: PropTypes.string,
name: PropTypes.string,
thread_counts: PropTypes.shape({
displayName: PropTypes.string,
threadCounts: PropTypes.shape({
discussions: PropTypes.number,
questions: PropTypes.number,
}),

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
export { default as ArchivedBaseGroup } from './ArchivedBaseGroup';
export { default as SectionBaseGroup } from './SectionBaseGroup';
export { default as Topic } from './Topic';

View File

@@ -1,4 +1,4 @@
export * from './discussions-home';
export * from './post-comments';
export { default as DiscussionsHome } from './discussions-home/DiscussionsHome';
export { default as PostCommentsView } from './post-comments/PostCommentsView';
export * from './posts';
export * from './topics';
export { default as TopicsView } from './topics/TopicsView';

View File

@@ -16,9 +16,9 @@ import {
RequestStatus,
Routes,
} from '../../data/constants';
import { DiscussionContext } from '../common/context';
import DiscussionContext from '../common/context';
import { selectUserHasModerationPrivileges, selectUserIsStaff } from '../data/selectors';
import { usePostList } from '../posts/data/hooks';
import usePostList from '../posts/data/hooks';
import {
selectAllThreadsIds,
selectThreadNextPage,

View File

@@ -16,10 +16,10 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import { getCohortsApiUrl } from '../cohorts/data/api';
import { fetchCourseCohorts } from '../cohorts/data/thunks';
import { DiscussionContext } from '../common/context';
import fetchCourseCohorts from '../cohorts/data/thunks';
import DiscussionContext from '../common/context';
import { learnerPostsApiUrl } from './data/api';
import { fetchUserPosts } from './data/thunks';
import LearnerPostsView from './LearnerPostsView';

View File

@@ -55,14 +55,14 @@ const LearnersView = () => {
dispatch(setUsernameSearch(''));
}, []);
const renderLearnersList = useMemo(() => (
(
courseConfigLoadingStatus === RequestStatus.SUCCESSFUL && learners.map((learner) => (
const renderLearnersList = useMemo(() => {
if (courseConfigLoadingStatus === RequestStatus.SUCCESSFUL) {
return learners.map((learner) => (
<LearnerCard learner={learner} key={learner.username} />
))
// eslint-disable-next-line react/jsx-no-useless-fragment
) || <></>
), [courseConfigLoadingStatus, learners]);
));
}
return null;
}, [courseConfigLoadingStatus, learners]);
return (
<div className="d-flex flex-column border-right border-light-400">

View File

@@ -1,4 +1,3 @@
/* eslint-disable default-param-last */
import React from 'react';
import {
@@ -16,10 +15,10 @@ import { AppProvider } from '@edx/frontend-platform/react';
import { PostActionsBar } from '../../components';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import { DiscussionContext } from '../common/context';
import executeThunk from '../../test-utils';
import DiscussionContext from '../common/context';
import { getDiscussionsConfigUrl } from '../data/api';
import { fetchCourseConfig } from '../data/thunks';
import fetchCourseConfig from '../data/thunks';
import { getUserProfileApiUrl, learnersApiUrl } from './data/api';
import { fetchLearners } from './data/thunks';
import LearnersView from './LearnersView';
@@ -81,9 +80,9 @@ describe('LearnersView', () => {
pageSize = 6,
page = 1,
username = ['learner-1', 'learner-2', 'learner-3'],
searchText,
activeFlags,
inactiveFlags,
searchText = null,
activeFlags = null,
inactiveFlags = null,
) {
Factory.resetAll();
const learnersData = Factory.build('learnersResult', {}, {

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import snakeCase from 'lodash/snakeCase';
import { ensureConfig, getConfig, snakeCaseObject } from '@edx/frontend-platform';

View File

@@ -5,7 +5,7 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import executeThunk from '../../../test-utils';
import { setupLearnerMockResponse } from '../test-utils';
import { setPostFilter, setSortedBy, setUsernameSearch } from './slices';
import { fetchLearners } from './thunks';

View File

@@ -5,7 +5,7 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import executeThunk from '../../../test-utils';
import { getUserProfileApiUrl, learnersApiUrl } from './api';
import {
learnersLoadingStatus,

View File

@@ -1,5 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { createSelector } from '@reduxjs/toolkit';
export const selectAllLearners = createSelector(

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign,import/prefer-default-export */
import { createSlice } from '@reduxjs/toolkit';
import {
@@ -28,38 +27,63 @@ const learnersSlice = createSlice({
usernameSearch: null,
},
reducers: {
fetchLearnersSuccess: (state, { payload }) => {
state.status = RequestStatus.SUCCESSFUL;
state.pages[payload.page - 1] = payload.results;
state.learnerProfiles = {
...state.learnerProfiles,
...(payload.learnerProfiles || {}),
};
state.nextPage = (payload.page < payload.pagination.numPages) ? payload.page + 1 : null;
state.totalPages = payload.pagination.numPages;
state.totalLearners = payload.pagination.count;
},
fetchLearnersFailed: (state) => {
state.status = RequestStatus.FAILED;
},
fetchLearnersDenied: (state) => {
state.status = RequestStatus.DENIED;
},
fetchLearnersRequest: (state) => {
state.status = RequestStatus.IN_PROGRESS;
},
setSortedBy: (state, { payload }) => {
state.pages = [];
state.sortedBy = payload;
},
setUsernameSearch: (state, { payload }) => {
state.usernameSearch = payload;
state.pages = [];
},
setPostFilter: (state, { payload }) => {
state.pages = [];
state.postFilter = payload;
},
fetchLearnersSuccess: (state, { payload }) => (
{
...state,
status: RequestStatus.SUCCESSFUL,
pages: [
...state.pages.slice(0, payload.page - 1),
payload.results,
...state.pages.slice(payload.page),
],
learnerProfiles: {
...state.learnerProfiles,
...(payload.learnerProfiles || {}),
},
nextPage: payload.page < payload.pagination.numPages ? payload.page + 1 : null,
totalPages: payload.pagination.numPages,
totalLearners: payload.pagination.count,
}
),
fetchLearnersFailed: (state) => (
{
...state,
status: RequestStatus.FAILED,
}
),
fetchLearnersDenied: (state) => (
{
...state,
status: RequestStatus.DENIED,
}
),
fetchLearnersRequest: (state) => (
{
...state,
status: RequestStatus.IN_PROGRESS,
}
),
setSortedBy: (state, { payload }) => (
{
...state,
pages: [],
sortedBy: payload,
}
),
setUsernameSearch: (state, { payload }) => (
{
...state,
usernameSearch: payload,
pages: [],
}
),
setPostFilter: (state, { payload }) => (
{
...state,
pages: [],
postFilter: payload,
}
),
},
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { camelCaseObject, snakeCaseObject } from '@edx/frontend-platform';
import { logError } from '@edx/frontend-platform/logging';

View File

@@ -1,3 +1,2 @@
/* eslint-disable import/prefer-default-export */
export { default as LearnerPostsView } from './LearnerPostsView';
export { default as LearnersView } from './LearnersView';

View File

@@ -8,8 +8,8 @@ import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import FilterBar from '../../../components/FilterBar';
import { PostsStatusFilter, ThreadType } from '../../../data/constants';
import { selectCourseCohorts } from '../../cohorts/data/selectors';
import { fetchCourseCohorts } from '../../cohorts/data/thunks';
import selectCourseCohorts from '../../cohorts/data/selectors';
import fetchCourseCohorts from '../../cohorts/data/thunks';
import { selectUserHasModerationPrivileges, selectUserIsGroupTa } from '../../data/selectors';
import { setPostFilter } from '../data/slices';

View File

@@ -10,7 +10,7 @@ import { initializeMockApp } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../../store';
import { DiscussionContext } from '../../common/context';
import DiscussionContext from '../../common/context';
import LearnerPostFilterBar from './LearnerPostFilterBar';
let store;

View File

@@ -3,11 +3,11 @@ import React, { useContext } from 'react';
import { Link } from 'react-router-dom';
import { Routes } from '../../../data/constants';
import { DiscussionContext } from '../../common/context';
import DiscussionContext from '../../common/context';
import { discussionsPath } from '../../utils';
import LearnerAvatar from './LearnerAvatar';
import LearnerFooter from './LearnerFooter';
import { learnerShape } from './proptypes';
import learnerShape from './proptypes';
const LearnerCard = ({ learner }) => {
const {

View File

@@ -5,9 +5,10 @@ import { useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Icon, OverlayTrigger, Tooltip } from '@edx/paragon';
import { Edit, Report, ReportGmailerrorred } from '@edx/paragon/icons';
import {
Edit, QuestionAnswerOutline, Report, ReportGmailerrorred,
} from '@edx/paragon/icons';
import { QuestionAnswerOutline } from '../../../components/icons';
import { selectUserHasModerationPrivileges, selectUserIsGroupTa } from '../../data/selectors';
import messages from '../messages';

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
export { default as LearnerCard } from './LearnerCard';
export { default as LearnerFilterBar } from './LearnerFilterBar';
export { default as LearnerFooter } from './LearnerFooter';

View File

@@ -1,7 +1,6 @@
/* eslint-disable import/prefer-default-export */
import PropTypes from 'prop-types';
export const learnerShape = PropTypes.shape({
const learnerShape = PropTypes.shape({
activeFlags: PropTypes.number,
inactiveFlags: PropTypes.number,
username: PropTypes.string,
@@ -9,3 +8,5 @@ export const learnerShape = PropTypes.shape({
responses: PropTypes.number,
threads: PropTypes.number,
});
export default learnerShape;

View File

@@ -4,9 +4,9 @@ import { Factory } from 'rosie';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeStore } from '../../store';
import { executeThunk } from '../../test-utils';
import executeThunk from '../../test-utils';
import { getDiscussionsConfigUrl } from '../data/api';
import { fetchCourseConfig } from '../data/thunks';
import fetchCourseConfig from '../data/thunks';
import { getUserProfileApiUrl, learnerPostsApiUrl, learnersApiUrl } from './data/api';
import { fetchLearners, fetchUserPosts } from './data/thunks';

View File

@@ -50,11 +50,21 @@ const BreadcrumbDropdown = ({
};
BreadcrumbDropdown.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
currentItem: PropTypes.any,
currentItem: PropTypes.shape({
name: PropTypes.string,
id: PropTypes.string,
questions: PropTypes.number,
discussions: PropTypes.number,
flags: PropTypes.number,
}),
showAllPath: PropTypes.func.isRequired,
// eslint-disable-next-line react/forbid-prop-types
items: PropTypes.array.isRequired,
items: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
id: PropTypes.string,
questions: PropTypes.number,
discussions: PropTypes.number,
flags: PropTypes.number,
})).isRequired,
itemPathFunc: PropTypes.func.isRequired,
itemLabelFunc: PropTypes.func.isRequired,
itemActiveFunc: PropTypes.func.isRequired,

View File

@@ -14,8 +14,8 @@ import { AppProvider } from '@edx/frontend-platform/react';
import { getApiBaseUrl, Routes as ROUTES } from '../../../data/constants';
import { initializeStore } from '../../../store';
import { executeThunk } from '../../../test-utils';
import { fetchCourseTopics } from '../../topics/data/thunks';
import executeThunk from '../../../test-utils';
import fetchCourseTopics from '../../topics/data/thunks';
import { LegacyBreadcrumbMenu } from '../index';
import '../../topics/data/__factories__';

Some files were not shown because too many files have changed in this diff Show More