feat: change blocked icon to lock icon (#1619)
* feat: replace blocked icon with locked * refactor: replace injectIntl with useIntl * revert: temporary test change * fix: failing test * fix: wording of message description * fix: lingering lint error * fix: missing message variable
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Button } from '@openedx/paragon';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
@@ -9,7 +7,8 @@ import { useModel } from '../../generic/model-store';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const ProgressHeader = ({ intl }) => {
|
||||
const ProgressHeader = () => {
|
||||
const intl = useIntl();
|
||||
const {
|
||||
courseId,
|
||||
targetUserId,
|
||||
@@ -37,8 +36,4 @@ const ProgressHeader = ({ intl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
ProgressHeader.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(ProgressHeader);
|
||||
export default ProgressHeader;
|
||||
|
||||
@@ -471,9 +471,12 @@ describe('Progress Tab', () => {
|
||||
await fetchAndRender();
|
||||
expect(screen.getByText('limited feature')).toBeInTheDocument();
|
||||
expect(screen.getByText('Unlock to work towards a certificate.')).toBeInTheDocument();
|
||||
expect(screen.queryAllByText('You have limited access to graded assignments as part of the audit track in this course.')).toHaveLength(2);
|
||||
expect(screen.queryAllByText(
|
||||
'You have limited access to graded assignments as part of the audit track in this course.',
|
||||
{ exact: false },
|
||||
)).toHaveLength(2);
|
||||
|
||||
expect(screen.queryAllByTestId('blocked-icon')).toHaveLength(4);
|
||||
expect(screen.queryAllByTestId('locked-icon')).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('does not render subsections for which showGrades is false', async () => {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { OverlayTrigger, Popover } from '@openedx/paragon';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const CompleteDonutSegment = ({ completePercentage, intl, lockedPercentage }) => {
|
||||
const CompleteDonutSegment = ({ completePercentage, lockedPercentage }) => {
|
||||
const intl = useIntl();
|
||||
const [showCompletePopover, setShowCompletePopover] = useState(false);
|
||||
|
||||
if (!completePercentage) {
|
||||
@@ -82,8 +83,7 @@ const CompleteDonutSegment = ({ completePercentage, intl, lockedPercentage }) =>
|
||||
|
||||
CompleteDonutSegment.propTypes = {
|
||||
completePercentage: PropTypes.number.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
lockedPercentage: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(CompleteDonutSegment);
|
||||
export default CompleteDonutSegment;
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
getLocale, injectIntl, intlShape, isRtl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { getLocale, isRtl, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { useContextId } from '../../../data/hooks';
|
||||
import { useModel } from '../../../generic/model-store';
|
||||
|
||||
@@ -10,7 +7,8 @@ import IncompleteDonutSegment from './IncompleteDonutSegment';
|
||||
import LockedDonutSegment from './LockedDonutSegment';
|
||||
import messages from './messages';
|
||||
|
||||
const CompletionDonutChart = ({ intl }) => {
|
||||
const CompletionDonutChart = () => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -60,8 +58,4 @@ const CompletionDonutChart = ({ intl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
CompletionDonutChart.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(CompletionDonutChart);
|
||||
export default CompletionDonutChart;
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
import React from 'react';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import CompletionDonutChart from './CompletionDonutChart';
|
||||
import messages from './messages';
|
||||
|
||||
const CourseCompletion = ({ intl }) => (
|
||||
<section className="text-dark-700 mb-4 rounded raised-card p-4">
|
||||
<div className="row w-100 m-0">
|
||||
<div className="col-12 col-sm-6 col-md-7 p-0">
|
||||
<h2>{intl.formatMessage(messages.courseCompletion)}</h2>
|
||||
<p className="small">
|
||||
{intl.formatMessage(messages.completionBody)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col-md-5 mt-sm-n3 p-0 text-center">
|
||||
<CompletionDonutChart />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
const CourseCompletion = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
CourseCompletion.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
return (
|
||||
<section className="text-dark-700 mb-4 rounded raised-card p-4">
|
||||
<div className="row w-100 m-0">
|
||||
<div className="col-12 col-sm-6 col-md-7 p-0">
|
||||
<h2>{intl.formatMessage(messages.courseCompletion)}</h2>
|
||||
<p className="small">
|
||||
{intl.formatMessage(messages.completionBody)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col-md-5 mt-sm-n3 p-0 text-center">
|
||||
<CompletionDonutChart />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default injectIntl(CourseCompletion);
|
||||
export default CourseCompletion;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { OverlayTrigger, Popover } from '@openedx/paragon';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const IncompleteDonutSegment = ({ incompletePercentage, intl }) => {
|
||||
const IncompleteDonutSegment = ({ incompletePercentage }) => {
|
||||
const intl = useIntl();
|
||||
const [showIncompletePopover, setShowIncompletePopover] = useState(false);
|
||||
|
||||
if (!incompletePercentage) {
|
||||
@@ -53,7 +54,6 @@ const IncompleteDonutSegment = ({ incompletePercentage, intl }) => {
|
||||
|
||||
IncompleteDonutSegment.propTypes = {
|
||||
incompletePercentage: PropTypes.number.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(IncompleteDonutSegment);
|
||||
export default IncompleteDonutSegment;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { OverlayTrigger, Popover } from '@openedx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const LockedDonutSegment = ({ intl, lockedPercentage }) => {
|
||||
const LockedDonutSegment = ({ lockedPercentage }) => {
|
||||
const intl = useIntl();
|
||||
const [showLockedPopover, setShowLockedPopover] = useState(false);
|
||||
|
||||
if (!lockedPercentage) {
|
||||
@@ -65,8 +66,7 @@ const LockedDonutSegment = ({ intl, lockedPercentage }) => {
|
||||
};
|
||||
|
||||
LockedDonutSegment.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
lockedPercentage: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(LockedDonutSegment);
|
||||
export default LockedDonutSegment;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { CheckCircle, WarningFilled, WatchFilled } from '@openedx/paragon/icons';
|
||||
import { Hyperlink, Icon } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../data/hooks';
|
||||
@@ -10,7 +9,8 @@ import { DashboardLink } from '../../../shared/links';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const CreditInformation = ({ intl }) => {
|
||||
const CreditInformation = () => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -34,36 +34,13 @@ const CreditInformation = ({ intl }) => {
|
||||
|
||||
switch (creditCourseRequirements.eligibilityStatus) {
|
||||
case 'not_eligible':
|
||||
eligibilityStatus = (
|
||||
<FormattedMessage
|
||||
id="progress.creditInformation.creditNotEligible"
|
||||
defaultMessage="You are no longer eligible for credit in this course. Learn more about {creditLink}."
|
||||
description="Message to learner who are not eligible for course credit, it can because the a requirement deadline have passed"
|
||||
values={{ creditLink }}
|
||||
/>
|
||||
);
|
||||
eligibilityStatus = intl.formatMessage(messages.creditNotEligibleStatus, { creditLink });
|
||||
break;
|
||||
case 'eligible':
|
||||
eligibilityStatus = (
|
||||
<FormattedMessage
|
||||
id="progress.creditInformation.creditEligible"
|
||||
defaultMessage="
|
||||
You have met the requirements for credit in this course. Go to your
|
||||
{dashboardLink} to purchase course credit. Or learn more about {creditLink}."
|
||||
description="After the credit requirements are met, leaners can then do the last step which purchasing the credit. Note that is only doable for leaners after they met all the requirements"
|
||||
values={{ dashboardLink, creditLink }}
|
||||
/>
|
||||
);
|
||||
eligibilityStatus = intl.formatMessage(messages.creditEligibleStatus, { dashboardLink, creditLink });
|
||||
break;
|
||||
case 'partial_eligible':
|
||||
eligibilityStatus = (
|
||||
<FormattedMessage
|
||||
id="progress.creditInformation.creditPartialEligible"
|
||||
defaultMessage="You have not yet met the requirements for credit. Learn more about {creditLink}."
|
||||
description="This means that one or more requirements is not satisfied yet"
|
||||
values={{ creditLink }}
|
||||
/>
|
||||
);
|
||||
eligibilityStatus = intl.formatMessage(messages.creditPartialEligibleStatus, { creditLink });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -106,8 +83,4 @@ const CreditInformation = ({ intl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
CreditInformation.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(CreditInformation);
|
||||
export default CreditInformation;
|
||||
|
||||
@@ -35,6 +35,22 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Verification submitted',
|
||||
description: 'It indicate that the learner submitted a requirement but is not graded or reviewed yet',
|
||||
},
|
||||
creditNotEligibleStatus: {
|
||||
id: 'progress.creditInformation.creditNotEligible',
|
||||
defaultMessage: 'You are no longer eligible for credit in this course. Learn more about {creditLink}.',
|
||||
description: 'Message to learner who are not eligible for course credit, it can be that a requirement deadline has passed',
|
||||
},
|
||||
creditEligibleStatus: {
|
||||
id: 'progress.creditInformation.creditEligible',
|
||||
defaultMessage: `You have met the requirements for credit in this course. Go to your
|
||||
{dashboardLink} to purchase course credit. Or learn more about {creditLink}.`,
|
||||
description: 'After the credit requirements are met, leaners can then do the last step which purchasing the credit. Note that is only doable for leaners after they met all the requirements',
|
||||
},
|
||||
creditPartialEligibleStatus: {
|
||||
id: 'progress.creditInformation.creditPartialEligible',
|
||||
defaultMessage: 'You have not yet met the requirements for credit. Learn more about {creditLink}.',
|
||||
description: 'This means that one or more requirements is not satisfied yet',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
|
||||
import { useModel } from '../../../../generic/model-store';
|
||||
@@ -11,7 +10,8 @@ import CreditInformation from '../../credit-information/CreditInformation';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
const CourseGrade = ({ intl }) => {
|
||||
const CourseGrade = () => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -52,8 +52,4 @@ const CourseGrade = ({ intl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
CourseGrade.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(CourseGrade);
|
||||
export default CourseGrade;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { CheckCircle, WarningFilled } from '@openedx/paragon/icons';
|
||||
import { breakpoints, Icon, useWindowSize } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
@@ -10,7 +9,8 @@ import { useModel } from '../../../../generic/model-store';
|
||||
import GradeRangeTooltip from './GradeRangeTooltip';
|
||||
import messages from '../messages';
|
||||
|
||||
const CourseGradeFooter = ({ intl, passingGrade }) => {
|
||||
const CourseGradeFooter = ({ passingGrade }) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -84,8 +84,7 @@ const CourseGradeFooter = ({ intl, passingGrade }) => {
|
||||
};
|
||||
|
||||
CourseGradeFooter.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
passingGrade: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(CourseGradeFooter);
|
||||
export default CourseGradeFooter;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Locked } from '@openedx/paragon/icons';
|
||||
import { Button, Icon } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
@@ -10,7 +8,8 @@ import { useContextId } from '../../../../data/hooks';
|
||||
import { useModel } from '../../../../generic/model-store';
|
||||
import messages from '../messages';
|
||||
|
||||
const CourseGradeHeader = ({ intl }) => {
|
||||
const CourseGradeHeader = () => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
const {
|
||||
org,
|
||||
@@ -81,8 +80,4 @@ const CourseGradeHeader = ({ intl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
CourseGradeHeader.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(CourseGradeHeader);
|
||||
export default CourseGradeHeader;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
getLocale, injectIntl, intlShape, isRtl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { getLocale, isRtl, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { OverlayTrigger, Popover } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
|
||||
@@ -11,7 +8,8 @@ import { useModel } from '../../../../generic/model-store';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
const CurrentGradeTooltip = ({ intl, tooltipClassName }) => {
|
||||
const CurrentGradeTooltip = ({ tooltipClassName }) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -67,8 +65,7 @@ CurrentGradeTooltip.defaultProps = {
|
||||
};
|
||||
|
||||
CurrentGradeTooltip.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
tooltipClassName: PropTypes.string,
|
||||
};
|
||||
|
||||
export default injectIntl(CurrentGradeTooltip);
|
||||
export default CurrentGradeTooltip;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
getLocale, injectIntl, intlShape, isRtl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { getLocale, isRtl, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
import { useModel } from '../../../../generic/model-store';
|
||||
import CurrentGradeTooltip from './CurrentGradeTooltip';
|
||||
@@ -11,7 +8,8 @@ import PassingGradeTooltip from './PassingGradeTooltip';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
const GradeBar = ({ intl, passingGrade }) => {
|
||||
const GradeBar = ({ passingGrade }) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -50,8 +48,7 @@ const GradeBar = ({ intl, passingGrade }) => {
|
||||
};
|
||||
|
||||
GradeBar.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
passingGrade: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(GradeBar);
|
||||
export default GradeBar;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { InfoOutline } from '@openedx/paragon/icons';
|
||||
import {
|
||||
Icon, IconButton, OverlayTrigger, Popover,
|
||||
@@ -11,7 +11,8 @@ import { useModel } from '../../../../generic/model-store';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
const GradeRangeTooltip = ({ intl, iconButtonClassName, passingGrade }) => {
|
||||
const GradeRangeTooltip = ({ iconButtonClassName, passingGrade }) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -78,8 +79,7 @@ GradeRangeTooltip.defaultProps = {
|
||||
|
||||
GradeRangeTooltip.propTypes = {
|
||||
iconButtonClassName: PropTypes.string,
|
||||
intl: intlShape.isRequired,
|
||||
passingGrade: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(GradeRangeTooltip);
|
||||
export default GradeRangeTooltip;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
getLocale, injectIntl, intlShape, isRtl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { getLocale, isRtl, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { OverlayTrigger, Popover } from '@openedx/paragon';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
const PassingGradeTooltip = ({ intl, passingGrade, tooltipClassName }) => {
|
||||
const PassingGradeTooltip = ({ passingGrade, tooltipClassName }) => {
|
||||
const intl = useIntl();
|
||||
const isLocaleRtl = isRtl(getLocale());
|
||||
|
||||
let passingGradeDirection = passingGrade < 50 ? '' : '-';
|
||||
@@ -54,9 +52,8 @@ PassingGradeTooltip.defaultProps = {
|
||||
};
|
||||
|
||||
PassingGradeTooltip.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
passingGrade: PropTypes.number.isRequired,
|
||||
tooltipClassName: PropTypes.string,
|
||||
};
|
||||
|
||||
export default injectIntl(PassingGradeTooltip);
|
||||
export default PassingGradeTooltip;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Blocked } from '@openedx/paragon/icons';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Locked } from '@openedx/paragon/icons';
|
||||
import { Icon, Hyperlink } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
import { useModel } from '../../../../generic/model-store';
|
||||
@@ -13,7 +11,8 @@ import DetailedGradesTable from './DetailedGradesTable';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
const DetailedGrades = ({ intl }) => {
|
||||
const DetailedGrades = () => {
|
||||
const intl = useIntl();
|
||||
const { administrator } = getAuthenticatedUser();
|
||||
const courseId = useContextId();
|
||||
const {
|
||||
@@ -59,25 +58,17 @@ const DetailedGrades = ({ intl }) => {
|
||||
<ul className="micro mb-3 pl-3 text-gray-700">
|
||||
<li>
|
||||
<b>{intl.formatMessage(messages.practiceScoreLabel)} </b>
|
||||
<FormattedMessage
|
||||
id="progress.detailedGrades.practice-label.info.text"
|
||||
defaultMessage="Scores from non-graded activities meant for practice and self-assessment."
|
||||
description="Information text about non-graded practice score label"
|
||||
/>
|
||||
{intl.formatMessage(messages.practiceScoreInfoText)}
|
||||
</li>
|
||||
<li>
|
||||
<b>{intl.formatMessage(messages.gradedScoreLabel)} </b>
|
||||
<FormattedMessage
|
||||
id="progress.detailedGrades.problem-label.info.text"
|
||||
defaultMessage="Scores from activities that contribute to your final grade."
|
||||
description="Information text about graded problem score label"
|
||||
/>
|
||||
{intl.formatMessage(messages.gradedScoreInfoText)}
|
||||
</li>
|
||||
</ul>
|
||||
{gradesFeatureIsPartiallyLocked && (
|
||||
<div className="mb-3 small ml-0 d-inline">
|
||||
<Icon className="mr-1 mt-1 d-inline-flex" style={{ height: '1rem', width: '1rem' }} src={Blocked} data-testid="blocked-icon" />
|
||||
{intl.formatMessage(messages.gradeSummaryLimitedAccessExplanation)}
|
||||
<Icon className="mr-1 mt-1 d-inline-flex" style={{ height: '1rem', width: '1rem' }} src={Locked} data-testid="locked-icon" />
|
||||
{intl.formatMessage(messages.gradeSummaryLimitedAccessExplanation, { upgradeLink: '' })}
|
||||
</div>
|
||||
)}
|
||||
{hasSectionScores && (
|
||||
@@ -88,20 +79,11 @@ const DetailedGrades = ({ intl }) => {
|
||||
)}
|
||||
{overviewTabUrl && !showUngradedAssignments() && (
|
||||
<p className="x-small m-0">
|
||||
<FormattedMessage
|
||||
id="progress.ungradedAlert"
|
||||
defaultMessage="For progress on ungraded aspects of the course, view your {outlineLink}."
|
||||
description="Text that precede link that redirect to course outline page"
|
||||
values={{ outlineLink }}
|
||||
/>
|
||||
{intl.formatMessage(messages.ungradedAlert, { outlineLink })}
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
DetailedGrades.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(DetailedGrades);
|
||||
export default DetailedGrades;
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
getLocale, injectIntl, intlShape, isRtl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { getLocale, isRtl, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { DataTable } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
|
||||
@@ -11,7 +7,8 @@ import messages from '../messages';
|
||||
import SubsectionTitleCell from './SubsectionTitleCell';
|
||||
import { showUngradedAssignments } from '../../utils';
|
||||
|
||||
const DetailedGradesTable = ({ intl }) => {
|
||||
const DetailedGradesTable = () => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
@@ -66,8 +63,4 @@ const DetailedGradesTable = ({ intl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
DetailedGradesTable.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(DetailedGradesTable);
|
||||
export default DetailedGradesTable;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import {
|
||||
getLocale, injectIntl, intlShape, isRtl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { getLocale, isRtl, useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
const ProblemScoreDrawer = ({ intl, problemScores, subsection }) => {
|
||||
const ProblemScoreDrawer = ({ problemScores, subsection }) => {
|
||||
const intl = useIntl();
|
||||
const isLocaleRtl = isRtl(getLocale());
|
||||
|
||||
const scoreLabel = subsection.hasGradedAssignment ? messages.gradedScoreLabel : messages.practiceScoreLabel;
|
||||
@@ -29,7 +27,6 @@ const ProblemScoreDrawer = ({ intl, problemScores, subsection }) => {
|
||||
};
|
||||
|
||||
ProblemScoreDrawer.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
problemScores: PropTypes.arrayOf(PropTypes.shape({
|
||||
earned: PropTypes.number.isRequired,
|
||||
possible: PropTypes.number.isRequired,
|
||||
@@ -40,4 +37,4 @@ ProblemScoreDrawer.propTypes = {
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(ProblemScoreDrawer);
|
||||
export default ProblemScoreDrawer;
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Collapsible, Icon, Row } from '@openedx/paragon';
|
||||
import {
|
||||
ArrowDropDown, ArrowDropUp, Blocked, Info,
|
||||
ArrowDropDown,
|
||||
ArrowDropUp,
|
||||
Info,
|
||||
Locked,
|
||||
} from '@openedx/paragon/icons';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
|
||||
@@ -14,7 +16,8 @@ import messages from '../messages';
|
||||
import { useModel } from '../../../../generic/model-store';
|
||||
import ProblemScoreDrawer from './ProblemScoreDrawer';
|
||||
|
||||
const SubsectionTitleCell = ({ intl, subsection }) => {
|
||||
const SubsectionTitleCell = ({ subsection }) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
const {
|
||||
org,
|
||||
@@ -59,8 +62,8 @@ const SubsectionTitleCell = ({ intl, subsection }) => {
|
||||
aria-label={intl.formatMessage(messages.noAccessToSubsection, { displayName })}
|
||||
className="mr-1 mt-1 d-inline-flex"
|
||||
style={{ height: '1rem', width: '1rem' }}
|
||||
src={Blocked}
|
||||
data-testid="blocked-icon"
|
||||
src={Locked}
|
||||
data-testid="locked-icon"
|
||||
/>
|
||||
)}
|
||||
{url ? (
|
||||
@@ -100,7 +103,6 @@ const SubsectionTitleCell = ({ intl, subsection }) => {
|
||||
};
|
||||
|
||||
SubsectionTitleCell.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
subsection: PropTypes.shape({
|
||||
blockKey: PropTypes.string.isRequired,
|
||||
displayName: PropTypes.string.isRequired,
|
||||
@@ -117,4 +119,4 @@ SubsectionTitleCell.propTypes = {
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(SubsectionTitleCell);
|
||||
export default SubsectionTitleCell;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Blocked } from '@openedx/paragon/icons';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Locked } from '@openedx/paragon/icons';
|
||||
import { Icon } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
import { useModel } from '../../../../generic/model-store';
|
||||
import messages from '../messages';
|
||||
|
||||
const AssignmentTypeCell = ({
|
||||
intl, assignmentType, footnoteMarker, footnoteId, locked,
|
||||
assignmentType, footnoteMarker, footnoteId, locked,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
|
||||
const {
|
||||
gradesFeatureIsFullyLocked,
|
||||
} = useModel('progress', courseId);
|
||||
|
||||
const lockedIcon = locked ? <Icon id={`assignmentTypeBlockedIcon${assignmentType}`} aria-label={intl.formatMessage(messages.noAccessToAssignmentType, { assignmentType })} className="mr-1 mt-1 d-inline-flex" style={{ height: '1rem', width: '1rem' }} src={Blocked} data-testid="blocked-icon" /> : '';
|
||||
const lockedIcon = locked ? <Icon id={`assignmentTypeBlockedIcon${assignmentType}`} aria-label={intl.formatMessage(messages.noAccessToAssignmentType, { assignmentType })} className="mr-1 mt-1 d-inline-flex" style={{ height: '1rem', width: '1rem' }} src={Locked} data-testid="locked-icon" /> : '';
|
||||
|
||||
return (
|
||||
<div className="d-flex small">
|
||||
@@ -43,7 +43,6 @@ const AssignmentTypeCell = ({
|
||||
};
|
||||
|
||||
AssignmentTypeCell.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
assignmentType: PropTypes.string.isRequired,
|
||||
footnoteId: PropTypes.string,
|
||||
footnoteMarker: PropTypes.number,
|
||||
@@ -56,4 +55,4 @@ AssignmentTypeCell.defaultProps = {
|
||||
locked: false,
|
||||
};
|
||||
|
||||
export default injectIntl(AssignmentTypeCell);
|
||||
export default AssignmentTypeCell;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
|
||||
import messages from '../messages';
|
||||
import { useModel } from '../../../../generic/model-store';
|
||||
|
||||
const DroppableAssignmentFootnote = ({ footnotes, intl }) => {
|
||||
const DroppableAssignmentFootnote = ({ footnotes }) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
const {
|
||||
gradesFeatureIsFullyLocked,
|
||||
@@ -20,14 +19,10 @@ const DroppableAssignmentFootnote = ({ footnotes, intl }) => {
|
||||
{footnotes.map((footnote, index) => (
|
||||
<li id={`${footnote.id}-footnote`} key={footnote.id} className="x-small mt-1">
|
||||
<sup>{index + 1}</sup>
|
||||
<FormattedMessage
|
||||
id="progress.footnotes.droppableAssignments"
|
||||
defaultMessage="The lowest {numDroppable, plural, one{# {assignmentType} score is} other{# {assignmentType} scores are}} dropped."
|
||||
values={{
|
||||
numDroppable: footnote.numDroppable,
|
||||
assignmentType: footnote.assignmentType,
|
||||
}}
|
||||
/>
|
||||
{intl.formatMessage(messages.droppableAssignmentsText, {
|
||||
numDroppable: footnote.numDroppable,
|
||||
assignmentType: footnote.assignmentType,
|
||||
})}
|
||||
<a className="sr-only" href={`#${footnote.id}-ref`} tabIndex={gradesFeatureIsFullyLocked ? '-1' : '0'}>
|
||||
{intl.formatMessage(messages.backToContent)}
|
||||
</a>
|
||||
@@ -44,7 +39,6 @@ DroppableAssignmentFootnote.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
numDroppable: PropTypes.number.isRequired,
|
||||
})).isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(DroppableAssignmentFootnote);
|
||||
export default DroppableAssignmentFootnote;
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Icon, OverlayTrigger, Tooltip } from '@openedx/paragon';
|
||||
import { Blocked, InfoOutline } from '@openedx/paragon/icons';
|
||||
import {
|
||||
Hyperlink,
|
||||
Icon,
|
||||
OverlayTrigger,
|
||||
Stack,
|
||||
Tooltip,
|
||||
} from '@openedx/paragon';
|
||||
import { InfoOutline, Locked } from '@openedx/paragon/icons';
|
||||
import { useContextId } from '../../../../data/hooks';
|
||||
|
||||
import messages from '../messages';
|
||||
@@ -12,35 +17,48 @@ const GradeSummaryHeader = ({ allOfSomeAssignmentTypeIsLocked }) => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
const {
|
||||
verifiedMode,
|
||||
gradesFeatureIsFullyLocked,
|
||||
} = useModel('progress', courseId);
|
||||
|
||||
return (
|
||||
<div className="row w-100 m-0 align-items-center">
|
||||
<h3 className="h4 mb-3 mr-1">{intl.formatMessage(messages.gradeSummary)}</h3>
|
||||
<OverlayTrigger
|
||||
trigger="hover"
|
||||
placement="top"
|
||||
overlay={(
|
||||
<Tooltip>
|
||||
{intl.formatMessage(messages.gradeSummaryTooltipBody)}
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
alt={intl.formatMessage(messages.gradeSummaryTooltipAlt)}
|
||||
src={InfoOutline}
|
||||
className="mb-3"
|
||||
size="sm"
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
<Stack gap={2} className="mb-3">
|
||||
<Stack direction="horizontal" gap={2}>
|
||||
<h3 className="h4 m-0">{intl.formatMessage(messages.gradeSummary)}</h3>
|
||||
<OverlayTrigger
|
||||
trigger="hover"
|
||||
placement="top"
|
||||
overlay={(
|
||||
<Tooltip>
|
||||
{intl.formatMessage(messages.gradeSummaryTooltipBody)}
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
alt={intl.formatMessage(messages.gradeSummaryTooltipAlt)}
|
||||
src={InfoOutline}
|
||||
size="sm"
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</Stack>
|
||||
{!gradesFeatureIsFullyLocked && allOfSomeAssignmentTypeIsLocked && (
|
||||
<div className="mb-3 small ml-0 d-inline">
|
||||
<Icon className="mr-1 mt-1 d-inline-flex" style={{ height: '1rem', width: '1rem' }} src={Blocked} data-testid="blocked-icon" />
|
||||
{intl.formatMessage(messages.gradeSummaryLimitedAccessExplanation)}
|
||||
</div>
|
||||
<Stack direction="horizontal" className="small" gap={2}>
|
||||
<Icon size="sm" src={Locked} data-testid="locked-icon" />
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
messages.gradeSummaryLimitedAccessExplanation,
|
||||
{
|
||||
upgradeLink: verifiedMode && (
|
||||
<Hyperlink destination={verifiedMode.upgradeUrl}>
|
||||
{intl.formatMessage(messages.courseGradePreviewUpgradeButton)}.
|
||||
</Hyperlink>
|
||||
),
|
||||
},
|
||||
)}
|
||||
</span>
|
||||
</Stack>
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ const messages = defineMessages({
|
||||
},
|
||||
gradeSummaryLimitedAccessExplanation: {
|
||||
id: 'progress.gradeSummary.limitedAccessExplanation',
|
||||
defaultMessage: 'You have limited access to graded assignments as part of the audit track in this course.',
|
||||
defaultMessage: 'You have limited access to graded assignments as part of the audit track in this course. {upgradeLink}',
|
||||
description: 'Text shown when learner has limited access to grade feature',
|
||||
},
|
||||
gradeSummaryTooltipAlt: {
|
||||
@@ -208,6 +208,26 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Your raw weighted grade summary is {rawGrade} and rounds to {roundedGrade}.',
|
||||
description: 'Tooltip content that explains the rounding of the summary versus individual assignments',
|
||||
},
|
||||
practiceScoreInfoText: {
|
||||
id: 'progress.detailedGrades.practice-label.info.text',
|
||||
defaultMessage: 'Scores from non-graded activities meant for practice and self-assessment.',
|
||||
description: 'Information text about non-graded practice score label',
|
||||
},
|
||||
gradedScoreInfoText: {
|
||||
id: 'progress.detailedGrades.problem-label.info.text',
|
||||
defaultMessage: 'Scores from activities that contribute to your final grade.',
|
||||
description: 'Information text about graded problem score label',
|
||||
},
|
||||
ungradedAlert: {
|
||||
id: 'progress.ungradedAlert',
|
||||
defaultMessage: 'For progress on ungraded aspects of the course, view your {outlineLink}.',
|
||||
description: 'Text that precede link that redirect to course outline page',
|
||||
},
|
||||
droppableAssignmentsText: {
|
||||
id: 'progress.footnotes.droppableAssignments',
|
||||
defaultMessage: 'The lowest {numDroppable, plural, one{# {assignmentType} score is} other{# {assignmentType} scores are}} dropped.',
|
||||
description: 'Footnote text stating how many assignments are dropped',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import React from 'react';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Hyperlink } from '@openedx/paragon';
|
||||
import { useContextId } from '../../../data/hooks';
|
||||
|
||||
import messages from './messages';
|
||||
import { useModel } from '../../../generic/model-store';
|
||||
|
||||
const RelatedLinks = ({ intl }) => {
|
||||
const RelatedLinks = () => {
|
||||
const intl = useIntl();
|
||||
const courseId = useContextId();
|
||||
const {
|
||||
org,
|
||||
@@ -56,8 +55,4 @@ const RelatedLinks = ({ intl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
RelatedLinks.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(RelatedLinks);
|
||||
export default RelatedLinks;
|
||||
|
||||
Reference in New Issue
Block a user