Skip to content

Commit 2e26524

Browse files
author
Ben Warzeski
authored
feat: global data state
feat: global data state
2 parents 2b35d47 + 3973cf2 commit 2e26524

Some content is hidden

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

59 files changed

+2029
-2022
lines changed

package-lock.json

Lines changed: 715 additions & 1694 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
"url": "https://github.com/edx/frontend-app-ora/issues"
3535
},
3636
"dependencies": {
37-
"@edx/brand": "npm:@edx/brand-openedx@1.2.0",
37+
"@edx/brand": "npm:@edx/brand-edx.org@2.1.2",
3838
"@edx/frontend-component-footer": "12.4.0",
3939
"@edx/frontend-component-header": "4.7.1",
40-
"@edx/frontend-platform": "5.6.0",
41-
"@edx/paragon": "^20.20.0",
40+
"@edx/frontend-platform": "5.6.1",
41+
"@edx/paragon": "^21.5.3",
4242
"@edx/react-unit-test-utils": "1.7.0",
4343
"@edx/tinymce-language-selector": "1.1.0",
4444
"@fortawesome/fontawesome-svg-core": "1.2.36",
@@ -54,6 +54,7 @@
5454
"core-js": "3.32.2",
5555
"filesize": "^8.0.6",
5656
"jest-when": "^3.6.0",
57+
"moment": "^2.29.4",
5758
"pdfjs-dist": "^3.11.174",
5859
"prop-types": "15.8.1",
5960
"query-string": "^8.1.0",

src/App.jsx

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,21 @@ const RouterRoot = () => {
2424
<Route
2525
path={route}
2626
element={(
27-
<PageDataProvider>
28-
<AppContainer Component={Component} />
29-
</PageDataProvider>
27+
<AppContainer>
28+
<Component />
29+
</AppContainer>
3030
)}
3131
/>
3232
);
3333
const modalRoute = (route, Component, title) => (
3434
<Route
3535
path={route}
3636
element={(
37-
<PageDataProvider>
38-
<ModalContainer {...{ title, Component }} />
39-
</PageDataProvider>
37+
<AppContainer>
38+
<ModalContainer title={title}>
39+
<Component />
40+
</ModalContainer>
41+
</AppContainer>
4042
)}
4143
/>
4244
);
@@ -50,29 +52,14 @@ const RouterRoot = () => {
5052
<Route path={routes.rootEmbed} element={<ErrorPage message={formatMessage(messages.error404Message)} />} />,
5153
];
5254
const baseRoutes = [
53-
appRoute(routes.xblock, PeerAssessmentView),
54-
appRoute(routes.peerAssessment, PeerAssessmentView),
55-
appRoute(routes.selfAssessment, SelfAssessmentView),
56-
appRoute(routes.studentTraining, StudentTrainingView),
57-
appRoute(routes.submission, SubmissionView),
55+
appRoute(routes.xblock, XBlockView),
56+
modalRoute(routes.peerAssessment, PeerAssessmentView, 'Assess your peers'),
57+
modalRoute(routes.selfAssessment, SelfAssessmentView, 'Assess yourself'),
58+
modalRoute(routes.studentTraining, StudentTrainingView, 'Practice grading'),
59+
modalRoute(routes.submission, SubmissionView, 'Your response'),
5860
<Route path={routes.root} element={<ErrorPage message={formatMessage(messages.error404Message)} />} />,
5961
];
6062

61-
const isConfigLoaded = useIsORAConfigLoaded();
62-
63-
if (!isConfigLoaded) {
64-
return (
65-
<div className="h-screen d-flex justify-content-center align-items-center">
66-
<Spinner
67-
animation="border"
68-
variant="primary"
69-
className="mr-3 spinner-md"
70-
screenReaderText="loading"
71-
/>
72-
</div>
73-
);
74-
}
75-
7663
return (
7764
<Routes>
7865
{embeddedRoutes}

src/components/AppContainer.jsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33

4+
import ProgressBar from 'components/ProgressBar';
5+
6+
import { useIsPageDataLoaded, useIsORAConfigLoaded } from 'data/services/lms/hooks/selectors';
7+
48
/* The purpose of this component is to wrap views with a header/footer for situations
59
* where we need to run non-embedded
610
*/
711

8-
const AppContainer = ({ Component }) => (
9-
<div className="bg-light-300">
10-
<Component />
11-
</div>
12-
);
12+
const AppContainer = ({ children }) => {
13+
const isConfigLoaded = useIsORAConfigLoaded();
14+
const isPageDataLoaded = useIsPageDataLoaded();
15+
if (!isConfigLoaded || !isPageDataLoaded) {
16+
return null;
17+
}
18+
return (
19+
<div style={{ width: '100%' }}>
20+
{children}
21+
</div>
22+
);
23+
};
1324
AppContainer.propTypes = {
14-
Component: PropTypes.elementType.isRequired,
25+
children: PropTypes.node.isRequired,
1526
};
1627

1728
export default AppContainer;

src/components/Assessment/EditableAssessment/hooks.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,6 @@ const useEditableAssessmentData = () => {
2525
submitRubricMutation.mutate(currentValue);
2626
};
2727

28-
console.log({
29-
criteria,
30-
formFields,
31-
onSubmit,
32-
});
33-
3428
return {
3529
criteria,
3630
formFields,

src/components/BaseAssessmentView/index.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const BaseAssessmentView = ({
2222
getValues,
2323
}) => (
2424
<AssessmentContextProvider>
25-
<ProgressBar />
2625
<div className="assessment-content-layout mr-auto ml-auto">
2726
<div className="content-wrapper">
2827
<Row className="flex-nowrap m-0">

src/components/FileUpload/UploadConfirmModal.jsx

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
44
import {
55
Form, FormLabel, ModalDialog, Button, ActionRow,
66
} from '@edx/paragon';
7-
import { useIntl } from '@edx/frontend-platform/i18n';
7+
import { useIntl, IntlProvider } from '@edx/frontend-platform/i18n';
88
import messages from './messages';
99
import { useUploadConfirmModalHooks } from './hooks';
1010

@@ -39,28 +39,30 @@ const UploadConfirmModal = ({
3939
</ModalDialog.Header>
4040

4141
<ModalDialog.Body>
42-
<div>
43-
{file && (
44-
<Form.Group>
45-
<FormLabel>
46-
<strong>
47-
{formatMessage(messages.uploadFileDescriptionFieldLabel)}
48-
</strong>
49-
<span className="file-name-ellipsis">{file.name}</span>
50-
</FormLabel>
51-
<Form.Control
52-
isInvalid={shouldShowError}
53-
name="file-description"
54-
onChange={onFileDescriptionChange}
55-
/>
56-
{shouldShowError && (
57-
<Form.Control.Feedback type="invalid">
58-
formatMessage(messages.fileDescriptionMissingError)
59-
</Form.Control.Feedback>
60-
)}
61-
</Form.Group>
62-
)}
63-
</div>
42+
<IntlProvider>
43+
<div>
44+
{file && (
45+
<Form.Group>
46+
<FormLabel>
47+
<strong>
48+
{formatMessage(messages.uploadFileDescriptionFieldLabel)}
49+
</strong>
50+
<span className="file-name-ellipsis">{file.name}</span>
51+
</FormLabel>
52+
<Form.Control
53+
isInvalid={shouldShowError}
54+
name="file-description"
55+
onChange={onFileDescriptionChange}
56+
/>
57+
{shouldShowError && (
58+
<Form.Control.Feedback type="invalid">
59+
formatMessage(messages.fileDescriptionMissingError)
60+
</Form.Control.Feedback>
61+
)}
62+
</Form.Group>
63+
)}
64+
</div>
65+
</IntlProvider>
6466
</ModalDialog.Body>
6567
<ModalDialog.Footer>
6668
<ActionRow>

src/components/FileUpload/index.jsx

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ const FileUpload = ({
3535
} = useFileUploadHooks({
3636
onFileUploaded,
3737
});
38-
3938
return (
4039
<div>
4140
<h3>File Upload</h3>
@@ -46,8 +45,7 @@ const FileUpload = ({
4645
itemCount={uploadedFiles.length}
4746
data={uploadedFiles.map((file) => ({
4847
...file,
49-
size:
50-
typeof file.size === 'number' ? filesize(file.size) : 'Unknown',
48+
size: typeof file.size === 'number' ? filesize(file.size) : 'Unknown',
5149
}))}
5250
columns={[
5351
{
@@ -72,19 +70,15 @@ const FileUpload = ({
7270
</>
7371
)}
7472
{!isReadOnly && (
75-
<>
76-
<Dropzone
77-
multiple
78-
onProcessUpload={onProcessUpload}
79-
progressVariant="bar"
80-
/>
81-
<UploadConfirmModal
82-
open={isModalOpen}
83-
file={uploadArgs.fileData?.getAll('file')[0]}
84-
closeHandler={closeUploadModal}
85-
uploadHandler={confirmUpload}
86-
/>
87-
</>
73+
<Dropzone multiple onProcessUpload={onProcessUpload} progressVariant="bar" />
74+
)}
75+
{!isReadOnly && isModalOpen && (
76+
<UploadConfirmModal
77+
open={isModalOpen}
78+
file={uploadArgs.fileData?.getAll('file')[0]}
79+
closeHandler={closeUploadModal}
80+
uploadHandler={confirmUpload}
81+
/>
8882
)}
8983
</div>
9084
);

src/components/Instructions/index.jsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import { stepStates } from 'data/services/lms/constants';
5+
import { useStepState } from 'data/services/lms/hooks/selectors';
6+
7+
import useInstructionsMessage from './useInstructionsMessage';
8+
9+
const Instructions = ({ step }) => {
10+
const message = useInstructionsMessage(step);
11+
const stepState = useStepState({ step });
12+
if (stepState !== stepStates.inProgress) {
13+
return null;
14+
}
15+
return (
16+
<div>
17+
<h2>Instructions</h2>
18+
{message}
19+
</div>
20+
);
21+
};
22+
Instructions.defaultProps = {
23+
step: null,
24+
};
25+
Instructions.propTypes = {
26+
step: PropTypes.string,
27+
};
28+
export default Instructions;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { defineMessages } from '@edx/frontend-platform/i18n';
2+
3+
import { stepNames } from 'data/services/lms/constants';
4+
5+
const messages = defineMessages({
6+
[stepNames.submission]: {
7+
defaultMessage: 'Submittion Instructions: TODO',
8+
description: 'Submission step instructions',
9+
id: 'frontend-app-ora.instructions.submisison',
10+
},
11+
[stepNames.studentTraining]: {
12+
defaultMessage: 'Student Training Instructions: TODO',
13+
description: 'StudentTraining step instructions',
14+
id: 'frontend-app-ora.instructions.studentTraining',
15+
},
16+
[stepNames.self]: {
17+
defaultMessage: 'Self Assessment Instructions: TODO',
18+
description: 'Self Assessment step instructions',
19+
id: 'frontend-app-ora.instructions.selfAssessment',
20+
},
21+
[stepNames.peer]: {
22+
defaultMessage: 'Peer Assessment Instructions: TODO',
23+
description: 'Peer Assessment step instructions',
24+
id: 'frontend-app-ora.instructions.peerAssessment',
25+
},
26+
[stepNames.done]: {
27+
defaultMessage: 'You have successfully completed this problem and received a {earned}/{possible}.',
28+
description: 'Graded step instructions',
29+
id: 'frontend-app-ora.instructions.done',
30+
},
31+
});
32+
33+
export default messages;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useIntl } from '@edx/frontend-platform/i18n';
2+
3+
import { useGlobalState } from 'data/services/lms/hooks/selectors';
4+
import { stepNames, stepStates } from 'data/services/lms/constants';
5+
6+
import messages from './messages';
7+
8+
const useInstructionsMessage = (step = null) => {
9+
const { formatMessage } = useIntl();
10+
const {
11+
activeStepName,
12+
effectiveGrade,
13+
stepState,
14+
} = useGlobalState();
15+
if (step || stepState !== stepStates.inProgress) {
16+
return null;
17+
}
18+
const stepName = step || activeStepName;
19+
if (stepName === stepNames.done) {
20+
return formatMessage(messages[stepNames.done], effectiveGrade);
21+
}
22+
return formatMessage(messages[activeStepName]);
23+
};
24+
25+
export default useInstructionsMessage;

src/components/ModalContainer.jsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,26 @@ import React from 'react';
22
import PropTypes from 'prop-types';
33
import { FullscreenModal } from '@edx/paragon';
44

5+
import ProgressBar from 'components/ProgressBar';
6+
57
/* The purpose of this component is to wrap views with a header/footer for situations
68
* where we need to run non-embedded
79
*/
810

9-
const ModalContainer = ({ Component, title }) => (
11+
const ModalContainer = ({ title, children }) => (
1012
<FullscreenModal
1113
isOpen
1214
onClose={null}
1315
hasCloseButton={false}
1416
title={title}
15-
modalBodyClassName="content-body"
17+
modalBodyClassName="content-body bg-light-300"
18+
beforeBodyNode={<ProgressBar className="px-2" />}
1619
>
17-
<Component />
20+
{children}
1821
</FullscreenModal>
1922
);
2023
ModalContainer.propTypes = {
21-
Component: PropTypes.elementType.isRequired,
24+
children: PropTypes.node.isRequired,
2225
title: PropTypes.string.isRequired,
2326
};
2427

0 commit comments

Comments
 (0)