Skip to content

Commit 1726236

Browse files
committed
feat: updated design for course outline sections and sequences, implemented isPreview key for outline API
1 parent 8ca5513 commit 1726236

File tree

8 files changed

+149
-35
lines changed

8 files changed

+149
-35
lines changed

src/course-home/data/api.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ export function normalizeOutlineBlocks(courseId, blocks) {
137137
resumeBlock: block.resume_block,
138138
sequenceIds: block.children || [],
139139
hideFromTOC: block.hide_from_toc,
140+
completionStat: {
141+
completed: block.completion_stat?.completion,
142+
total: block.completion_stat?.completable_children,
143+
},
140144
};
141145
break;
142146

@@ -155,6 +159,11 @@ export function normalizeOutlineBlocks(courseId, blocks) {
155159
title: block.display_name,
156160
hideFromTOC: block.hide_from_toc,
157161
navigationDisabled: block.navigation_disabled,
162+
isPreview: block.is_preview,
163+
completionStat: {
164+
completed: block.completion_stat?.completion,
165+
total: block.completion_stat?.completable_children,
166+
},
158167
};
159168
break;
160169

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import PropTypes from 'prop-types';
2+
3+
import { Complete, Incomplete, PartiallyComplete } from './icons';
4+
5+
const CompletionIcon = ({ completionStat: { completed = 0, total = 0 } }) => {
6+
switch (true) {
7+
case !completed:
8+
return <Incomplete className="text-light-700 pgn__icon" data-testid="completion-solid-icon" />;
9+
case completed === total:
10+
return <Complete className="text-success pgn__icon" data-testid="check-circle-icon" />;
11+
default:
12+
return <PartiallyComplete className="text-success pgn__icon" data-testid="dashed-circle-icon" />;
13+
}
14+
};
15+
16+
CompletionIcon.propTypes = {
17+
completionStat: PropTypes.shape({
18+
completed: PropTypes.number,
19+
total: PropTypes.number,
20+
}).isRequired,
21+
};
22+
23+
export default CompletionIcon;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import PropTypes from 'prop-types';
2+
3+
const Complete = (props) => (
4+
<span className={props.className}>
5+
<svg
6+
width="24"
7+
height="24"
8+
viewBox="0 0 24 24"
9+
fill="none"
10+
xmlns="http://www.w3.org/2000/svg"
11+
{...props}
12+
>
13+
<path
14+
d="M12 1.5C9.9233 1.5 7.89323 2.11581 6.16652 3.26957C4.4398 4.42332 3.09399 6.0632 2.29927 7.98182C1.50455 9.90045 1.29661 12.0116 1.70176 14.0484C2.1069 16.0852 3.10693 17.9562 4.57538 19.4246C6.04383 20.8931 7.91476 21.8931 9.95156 22.2982C11.9884 22.7034 14.0996 22.4955 16.0182 21.7007C17.9368 20.906 19.5767 19.5602 20.7304 17.8335C21.8842 16.1068 22.5 14.0767 22.5 12C22.5 9.21523 21.3938 6.54451 19.4246 4.57538C17.4555 2.60625 14.7848 1.5 12 1.5ZM10.5 16.1931L6.75 12.4431L7.94296 11.25L10.5 13.8069L16.0575 8.25L17.2543 9.43943L10.5 16.1931Z"
15+
fill="currentColor"
16+
/>
17+
</svg>
18+
</span>
19+
);
20+
21+
Complete.defaultProps = {
22+
className: '',
23+
};
24+
25+
Complete.propTypes = {
26+
className: PropTypes.string,
27+
};
28+
29+
export default Complete;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import PropTypes from 'prop-types';
2+
3+
const Incomplete = (props) => (
4+
<span className={props.className}>
5+
<svg
6+
width="24"
7+
height="24"
8+
viewBox="0 0 24 24"
9+
fill="none"
10+
xmlns="http://www.w3.org/2000/svg"
11+
{...props}
12+
>
13+
<path
14+
d="M12 1.5C9.9233 1.5 7.89323 2.11581 6.16652 3.26957C4.4398 4.42332 3.09399 6.0632 2.29927 7.98182C1.50455 9.90045 1.29661 12.0116 1.70176 14.0484C2.1069 16.0852 3.10693 17.9562 4.57538 19.4246C6.04383 20.8931 7.91476 21.8931 9.95156 22.2982C11.9884 22.7034 14.0996 22.4955 16.0182 21.7007C17.9368 20.906 19.5767 19.5602 20.7304 17.8335C21.8842 16.1068 22.5 14.0767 22.5 12C22.5 9.21523 21.3938 6.54451 19.4246 4.57538C17.4555 2.60625 14.7848 1.5 12 1.5ZM12 21C10.22 21 8.47992 20.4722 6.99987 19.4832C5.51983 18.4943 4.36628 17.0887 3.68509 15.4442C3.0039 13.7996 2.82567 11.99 3.17294 10.2442C3.5202 8.49836 4.37737 6.89471 5.63604 5.63604C6.89472 4.37737 8.49836 3.5202 10.2442 3.17293C11.99 2.82567 13.7996 3.0039 15.4442 3.68508C17.0887 4.36627 18.4943 5.51983 19.4832 6.99987C20.4722 8.47991 21 10.22 21 12C21 14.3869 20.0518 16.6761 18.364 18.364C16.6761 20.0518 14.387 21 12 21Z"
15+
fill="currentColor"
16+
/>
17+
</svg>
18+
</span>
19+
);
20+
21+
Incomplete.defaultProps = {
22+
className: '',
23+
};
24+
25+
Incomplete.propTypes = {
26+
className: PropTypes.string,
27+
};
28+
29+
export default Incomplete;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import PropTypes from 'prop-types';
2+
3+
const PartiallyComplete = (props) => (
4+
<span className={props.className}>
5+
<svg
6+
width="24"
7+
height="24"
8+
viewBox="0 0 24 24"
9+
fill="none"
10+
xmlns="http://www.w3.org/2000/svg"
11+
{...props}
12+
>
13+
<path
14+
d="M17.8222 5.14451L18.786 3.99588C17.8549 3.20783 16.7935 2.58833 15.6494 2.16528L15.1367 3.57348C16.1165 3.93691 17.0253 4.46857 17.8222 5.14451Z"
15+
fill="currentColor"
16+
/>
17+
<path
18+
d="M20.8557 10.4999L22.3314 10.1903C22.124 8.99193 21.7083 7.83914 21.1032 6.78418L19.8047 7.4999C20.323 8.43291 20.6784 9.44744 20.8557 10.4999Z"
19+
fill="currentColor"
20+
/>
21+
<path
22+
d="M15.1367 20.4265L15.6494 21.8347C16.7935 21.4116 17.8549 20.7921 18.786 20.0041L17.8222 18.8555C17.0253 19.5314 16.1165 20.0631 15.1367 20.4265Z"
23+
fill="currentColor"
24+
/>
25+
<path
26+
d="M19.8047 16.4999L21.1032 17.2499C21.7086 16.1828 22.1244 15.0187 22.3318 13.8095L20.8557 13.5493C20.6782 14.5861 20.3227 15.5844 19.8047 16.4999Z"
27+
fill="currentColor"
28+
/>
29+
<path
30+
d="M12 22.5V1.5C9.21523 1.5 6.54451 2.60625 4.57538 4.57538C2.60625 6.54451 1.5 9.21523 1.5 12C1.5 14.7848 2.60625 17.4555 4.57538 19.4246C6.54451 21.3938 9.21523 22.5 12 22.5Z"
31+
fill="currentColor"
32+
/>
33+
</svg>
34+
</span>
35+
);
36+
37+
PartiallyComplete.defaultProps = {
38+
className: '',
39+
};
40+
41+
PartiallyComplete.propTypes = {
42+
className: PropTypes.string,
43+
};
44+
45+
export default PartiallyComplete;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { default as Complete } from './Complete';
2+
export { default as Incomplete } from './Incomplete';
3+
export { default as PartiallyComplete } from './PartiallyComplete';

src/course-home/outline-tab/section-outline/SectionTitle.tsx

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,26 @@ import { Icon } from '@openedx/paragon';
44
import { CheckCircle, CheckCircleOutline, DisabledVisible } from '@openedx/paragon/icons';
55

66
import messages from '../messages';
7+
import CompletionIcon from '../CompletionIcon';
8+
9+
interface CompletionStat {
10+
completed: number;
11+
total: number;
12+
}
713

814
interface Props {
915
complete: boolean;
1016
hideFromTOC: boolean;
1117
title: string;
18+
completionStat: CompletionStat;
1219
}
1320

14-
const SectionTitle: React.FC<Props> = ({ complete, hideFromTOC, title }) => {
21+
const SectionTitle: React.FC<Props> = ({ complete, hideFromTOC, title, completionStat }) => {
1522
const intl = useIntl();
1623
return (
1724
<div className="d-flex row w-100 m-0">
1825
<div className="col-auto p-0">
19-
{complete ? (
20-
<Icon
21-
src={CheckCircle}
22-
className="float-left mt-1 text-success"
23-
aria-hidden="true"
24-
svgAttrs={{ 'aria-label': intl.formatMessage(messages.completedSection) }}
25-
size="sm"
26-
/>
27-
) : (
28-
<Icon
29-
src={CheckCircleOutline}
30-
className="float-left mt-1 text-gray-400"
31-
aria-hidden="true"
32-
svgAttrs={{ 'aria-label': intl.formatMessage(messages.incompleteSection) }}
33-
size="sm"
34-
/>
35-
)}
26+
<CompletionIcon completionStat={completionStat} />
3627
</div>
3728
<div className="col-7 ml-3 p-0 font-weight-bold text-dark-500">
3829
<span className="align-middle col-6">{title}</span>

src/course-home/outline-tab/section-outline/SequenceTitle.tsx

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { CheckCircleOutline, CheckCircle } from '@openedx/paragon/icons';
77
import EffortEstimate from '../../../shared/effort-estimate';
88
import messages from '../messages';
99
import { useContextId } from '../../../data/hooks';
10+
import CompletionIcon from '../CompletionIcon';
1011

1112
interface Props {
1213
complete: boolean;
@@ -31,23 +32,7 @@ const SequenceTitle: React.FC<Props> = ({
3132
return (
3233
<div className="row w-100 m-0">
3334
<div className="col-auto p-0">
34-
{complete ? (
35-
<Icon
36-
src={CheckCircle}
37-
className="float-left text-success mt-1"
38-
aria-hidden={complete}
39-
svgAttrs={{ 'aria-label': intl.formatMessage(messages.completedAssignment) }}
40-
size="sm"
41-
/>
42-
) : (
43-
<Icon
44-
src={CheckCircleOutline}
45-
className="float-left text-gray-400 mt-1"
46-
aria-hidden={complete}
47-
svgAttrs={{ 'aria-label': intl.formatMessage(messages.incompleteAssignment) }}
48-
size="sm"
49-
/>
50-
)}
35+
<CompletionIcon completionStat={sequence.completionStat} />
5136
</div>
5237
<div className="col-10 p-0 ml-3 text-break">
5338
<span className="align-middle">{displayTitle}</span>

0 commit comments

Comments
 (0)