UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

279 lines (275 loc) • 13.7 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 = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _uuid = require("uuid"); var _uiText = require("@instructure/ui-text"); var _uiA11yContent = require("@instructure/ui-a11y-content"); var _quizRce = require("@instructure/quiz-rce"); var _WordCount = require("../helpers/WordCount"); var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message")); var _quizCommon = require("@instructure/quiz-common"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 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)); } /** --- category: Essay --- Essay Take component ```jsx_example function Example (props) { const exampleProps = { itemBody: 'Why did the Roman Empire fall?', interactionData: { rce: true, spellCheck: true, wordCount: true, wordLimitEnabled: true, wordLimitMax: 10, wordLimitMin: 1, notes: 'Teachers grading notes' }, userResponse: { value: 'So it could learn to pick itself back up again.' } } return ( <EssayTake {...exampleProps} {...props} /> ) } <SettingsSwitcher locales={LOCALES}> <TakeStateProvider> <Example /> </TakeStateProvider> </SettingsSwitcher> ``` **/ var EssayTake = exports["default"] = /*#__PURE__*/function (_Component) { function EssayTake(props) { var _this2; (0, _classCallCheck2["default"])(this, EssayTake); _this2 = _callSuper(this, EssayTake, [props]); (0, _defineProperty2["default"])(_this2, "verifyErrors", function (text) { var documentTreeDepthOverLimit = _this2.isDocumentTreeDepthOverLimit(text); var dynamoRecordSize = _this2.getContentSize(text); _this2.setState({ documentTreeDepthOverLimit: documentTreeDepthOverLimit, dynamoRecordSize: dynamoRecordSize }); }); (0, _defineProperty2["default"])(_this2, "isDocumentTreeDepthOverLimit", function (text) { if (!text) return false; try { var template = document.createElement('template'); template.innerHTML = text; return _this2.isLevelOfChildrenOverLimit(template.content); } catch (e) { console.error(e); return false; } }); (0, _defineProperty2["default"])(_this2, "isLevelOfChildrenOverLimit", function (element) { var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; if (level > _quizCommon.DOCUMENT_TREE_DEPTH_LIMIT) return true; if (!element) return false; var children = element.childNodes; if (children.length === 0) return false; var childrenLevel = level + 1; return Array.from(children).some(function (e) { return _this2.isLevelOfChildrenOverLimit(e, childrenLevel); }); }); (0, _defineProperty2["default"])(_this2, "getContentSize", function (text) { if (!text) return 0; var match = new RegExp('[\&\<\>]', 'g'); // eslint-disable-line no-useless-escape // In backend the whole response is serialized into Unicode // every answer occupies CONTENT_SIZE_BY_ANSWER // every text answer is serialized twice // and then every ampersand, greater than and less than character // when converted to Unicode occupies 5 more bytes twice // Example, an & is turned into \u0026 return _quizCommon.CONTENT_SIZE_BY_ANSWER + text.length * 2 + (text.match(match) || []).length * 10; }); (0, _defineProperty2["default"])(_this2, "handleOnBlur", function (event, rceContent) { if (!_this2.props.readOnly) { var newVal = _this2.props.interactionData.rce ? rceContent.editorContent : event.target.value; if (newVal !== void 0 && newVal !== _this2.state.workingEssayContent) { _this2.props.handleResponseUpdate(newVal); _this2.verifyErrors(newVal); _this2.setState({ workingEssayContent: newVal }); } } }); (0, _defineProperty2["default"])(_this2, "handleOnChange", function (event, rceContent) { if (!_this2.props.readOnly) { var newVal = _this2.props.interactionData.rce ? rceContent.editorContent : event.target.value; if (newVal !== void 0 && newVal !== _this2.state.workingEssayContent) { _this2.props.handleResponseUpdate(newVal); _this2.setState({ workingEssayContent: newVal }); } } }); _this2.uniqId = (0, _uuid.v4)(); var workingEssayContent = props.userResponse && props.userResponse.value || ''; var _documentTreeDepthOverLimit = _this2.isDocumentTreeDepthOverLimit(workingEssayContent); var _dynamoRecordSize = _this2.getContentSize(workingEssayContent); _this2.state = { workingEssayContent: workingEssayContent, documentTreeDepthOverLimit: _documentTreeDepthOverLimit, dynamoRecordSize: _dynamoRecordSize, contentId: (0, _uuid.v4)() }; return _this2; } (0, _inherits2["default"])(EssayTake, _Component); return (0, _createClass2["default"])(EssayTake, [{ key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var _prevProps$userRespon; var userResponse = this.props.userResponse; var prevValue = (_prevProps$userRespon = prevProps.userResponse) === null || _prevProps$userRespon === void 0 ? void 0 : _prevProps$userRespon.value; var currentValue = userResponse === null || userResponse === void 0 ? void 0 : userResponse.value; if (currentValue && prevValue === undefined) { this.setState({ workingEssayContent: currentValue || '', contentId: (0, _uuid.v4)() }); } } }, { key: "renderEditor", value: function renderEditor() { var commonProps = { label: /*#__PURE__*/_react["default"].createElement(_uiA11yContent.ScreenReaderContent, null, /*#__PURE__*/_react["default"].createElement(_quizRce.RichContentRenderer, { content: this.props.itemBody })), readOnly: this.props.readOnly, onChange: this.handleOnChange, onBlur: this.handleOnBlur }; if (this.props.interactionData.rce) { var _this$props$interacti = this.props.interactionData, spellCheck = _this$props$interacti.spellCheck, wordCount = _this$props$interacti.wordCount; return /*#__PURE__*/_react["default"].createElement(_quizRce.RichContentInput, Object.assign({}, commonProps, { textareaId: "rceTextArea_".concat(this.uniqId), onKeyUp: this.handleOnChange, openImportModal: this.props.openImportModal, defaultContent: this.state.workingEssayContent, stem: this.props.itemBody, height: _quizRce.RCE_THREE_LINES_HEIGHT, editorOptions: { spellCheck: spellCheck, wordCount: wordCount }, key: this.state.contentId, disableDocumentAccess: this.props.disableDocumentAccess })); } return /*#__PURE__*/_react["default"].createElement(_quizCommon.TextArea, Object.assign({}, commonProps, { value: this.state.workingEssayContent, resize: "vertical", spellCheck: this.props.interactionData.spellCheck, autoGrow: this.context.disableTextAreaAutoGrow ? false : null })); } }, { key: "renderErrors", value: function renderErrors() { var _this$state = this.state, documentTreeDepthOverLimit = _this$state.documentTreeDepthOverLimit, dynamoRecordSize = _this$state.dynamoRecordSize; return /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement(_uiText.Text, { color: "danger", size: "small" }, documentTreeDepthOverLimit ? (0, _formatMessage["default"])('Formatting error. Please ensure that the text entry has not been pasted from a different source. Type text to submit response.') : '', dynamoRecordSize > _quizCommon.CONTENT_SIZE_LIMIT ? (0, _formatMessage["default"])('This submission is too large. Please adjust and try to submit again.') : '')); } }, { key: "renderWordCountMessage", value: function renderWordCountMessage() { var _this$props$interacti2 = this.props.interactionData, wordCount = _this$props$interacti2.wordCount, wordLimitMin = _this$props$interacti2.wordLimitMin, wordLimitEnabled = _this$props$interacti2.wordLimitEnabled, wordLimitMax = _this$props$interacti2.wordLimitMax; if (wordCount || wordLimitEnabled) { return /*#__PURE__*/_react["default"].createElement(_uiA11yContent.ScreenReaderContent, null, wordLimitEnabled && wordLimitMin ? (0, _formatMessage["default"])('This essay has a minimum word count of {wordLimitMin}.', { wordLimitMin: wordLimitMin }) : '', wordLimitEnabled && wordLimitMax ? (0, _formatMessage["default"])('This essay has a maximum word count of {wordLimitMax}.', { wordLimitMax: wordLimitMax }) : '', wordCount ? (0, _formatMessage["default"])('There is a word count below the text area.') : ''); } } }, { key: "render", value: function render() { var _this$props = this.props, interactionData = _this$props.interactionData, itemBody = _this$props.itemBody, notifyScreenreader = _this$props.notifyScreenreader; return /*#__PURE__*/_react["default"].createElement(_quizRce.ItemBodyWrapper, { itemBody: itemBody }, this.renderWordCountMessage(), /*#__PURE__*/_react["default"].createElement("div", { className: "fs-mask" }, this.renderEditor()), /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement(_WordCount.WordCount, { rce: interactionData.rce, isEditing: true, essay: this.state.workingEssayContent, wordCount: interactionData.wordCount, wordLimitEnabled: interactionData.wordLimitEnabled, wordLimitMin: parseInt(interactionData.wordLimitMin, 10), wordLimitMax: parseInt(interactionData.wordLimitMax, 10), notifyScreenreader: notifyScreenreader })), this.renderErrors()); } }]); }(_react.Component); (0, _defineProperty2["default"])(EssayTake, "propTypes", { handleResponseUpdate: _propTypes["default"].func, interactionData: _propTypes["default"].object.isRequired, itemBody: _propTypes["default"].string.isRequired, userResponse: _propTypes["default"].object, notifyScreenreader: _propTypes["default"].func, openImportModal: _propTypes["default"].func, readOnly: _propTypes["default"].bool, disableDocumentAccess: _propTypes["default"].bool }); (0, _defineProperty2["default"])(EssayTake, "defaultProps", { handleResponseUpdate: function handleResponseUpdate() {}, openImportModal: function openImportModal() {}, readOnly: false, userResponse: void 0, notifyScreenreader: void 0, disableDocumentAccess: false }); (0, _defineProperty2["default"])(EssayTake, "contextTypes", { disableTextAreaAutoGrow: _propTypes["default"].bool });