diff --git a/.eslintrc.js b/.eslintrc.js index 84be96047..b758dee97 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -7,9 +7,10 @@ const config = createConfig('eslint', { 'import/no-named-as-default-member': 'off', 'import/no-self-import': 'off', 'spaced-comment': ['error', 'always', { block: { exceptions: ['*'] } }], - 'react-hooks/rules-of-hooks': 'off', + 'react-hooks/rules-of-hooks': 2, 'react-hooks/exhaustive-deps': 'off', 'no-promise-executor-return': 'off', + 'no-param-reassign': ['error', { props: false }], radix: 'off', }, }); diff --git a/package-lock.json b/package-lock.json index 5732a2573..0869f78ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,8 +44,8 @@ "devDependencies": { "@edx/browserslist-config": "^1.1.1", "@edx/frontend-build": "12.8.27", - "@edx/frontend-platform": "^4.6.0", - "@edx/paragon": "^20.44.0", + "@edx/frontend-platform": "4.2.0", + "@edx/paragon": "^20.45.0", "@edx/reactifex": "^2.1.1", "@testing-library/dom": "^8.13.0", "@testing-library/jest-dom": "^5.16.5", @@ -2758,9 +2758,9 @@ } }, "node_modules/@edx/paragon": { - "version": "20.44.0", - "resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-20.44.0.tgz", - "integrity": "sha512-C1uC3RaRmlFANtHebFdZzVDM08vgFJRnHE3u97ix07e0ACSQDbVNoZ2H7JgBy8nqHz2JWGHPnvtpvPf5DAZsZQ==", + "version": "20.45.0", + "resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-20.45.0.tgz", + "integrity": "sha512-9lHcnSJ36sQ+bsYFhydf/Pvp3Bo5N3go8R3ORPTNtvYnwiKSfjlv11QpURC/xHobXsT2eYHiwl2gNmq1yP09BA==", "dev": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.1.1", diff --git a/package.json b/package.json index 75f29efde..a3c752018 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "devDependencies": { "@edx/browserslist-config": "^1.1.1", "@edx/frontend-build": "12.8.27", - "@edx/frontend-platform": "^4.6.0", - "@edx/paragon": "^20.44.0", + "@edx/frontend-platform": "4.2.0", + "@edx/paragon": "^20.45.0", "@edx/reactifex": "^2.1.1", "@testing-library/dom": "^8.13.0", "@testing-library/jest-dom": "^5.16.5", diff --git a/src/editors/containers/EditorContainer/__snapshots__/index.test.jsx.snap b/src/editors/containers/EditorContainer/__snapshots__/index.test.jsx.snap index 8991786da..3241cf9a6 100644 --- a/src/editors/containers/EditorContainer/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/EditorContainer/__snapshots__/index.test.jsx.snap @@ -9,14 +9,7 @@ exports[`EditorContainer component render snapshot: initialized. enable save and close={[MockFunction closeCancelConfirmModal]} confirmAction={ diff --git a/src/editors/containers/GameEditor/index.jsx b/src/editors/containers/GameEditor/index.jsx new file mode 100644 index 000000000..87a72f70d --- /dev/null +++ b/src/editors/containers/GameEditor/index.jsx @@ -0,0 +1,102 @@ +/* eslint-disable import/extensions */ +/* eslint-disable import/no-unresolved */ +/** + * This is an example component for an xblock Editor + * It uses pre-existing components to handle the saving of a the result of a function into the xblock's data. + * To use run npm run-script addXblock + */ + +/* eslint-disable no-unused-vars */ + +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; + +import { Spinner } from '@edx/paragon'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; + +import EditorContainer from '../EditorContainer'; +import * as module from '.'; +import { actions, selectors } from '../../data/redux'; +import { RequestKeys } from '../../data/constants/requests'; + +export const hooks = { + getContent: () => ({ + some: 'content', + }), +}; + +export const thumbEditor = ({ + onClose, + // redux + blockValue, + lmsEndpointUrl, + blockFailed, + blockFinished, + initializeEditor, + exampleValue, + // inject + intl, +}) => ( + +
+ {exampleValue} +
+
+ {!blockFinished + ? ( +
+ +
+ ) + : ( +

+ Your Editor Goes here. + You can get at the xblock data with the blockValue field. + here is what is in your xblock: {JSON.stringify(blockValue)} +

+ )} +
+
+); +thumbEditor.defaultProps = { + blockValue: null, + lmsEndpointUrl: null, +}; +thumbEditor.propTypes = { + onClose: PropTypes.func.isRequired, + // redux + blockValue: PropTypes.shape({ + data: PropTypes.shape({ data: PropTypes.string }), + }), + lmsEndpointUrl: PropTypes.string, + blockFailed: PropTypes.bool.isRequired, + blockFinished: PropTypes.bool.isRequired, + initializeEditor: PropTypes.func.isRequired, + // inject + intl: intlShape.isRequired, +}; + +export const mapStateToProps = (state) => ({ + blockValue: selectors.app.blockValue(state), + lmsEndpointUrl: selectors.app.lmsEndpointUrl(state), + blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }), + blockFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }), + // TODO fill with redux state here if needed + exampleValue: selectors.game.exampleValue(state), +}); + +export const mapDispatchToProps = { + initializeEditor: actions.app.initializeEditor, + // TODO fill with dispatches here if needed +}; + +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(thumbEditor)); diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx index 13407bfcd..475efac0d 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx @@ -18,7 +18,7 @@ jest.mock('@edx/frontend-platform/i18n', () => ({ getLocale: jest.fn(), })); -jest.mock('./AnswerOption', () => function () { +jest.mock('./AnswerOption', () => function mockAnswerOption() { return
MockAnswerOption
; }); diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswersContainer.test.jsx.snap b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswersContainer.test.jsx.snap index c2b7bbe64..118adc411 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswersContainer.test.jsx.snap +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswersContainer.test.jsx.snap @@ -4,7 +4,7 @@ exports[`AnswersContainer render snapshot: numeric problems: answer range/answer
- - - - - useState(val), }); diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/__snapshots__/index.test.jsx.snap b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/__snapshots__/index.test.jsx.snap index 76a7347a3..468b4b388 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/__snapshots__/index.test.jsx.snap @@ -23,12 +23,12 @@ exports[`SolutionWidget render snapshot: renders correct default 1`] = ` />
<[object Object] + editorContentHtml="This is my question" editorType="solution" id="solution" minHeight={150} placeholder="Enter your explanation" setEditorRef={[MockFunction prepareEditorRef.setEditorRef]} - textValue="This is my question" /> `; diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx index 2cd04cb95..0dccc5a95 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx @@ -28,7 +28,7 @@ export const ExplanationWidget = ({ id="solution" editorType="solution" editorRef={editorRef} - textValue={settings?.solutionExplanation} + editorContentHtml={settings?.solutionExplanation} setEditorRef={setEditorRef} minHeight={150} placeholder={intl.formatMessage(messages.placeholder)} diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/__snapshots__/index.test.jsx.snap b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/__snapshots__/index.test.jsx.snap index 6a0b69249..891bf8846 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/__snapshots__/index.test.jsx.snap @@ -14,12 +14,12 @@ exports[`QuestionWidget render snapshot: renders correct default 1`] = ` /> <[object Object] + editorContentHtml="This is my question" editorType="question" id="question" minHeight={150} placeholder="Enter your question" setEditorRef={[MockFunction prepareEditorRef.setEditorRef]} - textValue="This is my question" /> `; diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx index 0c95ad17a..df21809db 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx @@ -25,7 +25,7 @@ export const QuestionWidget = ({ id="question" editorType="question" editorRef={editorRef} - textValue={question} + editorContentHtml={question} setEditorRef={setEditorRef} minHeight={150} placeholder={intl.formatMessage(messages.placeholder)} diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js index 2b9c0220e..d8b058d9c 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js @@ -12,10 +12,15 @@ import { import { fetchEditorContent } from '../hooks'; export const state = { + // eslint-disable-next-line react-hooks/rules-of-hooks showAdvanced: (val) => useState(val), + // eslint-disable-next-line react-hooks/rules-of-hooks cardCollapsed: (val) => useState(val), + // eslint-disable-next-line react-hooks/rules-of-hooks summary: (val) => useState(val), + // eslint-disable-next-line react-hooks/rules-of-hooks showAttempts: (val) => useState(val), + // eslint-disable-next-line react-hooks/rules-of-hooks attemptDisplayValue: (val) => useState(val), }; @@ -44,6 +49,7 @@ export const showFullCard = (hasExpandableTextArea) => { export const hintsCardHooks = (hints, updateSettings) => { const [summary, setSummary] = module.state.summary({ message: messages.noHintSummary, values: {} }); + // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { const hintsNumber = hints.length; if (hintsNumber === 0) { diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js index 813d2b48f..cd4f8a77b 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js @@ -4,6 +4,7 @@ import messages from './messages'; import * as module from './hooks'; export const state = { + // eslint-disable-next-line react-hooks/rules-of-hooks summary: (val) => useState(val), }; @@ -12,6 +13,7 @@ export const generalFeedbackHooks = (generalFeedback, updateSettings) => { message: messages.noGeneralFeedbackSummary, values: {}, intl: true, }); + // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { if (_.isEmpty(generalFeedback)) { setSummary({ message: messages.noGeneralFeedbackSummary, values: {}, intl: true }); diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js index 3824e53fd..71956ee54 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js @@ -4,12 +4,14 @@ import messages from './messages'; import * as module from './hooks'; export const state = { + // eslint-disable-next-line react-hooks/rules-of-hooks summary: (val) => useState(val), }; export const groupFeedbackCardHooks = (groupFeedbacks, updateSettings, answerslist) => { const [summary, setSummary] = module.state.summary({ message: messages.noGroupFeedbackSummary, values: {} }); + // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { if (groupFeedbacks.length === 0) { setSummary({ message: messages.noGroupFeedbackSummary, values: {} }); diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js index e95fc3246..28c5e8fef 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js @@ -3,6 +3,7 @@ import { RandomizationTypes, RandomizationTypesKeys } from '../../../../../../.. import * as module from './hooks'; export const state = { + // eslint-disable-next-line react-hooks/rules-of-hooks summary: (val) => useState(val), }; diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx index 8dced80cb..7aab4a8cb 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx @@ -16,7 +16,7 @@ jest.mock('@edx/frontend-platform/i18n', () => ({ })); // eslint-disable-next-line react/prop-types -jest.mock('../../SettingsOption', () => function ({ children, summary }) { +jest.mock('../../SettingsOption', () => function mockSettingsOption({ children, summary }) { return
{summary}{children}
; }); diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js index ab6d113ec..5b338f127 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js @@ -7,6 +7,7 @@ import { setAssetToStaticUrl } from '../../../../sharedComponents/TinyMceWidget/ import { ProblemTypeKeys } from '../../../../data/constants/problem'; export const state = StrictDict({ + // eslint-disable-next-line react-hooks/rules-of-hooks isSaveWarningModalOpen: (val) => useState(val), }); @@ -123,7 +124,7 @@ export const checkForSettingDiscrepancy = ({ problem, ref, openSaveWarningModal const problemSettings = reactSettingsParser.getSettings(); const rawOlxSettings = reactSettingsParser.parseRawOlxSettings(); let isMismatched = false; - // console.log(rawOlxSettings); + Object.entries(rawOlxSettings).forEach(([key, value]) => { if (value !== problemSettings[key]) { isMismatched = true; diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js index f6cf10143..e28e3d306 100644 --- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js +++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js @@ -7,6 +7,7 @@ import * as module from './hooks'; import { getDataFromOlx } from '../../../../data/redux/thunkActions/problem'; export const state = StrictDict({ + // eslint-disable-next-line react-hooks/rules-of-hooks selected: (val) => useState(val), }); diff --git a/src/editors/containers/ProblemEditor/data/OLXParser.js b/src/editors/containers/ProblemEditor/data/OLXParser.js index 8c44dc28b..4e10ccc03 100644 --- a/src/editors/containers/ProblemEditor/data/OLXParser.js +++ b/src/editors/containers/ProblemEditor/data/OLXParser.js @@ -28,18 +28,6 @@ export const nonQuestionKeys = [ 'textline', ]; -export const richTextFormats = [ - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'div', - 'p', - 'pre', -]; - export const responseKeys = [ 'multiplechoiceresponse', 'numericalresponse', @@ -480,12 +468,13 @@ export class OLXParser { } questionArray.push(tag); } else if (responseKeys.includes(tagName)) { - /*