Skip to content

Commit 98ddeef

Browse files
author
Ben Warzeski
authored
feat: progress updates
Bw/fake data
2 parents 5363fae + d560277 commit 98ddeef

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1106
-669
lines changed

src/App.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ import { Spinner } from '@edx/paragon';
55

66
import { useIsORAConfigLoaded, useIsPageDataLoaded } from 'data/services/lms/hooks/selectors';
77

8-
import AppContainer from 'views/AppContainer';
9-
import ModalContainer from 'views/ModalContainer';
108
import PeerAssessmentView from 'views/PeerAssessmentView';
119
import SelfAssessmentView from 'views/SelfAssessmentView';
1210
import StudentTrainingView from 'views/StudentTrainingView';
1311
import SubmissionView from 'views/SubmissionView';
1412
import XBlockView from 'views/XBlockView';
13+
14+
import AppContainer from 'components/AppContainer';
15+
import ModalContainer from 'components/ModalContainer';
1516
import PageDataProvider from 'components/PageDataProvider';
1617

1718
import messages from './messages';
File renamed without changes.
File renamed without changes.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import classNames from 'classnames';
4+
5+
import { StrictDict } from '@edx/react-unit-test-utils';
6+
import { Nav, Icon } from '@edx/paragon';
7+
import {
8+
CheckCircle,
9+
Edit,
10+
Error,
11+
Highlight,
12+
Rule,
13+
} from '@edx/paragon/icons';
14+
15+
import { stepNames } from 'data/services/lms/constants';
16+
import { useProgressStepData } from './hooks';
17+
18+
export const stepIcons = StrictDict({
19+
[stepNames.submission]: Edit,
20+
[stepNames.studentTraining]: Highlight,
21+
[stepNames.self]: Highlight,
22+
[stepNames.peer]: Highlight,
23+
[stepNames.myGrades]: Rule,
24+
});
25+
26+
const ProgressStep = ({
27+
step,
28+
canRevisit,
29+
label,
30+
}) => {
31+
const {
32+
href,
33+
isActive,
34+
isEnabled,
35+
isComplete,
36+
isPastDue,
37+
myGrade,
38+
} = useProgressStepData({ step, canRevisit });
39+
let iconSrc = stepIcons[step];
40+
let subLabel = null;
41+
let colorClass = null;
42+
if (isPastDue) {
43+
colorClass = 'text-danger-500';
44+
iconSrc = Error;
45+
subLabel = 'Past due!';
46+
} else if (isComplete) {
47+
iconSrc = CheckCircle;
48+
if (step === stepNames.myGrades && myGrade) {
49+
subLabel = `${myGrade.earned} / ${myGrade.possible}`;
50+
}
51+
}
52+
return (
53+
<Nav.Link
54+
{...(!isActive && { href })}
55+
disabled={!isEnabled}
56+
className={classNames(
57+
'ora-progress-nav',
58+
'px-4',
59+
{ 'is-active': isActive },
60+
)}
61+
>
62+
<Icon className={classNames('nav-icon', colorClass)} src={iconSrc} />
63+
<div className="d-inline-block">
64+
{label}
65+
{subLabel && (
66+
<p className={classNames('x-small', colorClass)}>{subLabel}</p>
67+
)}
68+
</div>
69+
</Nav.Link>
70+
);
71+
};
72+
ProgressStep.propTypes = {
73+
label: PropTypes.node.isRequired,
74+
step: PropTypes.string.isRequired,
75+
canRevisit: PropTypes.bool.isRequired,
76+
};
77+
78+
export default ProgressStep;

src/components/ProgressBar/hooks.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useParams } from 'react-router-dom';
2+
import { useActiveView, useIsEmbedded } from 'hooks';
3+
import { useStepState, useEffectiveGrade } from 'data/services/lms/hooks/selectors';
4+
import {
5+
routeSteps,
6+
stepRoutes,
7+
stepStates,
8+
} from 'data/services/lms/constants';
9+
10+
export const useProgressStepData = ({ step, canRevisit = false }) => {
11+
const { xblockId } = useParams();
12+
const isEmbedded = useIsEmbedded();
13+
const activeView = useActiveView();
14+
const viewStep = routeSteps[activeView];
15+
const stepState = useStepState({ step });
16+
17+
const href = `/${stepRoutes[step]}${isEmbedded ? '/embedded' : ''}/${xblockId}`;
18+
const isActive = viewStep === step;
19+
const isEnabled = (
20+
isActive
21+
|| (stepState === stepStates.inProgress)
22+
|| (canRevisit && stepState === stepStates.completed)
23+
);
24+
const myGrade = useEffectiveGrade()?.stepScore;
25+
26+
return {
27+
href,
28+
isEnabled,
29+
isActive,
30+
isComplete: stepState === stepStates.completed,
31+
inProgress: stepState === stepStates.inProgress,
32+
isPastDue: stepState === stepStates.closed,
33+
myGrade,
34+
// myGrade: { earned: 8, possible: 10 },
35+
// isPastDue: step === 'self',
36+
37+
};
38+
};
39+
40+
export default { useProgressStepData };

src/components/ProgressBar/index.jsx

Lines changed: 36 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,64 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
3-
import { useLocation } from 'react-router-dom';
4-
import classNames from 'classnames';
52

63
import { useIntl } from '@edx/frontend-platform/i18n';
7-
import { Navbar, Nav, Icon } from '@edx/paragon';
8-
import { Locked, CheckCircle, Error } from '@edx/paragon/icons';
4+
import { Navbar } from '@edx/paragon';
95

106
import {
11-
useAssessmentStepConfig,
12-
useProgressData,
7+
useAssessmentStepOrder,
138
useIsPageDataLoaded,
149
} from 'data/services/lms/hooks/selectors';
10+
import { stepNames } from 'data/services/lms/constants';
11+
12+
import ProgressStep from './ProgressStep';
1513

1614
import messages from './messages';
1715
import './index.scss';
1816

19-
export const ProgressStep = ({
20-
children,
21-
href,
22-
isActive,
23-
isEnabled,
24-
isComplete,
25-
isError,
26-
number,
27-
}) => {
28-
let icon = <Icon className="nav-icon" src={Locked} />;
29-
if (isComplete) {
30-
icon = <Icon className="nav-icon" src={CheckCircle} />;
31-
} else if (isError) {
32-
icon = <Icon className="nav-icon text-danger-300" src={Error} />;
33-
} else if (number) {
34-
icon = <span className="nav-icon number-icon">{number}</span>;
35-
}
36-
return (
37-
<Nav.Link
38-
href={href}
39-
disabled={!isEnabled}
40-
className={classNames(
41-
'ora-progress-nav',
42-
'px-4',
43-
{ 'is-active': isActive },
44-
)}
45-
>
46-
{icon}
47-
{children}
48-
</Nav.Link>
49-
);
50-
};
51-
ProgressStep.defaultProps = {
52-
href: '#',
53-
isActive: false,
54-
isEnabled: false,
55-
isComplete: false,
56-
isError: false,
57-
number: null,
58-
};
59-
ProgressStep.propTypes = {
60-
children: PropTypes.node.isRequired,
61-
href: PropTypes.string,
62-
isActive: PropTypes.bool,
63-
isEnabled: PropTypes.bool,
64-
isError: PropTypes.bool,
65-
isComplete: PropTypes.bool,
66-
number: PropTypes.number,
17+
export const stepLabels = {
18+
[stepNames.submission]: messages.createSubmission,
19+
[stepNames.peer]: messages.peerAssess,
20+
[stepNames.studentTraining]: messages.studentTraining,
21+
[stepNames.self]: messages.selfAssess,
22+
[stepNames.myGrades]: messages.myGrade,
6723
};
6824

69-
export const SubmissionStep = () => {
70-
const { formatMessage } = useIntl();
71-
return (
72-
<ProgressStep>{formatMessage(messages.createSubmission)}</ProgressStep>
73-
);
25+
export const stepCanRevisit = {
26+
[stepNames.submission]: true,
27+
[stepNames.peer]: true,
28+
[stepNames.studentTraining]: false,
29+
[stepNames.self]: false,
30+
[stepNames.myGrades]: false,
7431
};
7532

76-
export const TrainingStep = () => {
77-
const { formatMessage } = useIntl();
78-
return (
79-
<ProgressStep>{formatMessage(messages.practice)}</ProgressStep>
80-
);
81-
};
82-
83-
export const SelfAssessStep = () => {
84-
const { formatMessage } = useIntl();
85-
return (
86-
<ProgressStep>{formatMessage(messages.selfAssess)}</ProgressStep>
87-
);
88-
};
89-
90-
export const PeerAssessStep = () => {
91-
const { formatMessage } = useIntl();
92-
return (
93-
<ProgressStep>{formatMessage(messages.peerAssess)}</ProgressStep>
94-
);
95-
};
33+
export const ProgressBar = () => {
34+
const isLoaded = useIsPageDataLoaded();
9635

97-
export const MyGradeStep = () => {
36+
const stepOrder = useAssessmentStepOrder();
9837
const { formatMessage } = useIntl();
99-
return (
100-
<ProgressStep>{formatMessage(messages.myGrade)}</ProgressStep>
101-
);
102-
};
10338

104-
export const ProgressBar = () => {
105-
const stepConfig = useAssessmentStepConfig();
106-
const progress = useProgressData();
107-
const isLoaded = useIsPageDataLoaded();
108-
const location = useLocation();
10939
if (!isLoaded) {
11040
return null;
11141
}
112-
console.log({
113-
stepConfig, progress, location,
114-
});
42+
43+
const stepEl = (step) => (
44+
stepLabels[step]
45+
? (
46+
<ProgressStep
47+
step={step}
48+
key={step}
49+
label={formatMessage(stepLabels[step])}
50+
canRevisit={stepCanRevisit[step]}
51+
/>
52+
) : null
53+
);
54+
11555
return (
11656
<Navbar>
11757
<Navbar.Collapse className="ora-progress-nav-group">
11858
<hr className="ora-progress-divider" />
119-
<SubmissionStep />
120-
{stepConfig.order.map(step => {
121-
if (step === 'peer') {
122-
return <PeerAssessStep key="peer" />;
123-
}
124-
if (step === 'training') {
125-
return <TrainingStep key="training" />;
126-
}
127-
if (step === 'self') {
128-
return <SelfAssessStep key="self" />;
129-
}
130-
return null;
131-
})}
132-
<MyGradeStep />
59+
{stepEl(stepNames.submission)}
60+
{stepOrder.map(stepEl)}
61+
{stepEl(stepNames.myGrades)}
13362
</Navbar.Collapse>
13463
</Navbar>
13564
);

src/components/ProgressBar/index.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@
2323
color: white;
2424
border-radius: 100%;
2525
}
26+
.active {
27+
border-bottom: 2px solid black;
28+
}
2629
}

src/components/ProgressBar/messages.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ const messages = defineMessages({
66
defaultMessage: 'Create your response',
77
description: 'Create response progress indicator',
88
},
9-
practice: {
10-
id: 'ora-grading.ProgressBar.practice',
9+
studentTraining: {
10+
id: 'ora-grading.ProgressBar.studentTraining',
1111
defaultMessage: 'Practice grading',
1212
description: 'Student training step progress indicator',
1313
},

src/components/StatefulStatus/index.jsx

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)