feat: change title when problem type changes (#231)

This commit is contained in:
Raymond Zhou
2023-02-06 10:11:59 -08:00
committed by GitHub
parent 65b663bfc6
commit 7e8f9a2f0c
11 changed files with 78 additions and 4 deletions

View File

@@ -15,7 +15,7 @@ exports[`TitleHeader snapshots initialized 1`] = `
className="d-flex flex-row align-items-center"
>
<Truncate>
TeST LocALtitLE
<Component />
</Truncate>
<IconButton
alt="Edit Title"

View File

@@ -1,11 +1,12 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { Icon, IconButton, Truncate } from '@edx/paragon';
import { EditOutline } from '@edx/paragon/icons';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { selectors } from '../../../../data/redux';
import { localTitleHooks } from './hooks';
import messages from './messages';
import EditableHeader from './EditableHeader';
@@ -17,6 +18,7 @@ export const TitleHeader = ({
}) => {
if (!isInitialized) { return intl.formatMessage(messages.loading); }
const dispatch = useDispatch();
const title = useSelector(selectors.app.displayTitle);
const {
inputRef,
@@ -46,7 +48,7 @@ export const TitleHeader = ({
return (
<div className="d-flex flex-row align-items-center">
<Truncate>
{localTitle}
{title}
</Truncate>
<IconButton
alt={intl.formatMessage(messages.editTitleLabel)}

View File

@@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
import _ from 'lodash-es';
import * as module from './hooks';
import messages from './messages';
import { ProblemTypeKeys, ShowAnswerTypesKeys } from '../../../../../data/constants/problem';
import { ProblemTypeKeys, ProblemTypes, ShowAnswerTypesKeys } from '../../../../../data/constants/problem';
export const state = {
showAdvanced: (val) => useState(val),
@@ -198,7 +198,10 @@ export const timerCardHooks = (updateSettings) => ({
export const typeRowHooks = ({
answers,
blockTitle,
correctAnswerCount,
problemType,
setBlockTitle,
typeKey,
updateField,
updateAnswer,
@@ -211,6 +214,9 @@ export const typeRowHooks = ({
});
}
}
if (blockTitle === ProblemTypes[problemType].title) {
setBlockTitle(ProblemTypes[typeKey].title);
}
updateField({ problemType: typeKey });
};
return {

View File

@@ -251,6 +251,9 @@ describe('Problem settings hooks', () => {
describe('Type row hooks', () => {
test('test onClick', () => {
const typekey = 'multiplechoiceresponse';
const problemType = 'choiceresponse';
const blockTitle = 'Multi-select';
const setBlockTitle = jest.fn();
const updateField = jest.fn();
const updateAnswer = jest.fn();
const answers = [{
@@ -263,12 +266,16 @@ describe('Problem settings hooks', () => {
}];
output = hooks.typeRowHooks({
answers,
blockTitle,
correctAnswerCount: 2,
problemType,
setBlockTitle,
typeKey: typekey,
updateField,
updateAnswer,
});
output.onClick();
expect(setBlockTitle).toHaveBeenCalledWith('Single select');
expect(updateAnswer).toHaveBeenNthCalledWith(1, { ...answers[0], correct: false });
expect(updateAnswer).toHaveBeenNthCalledWith(2, { ...answers[1], correct: false });
expect(updateField).toHaveBeenCalledWith({ problemType: typekey });

View File

@@ -24,8 +24,10 @@ export const SettingsWidget = ({
problemType,
// redux
answers,
blockTitle,
correctAnswerCount,
settings,
setBlockTitle,
updateSettings,
updateField,
updateAnswer,
@@ -36,8 +38,10 @@ export const SettingsWidget = ({
<div className="mb-3 settingsCardTopdiv">
<TypeCard
answers={answers}
blockTitle={blockTitle}
correctAnswerCount={correctAnswerCount}
problemType={problemType}
setBlockTitle={setBlockTitle}
updateField={updateField}
updateAnswer={updateAnswer}
/>
@@ -99,8 +103,10 @@ SettingsWidget.propTypes = {
title: PropTypes.string,
unselectedFeedback: PropTypes.string,
})).isRequired,
blockTitle: PropTypes.string.isRequired,
correctAnswerCount: PropTypes.number.isRequired,
problemType: PropTypes.string.isRequired,
setBlockTitle: PropTypes.func.isRequired,
updateAnswer: PropTypes.func.isRequired,
updateField: PropTypes.func.isRequired,
updateSettings: PropTypes.func.isRequired,
@@ -111,10 +117,12 @@ SettingsWidget.propTypes = {
const mapStateToProps = (state) => ({
settings: selectors.problem.settings(state),
answers: selectors.problem.answers(state),
blockTitle: selectors.app.blockTitle(state),
correctAnswerCount: selectors.problem.correctAnswerCount(state),
});
export const mapDispatchToProps = {
setBlockTitle: actions.app.setBlockTitle,
updateSettings: actions.problem.updateSettings,
updateField: actions.problem.updateField,
updateAnswer: actions.problem.updateAnswer,

View File

@@ -46,6 +46,12 @@ describe('SettingsWidget', () => {
});
});
describe('mapDispatchToProps', () => {
test('setBlockTitle from actions.app.setBlockTitle', () => {
expect(mapDispatchToProps.setBlockTitle).toEqual(actions.app.setBlockTitle);
});
});
describe('mapDispatchToProps', () => {
test('updateSettings from actions.problem.updateSettings', () => {
expect(mapDispatchToProps.updateSettings).toEqual(actions.problem.updateSettings);
@@ -57,4 +63,10 @@ describe('SettingsWidget', () => {
expect(mapDispatchToProps.updateField).toEqual(actions.problem.updateField);
});
});
describe('mapDispatchToProps', () => {
test('updateAnswer from actions.problem.updateAnswer', () => {
expect(mapDispatchToProps.updateAnswer).toEqual(actions.problem.updateAnswer);
});
});
});

View File

@@ -8,8 +8,10 @@ import TypeRow from './TypeRow';
export const TypeCard = ({
answers,
blockTitle,
correctAnswerCount,
problemType,
setBlockTitle,
updateField,
updateAnswer,
// inject
@@ -27,12 +29,15 @@ export const TypeCard = ({
{problemTypeKeysArray.map((typeKey, i) => (
<TypeRow
answers={answers}
blockTitle={blockTitle}
correctAnswerCount={correctAnswerCount}
key={typeKey}
typeKey={typeKey}
label={ProblemTypes[typeKey].title}
selected={typeKey !== problemType}
problemType={problemType}
lastRow={(i + 1) === problemTypeKeysArray.length}
setBlockTitle={setBlockTitle}
updateField={updateField}
updateAnswer={updateAnswer}
/>
@@ -49,8 +54,10 @@ TypeCard.propTypes = {
title: PropTypes.string,
unselectedFeedback: PropTypes.string,
})).isRequired,
blockTitle: PropTypes.string.isRequired,
correctAnswerCount: PropTypes.number.isRequired,
problemType: PropTypes.string.isRequired,
setBlockTitle: PropTypes.func.isRequired,
updateField: PropTypes.func.isRequired,
updateAnswer: PropTypes.func.isRequired,
// injected

View File

@@ -7,8 +7,10 @@ import { ProblemTypeKeys } from '../../../../../../data/constants/problem';
describe('TypeCard', () => {
const props = {
answers: [],
blockTitle: 'BLocktiTLE',
correctAnswerCount: 0,
problemType: ProblemTypeKeys.TEXTINPUT,
setBlockTitle: jest.fn().mockName('args.setBlockTitle'),
updateField: jest.fn().mockName('args.updateField'),
updateAnswer: jest.fn().mockName('args.updateAnswer'),
// injected

View File

@@ -8,17 +8,23 @@ import Button from '../../../../../../sharedComponents/Button';
export const TypeRow = ({
answers,
blockTitle,
correctAnswerCount,
typeKey,
label,
selected,
problemType,
lastRow,
setBlockTitle,
updateField,
updateAnswer,
}) => {
const { onClick } = typeRowHooks({
answers,
blockTitle,
correctAnswerCount,
problemType,
setBlockTitle,
typeKey,
updateField,
updateAnswer,
@@ -43,11 +49,14 @@ TypeRow.propTypes = {
title: PropTypes.string,
unselectedFeedback: PropTypes.string,
})).isRequired,
blockTitle: PropTypes.string.isRequired,
correctAnswerCount: PropTypes.number.isRequired,
typeKey: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
selected: PropTypes.bool.isRequired,
lastRow: PropTypes.bool.isRequired,
problemType: PropTypes.string.isRequired,
setBlockTitle: PropTypes.func.isRequired,
updateAnswer: PropTypes.func.isRequired,
updateField: PropTypes.func.isRequired,
};

View File

@@ -11,11 +11,14 @@ describe('TypeRow', () => {
const typeKey = 'TEXTINPUT';
const props = {
answers: [],
blockTitle: 'bLoCkTiTLE',
correctAnswerCount: 0,
typeKey,
label: 'Text Input Problem',
selected: true,
lastRow: false,
problemType: 'prOBlEMtyPE',
setBlockTitle: jest.fn().mockName('args.setBlockTitle'),
updateField: jest.fn().mockName('args.updateField'),
updateAnswer: jest.fn().mockName('args.updateAnswer'),
};
@@ -31,8 +34,11 @@ describe('TypeRow', () => {
shallow(<TypeRow {...props} />);
expect(typeRowHooks).toHaveBeenCalledWith({
answers: props.answers,
blockTitle: props.blockTitle,
correctAnswerCount: props.correctAnswerCount,
problemType: props.problemType,
typeKey,
setBlockTitle: props.setBlockTitle,
updateField: props.updateField,
updateAnswer: props.updateAnswer,
});

View File

@@ -9,55 +9,70 @@ exports[`TypeCard snapshot snapshot: renders type setting card 1`] = `
>
<TypeRow
answers={Array []}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="multiplechoiceresponse"
label="Single select"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="multiplechoiceresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={Array []}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="choiceresponse"
label="Multi-select"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="choiceresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={Array []}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="optionresponse"
label="Dropdown"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="optionresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={Array []}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="numericalresponse"
label="Numerical input"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="numericalresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={Array []}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="stringresponse"
label="Text input"
lastRow={true}
problemType="stringresponse"
selected={false}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="stringresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}