UNPKG

quiz-interactions

Version:

A React UI component Library for quiz interaction types.

418 lines (366 loc) 16.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); 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 _react = _interopRequireWildcard(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 _uiElements = require("@instructure/ui-elements"); var _uiThemeable = require("@instructure/ui-themeable"); 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 _theme = _interopRequireDefault(require("./theme")); var _withEditTools = _interopRequireDefault(require("../../../util/withEditTools")); var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/lib/format-message")); var _QuestionSettingsPanel = _interopRequireDefault(require("../../common/edit/components/QuestionSettingsPanel")); var _CalculatorOptionWithOqaatAlert = _interopRequireDefault(require("../../common/edit/components/CalculatorOptionWithOqaatAlert")); var _uiFormField = require("@instructure/ui-form-field"); var _uiA11y = require("@instructure/ui-a11y"); var _dec, _class, _class2, _temp; var styles = { componentId: 'beqzy', template: function template(theme) { return "\n\n.beqzy_bgAF{margin-top:".concat(theme.createButtonMargin || 'inherit', "}\n\n.beqzy_dYYb{margin:").concat(theme.hintMargin || 'inherit', " 0}\n\n.beqzy_ULRc{font-weight:").concat(theme.createBlankTextWeight || 'inherit', "}\n\n.beqzy_eYQy{font-size:").concat(theme.createBlankHotkeyTextSize || 'inherit', ";font-weight:").concat(theme.createBlankHotkeyTextWeight || 'inherit', ";padding-left:").concat(theme.createBlankHotkeyTextPadding || 'inherit', "}"); }, 'createButton': 'beqzy_bgAF', 'hint': 'beqzy_dYYb', 'createBlankText': 'beqzy_ULRc', 'createBlankHotkeyText': 'beqzy_eYQy' }; 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 = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), (0, _withEditTools.default)(_class = _dec(_class = (_temp = _class2 = /*#__PURE__*/ function (_Component) { (0, _inherits2.default)(FillBlankEdit, _Component); function FillBlankEdit(props) { var _this; (0, _classCallCheck2.default)(this, FillBlankEdit); _this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(FillBlankEdit).call(this, props)); _this.state = { selectedText: '' }; _this.getErrors = function (path) { if (_this.props.errorsAreShowing) { return (0, _get.default)(_this.props.errors, path, null); } return null; }; _this.setSelectedText = function (text) { _this.setState({ selectedText: text }); }; _this.handleCreateBlank = function (event) { _this.controller.onCreateBlank(event); _this.setState({ selectedText: '' }); }; _this.handleCreateBlankHotkey = function (event) { if (event.which === ENTER_KEY_CODE || event.which === SPACE_KEY_CODE && event.ctrlKey && event.altKey) { event.preventDefault(); _this.handleCreateBlank(event); _this.props.notifyScreenreader((0, _formatMessage.default)('Blank created. Navigate to edit blank below.')); } }; _this.handleDescriptionChange = function (prompt) { _this.controller.updateInteractionData({ prompt: prompt }); }; _this.controller = new _editController.default(props); return _this; } (0, _createClass2.default)(FillBlankEdit, [{ key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { this.controller.componentWillReceiveProps(nextProps); } // Other edit components use the `getErrors` helper passed in from the // withEditTools higher-order component, but fill blank has its own error // handling logic }, { key: "renderBlanksOptions", // ============= // RENDERING // ============= value: function renderBlanksOptions() { var _this2 = this; return this.controller.sortedBlanks().map(function (blank, blankIndex) { var blankScoringData = (0, _find.default)({ id: blank.id }, _this2.props.scoringData.value) || {}; var choicesErrors = (0, _concat.default)(_this2.getErrors("scoringData.value[".concat(blankIndex, "].scoringData.value.$errors")) || [], _this2.getErrors("interactionData.blanks[".concat(blankIndex, "].choices.$errors")) || []); return _react.default.createElement(_BlankTypeSelect.default, { key: blank.id, answerType: blank.answerType, blankPosition: blankIndex + 1, blankScoringAlgorithm: blankScoringData.scoringAlgorithm, blankScoringData: blankScoringData.scoringData, disabled: _this2.props.overrideEditableForRegrading, choices: blank.choices, interactionDataErrors: _this2.getErrors("interactionData.blanks[".concat(blankIndex, "]")) || {}, name: blank.id, notifyScreenreader: _this2.props.notifyScreenreader, onModalClose: _this2.props.onModalClose, onModalOpen: _this2.props.onModalOpen, scoringDataErrors: _this2.getErrors("scoringData.value[".concat(blankIndex, "].scoringData")) || {}, choicesErrors: choicesErrors, updateBlank: function updateBlank(blankMods) { _this2.controller.updateBlank(blank.id, blankMods); }, updateBlankScoringData: function updateBlankScoringData(scoringDataModifications) { _this2.controller.updateScoringDataForBlank(blank.id, scoringDataModifications); } }); }); } }, { key: "renderCreateBlankButton", value: function renderCreateBlankButton() { if (this.state.selectedText.trim() && !this.props.overrideEditableForRegrading) { return _react.default.createElement("div", { className: styles.createButton }, _react.default.createElement(_uiButtons.Button, { onClick: this.handleCreateBlank, variant: "light" }, _react.default.createElement("span", { className: styles.createBlankText }, (0, _formatMessage.default)('Create Blank Space')), _react.default.createElement("span", { className: styles.createBlankHotkeyText }, (0, _formatMessage.default)('(Enter)')))); } } }, { key: "renderOptionsDescription", value: function renderOptionsDescription() { return _react.default.createElement(_uiA11y.ScreenReaderContent, null, (0, _formatMessage.default)('Fill in the blank options')); } }, { key: "render", value: function render() { return _react.default.createElement("div", null, _react.default.createElement(_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)...'), renderImportModal: this.props.renderImportModal, stemErrors: [] }, _react.default.createElement("div", { className: styles.hint }, _react.default.createElement(_uiElements.Text, { color: "primary" }, (0, _formatMessage.default)('Type a statement, select text, and press Enter to create a new blank.'))), _react.default.createElement(_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() }), _react.default.createElement("div", null, this.renderCreateBlankButton(), _react.default.createElement(_Errors.default, { errorList: this.getErrors(['interactionData', 'blanks', '$errors']) || [] }, this.renderBlanksOptions()))), _react.default.createElement(_QuestionSettingsContainer.default, { additionalOptions: this.props.additionalOptions }, !this.props.hiddenOptions.calculator && _react.default.createElement(_QuestionSettingsPanel.default, { label: (0, _formatMessage.default)('Options'), defaultExpanded: true }, _react.default.createElement(_uiFormField.FormFieldGroup, { rowSpacing: "small", description: this.renderOptionsDescription() }, _react.default.createElement(_CalculatorOptionWithOqaatAlert.default, { disabled: this.props.overrideEditableForRegrading, calculatorValue: this.props.calculatorType, onCalculatorTypeChange: this.controller.handleCalculatorTypeChange, oqaatChecked: this.props.oneQuestionAtATime, onOqaatChange: this.props.setOneQuestionAtATime }))))); } }]); FillBlankEdit.displayName = "FillBlankEdit"; return FillBlankEdit; }(_react.Component), _class2.interactionType = _fill_blank.default, _class2.propTypes = { additionalOptions: _propTypes.default.array, calculatorType: _propTypes.default.string, enableRichContentEditor: _propTypes.default.bool, errors: _propTypes.default.object, errorsAreShowing: _propTypes.default.bool, hiddenOptions: _propTypes.default.shape({ calculator: _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, renderImportModal: _propTypes.default.func, scoringData: _propTypes.default.object.isRequired, setOneQuestionAtATime: _propTypes.default.func }, _class2.defaultProps = { calculatorType: 'none', enableRichContentEditor: true, hiddenOptions: { calculator: true }, 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, renderImportModal: void 0, scoringData: void 0 }, _temp)) || _class) || _class); exports.default = FillBlankEdit;