Skip to content

Commit 0bd729c

Browse files
feat: increased font-size for Progress page
1 parent 3cbbb02 commit 0bd729c

File tree

13 files changed

+168
-40
lines changed

13 files changed

+168
-40
lines changed

src/course-home/progress-tab/certificate-status/CertificateStatus.jsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { useEffect } from 'react';
2+
import classNames from 'classnames';
23
import { useDispatch } from 'react-redux';
34
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
45
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
56
import { FormattedDate, FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
67

7-
import { Button, Card } from '@openedx/paragon';
8+
import {
9+
Button, Card, breakpoints, useWindowSize,
10+
} from '@openedx/paragon';
811
import { getConfig } from '@edx/frontend-platform';
912
import { useContextId } from '../../../data/hooks';
1013
import { useModel } from '../../../generic/model-store';
@@ -29,6 +32,8 @@ const CertificateStatus = () => {
2932
userTimezone,
3033
} = useModel('courseHomeMeta', courseId);
3134

35+
const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth;
36+
3237
const {
3338
certificateData,
3439
end,
@@ -244,7 +249,7 @@ const CertificateStatus = () => {
244249
<ProgressCertificateStatusSlot courseId={courseId}>
245250
<div id={`${certCase}_certificate_status`}>
246251
<Card.Header title={header} />
247-
<Card.Section className="small text-gray-700">
252+
<Card.Section className={classNames('text-gray-700', { small: !wideScreen })}>
248253
{body}
249254
</Card.Section>
250255
<Card.Footer>

src/course-home/progress-tab/course-completion/CourseCompletion.jsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
import React from 'react';
2+
import classNames from 'classnames';
23
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
4+
import { breakpoints, useWindowSize } from '@openedx/paragon';
35

46
import CompletionDonutChart from './CompletionDonutChart';
57
import messages from './messages';
68

7-
const CourseCompletion = ({ intl }) => (
8-
<section className="text-dark-700 mb-4 rounded raised-card p-4">
9-
<div className="row w-100 m-0">
10-
<div className="col-12 col-sm-6 col-md-7 p-0">
11-
<h2>{intl.formatMessage(messages.courseCompletion)}</h2>
12-
<p className="small">
13-
{intl.formatMessage(messages.completionBody)}
14-
</p>
15-
</div>
16-
<div className="col-12 col-sm-6 col-md-5 mt-sm-n3 p-0 text-center">
17-
<CompletionDonutChart />
9+
const CourseCompletion = ({ intl }) => {
10+
const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth;
11+
12+
return (
13+
<section className={classNames('text-dark-700 mb-4 rounded raised-card p-4', { small: !wideScreen })}>
14+
<div className="row w-100 m-0">
15+
<div className="col-12 col-sm-6 col-md-7 p-0">
16+
<h2>{intl.formatMessage(messages.courseCompletion)}</h2>
17+
<p>
18+
{intl.formatMessage(messages.completionBody)}
19+
</p>
20+
</div>
21+
<div className="col-12 col-sm-6 col-md-5 mt-sm-n3 p-0 text-center">
22+
<CompletionDonutChart />
23+
</div>
1824
</div>
19-
</div>
20-
</section>
21-
);
25+
</section>
26+
);
27+
};
2228

2329
CourseCompletion.propTypes = {
2430
intl: intlShape.isRequired,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.course-completion-text {
2+
font-size: 18px;
3+
}

src/course-home/progress-tab/credit-information/CreditInformation.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const CreditInformation = ({ intl }) => {
8484
requirementStatus = (<>{intl.formatMessage(messages.upcoming)} <Icon src={WatchFilled} className="text-gray-500 d-inline-flex align-bottom" /></>);
8585
}
8686
requirements.push((
87-
<div className="row w-100 m-0 small" key={`requirement-${requirement.order}`}>
87+
<div className="row w-100 m-0" key={`requirement-${requirement.order}`}>
8888
<p className="font-weight-bold">
8989
{requirement.namespace === 'grade'
9090
? `${intl.formatMessage(messages.minimumGrade, { minGrade: Number(requirement.criteria.minGrade) * 100 })}:`
@@ -100,7 +100,7 @@ const CreditInformation = ({ intl }) => {
100100
return (
101101
<>
102102
<h3 className="h4 col-12 p-0">{intl.formatMessage(messages.requirementsHeader)}</h3>
103-
<p className="small">{eligibilityStatus}</p>
103+
<p>{eligibilityStatus}</p>
104104
{requirements}
105105
</>
106106
);

src/course-home/progress-tab/grades/course-grade/CourseGrade.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import React from 'react';
2+
import classNames from 'classnames';
23
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
4+
import { breakpoints, useWindowSize } from '@openedx/paragon';
35
import { useContextId } from '../../../../data/hooks';
46

57
import { useModel } from '../../../../generic/model-store';
@@ -14,6 +16,8 @@ import messages from '../messages';
1416
const CourseGrade = ({ intl }) => {
1517
const courseId = useContextId();
1618

19+
const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth;
20+
1721
const {
1822
creditCourseRequirements,
1923
gradesFeatureIsFullyLocked,
@@ -37,7 +41,7 @@ const CourseGrade = ({ intl }) => {
3741
? intl.formatMessage(messages.gradesAndCredit)
3842
: intl.formatMessage(messages.grades)}
3943
</h2>
40-
<p className="small">
44+
<p className={classNames({ small: !wideScreen })}>
4145
{intl.formatMessage(messages.courseGradeBody)}
4246
</p>
4347
</div>

src/course-home/progress-tab/grades/detailed-grades/DetailedGrades.jsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import React from 'react';
2+
import classNames from 'classnames';
23

34
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
45
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
56
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
67
import { Blocked } from '@openedx/paragon/icons';
7-
import { Icon, Hyperlink } from '@openedx/paragon';
8+
import {
9+
Icon, Hyperlink, breakpoints, useWindowSize,
10+
} from '@openedx/paragon';
811
import { useContextId } from '../../../../data/hooks';
912
import { useModel } from '../../../../generic/model-store';
1013
import { showUngradedAssignments } from '../../utils';
@@ -25,6 +28,7 @@ const DetailedGrades = ({ intl }) => {
2528
gradesFeatureIsPartiallyLocked,
2629
sectionScores,
2730
} = useModel('progress', courseId);
31+
const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth;
2832

2933
const hasSectionScores = sectionScores.length > 0;
3034
const emptyTableMsg = showUngradedAssignments()
@@ -84,10 +88,12 @@ const DetailedGrades = ({ intl }) => {
8488
<DetailedGradesTable />
8589
)}
8690
{!hasSectionScores && (
87-
<p className="small">{intl.formatMessage(emptyTableMsg)}</p>
91+
<p className={classNames({ small: !wideScreen })}>
92+
{intl.formatMessage(emptyTableMsg)}
93+
</p>
8894
)}
8995
{overviewTabUrl && !showUngradedAssignments() && (
90-
<p className="x-small m-0">
96+
<p className={classNames('m-0', { small: !wideScreen })}>
9197
<FormattedMessage
9298
id="progress.ungradedAlert"
9399
defaultMessage="For progress on ungraded aspects of the course, view your {outlineLink}."

src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react';
2+
import classNames from 'classnames';
23

34
import PropTypes from 'prop-types';
5+
import { breakpoints, useWindowSize } from '@openedx/paragon';
46

57
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
68
import { useContextId } from '../../../../data/hooks';
@@ -13,12 +15,14 @@ const DroppableAssignmentFootnote = ({ footnotes, intl }) => {
1315
const {
1416
gradesFeatureIsFullyLocked,
1517
} = useModel('progress', courseId);
18+
const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth;
19+
1620
return (
1721
<>
1822
<span id="grade-summary-footnote-label" className="sr-only">{intl.formatMessage(messages.footnotesTitle)}</span>
1923
<ul className="list-unstyled mt-2">
2024
{footnotes.map((footnote, index) => (
21-
<li id={`${footnote.id}-footnote`} key={footnote.id} className="x-small mt-1">
25+
<li id={`${footnote.id}-footnote`} key={footnote.id} className={classNames('mt-1', { small: !wideScreen })}>
2226
<sup>{index + 1}</sup>
2327
<FormattedMessage
2428
id="progress.footnotes.droppableAssignments"

src/course-home/progress-tab/grades/grade-summary/GradeSummaryHeader.jsx

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import React, { useState } from 'react';
2+
import classNames from 'classnames';
13
import PropTypes from 'prop-types';
24

3-
import { useIntl } from '@edx/frontend-platform/i18n';
4-
import { Icon, OverlayTrigger, Tooltip } from '@openedx/paragon';
5+
import {
6+
Icon, IconButton, OverlayTrigger, Popover, breakpoints, useWindowSize,
7+
} from '@openedx/paragon';
58
import { Blocked, InfoOutline } from '@openedx/paragon/icons';
9+
import { useIntl } from '@edx/frontend-platform/i18n';
610
import { useContextId } from '../../../../data/hooks';
711

812
import messages from '../messages';
@@ -14,24 +18,42 @@ const GradeSummaryHeader = ({ allOfSomeAssignmentTypeIsLocked }) => {
1418
const {
1519
gradesFeatureIsFullyLocked,
1620
} = useModel('progress', courseId);
21+
const [showTooltip, setShowTooltip] = useState(false);
22+
const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth;
23+
24+
const handleKeyDown = (e) => {
25+
if (e.key === 'Escape') {
26+
setShowTooltip(false);
27+
}
28+
};
1729

1830
return (
1931
<div className="row w-100 m-0 align-items-center">
2032
<h3 className="h4 mb-3 mr-1">{intl.formatMessage(messages.gradeSummary)}</h3>
2133
<OverlayTrigger
22-
trigger="hover"
34+
trigger="click"
2335
placement="top"
36+
show={showTooltip}
2437
overlay={(
25-
<Tooltip>
26-
{intl.formatMessage(messages.gradeSummaryTooltipBody)}
27-
</Tooltip>
38+
<Popover>
39+
<Popover.Content
40+
className={classNames('text-dark-700', { small: !wideScreen })}
41+
>
42+
{intl.formatMessage(messages.gradeSummaryTooltipBody)}
43+
</Popover.Content>
44+
</Popover>
2845
)}
2946
>
30-
<Icon
47+
<IconButton
48+
onClick={() => { setShowTooltip(!showTooltip); }}
49+
onBlur={() => { setShowTooltip(false); }}
50+
onKeyDown={handleKeyDown}
3151
alt={intl.formatMessage(messages.gradeSummaryTooltipAlt)}
3252
src={InfoOutline}
53+
iconAs={Icon}
3354
className="mb-3"
3455
size="sm"
56+
disabled={gradesFeatureIsFullyLocked}
3557
/>
3658
</OverlayTrigger>
3759
{!gradesFeatureIsFullyLocked && allOfSomeAssignmentTypeIsLocked && (
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import React from 'react';
2+
import {
3+
render, screen, waitFor,
4+
} from '@testing-library/react';
5+
import userEvent from '@testing-library/user-event';
6+
import { useSelector } from 'react-redux';
7+
import { IntlProvider } from 'react-intl';
8+
9+
import GradeSummaryHeader from './GradeSummaryHeader';
10+
import { useModel } from '../../../../generic/model-store';
11+
import messages from '../messages';
12+
13+
jest.mock('react-redux', () => ({
14+
useSelector: jest.fn(),
15+
}));
16+
17+
jest.mock('../../../../generic/model-store', () => ({
18+
useModel: jest.fn(),
19+
}));
20+
21+
describe('GradeSummaryHeader', () => {
22+
beforeEach(() => {
23+
useSelector.mockImplementation((selector) => selector({
24+
courseHome: { courseId: 'test-course-id' },
25+
}));
26+
useModel.mockReturnValue({ gradesFeatureIsFullyLocked: false });
27+
});
28+
29+
const renderComponent = (props = {}) => {
30+
render(
31+
<IntlProvider locale="en" messages={messages}>
32+
<GradeSummaryHeader
33+
intl={{ formatMessage: jest.fn((msg) => msg.defaultMessage) }}
34+
allOfSomeAssignmentTypeIsLocked={false}
35+
{...props}
36+
/>
37+
</IntlProvider>,
38+
);
39+
};
40+
41+
it('opens and closes the tooltip when Escape is pressed', async () => {
42+
renderComponent();
43+
44+
const iconButton = screen.getByRole('button', {
45+
name: messages.gradeSummaryTooltipAlt.defaultMessage,
46+
});
47+
48+
userEvent.click(iconButton);
49+
50+
await waitFor(() => {
51+
expect(screen.getByText(messages.gradeSummaryTooltipBody.defaultMessage)).toBeVisible();
52+
});
53+
54+
userEvent.keyboard('{Escape}');
55+
56+
await waitFor(() => {
57+
expect(screen.queryByText(messages.gradeSummaryTooltipBody.defaultMessage)).not.toBeInTheDocument();
58+
});
59+
});
60+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@import "course-completion/CompletionDonutChart.scss";
2+
@import "course-completion/CourseCompletion.scss";
3+
4+
@import "grades/course-grade/GradeBar.scss";
5+
6+
@import "related-links/RelatedLinks.scss";

src/course-home/progress-tab/related-links/RelatedLinks.jsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react';
2+
import classNames from 'classnames';
23

34
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
45
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
56
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
6-
import { Hyperlink } from '@openedx/paragon';
7+
import { Hyperlink, breakpoints, useWindowSize } from '@openedx/paragon';
78
import { useContextId } from '../../../data/hooks';
89

910
import messages from './messages';
@@ -15,6 +16,7 @@ const RelatedLinks = ({ intl }) => {
1516
org,
1617
tabs,
1718
} = useModel('courseHomeMeta', courseId);
19+
const wideScreen = useWindowSize().width >= breakpoints.medium.minWidth;
1820

1921
const { administrator } = getAuthenticatedUser();
2022
const logLinkClicked = (linkName) => {
@@ -32,19 +34,21 @@ const RelatedLinks = ({ intl }) => {
3234
const datesTabUrl = datesTab && datesTab.url;
3335

3436
return (
35-
<section className="mb-4 x-small">
36-
<h3 className="h4">{intl.formatMessage(messages.relatedLinks)}</h3>
37-
<ul className="pl-4">
37+
<section className="mb-4 x-small related-links">
38+
<h3 className={classNames('h4', { 'related-links-title': wideScreen })}>
39+
{intl.formatMessage(messages.relatedLinks)}
40+
</h3>
41+
<ul className="pl-4 related-links-list">
3842
{datesTabUrl && (
39-
<li>
43+
<li className={classNames({ 'related-links-list-item': wideScreen })}>
4044
<Hyperlink destination={datesTabUrl} onClick={() => logLinkClicked('dates')}>
4145
{intl.formatMessage(messages.datesCardLink)}
4246
</Hyperlink>
4347
<p>{intl.formatMessage(messages.datesCardDescription)}</p>
4448
</li>
4549
)}
4650
{overviewTabUrl && (
47-
<li>
51+
<li className={classNames({ 'related-links-list-item': wideScreen })}>
4852
<Hyperlink destination={overviewTabUrl} onClick={() => logLinkClicked('course_outline')}>
4953
{intl.formatMessage(messages.outlineCardLink)}
5054
</Hyperlink>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.related-links {
2+
.related-links-title {
3+
font-size: 20px;
4+
}
5+
6+
.related-links-list .related-links-list-item {
7+
font-size: 18px;
8+
}
9+
}

0 commit comments

Comments
 (0)