Merge pull request #200 from openedx/kenclary/TNL-10332
fix: various style and UX fixes. TNL-10332.
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
>
|
||||
|
||||
@@ -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>
|
||||
`;
|
||||
|
||||
@@ -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>
|
||||
`;
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -18,7 +18,7 @@ const initialState = {
|
||||
weight: 0,
|
||||
attempts: {
|
||||
unlimited: true,
|
||||
number: 0,
|
||||
number: null,
|
||||
},
|
||||
},
|
||||
hints: [],
|
||||
|
||||
Reference in New Issue
Block a user