UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

386 lines (379 loc) • 17.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = require("react"); var _propTypes = _interopRequireDefault(require("prop-types")); var _concat = _interopRequireDefault(require("lodash/fp/concat")); var _find = _interopRequireDefault(require("lodash/fp/find")); var _get = _interopRequireDefault(require("lodash/get")); var _uiButtons = require("@instructure/ui-buttons"); var _uiText = require("@instructure/ui-text"); var _emotion = require("@instructure/emotion"); var _Errors = _interopRequireDefault(require("../../common/edit/components/Errors")); var _QuestionSettingsContainer = _interopRequireDefault(require("../../common/edit/components/QuestionSettingsContainer")); var _QuestionContainer = _interopRequireDefault(require("../../common/edit/components/QuestionContainer")); var _fill_blank = _interopRequireDefault(require("../../../records/interactions/fill_blank")); var _BlankTypeSelect = _interopRequireDefault(require("./answer_field/BlankTypeSelect")); var _EditStem = _interopRequireDefault(require("./EditStem")); var _editController = _interopRequireDefault(require("./editController")); var _styles = _interopRequireDefault(require("./styles")); var _theme = _interopRequireDefault(require("./theme")); var _withEditTools = _interopRequireDefault(require("../../../util/withEditTools")); var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message")); var _QuestionSettingsPanel = _interopRequireDefault(require("../../common/edit/components/QuestionSettingsPanel")); var _CalculatorOptionWithOqaatAlert = _interopRequireDefault(require("../../common/edit/components/CalculatorOptionWithOqaatAlert")); var _uiA11yContent = require("@instructure/ui-a11y-content"); var _quizCommon = require("@instructure/quiz-common"); var _dec, _class, _FillBlankEdit; /** @jsx jsx */ 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 = (0, _getPrototypeOf2["default"])(derived); return (0, _possibleConstructorReturn2["default"])(_this, isNativeReflectConstruct() ? Reflect.construct(derived, args || [], (0, _getPrototypeOf2["default"])(_this).constructor) : derived.apply(_this, args)); } var SPACE_KEY_CODE = 32; var ENTER_KEY_CODE = 13; /** --- category: FillInTheBlank --- Fill in the Blank Edit component ```jsx_example function Example (props) { const exampleProps = { interactionData: { prompt: '<p><strong>Please</strong> fill in all the blanks</p>', 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' } ] }], stemItems: [ { id: 'uuid-stem0', position: 1, type: 'text', value: ' ' }, { id: 'uuid-stem1', position: 2, type: 'blank', blankId: 'uuid-blank1' }, { id: 'uuid-stem2', position: 3, type: 'text', value: ' ' }, { id: 'uuid-stem3', position: 4, type: 'blank', blankId: 'uuid-blank2' }, { id: 'uuid-stem4', position: 5, type: 'text', value: ' ' }, { id: 'uuid-stem5', position: 6, type: 'blank', blankId: 'uuid-blank3' }, { id: 'uuid-stem6', position: 7, type: 'text', value: ' ' }, { id: 'uuid-stem7', position: 8, type: 'blank', blankId: 'uuid-blank4' }, { id: 'uuid-stem8', position: 9, type: 'text', value: ' ' }, { id: 'uuid-stem9', position: 10, type: 'blank', blankId: 'uuid-blank5' }, { id: 'uuid-stem10', position: 11, type: 'text', value: ' ' }, { id: 'uuid-stem11', position: 12, type: 'blank', blankId: 'uuid-blank6' }, { id: 'uuid-stem12', position: 13, type: 'text', value: ' <the> ' }, { id: 'uuid-stem13', position: 14, type: 'blank', blankId: 'uuid-blank7' }, { id: 'uuid-stem14', position: 15, type: 'text', value: '.' } ] }, scoringData: { 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 ( <FillBlankEdit {...exampleProps} {...props} /> ) } <SettingsSwitcher locales={LOCALES}> <EditStateProvider> <Example /> </EditStateProvider> </SettingsSwitcher> ``` **/ var FillBlankEdit = exports["default"] = (_dec = (0, _quizCommon.withStyleOverrides)(_styles["default"], _theme["default"]), (0, _withEditTools["default"])(_class = _dec(_class = (_FillBlankEdit = /*#__PURE__*/function (_Component) { function FillBlankEdit(props) { var _this2; (0, _classCallCheck2["default"])(this, FillBlankEdit); _this2 = _callSuper(this, FillBlankEdit, [props]); (0, _defineProperty2["default"])(_this2, "state", { selectedText: '' }); // Other edit components use the `getErrors` helper passed in from the // withEditTools higher-order component, but fill blank has its own error // handling logic (0, _defineProperty2["default"])(_this2, "getErrors", function (path) { if (_this2.props.errorsAreShowing) { return (0, _get["default"])(_this2.props.errors, path, null); } return null; }); // ================ // HANDLERS // ================ (0, _defineProperty2["default"])(_this2, "setSelectedText", function (text) { _this2.setState({ selectedText: text }); }); (0, _defineProperty2["default"])(_this2, "handleCreateBlank", function (event) { _this2.controller.onCreateBlank(event); _this2.setState({ selectedText: '' }); }); (0, _defineProperty2["default"])(_this2, "handleCreateBlankHotkey", function (event) { if (event.which === ENTER_KEY_CODE || event.which === SPACE_KEY_CODE && event.ctrlKey && event.altKey) { event.preventDefault(); _this2.handleCreateBlank(event); _this2.props.notifyScreenreader((0, _formatMessage["default"])('Blank created. Navigate to edit blank below.')); } }); (0, _defineProperty2["default"])(_this2, "handleDescriptionChange", function (prompt) { _this2.controller.updateInteractionData({ prompt: prompt }); }); (0, _defineProperty2["default"])(_this2, "updateBlank", function (blankId) { return function (blankMods) { _this2.controller.updateBlank(blankId, blankMods); }; }); (0, _defineProperty2["default"])(_this2, "updateBlankScoringData", function (blankId) { return function (scoringDataModifications) { _this2.controller.updateScoringDataForBlank(blankId, scoringDataModifications); }; }); _this2.controller = new _editController["default"](props); return _this2; } (0, _inherits2["default"])(FillBlankEdit, _Component); return (0, _createClass2["default"])(FillBlankEdit, [{ key: "UNSAFE_componentWillReceiveProps", value: function UNSAFE_componentWillReceiveProps(nextProps) { this.controller.UNSAFE_componentWillReceiveProps(nextProps); } }, { key: "renderBlanksOptions", value: // ============= // RENDERING // ============= function renderBlanksOptions() { var _this3 = this; return this.controller.sortedBlanks().map(function (blank, blankIndex) { var blankScoringData = (0, _find["default"])({ id: blank.id }, _this3.props.scoringData.value) || {}; var choicesErrors = (0, _concat["default"])(_this3.getErrors("scoringData.value[".concat(blankIndex, "].scoringData.value.$errors")) || [], _this3.getErrors("interactionData.blanks[".concat(blankIndex, "].choices.$errors")) || []); return (0, _emotion.jsx)(_BlankTypeSelect["default"], { key: blank.id, answerType: blank.answerType, blankPosition: blankIndex + 1, blankScoringAlgorithm: blankScoringData.scoringAlgorithm, blankScoringData: blankScoringData.scoringData, disabled: _this3.props.overrideEditableForRegrading, choices: blank.choices, fitbCommonWordbankEnabled: _this3.props.fitbCommonWordbankEnabled, 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] || [], updateBlank: _this3.updateBlank(blank.id), updateBlankScoringData: _this3.updateBlankScoringData(blank.id), useCommonWordbank: false }); }); } }, { key: "renderCreateBlankButton", value: function renderCreateBlankButton() { if (this.state.selectedText.trim() && !this.props.overrideEditableForRegrading) { return (0, _emotion.jsx)("div", { css: this.props.styles.createButton }, (0, _emotion.jsx)(_uiButtons.Button, { onClick: this.handleCreateBlank, color: "primary-inverse" }, (0, _emotion.jsx)("span", { css: this.props.styles.createBlankText }, (0, _formatMessage["default"])('Create Blank Space')), (0, _emotion.jsx)("span", { css: this.props.styles.createBlankHotkeyText }, (0, _formatMessage["default"])('(Enter)')))); } } }, { key: "renderOptionsDescription", value: function renderOptionsDescription() { return (0, _emotion.jsx)(_uiA11yContent.ScreenReaderContent, null, (0, _formatMessage["default"])('Fill in the blank options')); } }, { key: "render", value: function render() { return (0, _emotion.jsx)("div", null, (0, _emotion.jsx)(_QuestionContainer["default"], { disabled: this.props.overrideEditableForRegrading, enableRichContentEditor: this.props.enableRichContentEditor, itemBody: this.props.interactionData.prompt, onDescriptionChange: this.handleDescriptionChange, onModalClose: this.props.onModalClose, onModalOpen: this.props.onModalOpen, openImportModal: this.props.openImportModal, placeholder: (0, _formatMessage["default"])('Add Question Stem (optional)...'), stemErrors: [] }, (0, _emotion.jsx)("div", { css: this.props.styles.hint }, (0, _emotion.jsx)(_uiText.Text, { color: "primary" }, (0, _formatMessage["default"])('Type a statement, select text, and press Enter to create a new blank.'))), (0, _emotion.jsx)(_EditStem["default"], { disabled: this.props.overrideEditableForRegrading, errors: this.getErrors('itemBody') || [], destroyBlank: this.controller.onDestroyBlank, onCreateBlankHotkey: this.handleCreateBlankHotkey, onStemChange: this.controller.onStemChange, scoringData: this.props.scoringData, setSelectedText: this.setSelectedText, stemItems: this.controller.sortedStemItems() }), (0, _emotion.jsx)("div", null, this.renderCreateBlankButton(), (0, _emotion.jsx)(_Errors["default"], { errorList: this.getErrors(['interactionData', 'blanks', '$errors']) || [] }, this.renderBlanksOptions()))), (0, _emotion.jsx)(_QuestionSettingsContainer["default"], { additionalOptions: this.props.additionalOptions }, this.props.showCalculatorOption && (0, _emotion.jsx)(_QuestionSettingsPanel["default"], { label: (0, _formatMessage["default"])('Options'), defaultExpanded: true }, (0, _emotion.jsx)(_quizCommon.FormFieldGroup, { rowSpacing: "small", description: this.renderOptionsDescription() }, (0, _emotion.jsx)(_CalculatorOptionWithOqaatAlert["default"], { disabled: this.props.overrideEditableForRegrading, calculatorValue: this.props.calculatorType, onCalculatorTypeChange: this.controller.handleCalculatorTypeChange, oqaatChecked: this.props.oneQuestionAtATime, onOqaatChange: this.props.setOneQuestionAtATime }))))); } }]); }(_react.Component), (0, _defineProperty2["default"])(_FillBlankEdit, "displayName", 'FillBlankEdit'), (0, _defineProperty2["default"])(_FillBlankEdit, "componentId", "Quizzes".concat(_FillBlankEdit.displayName)), (0, _defineProperty2["default"])(_FillBlankEdit, "interactionType", _fill_blank["default"]), (0, _defineProperty2["default"])(_FillBlankEdit, "propTypes", { additionalOptions: _propTypes["default"].array, calculatorType: _propTypes["default"].string, enableRichContentEditor: _propTypes["default"].bool, errors: _propTypes["default"].object, errorsAreShowing: _propTypes["default"].bool, fitbCommonWordbankEnabled: _propTypes["default"].bool, interactionData: _propTypes["default"].object.isRequired, notifyScreenreader: _propTypes["default"].func.isRequired, onModalClose: _propTypes["default"].func, onModalOpen: _propTypes["default"].func, oneQuestionAtATime: _propTypes["default"].bool, openImportModal: _propTypes["default"].func, overrideEditableForRegrading: _propTypes["default"].bool, scoringData: _propTypes["default"].object.isRequired, setOneQuestionAtATime: _propTypes["default"].func, validationErrorsFromApi: _propTypes["default"].object, styles: _propTypes["default"].object, showCalculatorOption: _propTypes["default"].bool }), (0, _defineProperty2["default"])(_FillBlankEdit, "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, scoringData: void 0, validationErrorsFromApi: {}, showCalculatorOption: true }), _FillBlankEdit)) || _class) || _class);