fix: Correct summary of number of attempts; new separator between attempts summary and points summary; hint text for both attempts and points settings; fixed some widget paddings; advanced problems do not show type setting, and type setting menu does not show advanced problems. TNL-10332.

This commit is contained in:
Ken Clary
2023-01-18 11:29:22 -05:00
parent 5aca835a4b
commit d3be3d4240
11 changed files with 139 additions and 40 deletions

View File

@@ -36,7 +36,7 @@ export const messages = {
},
noHintSummary: {
id: 'authoring.problemeditor.settings.hint.noHintSummary',
defaultMessage: 'No Hints',
defaultMessage: 'None',
description: 'Summary text for no hints',
},
hintSummary: {
@@ -104,10 +104,35 @@ export const messages = {
defaultMessage: 'Points',
description: 'Scoring weight input label',
},
scoringSummary: {
id: 'authoring.problemeditor.settings.scoring.summary',
defaultMessage: '{attempts, plural, =0 {Unlimited} other {#}} attempts - {weight, plural, =0 {Ungraded} other {# points}}',
description: 'Summary text for scoring settings',
unlimitedAttemptsSummary: {
id: 'authoring.problemeditor.settings.scoring.unlimited',
defaultMessage: 'Unlimited attempts',
description: 'Summary text for unlimited attempts',
},
attemptsSummary: {
id: 'authoring.problemeditor.settings.scoring.attempts',
defaultMessage: '{attempts, plural, =1 {# attempt} other {# attempts}}',
description: 'Summary text for number of attempts',
},
weightSummary: {
id: 'authoring.problemeditor.settings.scoring.weight',
defaultMessage: '{weight, plural, =0 {Ungraded} other {# points}}',
description: 'Summary text for scoring weight',
},
scoringSettingsLabel: {
id: 'authoring.problemeditor.settings.scoring.label',
defaultMessage: 'Specify point weight and the number of answer attempts',
description: 'Descriptive text for scoring settings',
},
attemptsHint: {
id: 'authoring.problemeditor.settings.scoring.attempts.hint',
defaultMessage: 'If a value is not set, unlimited attempts are allowed',
description: 'Summary text for scoring weight',
},
weightHint: {
id: 'authoring.problemeditor.settings.scoring.weight.hint',
defaultMessage: 'If a value is not set, the problem is worth one point',
description: 'Summary text for scoring weight',
},
showAnswerSettingsTitle: {
id: 'authoring.problemeditor.settings.showAnswer.title',

View File

@@ -29,7 +29,7 @@ export const HintsCard = ({
/>
))}
<Button
className="my-3 ml-2"
className="pl-0 text-primary-500"
iconBefore={Add}
variant="tertiary"
onClick={handleAdd}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Form } from '@edx/paragon';
import SettingsOption from '../SettingsOption';
import messages from '../messages';
@@ -14,12 +14,23 @@ export const ScoringCard = ({
}) => {
const { handleMaxAttemptChange, handleWeightChange } = scoringCardHooks(scoring, updateSettings);
const getScoringSummary = (attempts, unlimited, weight) => {
let summary = unlimited
? intl.formatMessage(messages.unlimitedAttemptsSummary)
: intl.formatMessage(messages.attemptsSummary, { attempts });
summary += ` ${String.fromCharCode(183)} `;
summary += intl.formatMessage(messages.weightSummary, { weight });
return summary;
};
return (
<SettingsOption
title={intl.formatMessage(messages.scoringSettingsTitle)}
summary={intl.formatMessage(messages.scoringSummary,
{ attempts: scoring.attempts.number, weight: scoring.weight })}
summary={getScoringSummary(scoring.attempts.number, scoring.attempts.unlimited, scoring.weight)}
>
<Form.Label className="mb-4">
<FormattedMessage {...messages.scoringSettingsLabel} />
</Form.Label>
<Form.Group>
<Form.Control
type="number"
@@ -27,6 +38,9 @@ export const ScoringCard = ({
onChange={handleMaxAttemptChange}
floatingLabel={intl.formatMessage(messages.scoringAttemptsInputLabel)}
/>
<Form.Control.Feedback>
<FormattedMessage {...messages.attemptsHint} />
</Form.Control.Feedback>
</Form.Group>
<Form.Group>
<Form.Control
@@ -35,6 +49,9 @@ export const ScoringCard = ({
onChange={handleWeightChange}
floatingLabel={intl.formatMessage(messages.scoringWeightInputLabel)}
/>
<Form.Control.Feedback>
<FormattedMessage {...messages.weightHint} />
</Form.Control.Feedback>
</Form.Group>
</SettingsOption>
);

View File

@@ -15,7 +15,9 @@ export const TypeCard = ({
// inject
intl,
}) => {
const problemTypeKeysArray = Object.values(ProblemTypeKeys);
const problemTypeKeysArray = Object.values(ProblemTypeKeys).filter(key => key !== ProblemTypeKeys.ADVANCED);
if (problemType === ProblemTypeKeys.ADVANCED) { return null; }
return (
<SettingsOption

View File

@@ -20,7 +20,7 @@ exports[`HintsCard snapshot snapshot: renders hints setting card multiple hints
value=""
/>
<Button
className="my-3 ml-2"
className="pl-0 text-primary-500"
onClick={[MockFunction hintsCardHooks.handleAdd]}
variant="tertiary"
>
@@ -35,11 +35,11 @@ exports[`HintsCard snapshot snapshot: renders hints setting card multiple hints
exports[`HintsCard snapshot snapshot: renders hints setting card no hints 1`] = `
<SettingsOption
summary="No Hints"
summary="None"
title="Hints"
>
<Button
className="my-3 ml-2"
className="pl-0 text-primary-500"
onClick={[MockFunction hintsCardHooks.handleAdd]}
variant="tertiary"
>
@@ -65,7 +65,7 @@ exports[`HintsCard snapshot snapshot: renders hints setting card one hint 1`] =
value="hint1"
/>
<Button
className="my-3 ml-2"
className="pl-0 text-primary-500"
onClick={[MockFunction hintsCardHooks.handleAdd]}
variant="tertiary"
>

View File

@@ -2,9 +2,18 @@
exports[`ScoringCard snapshot snapshot: scoring setting card 1`] = `
<SettingsOption
summary="{attempts, plural, =0 {Unlimited} other {#}} attempts - {weight, plural, =0 {Ungraded} other {# points}}"
summary="{attempts, plural, =1 {# attempt} other {# attempts}} · {weight, plural, =0 {Ungraded} other {# points}}"
title="Scoring"
>
<Form.Label
className="mb-4"
>
<FormattedMessage
defaultMessage="Specify point weight and the number of answer attempts"
description="Descriptive text for scoring settings"
id="authoring.problemeditor.settings.scoring.label"
/>
</Form.Label>
<Form.Group>
<Form.Control
floatingLabel="Attempts"
@@ -12,6 +21,13 @@ exports[`ScoringCard snapshot snapshot: scoring setting card 1`] = `
type="number"
value={5}
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="If a value is not set, unlimited attempts are allowed"
description="Summary text for scoring weight"
id="authoring.problemeditor.settings.scoring.attempts.hint"
/>
</Form.Control.Feedback>
</Form.Group>
<Form.Group>
<Form.Control
@@ -20,15 +36,31 @@ exports[`ScoringCard snapshot snapshot: scoring setting card 1`] = `
type="number"
value={1.5}
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="If a value is not set, the problem is worth one point"
description="Summary text for scoring weight"
id="authoring.problemeditor.settings.scoring.weight.hint"
/>
</Form.Control.Feedback>
</Form.Group>
</SettingsOption>
`;
exports[`ScoringCard snapshot snapshot: scoring setting card max attempts 1`] = `
<SettingsOption
summary="{attempts, plural, =0 {Unlimited} other {#}} attempts - {weight, plural, =0 {Ungraded} other {# points}}"
summary="Unlimited attempts · {weight, plural, =0 {Ungraded} other {# points}}"
title="Scoring"
>
<Form.Label
className="mb-4"
>
<FormattedMessage
defaultMessage="Specify point weight and the number of answer attempts"
description="Descriptive text for scoring settings"
id="authoring.problemeditor.settings.scoring.label"
/>
</Form.Label>
<Form.Group>
<Form.Control
floatingLabel="Attempts"
@@ -36,6 +68,13 @@ exports[`ScoringCard snapshot snapshot: scoring setting card max attempts 1`] =
type="number"
value={0}
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="If a value is not set, unlimited attempts are allowed"
description="Summary text for scoring weight"
id="authoring.problemeditor.settings.scoring.attempts.hint"
/>
</Form.Control.Feedback>
</Form.Group>
<Form.Group>
<Form.Control
@@ -44,15 +83,31 @@ exports[`ScoringCard snapshot snapshot: scoring setting card max attempts 1`] =
type="number"
value={1.5}
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="If a value is not set, the problem is worth one point"
description="Summary text for scoring weight"
id="authoring.problemeditor.settings.scoring.weight.hint"
/>
</Form.Control.Feedback>
</Form.Group>
</SettingsOption>
`;
exports[`ScoringCard snapshot snapshot: scoring setting card zero zero weight 1`] = `
<SettingsOption
summary="{attempts, plural, =0 {Unlimited} other {#}} attempts - {weight, plural, =0 {Ungraded} other {# points}}"
summary="{attempts, plural, =1 {# attempt} other {# attempts}} · {weight, plural, =0 {Ungraded} other {# points}}"
title="Scoring"
>
<Form.Label
className="mb-4"
>
<FormattedMessage
defaultMessage="Specify point weight and the number of answer attempts"
description="Descriptive text for scoring settings"
id="authoring.problemeditor.settings.scoring.label"
/>
</Form.Label>
<Form.Group>
<Form.Control
floatingLabel="Attempts"
@@ -60,6 +115,13 @@ exports[`ScoringCard snapshot snapshot: scoring setting card zero zero weight 1`
type="number"
value={5}
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="If a value is not set, unlimited attempts are allowed"
description="Summary text for scoring weight"
id="authoring.problemeditor.settings.scoring.attempts.hint"
/>
</Form.Control.Feedback>
</Form.Group>
<Form.Group>
<Form.Control
@@ -68,6 +130,13 @@ exports[`ScoringCard snapshot snapshot: scoring setting card zero zero weight 1`
type="number"
value={0}
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="If a value is not set, the problem is worth one point"
description="Summary text for scoring weight"
id="authoring.problemeditor.settings.scoring.weight.hint"
/>
</Form.Control.Feedback>
</Form.Group>
</SettingsOption>
`;

View File

@@ -54,22 +54,11 @@ exports[`TypeCard snapshot snapshot: renders type setting card 1`] = `
correctAnswerCount={0}
key="stringresponse"
label="Text input"
lastRow={false}
lastRow={true}
selected={false}
typeKey="stringresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={Array []}
correctAnswerCount={0}
key="advanced"
label="Advanced Problem"
lastRow={true}
selected={true}
typeKey="advanced"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
</SettingsOption>
`;

View File

@@ -16,10 +16,7 @@ export const parseScoringSettings = (metadata) => {
let attempts = popuplateItem({}, 'max_attempts', 'number', metadata);
if (!_.isEmpty(attempts)) {
let unlimited = true;
if (attempts.number > 0) {
unlimited = false;
}
const unlimited = _.isNaN(attempts.number);
attempts = { ...attempts, unlimited };
scoring = { ...scoring, attempts };
}

View File

@@ -4,7 +4,7 @@ import {
dropdownWithFeedbackHints,
numericWithHints,
textInputWithHints,
sigleSelectWithHints,
singleSelectWithHints,
} from './mockData/problemTestData';
describe('Test Settings to State Parser', () => {
@@ -38,7 +38,7 @@ describe('Test Settings to State Parser', () => {
});
test('Test score settings missing', () => {
const settings = parseSettings(sigleSelectWithHints.metadata);
const settings = parseSettings(singleSelectWithHints.metadata);
expect(settings.scoring).toBeUndefined();
});

View File

@@ -217,7 +217,7 @@ export const numericWithHints = {
scoring: {
weight: 2.5,
attempts: {
unlimited: true,
unlimited: false,
number: 0,
},
},
@@ -288,7 +288,7 @@ export const textInputWithHints = {
scoring: {
weight: 2.5,
attempts: {
unlimited: true,
unlimited: false,
number: 0,
},
},
@@ -315,7 +315,7 @@ not=optional incorrect answer such as a frequent misconception {{You can specify
},
};
export const sigleSelectWithHints = {
export const singleSelectWithHints = {
state: {
rawOLX: '<problem>\n<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for checkboxes with hints and feedback problems. Edit this component to replace this template with your own assessment.</p>\n\n<label>Add the question text, or prompt, here. This text is required.</label>\n<description>You can add an optional tip or note related to the prompt like this.</description>\n<multiplechoiceresponse>\n <choicegroup type="MultipleChoice">\n <choice correct="true">a correct answer <choicehint>selected: You can specify optional feedback that appears after the learner selects and submits this answer. }, { unselected: You can specify optional feedback that appears after the learner clears and submits this answer.</choicehint></choice>\n <choice correct="false">an incorrect answer</choice>\n <choice correct="false">an incorrect answer <choicehint>selected: You can specify optional feedback for none, all, or a subset of the answers. }, { unselected: You can specify optional feedback for selected answers, cleared answers, or both.</choicehint></choice>\n <choice correct="false">an incorrect answer again</choice>\n </choicegroup>\n</multiplechoiceresponse>\n<choiceresponse>\n <checkboxgroup>\n <compoundhint value="A B D">You can specify optional feedback for a combination of answers which appears after the specified set of answers is submitted.</compoundhint>\n <compoundhint value="A B C D">You can specify optional feedback for one, several, or all answer combinations.</compoundhint>\n </checkboxgroup>\n</choiceresponse>\n\n\n<demandhint>\n <hint>You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.</hint>\n <hint>If you add more than one hint, a different hint appears each time learners select the hint button.</hint>\n</demandhint>\n</problem>',
problemType: 'SINGLESELECT',
@@ -362,7 +362,7 @@ export const sigleSelectWithHints = {
weight: 0,
attempts: {
unlimited: true,
number: 0,
number: null,
},
},
timeBetween: 0,

View File

@@ -18,7 +18,7 @@ const initialState = {
weight: 0,
attempts: {
unlimited: true,
number: 0,
number: null,
},
},
hints: [],