@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
705 lines (691 loc) • 30.6 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
var _dec, _class, _RichFillBlankEdit;
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _callSuper(_this, derived, args) {
function isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
return !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
} catch (e) {
return false;
}
}
derived = _getPrototypeOf(derived);
return _possibleConstructorReturn(_this, isNativeReflectConstruct() ? Reflect.construct(derived, args || [], _getPrototypeOf(_this).constructor) : derived.apply(_this, args));
}
/** @jsx jsx */
import { Component } from 'react';
import PropTypes from 'prop-types';
import concat from 'lodash/fp/concat';
import find from 'lodash/fp/find';
import get from 'lodash/get';
import { v4 as uuid } from 'uuid';
import update from 'immutability-helper';
import findIndex from 'lodash/findIndex';
import omit from 'lodash/omit';
import isEqual from 'lodash/isEqual';
import escape from 'lodash/escape';
import { Checkbox } from '@instructure/ui-checkbox';
import { jsx } from '@instructure/emotion';
import QuestionSettingsContainer from '../../common/edit/components/QuestionSettingsContainer';
import QuestionContainer from '../../common/edit/components/QuestionContainer';
import RichFillBlankInteractionType from '../../../records/interactions/rich_fill_blank';
import BlankTypeSelect from '../../fill_blank/Edit/answer_field/BlankTypeSelect';
import WordBankDistractors from './WordBankDistractors';
import generateStyle from './styles';
import generateComponentTheme from './theme';
import withEditTools from '../../../util/withEditTools';
import t from '@instructure/quiz-i18n/es/format-message';
import QuestionSettingsPanel from '../../common/edit/components/QuestionSettingsPanel';
import CalculatorOptionWithOqaatAlert from '../../common/edit/components/CalculatorOptionWithOqaatAlert';
import { ScreenReaderContent } from '@instructure/ui-a11y-content';
import { Text } from '@instructure/ui-text';
import { Flex, withStyleOverrides, FormFieldGroup } from '@instructure/quiz-common';
/**
---
category: RichFillInTheBlank
---
Rich Fill in the Blank Edit component
```jsx_example
function Example (props) {
const exampleProps = {
interactionData: {
blanks: [{
answerType: 'openEntry',
id: 'uuid-blank1'
}, {
answerType: 'openEntry',
id: 'uuid-blank2'
}, {
answerType: 'openEntry',
id: 'uuid-blank3'
}, {
answerType: 'openEntry',
id: 'uuid-blank4'
}, {
answerType: 'openEntry',
id: 'uuid-blank5'
}, {
answerType: 'dropdown',
id: 'uuid-blank6',
choices: [
{ id: 'uuid6-choice1', position: 1, itemBody: 'with' },
{ id: 'uuid6-choice2', position: 2, itemBody: 'on' },
{ id: 'uuid6-choice3', position: 3, itemBody: 'which' }
]
}, {
answerType: 'wordbank',
id: 'uuid-blank7',
choices: [
{ id: 'uuid7-choice1', position: 1, itemBody: 'bathwater' },
{ id: 'uuid7-choice2', position: 2, itemBody: 'bathtub' },
{ id: 'uuid7-choice3', position: 3, itemBody: 'water' }
]
}]
},
scoringData: {
workingItemBody: "<p>`Don't` `throw` `the` `baby` `out` `with` the `bathwater`.</p>",
value: [{
id: 'uuid-blank1',
scoringAlgorithm: 'TextCloseEnough',
scoringData: {
blankText: 'Don\'t',
editDistance: '1',
ignoreCase: true,
value: 'Don\'t'
}
}, {
id: 'uuid-blank2',
scoringAlgorithm: 'TextEquivalence',
scoringData: {
blankText: 'throw',
value: 'throw'
}
}, {
id: 'uuid-blank3',
scoringAlgorithm: 'TextContainsAnswer',
scoringData: {
blankText: 'the',
value: 'the'
}
}, {
id: 'uuid-blank4',
scoringAlgorithm: 'TextInChoices',
scoringData: {
blankText: 'baby',
value: ['baby', 'kid', 'child']
}
}, {
id: 'uuid-blank5',
scoringAlgorithm: 'TextRegex',
scoringData: {
blankText: 'out',
value: 'out'
}
}, {
id: 'uuid-blank6',
scoringAlgorithm: 'Equivalence',
scoringData: {
blankText: 'with',
value: 'uuid6-choice1'
}
}, {
id: 'uuid-blank7',
scoringAlgorithm: 'Equivalence',
scoringData: {
blankText: 'bathwater',
value: 'uuid7-choice1'
}
}]
}
}
return (
<RichFillBlankEdit {...exampleProps} {...props} />
)
}
<SettingsSwitcher locales={LOCALES}>
<EditStateProvider>
<Example />
</EditStateProvider>
</SettingsSwitcher>
```
**/
var RichFillBlankEdit = (_dec = withStyleOverrides(generateStyle, generateComponentTheme), withEditTools(_class = _dec(_class = (_RichFillBlankEdit = /*#__PURE__*/function (_Component) {
function RichFillBlankEdit() {
var _this2;
_classCallCheck(this, RichFillBlankEdit);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this2 = _callSuper(this, RichFillBlankEdit, [].concat(args));
_defineProperty(_this2, "validBlankRegex", function () {
return new RegExp(_this2.props.interactionType.validBlankRegex, 'g');
});
// Other edit components use the `getErrors` helper passed in from the
// withEditTools higher-order component, but fill blank has its own error
// handling logic
_defineProperty(_this2, "getErrors", function (path) {
if (_this2.props.errorsAreShowing) {
return get(_this2.props.errors, path, null);
}
return null;
});
_defineProperty(_this2, "blankValues", function () {
return (_this2.props.scoringData.value || []).map(function (blankValue) {
return blankValue.scoringData.blankText;
});
});
_defineProperty(_this2, "arrayDiff", function (arr1, arr2) {
// items in arr1 that are not in arr2 (accounting for duplicate items)
// examples (arr1 - arr2 = return):
// [a,b,c] - [a] = [b,c]
// [a,a,b] - [a] = [a,b]
// [a,b] - [b,c] = [a]
var arr1Copy = _toConsumableArray(arr1);
arr2.forEach(function (blank) {
var blankIndex = arr1Copy.indexOf(blank);
if (blankIndex > -1) {
arr1Copy.splice(blankIndex, 1);
}
});
return arr1Copy;
});
_defineProperty(_this2, "defaultBlankScoringData", function (blankValue, id) {
return {
id: id,
scoringAlgorithm: 'TextContainsAnswer',
scoringData: {
value: blankValue,
blankText: blankValue
}
};
});
_defineProperty(_this2, "defaultBlankInteractionData", function (blankValue, id) {
return {
id: id,
answerType: 'openEntry'
};
});
_defineProperty(_this2, "updateScoringDataBlankTexts", function (scoringDataValue, interactionDataBlankValues, blankMatches) {
return scoringDataValue.map(function (scoringDataBlankValue, i) {
var prevBlankText = scoringDataBlankValue.scoringData.blankText;
var newBlankText = blankMatches[i];
if (prevBlankText === newBlankText) {
return scoringDataBlankValue;
}
var scoringAlgorithm = scoringDataBlankValue.scoringAlgorithm;
var answerType = interactionDataBlankValues[i].answerType;
var scoringDataMods = {
blankText: blankMatches[i]
};
if (answerType === 'openEntry') {
if (['TextRegex', 'TextContainsAnswer', 'TextEquivalence', 'Equivalence', 'TextCloseEnough'].includes(scoringAlgorithm)) {
scoringDataMods.value = blankMatches[i];
} else if (scoringAlgorithm === 'TextInChoices') {
scoringDataMods.value = scoringDataBlankValue.scoringData.value;
scoringDataMods.value[0] = blankMatches[i];
}
}
if (answerType === 'wordbank' && scoringDataBlankValue.scoringData.choiceId) {
scoringDataMods.value = blankMatches[i];
}
return _objectSpread(_objectSpread({}, scoringDataBlankValue), {}, {
scoringData: _objectSpread(_objectSpread({}, scoringDataBlankValue.scoringData), scoringDataMods)
});
});
});
_defineProperty(_this2, "updateInteractionDataBlankTexts", function (interactionDataBlankValues, newScoringDataValue, blankMatches) {
return interactionDataBlankValues.map(function (interactionDataBlankValue, i) {
if (['dropdown', 'wordbank'].includes(interactionDataBlankValue.answerType)) {
var choices = interactionDataBlankValue.choices;
var blankId = interactionDataBlankValue.id;
var blankScoringDataValue = newScoringDataValue.find(function (value) {
return value.id === blankId;
});
if (choices && blankScoringDataValue) {
var correctChoiceIdx = choices.findIndex(function (choice) {
return choice.id === blankScoringDataValue.scoringData.value;
});
choices[correctChoiceIdx].itemBody = blankMatches[i];
}
return _objectSpread(_objectSpread({}, interactionDataBlankValue), choices && {
choices: choices
});
}
return interactionDataBlankValue;
});
});
_defineProperty(_this2, "updateWordBankChoicesTexts", function (wordBankChoices, scoringDataValue) {
if (!wordBankChoices) return;
return wordBankChoices.map(function (wordBankChoice) {
var choiceScoringData = scoringDataValue.find(function (scoringData) {
return scoringData.scoringData.choiceId === wordBankChoice.id;
});
return _objectSpread(_objectSpread({}, wordBankChoice), choiceScoringData && {
itemBody: choiceScoringData.scoringData.blankText
});
});
});
_defineProperty(_this2, "indexForWordBankChoice", function (choiceId) {
return findIndex(_this2.props.interactionData.wordBankChoices, function (wordBankChoice) {
return wordBankChoice.id === choiceId;
});
});
_defineProperty(_this2, "makeNewProperties", function (interactionData) {
// syncs shuffling properties data with new interaction data.
// this runs each time we changeItemState so that we dont have
// to manage syncing properties and interactionData on each individual
// change to blank type or blank creation/deletion
var blankRules = interactionData.blanks.reduce(function (memo, blank, blankIndex) {
// eslint-disable-next-line no-param-reassign
memo[blankIndex] = blank.answerType === 'openEntry' ? {
children: null
} : {
children: {
choices: {
shuffled: true
}
}
};
return memo;
}, {});
var newShuffleRules = {
shuffleRules: {
blanks: {
children: blankRules
}
}
};
return Object.assign({}, _this2.props.properties, newShuffleRules);
});
_defineProperty(_this2, "changeItemState", function (modifications, blankId) {
var newestIntData = Object.assign({}, _this2.props.interactionData, modifications.interactionData);
var newProperties = _this2.makeNewProperties(newestIntData);
var newMods = {
properties: newProperties
};
if (modifications.scoringData) {
newMods.scoringData = modifications.scoringData;
}
var newModifications = Object.assign({}, modifications, newMods);
_this2.props.changeItemState(newModifications, blankId);
});
_defineProperty(_this2, "insert", function (arr, index) {
for (var _len2 = arguments.length, newItems = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
newItems[_key2 - 2] = arguments[_key2];
}
return [].concat(_toConsumableArray(arr.slice(0, index)), newItems, _toConsumableArray(arr.slice(index)));
});
_defineProperty(_this2, "blankIdsFromValues", function (removedBlanks) {
var blankIds = [];
var scoringDataValue = _toConsumableArray(_this2.props.scoringData.value);
removedBlanks.forEach(function (blank) {
var blankValueIndex = scoringDataValue.findIndex(function (blankValue) {
return blankValue.scoringData.blankText === blank;
});
if (blankValueIndex > -1) {
blankIds.push(scoringDataValue[blankValueIndex].id);
scoringDataValue.splice(blankValueIndex, 1);
}
});
return blankIds;
});
// ================
// HANDLERS
// ================
_defineProperty(_this2, "handleCheckboxChange", function (event) {
var interactionData = update(_this2.props.interactionData, _defineProperty({}, event.target.value, {
$set: !_this2.props.interactionData[event.target.value]
}));
_this2.changeItemState({
interactionData: interactionData
});
});
_defineProperty(_this2, "handleCalculatorTypeChange", function (e, value) {
_this2.changeItemState({
calculatorType: value
});
});
_defineProperty(_this2, "updateScoringDataForBlank", function (blankId) {
return function (scoringDataMods) {
var indexForBlank = _this2.indexForBlank(blankId);
var workingItemBody = _this2.props.scoringData.workingItemBody;
var index = 0;
var newWorkingItemBody = workingItemBody.replace(_this2.validBlankRegex(), function (match) {
return index++ === indexForBlank ? "`".concat(escape(scoringDataMods.scoringData.blankText), "`") : match;
});
var scoringData = update(_this2.props.scoringData, {
workingItemBody: {
$set: newWorkingItemBody
},
value: _defineProperty({}, indexForBlank, {
$merge: scoringDataMods
})
});
var interactionData = _this2.props.interactionData;
// if the text of a wordbank choice was updated,
// reflect the change in the wordBankChoices list
if (scoringDataMods.scoringData.choiceId && _this2.props.interactionData.wordBankChoices) {
var wordBankChoiceIndex = _this2.indexForWordBankChoice(scoringDataMods.scoringData.choiceId);
if (wordBankChoiceIndex > -1) {
interactionData = update(interactionData, {
wordBankChoices: _defineProperty({}, wordBankChoiceIndex, {
itemBody: {
$set: scoringDataMods.scoringData.blankText
}
})
});
}
}
_this2.changeItemState({
scoringData: scoringData,
interactionData: interactionData
}, blankId);
};
});
// Setting choices to null will remove the choice from the blank. This is necessary
// because when switching between blank types we need a way to remove the choices
// data from the interactionData since it won't be relevant to the new type (not
// to mention that leaving it will expose the openEntry's answer)
_defineProperty(_this2, "updateBlank", function (blankId) {
return function (modifications) {
var indexForBlank = _this2.indexForBlank(blankId);
var blankData = _this2.props.interactionData.blanks[indexForBlank];
var mods = modifications;
if (modifications.choices === null) {
mods = omit(modifications, ['choices']);
blankData = omit(_this2.props.interactionData.blanks[indexForBlank], ['choices']);
}
// if there's a new wordbank choice, add it to the wordBankChoice list
var wordBankChoicesMods;
if (modifications.choice) {
wordBankChoicesMods = update(_this2.props.interactionData.wordBankChoices || [{
id: uuid(),
itemBody: ''
}], {
$push: [modifications.choice]
});
}
// omit "choice" because "choice" is added to wordBankChoices, not the blank itself
mods = omit(modifications, ['choice']);
var finalMods = update(blankData, {
$merge: mods
});
var interactionData = update(_this2.props.interactionData, _objectSpread({
blanks: _defineProperty({}, indexForBlank, {
$set: finalMods
})
}, wordBankChoicesMods && {
wordBankChoices: {
$set: wordBankChoicesMods
}
}));
// if the blank no longer has answerType "wordbank",
// remove the choice from wordBankChoices
var noLongerWordbank = blankData.answerType === 'wordbank' && modifications.answerType && modifications.answerType !== 'wordbank';
if (noLongerWordbank && interactionData.wordBankChoices) {
var scoringDataForBlank = _this2.props.scoringData.value[indexForBlank];
var wordBankChoiceIndex = _this2.indexForWordBankChoice(scoringDataForBlank.scoringData.choiceId);
interactionData = update(interactionData, {
wordBankChoices: {
$splice: [[wordBankChoiceIndex, 1]]
}
});
}
// if there are aren't any wordbank blanks,
// clear out wordBankChoices list
if (!interactionData.blanks.some(function (blank) {
return blank.answerType === 'wordbank';
})) {
interactionData = update(interactionData, {
$unset: ['wordBankChoices']
});
}
_this2.changeItemState({
interactionData: interactionData
}, blankId);
};
});
_defineProperty(_this2, "handleDescriptionChange", function (itemBody) {
var blankMatches = (itemBody.match(_this2.validBlankRegex()) || []).map(function (match) {
return _this2.htmlDecode(match.slice(1, -1));
});
var knownBlanks = _this2.blankValues();
var newScoringDataValue = _this2.props.scoringData.value || [];
var newInteractionDataBlanks = _this2.props.interactionData.blanks || [];
var newWordBankChoices = _this2.props.interactionData.wordBankChoices;
var updateBlankTexts = function updateBlankTexts() {
newScoringDataValue = _this2.updateScoringDataBlankTexts(newScoringDataValue, newInteractionDataBlanks, blankMatches);
newInteractionDataBlanks = _this2.updateInteractionDataBlankTexts(newInteractionDataBlanks, newScoringDataValue, blankMatches);
newWordBankChoices = _this2.updateWordBankChoicesTexts(newWordBankChoices, newScoringDataValue);
};
if (blankMatches.length === knownBlanks.length) {
// update blank values (may or may not have changed)
updateBlankTexts();
} else {
// remove any removed blanks
var removedBlanks = _this2.arrayDiff(knownBlanks, blankMatches);
var removedBlankIds = _this2.blankIdsFromValues(removedBlanks);
var removedWordBankChoiceIds = [];
newScoringDataValue = newScoringDataValue.filter(function (blankValue) {
if (removedBlankIds.includes(blankValue.id) && blankValue.scoringData.choiceId) {
removedWordBankChoiceIds.push(blankValue.scoringData.choiceId);
}
return !removedBlankIds.includes(blankValue.id);
});
newInteractionDataBlanks = newInteractionDataBlanks.filter(function (blankValue) {
return !removedBlankIds.includes(blankValue.id);
});
if (newWordBankChoices) {
newWordBankChoices = newWordBankChoices.filter(function (wordBankChoice) {
return !removedWordBankChoiceIds.includes(wordBankChoice.id);
});
// if there are aren't any wordbank blanks, clear out wordBankChoices list
if (!newInteractionDataBlanks.some(function (blank) {
return blank.answerType === 'wordbank';
})) {
newWordBankChoices = null;
}
}
// add any newly added blanks
var newBlanks = _this2.arrayDiff(blankMatches, knownBlanks);
newBlanks.forEach(function (newBlank) {
var id = uuid();
var index = blankMatches.indexOf(newBlank);
newScoringDataValue = _this2.insert(newScoringDataValue, index, _this2.defaultBlankScoringData(newBlank, id));
newInteractionDataBlanks = _this2.insert(newInteractionDataBlanks, index, _this2.defaultBlankInteractionData(newBlank, id));
});
}
// There are many ways for the scoringData/interactionData to get desynced from what the RCE shows,
// especially considering we allow blanks to have duplicate blankText, and users can change
// multiple blanks at once by pasting anything in the RCE. This check is intended as a failsafe.
// If the blankTexts don't match what's in the RCE, just force them to match.
var blankTexts = newScoringDataValue.map(function (blankValue) {
return blankValue.scoringData.blankText;
});
if (!isEqual(blankTexts, blankMatches)) {
updateBlankTexts();
}
_this2.props.changeItemState({
interactionData: _objectSpread({
blanks: newInteractionDataBlanks
}, newWordBankChoices && {
wordBankChoices: newWordBankChoices
}),
scoringData: {
workingItemBody: itemBody,
value: newScoringDataValue
}
});
});
_defineProperty(_this2, "renderExplanation", function () {
return jsx(Flex, {
direction: "column",
padding: "0 0 small 0"
}, jsx(Text, null, t('Type a statement and surround a word with backticks to indicate where a student will fill in the answer.')));
});
return _this2;
}
_inherits(RichFillBlankEdit, _Component);
return _createClass(RichFillBlankEdit, [{
key: "indexForBlank",
value: function indexForBlank(blankId) {
return findIndex(this.props.interactionData.blanks, function (blank) {
return blank.id === blankId;
});
}
}, {
key: "htmlDecode",
value: function htmlDecode(input) {
var doc = new DOMParser().parseFromString(input, 'text/html');
return doc.documentElement.textContent;
}
}, {
key: "renderBlanksOptions",
value:
// =============
// RENDERING
// =============
function renderBlanksOptions() {
var _this3 = this;
var hasIndividualWordBanks = this.props.interactionData.blanks.some(function (blank) {
return blank.answerType === 'wordbank' && blank.choices && blank.choices.length;
});
return this.props.interactionData.blanks.map(function (blank, blankIndex) {
var blankScoringData = find({
id: blank.id
}, _this3.props.scoringData.value) || {};
var choicesErrors = concat(_this3.getErrors("scoringData.value[".concat(blankIndex, "].scoringData.value.$errors")) || [], _this3.getErrors("interactionData.blanks[".concat(blankIndex, "].choices.$errors")) || []);
return jsx(BlankTypeSelect, {
key: blank.id,
answerType: blank.answerType,
blankPosition: blankIndex + 1,
blankScoringAlgorithm: blankScoringData.scoringAlgorithm,
blankScoringData: blankScoringData.scoringData,
choices: blank.choices,
disabled: _this3.props.overrideEditableForRegrading,
interactionDataErrors: _this3.getErrors("interactionData.blanks[".concat(blankIndex, "]")) || {},
name: blank.id,
notifyScreenreader: _this3.props.notifyScreenreader,
onModalClose: _this3.props.onModalClose,
onModalOpen: _this3.props.onModalOpen,
scoringDataErrors: _this3.getErrors("scoringData.value[".concat(blankIndex, "].scoringData")) || {},
choicesErrors: choicesErrors,
validationErrorsFromApi: _this3.props.validationErrorsFromApi[blank.id] || [],
wordBankChoices: _this3.props.interactionData.wordBankChoices,
updateBlank: _this3.updateBlank(blank.id),
updateBlankScoringData: _this3.updateScoringDataForBlank(blank.id),
useCommonWordbank: _this3.props.fitbCommonWordbankEnabled && !hasIndividualWordBanks
});
});
}
}, {
key: "renderOptionsDescription",
value: function renderOptionsDescription() {
return jsx(ScreenReaderContent, null, t('Fill in the blank options'));
}
}, {
key: "render",
value: function render() {
var stemErrors = this.getErrors('scoringData.workingItemBody') || [];
var blankErrors = this.getErrors(['interactionData', 'blanks', '$errors']) || [];
return jsx("div", null, this.renderExplanation(), jsx(QuestionContainer, {
disabled: this.props.overrideEditableForRegrading,
enableRichContentEditor: this.props.enableRichContentEditor,
itemBody: this.props.scoringData.workingItemBody,
onDescriptionChange: this.handleDescriptionChange,
onModalClose: this.props.onModalClose,
onModalOpen: this.props.onModalOpen,
openImportModal: this.props.openImportModal,
stemErrors: stemErrors.concat(blankErrors) || []
}, this.renderBlanksOptions(), jsx(WordBankDistractors, {
changeItemState: this.props.changeItemState,
indexForWordBankChoice: this.indexForWordBankChoice,
interactionData: this.props.interactionData,
interactionDataErrors: this.getErrors('interactionData.wordBankChoices') || {},
notifyScreenreader: this.props.notifyScreenreader,
onModalClose: this.props.onModalClose,
onModalOpen: this.props.onModalOpen,
overrideEditableForRegrading: this.props.overrideEditableForRegrading,
scoringData: this.props.scoringData
})), jsx(QuestionSettingsContainer, {
additionalOptions: this.props.additionalOptions
}, jsx(QuestionSettingsPanel, {
label: t('Options'),
defaultExpanded: true
}, jsx(FormFieldGroup, {
rowSpacing: "small",
description: this.renderOptionsDescription()
}, this.props.interactionData.wordBankChoices && jsx(Checkbox, {
label: t('Allow word bank choices to be reused'),
value: "reuseWordBankChoices",
onChange: this.handleCheckboxChange,
checked: this.props.interactionData.reuseWordBankChoices,
disabled: this.props.overrideEditableForRegrading
}), this.props.showCalculatorOption && jsx(CalculatorOptionWithOqaatAlert, {
disabled: this.props.overrideEditableForRegrading,
calculatorValue: this.props.calculatorType,
onCalculatorTypeChange: this.handleCalculatorTypeChange,
oqaatChecked: this.props.oneQuestionAtATime,
onOqaatChange: this.props.setOneQuestionAtATime
})))));
}
}]);
}(Component), _defineProperty(_RichFillBlankEdit, "displayName", 'RichFillBlankEdit'), _defineProperty(_RichFillBlankEdit, "componentId", "Quizzes".concat(_RichFillBlankEdit.displayName)), _defineProperty(_RichFillBlankEdit, "interactionType", RichFillBlankInteractionType), _defineProperty(_RichFillBlankEdit, "propTypes", {
additionalOptions: PropTypes.array,
calculatorType: PropTypes.string,
changeItemState: PropTypes.func.isRequired,
enableRichContentEditor: PropTypes.bool,
errors: PropTypes.object,
errorsAreShowing: PropTypes.bool,
fitbCommonWordbankEnabled: PropTypes.bool,
interactionData: PropTypes.object.isRequired,
interactionType: PropTypes.shape({
validBlankRegex: PropTypes.string
}).isRequired,
notifyScreenreader: PropTypes.func.isRequired,
onModalClose: PropTypes.func,
onModalOpen: PropTypes.func,
oneQuestionAtATime: PropTypes.bool,
openImportModal: PropTypes.func,
overrideEditableForRegrading: PropTypes.bool,
properties: PropTypes.shape({
shuffleRules: PropTypes.shape({
blanks: PropTypes.shape({
children: PropTypes.object
})
})
}),
scoringData: PropTypes.object.isRequired,
setOneQuestionAtATime: PropTypes.func,
validationErrorsFromApi: PropTypes.object,
styles: PropTypes.object,
showCalculatorOption: PropTypes.bool
}), _defineProperty(_RichFillBlankEdit, "defaultProps", {
calculatorType: 'none',
enableRichContentEditor: true,
fitbCommonWordbankEnabled: false,
oneQuestionAtATime: false,
overrideEditableForRegrading: false,
setOneQuestionAtATime: Function.prototype,
additionalOptions: void 0,
errors: void 0,
errorsAreShowing: void 0,
onModalClose: void 0,
onModalOpen: void 0,
openImportModal: void 0,
properties: {},
scoringData: void 0,
validationErrorsFromApi: {},
showCalculatorOption: true
}), _RichFillBlankEdit)) || _class) || _class);
export { RichFillBlankEdit as default };