Feat add templates for default problems after problem select (#185)

https://2u-internal.atlassian.net/browse/TNL-10316 is the relevant bug.

Problems have default values when created using the select type page.
This commit is contained in:
connorhaugh
2023-01-11 14:26:46 -05:00
committed by GitHub
parent 2c6679fe06
commit cf1daa3ba5
21 changed files with 132 additions and 40 deletions

View File

@@ -17,7 +17,6 @@ export const SelectTypeFooter = ({
onCancel,
selected,
// redux
setProblemType,
updateField,
// injected,
intl,
@@ -35,7 +34,7 @@ export const SelectTypeFooter = ({
</Button>
<Button
aria-label={intl.formatMessage(messages.selectButtonAriaLabel)}
onClick={hooks.onSelect(setProblemType, selected, updateField)}
onClick={hooks.onSelect(selected, updateField)}
disabled={!selected}
>
<FormattedMessage {...messages.selectButtonLabel} />
@@ -52,7 +51,6 @@ SelectTypeFooter.defaultProps = {
SelectTypeFooter.propTypes = {
onCancel: PropTypes.func.isRequired,
selected: PropTypes.string,
setProblemType: PropTypes.func.isRequired,
updateField: PropTypes.func.isRequired,
// injected
intl: intlShape.isRequired,
@@ -62,7 +60,6 @@ export const mapStateToProps = () => ({
});
export const mapDispatchToProps = {
setProblemType: actions.problem.setProblemType,
updateField: actions.problem.updateField,
};

View File

@@ -16,7 +16,7 @@ describe('SelectTypeFooter', () => {
onCancel: jest.fn().mockName('onCancel'),
selected: null,
// redux
setProblemType: jest.fn().mockName('setProblemType'),
updateField: jest.fn().mockName('UpdateField'),
// inject
intl: { formatMessage },
};
@@ -36,7 +36,7 @@ describe('SelectTypeFooter', () => {
.toEqual(expected);
});
test('select behavior is linked to modal onSelect', () => {
const expected = hooks.onSelect(props.setProblemType, props.selected);
const expected = hooks.onSelect(props.selected, props.updateField);
expect(el.find(Button).last().props().onClick)
.toEqual(expected);
});
@@ -48,8 +48,8 @@ describe('SelectTypeFooter', () => {
});
});
describe('mapDispatchToProps', () => {
test('loads setProblemType from problem.setProblemType actions', () => {
expect(module.mapDispatchToProps.setProblemType).toEqual(actions.problem.setProblemType);
test('loads updateField from problem.updateField actions', () => {
expect(module.mapDispatchToProps.updateField).toEqual(actions.problem.updateField);
});
});
});

View File

@@ -4,6 +4,7 @@ import {
} from '../../../../data/constants/problem';
import { StrictDict } from '../../../../utils';
import * as module from './hooks';
import { getDataFromOlx } from '../../../../data/redux/thunkActions/problem';
export const state = StrictDict({
selected: (val) => useState(val),
@@ -17,12 +18,14 @@ export const selectHooks = () => {
};
};
export const onSelect = (setProblemType, selected, updateField) => () => {
export const onSelect = (selected, updateField) => () => {
if (Object.values(AdvanceProblemKeys).includes(selected)) {
updateField({ problemType: ProblemTypeKeys.ADVANCED, rawOLX: AdvanceProblems[selected].template });
return;
updateField({ problemType: ProblemTypeKeys.ADVANCED, rawOLX: AdvanceProblems[selected] });
} else {
const newOLX = ProblemTypes[selected].template;
const { settings, ...newState } = getDataFromOlx({ rawOLX: newOLX, rawSettings: {} });
updateField({ ...newState });
}
setProblemType({ selected });
};
export const useArrowNav = (selected, setSelected) => {

View File

@@ -2,7 +2,8 @@
import React from 'react';
import { MockUseState } from '../../../../../testUtils';
import * as module from './hooks';
import { AdvanceProblems, ProblemTypeKeys } from '../../../../data/constants/problem';
import { AdvanceProblems, ProblemTypeKeys, ProblemTypes } from '../../../../data/constants/problem';
import { OLXParser } from '../../data/OLXParser';
jest.mock('react', () => ({
...jest.requireActual('react'),
@@ -11,10 +12,9 @@ jest.mock('react', () => ({
}));
const state = new MockUseState(module);
const mockSetProblemType = jest.fn().mockName('setProblemType');
const mockUpdateField = jest.fn().mockName('updateField');
const mockSelected = 'vAl';
const mockAdvancedSelected = 'blankadvanced';
const mockSelected = 'multiplechoiceresponse';
const mockAdvancedSelected = 'circuitschematic';
const mockSetSelected = jest.fn().mockName('setSelected');
let hook;
@@ -45,15 +45,20 @@ describe('SelectTypeModal hooks', () => {
describe('onSelect', () => {
test('updateField is called with selected templated if selected is an Advanced Problem', () => {
module.onSelect(mockSetProblemType, mockAdvancedSelected, mockUpdateField)();
module.onSelect(mockAdvancedSelected, mockUpdateField)();
expect(mockUpdateField).toHaveBeenCalledWith({
problemType: ProblemTypeKeys.ADVANCED,
rawOLX: AdvanceProblems[mockAdvancedSelected].template,
rawOLX: AdvanceProblems[mockAdvancedSelected],
});
});
test('setProblemType is called with selected', () => {
module.onSelect(mockSetProblemType, mockSelected, mockUpdateField)();
expect(mockSetProblemType).toHaveBeenCalledWith({ selected: mockSelected });
test('updateField is called with selected on visual propblems', () => {
module.onSelect(mockSelected, mockUpdateField)();
const testOlXParser = new OLXParser(ProblemTypes[mockSelected].template);
const { settings, ...testState } = testOlXParser.getParsedOLXData();
expect(mockUpdateField).toHaveBeenCalledWith({
...testState,
rawOLX: ProblemTypes[mockSelected].template,
});
});
});

View File

@@ -0,0 +1,12 @@
import { StrictDict } from '../../../utils';
import circuitSchematic from './circuitschematic';
import customGrader from './customgrader';
import dragAndDrop from './drag_and_drop';
import formulaResponse from './formularesponse';
import imageResponse from './imageresponse';
import jsInputResponse from './jsinput_response';
import problemWithHint from './problem_with_hint';
export default StrictDict({
circuitSchematic, customGrader, dragAndDrop, formulaResponse, imageResponse, jsInputResponse, problemWithHint,
});

View File

@@ -0,0 +1,15 @@
/* eslint-disable */
export const dropdown = `<problem>
<optionresponse>
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown problems. Edit this component to replace this template with your own assessment.</p>
<label>Add the question text, or prompt, here. This text is required.</label>
<description>You can add an optional tip or note related to the prompt like this. </description>
<optioninput>
<option correct="False">an incorrect answer</option>
<option correct="True">the correct answer</option>
<option correct="False">an incorrect answer</option>
</optioninput>
</optionresponse>
</problem>`
export default dropdown;

View File

@@ -0,0 +1,10 @@
import { StrictDict } from '../../../utils';
import dropdown from './dropdown';
import multiSelect from './multiSelect';
import numeric from './numeric';
import singleSelect from './singleSelect';
import textInput from './textInput';
export default StrictDict({
dropdown, multiSelect, numeric, singleSelect, textInput,
});

View File

@@ -0,0 +1,15 @@
/* eslint-disable */
const multiSelect= `<problem>
<choiceresponse>
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes problems. Edit this component to replace this template with your own assessment.</p>
<label>Add the question text, or prompt, here. This text is required.</label>
<description>You can add an optional tip or note related to the prompt like this. </description>
<checkboxgroup>
<choice correct="true">a correct answer</choice>
<choice correct="false">an incorrect answer</choice>
<choice correct="false">an incorrect answer</choice>
<choice correct="true">a correct answer</choice>
</checkboxgroup>
</choiceresponse>
</problem>`
export default multiSelect;

View File

@@ -0,0 +1,12 @@
/* eslint-disable */
export const numeric = `<problem>
<numericalresponse answer="100">
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input problems. Edit this component to replace this template with your own assessment.</p>
<label>Add the question text, or prompt, here. This text is required.</label>
<description>You can add an optional tip or note related to the prompt like this. </description>
<responseparam type="tolerance" default="5"/>
<formulaequationinput/>
</numericalresponse>
</problem>`
export default numeric;

View File

@@ -0,0 +1,14 @@
/* eslint-disable */
export const singleSelect = `<problem>
<multiplechoiceresponse>
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for multiple choice problems. Edit this component to replace this template with your own assessment.</p>
<label>Add the question text, or prompt, here. This text is required.</label>
<description>You can add an optional tip or note related to the prompt like this.</description>
<choicegroup>
<choice correct="false">an incorrect answer</choice>
<choice correct="true">the correct answer</choice>
<choice correct="false">an incorrect answer</choice>
</choicegroup>
</multiplechoiceresponse>
</problem>`
export default singleSelect;

View File

@@ -0,0 +1,11 @@
/* eslint-disable */
const textInput =`<problem>
<stringresponse answer="the correct answer" type="ci">
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for text input problems. Edit this component to replace this template with your own assessment.</p>
<label>Add the question text, or prompt, here. This text is required.</label>
<description>You can add an optional tip or note related to the prompt like this. </description>
<additional_answer answer="optional acceptable variant of the correct answer"/>
<textline size="20"/>
</stringresponse>
</problem>`
export default textInput;

View File

@@ -4,13 +4,8 @@ import multiSelect from '../images/multiSelect.png';
import dropdown from '../images/dropdown.png';
import numericalInput from '../images/numericalInput.png';
import textInput from '../images/textInput.png';
import { circuitSchematic } from './olxTemplates/circuitschematic';
import { customGrader } from './olxTemplates/customgrader';
import { dragAndDrop } from './olxTemplates/drag_and_drop';
import { formulaResponse } from './olxTemplates/formularesponse';
import { imageResponse } from './olxTemplates/imageresponse';
import { jsInputResponse } from './olxTemplates/jsinput_response';
import { problemWithHint } from './olxTemplates/problem_with_hint';
import advancedOlxTemplates from './advancedOlxTemplates';
import basicOlxTemplates from './basicOlxTemplates';
export const ProblemTypeKeys = StrictDict({
SINGLESELECT: 'multiplechoiceresponse',
@@ -29,6 +24,8 @@ export const ProblemTypes = StrictDict({
helpLink: 'https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/multiple_choice.html',
prev: ProblemTypeKeys.TEXTINPUT,
next: ProblemTypeKeys.MULTISELECT,
template: basicOlxTemplates.singleSelect,
},
[ProblemTypeKeys.MULTISELECT]: {
title: 'Multi Select Problem',
@@ -37,6 +34,7 @@ export const ProblemTypes = StrictDict({
helpLink: 'https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/checkbox.html',
next: ProblemTypeKeys.DROPDOWN,
prev: ProblemTypeKeys.SINGLESELECT,
template: basicOlxTemplates.multiSelect,
},
[ProblemTypeKeys.DROPDOWN]: {
title: 'Dropdown Problem',
@@ -45,6 +43,7 @@ export const ProblemTypes = StrictDict({
helpLink: 'https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/dropdown.html',
next: ProblemTypeKeys.NUMERIC,
prev: ProblemTypeKeys.MULTISELECT,
template: basicOlxTemplates.dropdown,
},
[ProblemTypeKeys.NUMERIC]: {
title: 'Numeric Response Problem',
@@ -53,6 +52,7 @@ export const ProblemTypes = StrictDict({
helpLink: 'https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/numerical_input.html',
next: ProblemTypeKeys.TEXTINPUT,
prev: ProblemTypeKeys.DROPDOWN,
template: basicOlxTemplates.numeric,
},
[ProblemTypeKeys.TEXTINPUT]: {
title: 'Text Input Problem',
@@ -61,6 +61,7 @@ export const ProblemTypes = StrictDict({
helpLink: 'https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/text_input.html',
prev: ProblemTypeKeys.NUMERIC,
next: ProblemTypeKeys.SINGLESELECT,
template: basicOlxTemplates.textInput,
},
[ProblemTypeKeys.ADVANCED]: {
title: 'Advanced Problem',
@@ -90,37 +91,37 @@ export const AdvanceProblems = StrictDict({
[AdvanceProblemKeys.CIRCUITSCHEMATIC]: {
title: 'Circuit schematic builder',
status: 'Not supported',
template: circuitSchematic,
template: advancedOlxTemplates.circuitSchematic,
},
[AdvanceProblemKeys.JSINPUT]: {
title: 'Custom JavaScript display and grading',
status: '',
template: jsInputResponse,
template: advancedOlxTemplates.jsInputResponse,
},
[AdvanceProblemKeys.CUSTOMGRADER]: {
title: 'Custom Python-evaluated input',
status: 'Provisional',
template: customGrader,
template: advancedOlxTemplates.customGrader,
},
[AdvanceProblemKeys.DRAGANDDROP]: {
title: 'Drag and drop (deprecated version)',
status: 'Not supported',
template: dragAndDrop,
template: advancedOlxTemplates.dragAndDrop,
},
[AdvanceProblemKeys.IMAGE]: {
title: 'Image mapped input',
status: 'Not supported',
template: imageResponse,
template: advancedOlxTemplates.imageResponse,
},
[AdvanceProblemKeys.FORMULA]: {
title: 'Math expression input',
status: '',
template: formulaResponse,
template: advancedOlxTemplates.formulaResponse,
},
[AdvanceProblemKeys.PROBLEMWITHHINT]: {
title: 'Problem with adaptive hint',
status: 'Not supported',
template: problemWithHint,
template: advancedOlxTemplates.problemWithHint,
},
});

View File

@@ -144,10 +144,6 @@ const problem = createSlice({
...state,
problemType: null,
}),
setProblemType: (state, { payload: { selected } }) => ({
...state,
problemType: selected,
}),
},
});

View File

@@ -9,7 +9,8 @@ export const fetchBlockById = ({ blockId, studioEndpointUrl }) => {
let data = {};
if (blockId === 'html-block-id') {
data = {
data: '<p>Test prompt content</p>',
data: `<problem>
</problem>`,
display_name: 'My Text Prompt',
metadata: {
display_name: 'Welcome!',