quiz-interactions
Version:
A React UI component Library for quiz interaction types.
449 lines (376 loc) • 16.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.drawTypes = drawTypes;
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
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 _getPrototypeOf3 = _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 _immutabilityHelper = _interopRequireDefault(require("immutability-helper"));
var _pick = _interopRequireDefault(require("lodash/fp/pick"));
var _find2 = _interopRequireDefault(require("lodash/fp/find"));
var _uiElements = require("@instructure/ui-elements");
var _uiIcons = require("@instructure/ui-icons");
var _uiThemeable = require("@instructure/ui-themeable");
var _hotspot = _interopRequireDefault(require("../../../records/interactions/hotspot"));
var _QuestionSettingsContainer = _interopRequireDefault(require("../../common/edit/components/QuestionSettingsContainer"));
var _QuestionContainer = _interopRequireDefault(require("../../common/edit/components/QuestionContainer"));
var _RemoveChoiceButton = _interopRequireDefault(require("../../common/edit/components/RemoveChoiceButton"));
var _DrawingContainer = _interopRequireDefault(require("./DrawingContainer"));
var _Oval = _interopRequireDefault(require("../common/Oval"));
var _Polygon = _interopRequireDefault(require("../common/Polygon"));
var _Square = _interopRequireDefault(require("../common/Square"));
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;
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(source, true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var styles = {
componentId: 'ckcaF',
template: function template(theme) {
return "\n\n.ckcaF_dTIX{align-items:flex-end;display:flex;margin-top:".concat(theme.footerContainerMargin || 'inherit', "}\n\n.ckcaF_fhUM{flex:1}\n\n.ckcaF_djjy{align-items:center;display:flex;margin:").concat(theme.accessibilityInfoMargin || 'inherit', " 0 ").concat(theme.accessibilityInfoMargin || 'inherit', " 0}\n\n.ckcaF_cMfx{margin-right:").concat(theme.iconRightMargin || 'inherit', "}");
},
'footerContainer': 'ckcaF_dTIX',
'footerContainerText': 'ckcaF_fhUM',
'accessibilityInfo': 'ckcaF_djjy',
'accessibilityInfoIcon': 'ckcaF_cMfx'
};
function drawTypes() {
return [{
type: 'square',
title: (0, _formatMessage.default)('Square'),
icon: _uiIcons.IconBoxLine,
component: _Square.default
}, {
type: 'oval',
title: (0, _formatMessage.default)('Oval'),
icon: _uiIcons.IconEmptyLine,
component: _Oval.default
}, {
type: 'polygon',
title: (0, _formatMessage.default)('Polygon'),
icon: _uiIcons.IconMarkerLine,
component: _Polygon.default
}];
}
/**
---
category: HotSpot
---
HotSpot Edit component
```jsx_example
function Example (props) {
const exampleProps = {
itemBody: 'Which of these players is David Ferrer',
interactionData: {
imageUrl: 'https://i.ytimg.com/vi/LgkAebhJ7iE/maxresdefault.jpg'
},
scoringData: {
value: {
type: 'oval',
coordinates: [
{ x: 0.6, y: 0.13 },
{ x: 0.7, y: 0.2 }
]
}
}
}
return (
<HotSpotEdit {...exampleProps} {...props} />
)
}
<SettingsSwitcher locales={LOCALES}>
<EditStateProvider>
<Example />
</EditStateProvider>
</SettingsSwitcher>
```
**/
var HotSpotEdit = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), (0, _withEditTools.default)(_class = _dec(_class = (_temp = _class2 =
/*#__PURE__*/
function (_Component) {
(0, _inherits2.default)(HotSpotEdit, _Component);
function HotSpotEdit() {
var _getPrototypeOf2;
var _this;
(0, _classCallCheck2.default)(this, HotSpotEdit);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = (0, _possibleConstructorReturn2.default)(this, (_getPrototypeOf2 = (0, _getPrototypeOf3.default)(HotSpotEdit)).call.apply(_getPrototypeOf2, [this].concat(args)));
_this.drawingContainer = null;
_this.state = {
file: null
};
_this.updateProps = function (newProps) {
var propsToUpdate = (0, _pick.default)(['interactionData', 'scoringData', 'properties'], _this.props);
_this.props.changeItemState((0, _immutabilityHelper.default)(propsToUpdate, newProps));
};
_this.convertCoordinates = function (coordinatesArray) {
var convertedCoordinates = coordinatesArray.map(function (_ref) {
var x = _ref.x,
y = _ref.y;
return {
x: x / _this.drawingContainer.currentImageWidth(),
y: y / _this.drawingContainer.currentImageHeight()
};
});
_this.updateProps({
scoringData: {
value: {
coordinates: {
$set: convertedCoordinates
}
}
}
});
};
_this.handleCalculatorTypeChange = function (e, value) {
_this.props.changeItemState({
calculatorType: value
});
};
_this.handleTypeChange = function (newType) {
_this.updateProps({
scoringData: {
value: {
$set: {
type: newType,
coordinates: []
}
}
}
});
};
_this.handleRemoveImage = function () {
_this.updateProps({
interactionData: {
$set: {}
},
scoringData: {
value: {
coordinates: {
$set: []
}
}
}
});
};
_this.handleUpload = function (url) {
_this.updateProps({
interactionData: {
imageUrl: {
$set: url
}
},
scoringData: {
value: {
$set: {
coordinates: [],
type: 'square'
}
}
}
});
_this.setState({
file: null
});
};
_this.handleDropAccepted = function (_ref2) {
var _ref3 = (0, _slicedToArray2.default)(_ref2, 1),
file = _ref3[0];
if (file instanceof Blob) {
var reader = new FileReader();
reader.onload = function (e) {
_this.setState({
file: {
url: e.target.result
}
});
};
reader.readAsDataURL(file);
}
_this.setState({
file: {}
});
_this.props.mediaUpload(file, _this.handleUpload);
};
_this.handleDrawingRemove = function () {
_this.drawingContainer.canvas.clearCanvas();
_this.drawingContainer.canvas.focus();
_this.handleTypeChange(_this.props.scoringData.value.type);
};
_this.handleDescriptionChange = function (itemBody) {
return _this.props.changeItemState({
itemBody: itemBody
});
};
_this.handleDrawingContainerRef = function (node) {
_this.drawingContainer = node;
};
return _this;
}
(0, _createClass2.default)(HotSpotEdit, [{
key: "renderFooter",
// ===========
// RENDER
// ===========
value: function renderFooter() {
var coordinates = this.props.scoringData.value.coordinates;
var url = this.props.interactionData.imageUrl;
if (url !== void 0 && coordinates !== void 0 && coordinates.length > 1) {
var _find = (0, _find2.default)({
type: this.props.scoringData.value.type
}, drawTypes()),
title = _find.title; // FIXME: some of the translations for this don't look right (fr, it...)
var mainText = (0, _formatMessage.default)('{title} Hot Spot', {
title: title
});
return _react.default.createElement("div", {
className: styles.footerContainer
}, _react.default.createElement("div", {
className: styles.footerContainerText
}, _react.default.createElement("div", null, _react.default.createElement(_uiElements.Text, {
weight: "bold"
}, mainText)), _react.default.createElement("div", null, _react.default.createElement(_uiElements.Text, {
color: "primary"
}, (0, _formatMessage.default)('Clicks within the hot spot will receive full points')))), _react.default.createElement(_RemoveChoiceButton.default, {
buttonSize: "large",
onRemoveChoice: this.handleDrawingRemove,
screenReaderText: (0, _formatMessage.default)('Remove current drawing')
}));
}
}
}, {
key: "renderOptionsDescription",
value: function renderOptionsDescription() {
return _react.default.createElement(_uiA11y.ScreenReaderContent, null, (0, _formatMessage.default)('Hotspot options'));
}
}, {
key: "render",
value: function render() {
return _react.default.createElement("div", null, _react.default.createElement("div", {
className: styles.accessibilityInfo
}, _react.default.createElement(_uiElements.Text, {
color: "secondary"
}, _react.default.createElement(_uiIcons.IconInfoLine, {
size: "x-small",
className: styles.accessibilityInfoIcon
}), (0, _formatMessage.default)('This question type is not accessible to users requiring keyboard-only access or screen readers.'))), _react.default.createElement(_QuestionContainer.default, {
disabled: this.props.overrideEditableForRegrading,
enableRichContentEditor: this.props.enableRichContentEditor,
itemBody: this.props.itemBody,
onDescriptionChange: this.handleDescriptionChange,
onModalClose: this.props.onModalClose,
onModalOpen: this.props.onModalOpen,
openImportModal: this.props.openImportModal,
renderImportModal: this.props.renderImportModal,
stemErrors: this.props.getErrors('itemBody')
}, _react.default.createElement(_DrawingContainer.default, {
ref: this.handleDrawingContainerRef,
canvasErrors: this.props.getErrors('scoringData.value.coordinates'),
coordinates: this.props.scoringData.value.coordinates,
currentType: this.props.scoringData.value.type,
drawTypes: drawTypes(),
fileDropErrors: this.props.getErrors('interactionData.imageUrl'),
onModalOpen: this.props.onModalOpen,
onModalClose: this.props.onModalClose,
onDropAccepted: this.handleDropAccepted,
onSetType: this.handleTypeChange,
convertCoordinates: this.convertCoordinates,
onRemoveImage: this.handleRemoveImage,
typeErrors: this.props.getErrors('scoringData.value.type'),
url: this.props.interactionData.imageUrl || this.state.file && this.state.file.url,
isUploading: this.state.file !== null
}), this.renderFooter()), _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.handleCalculatorTypeChange,
oqaatChecked: this.props.oneQuestionAtATime,
onOqaatChange: this.props.setOneQuestionAtATime
})))));
}
}]);
HotSpotEdit.displayName = "HotSpotEdit";
return HotSpotEdit;
}(_react.Component), _class2.interactionType = _hotspot.default, _class2.propTypes = _objectSpread({
additionalOptions: _propTypes.default.array,
calculatorType: _propTypes.default.string,
changeItemState: _propTypes.default.func.isRequired,
enableRichContentEditor: _propTypes.default.bool,
errors: _propTypes.default.shape({
itemBody: _propTypes.default.arrayOf(_propTypes.default.string),
interactionData: _propTypes.default.shape({
imageUrl: _propTypes.default.arrayOf(_propTypes.default.string)
}),
scoringData: _propTypes.default.shape({
value: _propTypes.default.shape({
type: _propTypes.default.arrayOf(_propTypes.default.string),
coordinates: _propTypes.default.arrayOf(_propTypes.default.string)
})
})
}),
hiddenOptions: _propTypes.default.shape({
calculator: _propTypes.default.bool
}),
interactionData: _propTypes.default.shape({
imageUrl: _propTypes.default.string
}).isRequired,
itemBody: _propTypes.default.string,
mediaUpload: _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.shape({
value: _propTypes.default.shape({
type: _propTypes.default.oneOf(['square', 'oval', 'polygon']),
coordinates: _propTypes.default.arrayOf(_propTypes.default.shape({
x: _propTypes.default.number.isRequired,
y: _propTypes.default.number.isRequired
}))
}).isRequired
}).isRequired,
setOneQuestionAtATime: _propTypes.default.func
}, _withEditTools.default.injectedProps), _class2.defaultProps = {
calculatorType: 'none',
enableRichContentEditor: true,
hiddenOptions: {
calculator: true
},
oneQuestionAtATime: false,
overrideEditableForRegrading: false,
setOneQuestionAtATime: Function.prototype,
additionalOptions: void 0,
errors: void 0,
itemBody: void 0,
onModalClose: void 0,
onModalOpen: void 0,
openImportModal: void 0,
renderImportModal: void 0
}, _temp)) || _class) || _class);
exports.default = HotSpotEdit;