diff --git a/src/course-home/data/__snapshots__/redux.test.js.snap b/src/course-home/data/__snapshots__/redux.test.js.snap
index 65459211..7a8a20b0 100644
--- a/src/course-home/data/__snapshots__/redux.test.js.snap
+++ b/src/course-home/data/__snapshots__/redux.test.js.snap
@@ -5,6 +5,7 @@ Object {
"courseHome": Object {
"courseId": "course-v1:edX+DemoX+Demo_Course_1",
"courseStatus": "loaded",
+ "gradesFeatureIsLocked": false,
"toastBodyLink": null,
"toastBodyText": null,
"toastHeader": "",
@@ -300,6 +301,7 @@ Object {
"courseHome": Object {
"courseId": "course-v1:edX+DemoX+Demo_Course_1",
"courseStatus": "loaded",
+ "gradesFeatureIsLocked": false,
"toastBodyLink": null,
"toastBodyText": null,
"toastHeader": "",
@@ -476,6 +478,7 @@ Object {
"courseHome": Object {
"courseId": "course-v1:edX+DemoX+Demo_Course_1",
"courseStatus": "loaded",
+ "gradesFeatureIsLocked": false,
"toastBodyLink": null,
"toastBodyText": null,
"toastHeader": "",
diff --git a/src/course-home/data/slice.js b/src/course-home/data/slice.js
index 7e037d7c..0cefaae3 100644
--- a/src/course-home/data/slice.js
+++ b/src/course-home/data/slice.js
@@ -10,6 +10,7 @@ const slice = createSlice({
initialState: {
courseStatus: 'loading',
courseId: null,
+ gradesFeatureIsLocked: false,
toastBodyText: null,
toastBodyLink: null,
toastHeader: '',
@@ -37,6 +38,9 @@ const slice = createSlice({
state.toastBodyText = linkText;
state.toastHeader = header;
},
+ setGradesFeatureStatus: (state, { payload }) => {
+ state.gradesFeatureIsLocked = payload.gradesFeatureIsLocked;
+ },
},
});
@@ -45,6 +49,7 @@ export const {
fetchTabSuccess,
fetchTabFailure,
setCallToActionToast,
+ setGradesFeatureStatus,
} = slice.actions;
export const {
diff --git a/src/course-home/progress-tab/ProgressTab.jsx b/src/course-home/progress-tab/ProgressTab.jsx
index 9dbb6570..f4f1a4a9 100644
--- a/src/course-home/progress-tab/ProgressTab.jsx
+++ b/src/course-home/progress-tab/ProgressTab.jsx
@@ -1,6 +1,6 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import { layoutGenerator } from 'react-break';
-import { useSelector } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
import CertificateStatus from './certificate-status/CertificateStatus';
import CourseCompletion from './course-completion/CourseCompletion';
@@ -10,6 +10,7 @@ import GradeSummary from './grades/grade-summary/GradeSummary';
import ProgressHeader from './ProgressHeader';
import RelatedLinks from './related-links/RelatedLinks';
+import { setGradesFeatureStatus } from '../data/slice';
import { useModel } from '../../generic/model-store';
function ProgressTab() {
@@ -22,8 +23,14 @@ function ProgressTab() {
lockedCount,
},
} = useModel('progress', courseId);
- const isLocked = lockedCount > 0;
- const applyLockedOverlay = isLocked ? 'locked-overlay' : '';
+
+ const gradesFeatureIsLocked = lockedCount > 0;
+ const applyLockedOverlay = gradesFeatureIsLocked ? 'locked-overlay' : '';
+
+ const dispatch = useDispatch();
+ useEffect(() => {
+ dispatch(setGradesFeatureStatus({ gradesFeatureIsLocked }));
+ }, []);
const layout = layoutGenerator({
mobile: 0,
@@ -43,7 +50,7 @@ function ProgressTab() {
-
+
diff --git a/src/course-home/progress-tab/course-completion/CompleteDonutSegment.jsx b/src/course-home/progress-tab/course-completion/CompleteDonutSegment.jsx
index 03d17e47..2615b270 100644
--- a/src/course-home/progress-tab/course-completion/CompleteDonutSegment.jsx
+++ b/src/course-home/progress-tab/course-completion/CompleteDonutSegment.jsx
@@ -7,6 +7,10 @@ import { OverlayTrigger, Popover } from '@edx/paragon';
import messages from './messages';
function CompleteDonutSegment({ completePercentage, intl, lockedPercentage }) {
+ if (!completePercentage) {
+ return null;
+ }
+
const [showCompletePopover, setShowCompletePopover] = useState(false);
const completeSegmentOffset = (3.6 * completePercentage) / 8;
@@ -24,15 +28,6 @@ function CompleteDonutSegment({ completePercentage, intl, lockedPercentage }) {
onFocus={() => setShowCompletePopover(true)}
tabIndex="-1"
>
-
-
{/* Tooltip */}
+ {/* Complete segment */}
+
+
{/* Segment dividers */}
{lockedPercentage > 0 && lockedPercentage < 100 && (
)}
- {completePercentage < 100 && lockedPercentage < 100 && lockedPercentage + completePercentage === 100 && (
+ {completePercentage < 100 && lockedPercentage > 0 && lockedPercentage < 100
+ && lockedPercentage + completePercentage === 100 && (
0) {
+ if (!lockedPercentage) {
return null;
}
diff --git a/src/course-home/progress-tab/grades/course-grade/CourseGrade.jsx b/src/course-home/progress-tab/grades/course-grade/CourseGrade.jsx
index 94156f12..65b5a817 100644
--- a/src/course-home/progress-tab/grades/course-grade/CourseGrade.jsx
+++ b/src/course-home/progress-tab/grades/course-grade/CourseGrade.jsx
@@ -13,12 +13,10 @@ import messages from '../messages';
function CourseGrade({ intl }) {
const {
courseId,
+ gradesFeatureIsLocked,
} = useSelector(state => state.courseHome);
const {
- completionSummary: {
- lockedCount,
- },
gradingPolicy: {
gradeRange,
},
@@ -26,13 +24,12 @@ function CourseGrade({ intl }) {
const passingGrade = Number((Math.min(...Object.values(gradeRange)) * 100).toFixed(0));
- const isLocked = lockedCount > 0;
- const applyLockedOverlay = isLocked ? 'locked-overlay' : '';
+ const applyLockedOverlay = gradesFeatureIsLocked ? 'locked-overlay' : '';
return (
- {isLocked && }
-
+ {gradesFeatureIsLocked &&
}
+
{intl.formatMessage(messages.grades)}
diff --git a/src/course-home/progress-tab/grades/course-grade/GradeBar.jsx b/src/course-home/progress-tab/grades/course-grade/GradeBar.jsx
index 319528c3..424c13d3 100644
--- a/src/course-home/progress-tab/grades/course-grade/GradeBar.jsx
+++ b/src/course-home/progress-tab/grades/course-grade/GradeBar.jsx
@@ -12,12 +12,10 @@ import messages from '../messages';
function GradeBar({ intl, passingGrade }) {
const {
courseId,
+ gradesFeatureIsLocked,
} = useSelector(state => state.courseHome);
const {
- completionSummary: {
- lockedCount,
- },
courseGrade: {
isPassing,
visiblePercent,
@@ -26,8 +24,7 @@ function GradeBar({ intl, passingGrade }) {
const currentGrade = Number((visiblePercent * 100).toFixed(0));
- const isLocked = lockedCount > 0;
- const lockedTooltipClassName = isLocked ? 'locked-overlay' : '';
+ const lockedTooltipClassName = gradesFeatureIsLocked ? 'locked-overlay' : '';
return (
diff --git a/src/course-home/progress-tab/grades/course-grade/GradeRangeTooltip.jsx b/src/course-home/progress-tab/grades/course-grade/GradeRangeTooltip.jsx
index 81b01ce1..856fe07b 100644
--- a/src/course-home/progress-tab/grades/course-grade/GradeRangeTooltip.jsx
+++ b/src/course-home/progress-tab/grades/course-grade/GradeRangeTooltip.jsx
@@ -14,6 +14,7 @@ import messages from '../messages';
function GradeRangeTooltip({ intl, iconButtonClassName, passingGrade }) {
const {
courseId,
+ gradesFeatureIsLocked,
} = useSelector(state => state.courseHome);
const {
@@ -67,6 +68,7 @@ function GradeRangeTooltip({ intl, iconButtonClassName, passingGrade }) {
src={InfoOutline}
iconAs={Icon}
size="inline"
+ disabled={gradesFeatureIsLocked}
/>
);
diff --git a/src/course-home/progress-tab/grades/detailed-grades/DetailedGrades.jsx b/src/course-home/progress-tab/grades/detailed-grades/DetailedGrades.jsx
index 908ec650..9b579ac1 100644
--- a/src/course-home/progress-tab/grades/detailed-grades/DetailedGrades.jsx
+++ b/src/course-home/progress-tab/grades/detailed-grades/DetailedGrades.jsx
@@ -16,6 +16,7 @@ function DetailedGrades({ intl }) {
const { administrator } = getAuthenticatedUser();
const {
courseId,
+ gradesFeatureIsLocked,
} = useSelector(state => state.courseHome);
const {
org,
@@ -39,6 +40,7 @@ function DetailedGrades({ intl }) {
className="muted-link inline-link"
destination={`${getConfig().LMS_BASE_URL}/courses/${courseId}/course`}
onClick={logOutlineLinkClick}
+ tabIndex={gradesFeatureIsLocked ? '-1' : '0'}
>
{intl.formatMessage(messages.courseOutline)}
diff --git a/src/course-home/progress-tab/grades/detailed-grades/DetailedGradesTable.jsx b/src/course-home/progress-tab/grades/detailed-grades/DetailedGradesTable.jsx
index 77514bbe..fe8b673e 100644
--- a/src/course-home/progress-tab/grades/detailed-grades/DetailedGradesTable.jsx
+++ b/src/course-home/progress-tab/grades/detailed-grades/DetailedGradesTable.jsx
@@ -13,6 +13,7 @@ import { useModel } from '../../../../generic/model-store';
function DetailedGradesTable({ intl, sectionScores }) {
const {
courseId,
+ gradesFeatureIsLocked,
} = useSelector(state => state.courseHome);
const {
org,
@@ -43,10 +44,11 @@ function DetailedGradesTable({ intl, sectionScores }) {
const title = (
{
logSubsectionClicked(subsection.blockKey);
}}
+ tabIndex={gradesFeatureIsLocked ? '-1' : '0'}
>
{subsection.displayName}
diff --git a/src/course-home/progress-tab/grades/grade-summary/AssignmentTypeCell.jsx b/src/course-home/progress-tab/grades/grade-summary/AssignmentTypeCell.jsx
index bdb79173..2ffaa3a5 100644
--- a/src/course-home/progress-tab/grades/grade-summary/AssignmentTypeCell.jsx
+++ b/src/course-home/progress-tab/grades/grade-summary/AssignmentTypeCell.jsx
@@ -1,13 +1,23 @@
import React from 'react';
+import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
function AssignmentTypeCell({ assignmentType, footnoteMarker, footnoteId }) {
+ const {
+ gradesFeatureIsLocked,
+ } = useSelector(state => state.courseHome);
return (
{assignmentType}
{footnoteId && footnoteMarker && (
-
diff --git a/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx b/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx
index f897b892..4d114fc8 100644
--- a/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx
+++ b/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
@@ -6,6 +7,9 @@ import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/
import messages from '../messages';
function DroppableAssignmentFootnote({ footnotes, intl }) {
+ const {
+ gradesFeatureIsLocked,
+ } = useSelector(state => state.courseHome);
return (
<>
@@ -21,7 +25,9 @@ function DroppableAssignmentFootnote({ footnotes, intl }) {
assignmentType: footnote.assignmentType,
}}
/>
-
{intl.formatMessage(messages.backToContent)}
+
+ {intl.formatMessage(messages.backToContent)}
+
))}
diff --git a/src/course-home/progress-tab/grades/grade-summary/GradeSummaryHeader.jsx b/src/course-home/progress-tab/grades/grade-summary/GradeSummaryHeader.jsx
index f13de058..8ee62924 100644
--- a/src/course-home/progress-tab/grades/grade-summary/GradeSummaryHeader.jsx
+++ b/src/course-home/progress-tab/grades/grade-summary/GradeSummaryHeader.jsx
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
+import { useSelector } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import {
@@ -9,6 +10,9 @@ import { InfoOutline } from '@edx/paragon/icons';
import messages from '../messages';
function GradeSummaryHeader({ intl }) {
+ const {
+ gradesFeatureIsLocked,
+ } = useSelector(state => state.courseHome);
const [showTooltip, setShowTooltip] = useState(false);
return (
@@ -33,6 +37,7 @@ function GradeSummaryHeader({ intl }) {
iconAs={Icon}
className="mb-3"
size="sm"
+ disabled={gradesFeatureIsLocked}
/>
diff --git a/src/course-home/progress-tab/grades/grade-summary/GradeSummaryTable.jsx b/src/course-home/progress-tab/grades/grade-summary/GradeSummaryTable.jsx
index 9e229434..09a0edb9 100644
--- a/src/course-home/progress-tab/grades/grade-summary/GradeSummaryTable.jsx
+++ b/src/course-home/progress-tab/grades/grade-summary/GradeSummaryTable.jsx
@@ -46,7 +46,7 @@ function GradeSummaryTable({ intl }) {
return {
type: { footnoteId, footnoteMarker, type: assignment.type },
- weight: `${assignment.weight * 100}%`,
+ weight: `${(assignment.weight * 100).toFixed(0)}%`,
grade: `${(assignment.averageGrade * 100).toFixed(0)}%`,
weightedGrade: `${(assignment.weightedGrade * 100).toFixed(0)}%`,
};