@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
177 lines (175 loc) • 7.47 kB
JavaScript
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";
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));
}
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import pick from 'lodash/pick';
// TODO: Kill this HOC and use composition instead. This thing is a nightmare to maintain...
/**
* Higher Order Component used in Edit views to pass generic helper functions
*/
export default function withEditTools(WrappedComponent) {
var _Wrapper;
var Wrapper = /*#__PURE__*/function (_Component) {
function Wrapper() {
var _this2;
_classCallCheck(this, Wrapper);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this2 = _callSuper(this, Wrapper, [].concat(args));
_defineProperty(_this2, "node", null);
/**
* default handling of stem changes
*/
_defineProperty(_this2, "handleDescriptionChange", function (itemBody) {
return _this2.props.changeItemState({
itemBody: itemBody
});
});
/**
* helper function that gives out errors in instui format
*/
_defineProperty(_this2, "getErrors", function (path) {
var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var errors = get(_this2.props.errors, path);
if (errors != null && _this2.props.errorsAreShowing) {
return formatErrors(errors);
}
return fallback;
});
_defineProperty(_this2, "getWrappedComponent", function () {
return _this2.node;
});
_defineProperty(_this2, "handleRef", function (node) {
_this2.node = node;
});
return _this2;
}
_inherits(Wrapper, _Component);
return _createClass(Wrapper, [{
key: "componentDidMount",
value:
// If the props passed to the component on mount result in validation
// errors, call the changeItemState callback with the validation errors to
// notify the parent component
function componentDidMount() {
var itemState = this.getItemState();
if (Object.keys(itemState.errors).length > 0) {
this.props.changeItemState(itemState);
}
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
var itemState = this.getItemState();
if (!isEqual(itemState.errors, prevProps.errors)) {
this.props.changeItemState(itemState);
}
}
}, {
key: "getItem",
value: function getItem() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
return pick(props, ['calculatorType', 'interactionData', 'itemBody', 'properties', 'scoringAlgorithm', 'scoringData']);
}
}, {
key: "getItemErrors",
value: function getItemErrors(item) {
return WrappedComponent.interactionType.getErrors(item);
}
}, {
key: "getItemState",
value: function getItemState() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
var item = this.getItem(props);
var errors = this.getItemErrors(item);
return _objectSpread(_objectSpread({}, item), {}, {
errors: errors
});
}
}, {
key: "render",
value:
/**
* render the decorated component, passing helpers through props
*/
function render() {
return /*#__PURE__*/React.createElement(WrappedComponent, Object.assign({
ref: this.handleRef,
onDescriptionChange: this.handleDescriptionChange,
getErrors: this.getErrors
}, this.props));
}
}]);
}(Component);
_Wrapper = Wrapper;
_defineProperty(Wrapper, "displayName", "".concat(_Wrapper.name, "(").concat(WrappedComponent.displayName, ")"));
// [jsimon]: I originally tried to switch these PropTypes.object calls to WrappedComponent.propTypes.<name> but
// these props don't exist on every edit component. To make matters worse, their shape isn't consistent so we can't
// make these more specific.
_defineProperty(Wrapper, "propTypes", {
changeItemState: PropTypes.func.isRequired,
errors: PropTypes.object,
errorsAreShowing: PropTypes.bool,
interactionData: PropTypes.object,
itemBody: PropTypes.string,
properties: PropTypes.object,
scoringData: PropTypes.object,
children: PropTypes.node
});
_defineProperty(Wrapper, "defaultProps", {
errors: void 0,
errorsAreShowing: void 0,
interactionData: void 0,
itemBody: void 0,
properties: void 0,
scoringData: void 0,
children: void 0
});
Wrapper.WrappedComponent = WrappedComponent;
return Wrapper;
}
// These can be included by components that use withEditTools, to provide
// propType validation without including these private, internal props in the
// auto-generated documentation.
withEditTools.injectedProps = {
getErrors: PropTypes.func.isRequired,
onDescriptionChange: PropTypes.func.isRequired
};
function formatErrors(node) {
if (typeof node === 'string') {
return {
text: node,
type: 'error'
};
} else if (Array.isArray(node)) {
return node.map(formatErrors);
} else if (typeof node === 'object') {
return Object.keys(node).reduce(function (obj, key) {
return _objectSpread(_objectSpread({}, obj), {}, _defineProperty({}, key, formatErrors(node[key])));
}, {});
}
return node;
}