Skip to content
This repository was archived by the owner on Feb 14, 2025. It is now read-only.

Commit ed7e98b

Browse files
author
mashal-m
committed
Merge branch 'main' of https://github.com/openedx/frontend-lib-content-components into mashal-m/react-upgrade-to-v17
2 parents 505704e + a935d29 commit ed7e98b

File tree

99 files changed

+2466
-782
lines changed

Some content is hidden

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

99 files changed

+2466
-782
lines changed

.eslintrc.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ const config = createConfig('eslint', {
77
'import/no-named-as-default-member': 'off',
88
'import/no-self-import': 'off',
99
'spaced-comment': ['error', 'always', { block: { exceptions: ['*'] } }],
10-
'react-hooks/rules-of-hooks': 'off',
10+
'react-hooks/rules-of-hooks': 2,
1111
'react-hooks/exhaustive-deps': 'off',
1212
'no-promise-executor-return': 'off',
13+
'no-param-reassign': ['error', { props: false }],
1314
radix: 'off',
1415
},
1516
});

package-lock.json

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
"devDependencies": {
4040
"@edx/browserslist-config": "^1.1.1",
4141
"@edx/frontend-build": "12.8.27",
42-
"@edx/frontend-platform": "^4.6.0",
43-
"@edx/paragon": "^20.44.0",
42+
"@edx/frontend-platform": "4.2.0",
43+
"@edx/paragon": "^20.45.0",
4444
"@edx/reactifex": "^2.1.1",
4545
"@testing-library/dom": "^8.13.0",
4646
"@testing-library/jest-dom": "^5.16.5",

src/editors/containers/EditorContainer/__snapshots__/index.test.jsx.snap

+2-16
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,7 @@ exports[`EditorContainer component render snapshot: initialized. enable save and
99
close={[MockFunction closeCancelConfirmModal]}
1010
confirmAction={
1111
<Button
12-
onClick={
13-
Object {
14-
"handleCancel": Object {
15-
"onClose": [MockFunction props.onClose],
16-
"returnFunction": [MockFunction props.returnFunction],
17-
},
18-
}
19-
}
12+
onClick={[Function]}
2013
variant="primary"
2114
>
2215
<FormattedMessage
@@ -92,14 +85,7 @@ exports[`EditorContainer component render snapshot: not initialized. disable sav
9285
close={[MockFunction closeCancelConfirmModal]}
9386
confirmAction={
9487
<Button
95-
onClick={
96-
Object {
97-
"handleCancel": Object {
98-
"onClose": [MockFunction props.onClose],
99-
"returnFunction": [MockFunction props.returnFunction],
100-
},
101-
}
102-
}
88+
onClick={[Function]}
10389
variant="primary"
10490
>
10591
<FormattedMessage

src/editors/containers/EditorContainer/components/TitleHeader/hooks.js

+3
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import * as module from './hooks';
88
export const { navigateCallback } = textEditorHooks;
99

1010
export const state = {
11+
// eslint-disable-next-line react-hooks/rules-of-hooks
1112
localTitle: (args) => React.useState(args),
1213
};
1314

1415
export const hooks = {
1516
isEditing: () => {
17+
// eslint-disable-next-line react-hooks/rules-of-hooks
1618
const [isEditing, setIsEditing] = React.useState(false);
1719
return {
1820
isEditing,
@@ -22,6 +24,7 @@ export const hooks = {
2224
},
2325

2426
localTitle: ({ dispatch, stopEditing }) => {
27+
// eslint-disable-next-line react-hooks/rules-of-hooks
2528
const title = useSelector(selectors.app.displayTitle);
2629
const [localTitle, setLocalTitle] = module.state.localTitle(title);
2730
return {

src/editors/containers/EditorContainer/components/TitleHeader/index.jsx

+2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ export const TitleHeader = ({
1717
intl,
1818
}) => {
1919
if (!isInitialized) { return intl.formatMessage(messages.loading); }
20+
// eslint-disable-next-line react-hooks/rules-of-hooks
2021
const dispatch = useDispatch();
22+
// eslint-disable-next-line react-hooks/rules-of-hooks
2123
const title = useSelector(selectors.app.displayTitle);
2224

2325
const {

src/editors/containers/EditorContainer/hooks.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const {
1616
} = appHooks;
1717

1818
export const state = StrictDict({
19+
// eslint-disable-next-line react-hooks/rules-of-hooks
1920
isCancelConfirmModalOpen: (val) => useState(val),
2021
});
2122

@@ -25,7 +26,9 @@ export const handleSaveClicked = ({
2526
validateEntry,
2627
returnFunction,
2728
}) => {
28-
const destination = useSelector(selectors.app.returnUrl);
29+
// eslint-disable-next-line react-hooks/rules-of-hooks
30+
const destination = returnFunction ? '' : useSelector(selectors.app.returnUrl);
31+
// eslint-disable-next-line react-hooks/rules-of-hooks
2932
const analytics = useSelector(selectors.app.analytics);
3033

3134
return () => saveBlock({
@@ -53,14 +56,18 @@ export const handleCancel = ({ onClose, returnFunction }) => {
5356
}
5457
return navigateCallback({
5558
returnFunction,
56-
destination: useSelector(selectors.app.returnUrl),
59+
// eslint-disable-next-line react-hooks/rules-of-hooks
60+
destination: returnFunction ? '' : useSelector(selectors.app.returnUrl),
5761
analyticsEvent: analyticsEvt.editorCancelClick,
62+
// eslint-disable-next-line react-hooks/rules-of-hooks
5863
analytics: useSelector(selectors.app.analytics),
5964
});
6065
};
6166

67+
// eslint-disable-next-line react-hooks/rules-of-hooks
6268
export const isInitialized = () => useSelector(selectors.app.isInitialized);
6369

70+
// eslint-disable-next-line react-hooks/rules-of-hooks
6471
export const saveFailed = () => useSelector((rootState) => (
6572
selectors.requests.isFailed(rootState, { requestKey: RequestKeys.saveBlock })
6673
));

src/editors/containers/EditorContainer/index.jsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ export const EditorContainer = ({
3636
confirmAction={(
3737
<Button
3838
variant="primary"
39-
onClick={handleCancel}
39+
onClick={() => {
40+
handleCancel();
41+
if (returnFunction) {
42+
closeCancelConfirmModal();
43+
}
44+
}}
4045
>
4146
<FormattedMessage {...messages.okButtonLabel} />
4247
</Button>
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* eslint-disable import/extensions */
2+
/* eslint-disable import/no-unresolved */
3+
/**
4+
* This is an example component for an xblock Editor
5+
* It uses pre-existing components to handle the saving of a the result of a function into the xblock's data.
6+
* To use run npm run-script addXblock <your>
7+
*/
8+
9+
/* eslint-disable no-unused-vars */
10+
11+
import React from 'react';
12+
import { connect } from 'react-redux';
13+
import PropTypes from 'prop-types';
14+
15+
import { Spinner } from '@edx/paragon';
16+
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
17+
18+
import EditorContainer from '../EditorContainer';
19+
import * as module from '.';
20+
import { actions, selectors } from '../../data/redux';
21+
import { RequestKeys } from '../../data/constants/requests';
22+
23+
export const hooks = {
24+
getContent: () => ({
25+
some: 'content',
26+
}),
27+
};
28+
29+
export const thumbEditor = ({
30+
onClose,
31+
// redux
32+
blockValue,
33+
lmsEndpointUrl,
34+
blockFailed,
35+
blockFinished,
36+
initializeEditor,
37+
exampleValue,
38+
// inject
39+
intl,
40+
}) => (
41+
<EditorContainer
42+
getContent={module.hooks.getContent}
43+
onClose={onClose}
44+
>
45+
<div>
46+
{exampleValue}
47+
</div>
48+
<div className="editor-body h-75 overflow-auto">
49+
{!blockFinished
50+
? (
51+
<div className="text-center p-6">
52+
<Spinner
53+
animation="border"
54+
className="m-3"
55+
// Use a messages.js file for intl messages.
56+
screenreadertext={intl.formatMessage('Loading Spinner')}
57+
/>
58+
</div>
59+
)
60+
: (
61+
<p>
62+
Your Editor Goes here.
63+
You can get at the xblock data with the blockValue field.
64+
here is what is in your xblock: {JSON.stringify(blockValue)}
65+
</p>
66+
)}
67+
</div>
68+
</EditorContainer>
69+
);
70+
thumbEditor.defaultProps = {
71+
blockValue: null,
72+
lmsEndpointUrl: null,
73+
};
74+
thumbEditor.propTypes = {
75+
onClose: PropTypes.func.isRequired,
76+
// redux
77+
blockValue: PropTypes.shape({
78+
data: PropTypes.shape({ data: PropTypes.string }),
79+
}),
80+
lmsEndpointUrl: PropTypes.string,
81+
blockFailed: PropTypes.bool.isRequired,
82+
blockFinished: PropTypes.bool.isRequired,
83+
initializeEditor: PropTypes.func.isRequired,
84+
// inject
85+
intl: intlShape.isRequired,
86+
};
87+
88+
export const mapStateToProps = (state) => ({
89+
blockValue: selectors.app.blockValue(state),
90+
lmsEndpointUrl: selectors.app.lmsEndpointUrl(state),
91+
blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }),
92+
blockFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }),
93+
// TODO fill with redux state here if needed
94+
exampleValue: selectors.game.exampleValue(state),
95+
});
96+
97+
export const mapDispatchToProps = {
98+
initializeEditor: actions.app.initializeEditor,
99+
// TODO fill with dispatches here if needed
100+
};
101+
102+
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(thumbEditor));

src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jest.mock('@edx/frontend-platform/i18n', () => ({
1818
getLocale: jest.fn(),
1919
}));
2020

21-
jest.mock('./AnswerOption', () => function () {
21+
jest.mock('./AnswerOption', () => function mockAnswerOption() {
2222
return <div>MockAnswerOption</div>;
2323
});
2424

src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswersContainer.test.jsx.snap

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ exports[`AnswersContainer render snapshot: numeric problems: answer range/answer
44
<div
55
className="answers-container border border-light-700 rounded py-4 pl-4 pr-3"
66
>
7-
<Component
7+
<mockAnswerOption
88
answer={
99
Object {
1010
"correct": true,
@@ -108,7 +108,7 @@ exports[`AnswersContainer render snapshot: numeric problems: answer range/answer
108108
<div
109109
className="answers-container border border-light-700 rounded py-4 pl-4 pr-3"
110110
>
111-
<Component
111+
<mockAnswerOption
112112
answer={
113113
Object {
114114
"correct": true,
@@ -122,7 +122,7 @@ exports[`AnswersContainer render snapshot: numeric problems: answer range/answer
122122
hasSingleAnswer={false}
123123
key="A"
124124
/>
125-
<Component
125+
<mockAnswerOption
126126
answer={
127127
Object {
128128
"correct": true,
@@ -200,7 +200,7 @@ exports[`AnswersContainer render snapshot: renders correctly with answers 1`] =
200200
<div
201201
className="answers-container border border-light-700 rounded py-4 pl-4 pr-3"
202202
>
203-
<Component
203+
<mockAnswerOption
204204
answer={
205205
Object {
206206
"correct": true,
@@ -211,7 +211,7 @@ exports[`AnswersContainer render snapshot: renders correctly with answers 1`] =
211211
hasSingleAnswer={false}
212212
key="a"
213213
/>
214-
<Component
214+
<mockAnswerOption
215215
answer={
216216
Object {
217217
"correct": true,

src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ProblemTypeKeys } from '../../../../../data/constants/problem';
66
import { fetchEditorContent } from '../hooks';
77

88
export const state = StrictDict({
9+
// eslint-disable-next-line react-hooks/rules-of-hooks
910
isFeedbackVisible: (val) => useState(val),
1011
});
1112

src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/__snapshots__/index.test.jsx.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ exports[`SolutionWidget render snapshot: renders correct default 1`] = `
2323
/>
2424
</div>
2525
<[object Object]
26+
editorContentHtml="This is my question"
2627
editorType="solution"
2728
id="solution"
2829
minHeight={150}
2930
placeholder="Enter your explanation"
3031
setEditorRef={[MockFunction prepareEditorRef.setEditorRef]}
31-
textValue="This is my question"
3232
/>
3333
</div>
3434
`;

src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const ExplanationWidget = ({
2828
id="solution"
2929
editorType="solution"
3030
editorRef={editorRef}
31-
textValue={settings?.solutionExplanation}
31+
editorContentHtml={settings?.solutionExplanation}
3232
setEditorRef={setEditorRef}
3333
minHeight={150}
3434
placeholder={intl.formatMessage(messages.placeholder)}

src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/__snapshots__/index.test.jsx.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ exports[`QuestionWidget render snapshot: renders correct default 1`] = `
1414
/>
1515
</div>
1616
<[object Object]
17+
editorContentHtml="This is my question"
1718
editorType="question"
1819
id="question"
1920
minHeight={150}
2021
placeholder="Enter your question"
2122
setEditorRef={[MockFunction prepareEditorRef.setEditorRef]}
22-
textValue="This is my question"
2323
/>
2424
</div>
2525
`;

src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const QuestionWidget = ({
2525
id="question"
2626
editorType="question"
2727
editorRef={editorRef}
28-
textValue={question}
28+
editorContentHtml={question}
2929
setEditorRef={setEditorRef}
3030
minHeight={150}
3131
placeholder={intl.formatMessage(messages.placeholder)}

src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js

+6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ import {
1212
import { fetchEditorContent } from '../hooks';
1313

1414
export const state = {
15+
// eslint-disable-next-line react-hooks/rules-of-hooks
1516
showAdvanced: (val) => useState(val),
17+
// eslint-disable-next-line react-hooks/rules-of-hooks
1618
cardCollapsed: (val) => useState(val),
19+
// eslint-disable-next-line react-hooks/rules-of-hooks
1720
summary: (val) => useState(val),
21+
// eslint-disable-next-line react-hooks/rules-of-hooks
1822
showAttempts: (val) => useState(val),
23+
// eslint-disable-next-line react-hooks/rules-of-hooks
1924
attemptDisplayValue: (val) => useState(val),
2025
};
2126

@@ -44,6 +49,7 @@ export const showFullCard = (hasExpandableTextArea) => {
4449
export const hintsCardHooks = (hints, updateSettings) => {
4550
const [summary, setSummary] = module.state.summary({ message: messages.noHintSummary, values: {} });
4651

52+
// eslint-disable-next-line react-hooks/rules-of-hooks
4753
useEffect(() => {
4854
const hintsNumber = hints.length;
4955
if (hintsNumber === 0) {

0 commit comments

Comments
 (0)