@instructure/quiz-core 21.0.0 → 21.0.1-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/es/banks/components/BankEntry/presenter.js +2 -2
  2. package/es/banks/components/BanksList/presenter.js +1 -1
  3. package/es/banks/components/SharingModal/presenter.js +2 -2
  4. package/es/building/components/layout/header/BuildingButtons/theme.js +1 -1
  5. package/es/building/components/resources/quizEntry/QuizEntryEdit/Footer/presenter.js +2 -2
  6. package/es/building/components/resources/quizEntry/QuizEntryEdit/presenter.js +2 -2
  7. package/es/common/actions/taking.js +3 -2
  8. package/es/common/components/PrintFontSizeModal/presenter.js +2 -2
  9. package/es/common/components/SDKApp/index.js +4 -4
  10. package/es/common/components/layout/navbar/theme.js +1 -1
  11. package/es/common/components/resources/entry/EntrySave/presenter.js +2 -2
  12. package/es/common/components/resources/stimulus/StimulusEditInfo/index.js +5 -1
  13. package/es/common/components/resources/stimulus/StimulusEditInfo/presenter.js +15 -2
  14. package/es/common/components/resources/stimulus/StimulusShow/index.js +1 -1
  15. package/es/common/components/shared/Card/CardWrapper/theme.js +1 -1
  16. package/es/common/components/shared/PaginatedCollection/presenter.js +2 -2
  17. package/es/common/components/shared/TimeUnitsInput/index.js +2 -2
  18. package/es/common/components/shared/functionality/makeEditable.js +2 -2
  19. package/es/common/reducers/taking.js +5 -1
  20. package/es/common/selectors/taking.js +3 -0
  21. package/es/common/util/getClientIpAddress.js +35 -0
  22. package/es/common/util/serializeEvent.js +4 -2
  23. package/es/index.js +2 -3
  24. package/es/moderating/components/events/Event.js +27 -10
  25. package/es/moderating/components/events/ResponseEvent.js +24 -7
  26. package/es/moderating/components/events/SessionStartEvent.js +16 -15
  27. package/es/moderating/components/events/SessionSubmitEvent.js +42 -0
  28. package/es/moderating/components/resources/AccommodationsModal/ExtraTimeMultiplier/index.js +2 -2
  29. package/es/moderating/components/resources/EventDetails.js +43 -0
  30. package/es/moderating/components/resources/SessionBreachAlert.js +10 -0
  31. package/es/moderating/components/resources/util/checkIsBreach.js +28 -0
  32. package/es/moderating/components/resources/util/extractSessionData.js +20 -0
  33. package/es/reporting/components/resources/QuizAndItemAnalysis/presenter.js +2 -2
  34. package/es/reporting/components/resources/common/propTypes.js +14 -0
  35. package/es/taking/api/taking.js +26 -3
  36. package/lib/banks/components/BankEntry/presenter.js +2 -2
  37. package/lib/banks/components/BanksList/presenter.js +1 -1
  38. package/lib/banks/components/SharingModal/presenter.js +2 -2
  39. package/lib/building/components/layout/header/BuildingButtons/theme.js +1 -1
  40. package/lib/building/components/resources/quizEntry/QuizEntryEdit/Footer/presenter.js +2 -2
  41. package/lib/building/components/resources/quizEntry/QuizEntryEdit/presenter.js +2 -2
  42. package/lib/common/actions/taking.js +3 -2
  43. package/lib/common/components/PrintFontSizeModal/presenter.js +2 -2
  44. package/lib/common/components/SDKApp/index.js +4 -4
  45. package/lib/common/components/layout/navbar/theme.js +1 -1
  46. package/lib/common/components/resources/entry/EntrySave/presenter.js +2 -2
  47. package/lib/common/components/resources/stimulus/StimulusEditInfo/index.js +5 -1
  48. package/lib/common/components/resources/stimulus/StimulusEditInfo/presenter.js +15 -2
  49. package/lib/common/components/resources/stimulus/StimulusShow/index.js +1 -1
  50. package/lib/common/components/shared/Card/CardWrapper/theme.js +1 -1
  51. package/lib/common/components/shared/PaginatedCollection/presenter.js +2 -2
  52. package/lib/common/components/shared/TimeUnitsInput/index.js +2 -2
  53. package/lib/common/components/shared/functionality/makeEditable.js +2 -2
  54. package/lib/common/reducers/taking.js +5 -1
  55. package/lib/common/selectors/taking.js +5 -1
  56. package/lib/common/util/getClientIpAddress.js +43 -0
  57. package/lib/common/util/serializeEvent.js +3 -1
  58. package/lib/index.js +15 -0
  59. package/lib/moderating/components/events/Event.js +26 -9
  60. package/lib/moderating/components/events/ResponseEvent.js +25 -7
  61. package/lib/moderating/components/events/SessionStartEvent.js +16 -15
  62. package/lib/moderating/components/events/SessionSubmitEvent.js +52 -0
  63. package/lib/moderating/components/resources/AccommodationsModal/ExtraTimeMultiplier/index.js +2 -2
  64. package/lib/moderating/components/resources/EventDetails.js +51 -0
  65. package/lib/moderating/components/resources/SessionBreachAlert.js +18 -0
  66. package/lib/moderating/components/resources/util/checkIsBreach.js +36 -0
  67. package/lib/moderating/components/resources/util/extractSessionData.js +28 -0
  68. package/lib/reporting/components/resources/QuizAndItemAnalysis/presenter.js +2 -2
  69. package/lib/reporting/components/resources/common/propTypes.js +18 -2
  70. package/lib/taking/api/taking.js +26 -3
  71. package/package.json +34 -33
@@ -18,9 +18,12 @@ var _uiTable = require("@instructure/ui-table");
18
18
  var _ElapsedTime = _interopRequireDefault(require("../resources/ElapsedTime.js"));
19
19
  var _ResponseEvent = _interopRequireDefault(require("./ResponseEvent.js"));
20
20
  var _SessionStartEvent = _interopRequireDefault(require("./SessionStartEvent.js"));
21
+ var _SessionSubmitEvent = require("./SessionSubmitEvent.js");
21
22
  var _RCEEvent = _interopRequireDefault(require("./RCEEvent.js"));
22
23
  var _PageBlurredEvent = _interopRequireDefault(require("./PageBlurredEvent.js"));
23
24
  var _PageFocusedEvent = _interopRequireDefault(require("./PageFocusedEvent.js"));
25
+ var _extractSessionData = require("../resources/util/extractSessionData.js");
26
+ var _checkIsBreach = require("../resources/util/checkIsBreach.js");
24
27
  var _Event;
25
28
  var _ref = /*#__PURE__*/_react.default.createElement(_PageBlurredEvent.default, null);
26
29
  var _ref2 = /*#__PURE__*/_react.default.createElement(_PageFocusedEvent.default, null);
@@ -33,26 +36,34 @@ var Event = /*#__PURE__*/function (_Component) {
33
36
  }
34
37
  (0, _createClass2.default)(Event, [{
35
38
  key: "renderResponseEvent",
36
- value: function renderResponseEvent(event) {
39
+ value: function renderResponseEvent(event, validationErrors, currentEventData) {
37
40
  var item = event.getItem();
38
41
  if (!item) {
39
42
  return null;
40
43
  } else {
41
44
  return /*#__PURE__*/_react.default.createElement(_ResponseEvent.default, {
42
45
  event: event,
43
- item: item
46
+ item: item,
47
+ validationErrors: validationErrors,
48
+ currentEventData: currentEventData
44
49
  });
45
50
  }
46
51
  }
47
52
  }, {
48
53
  key: "renderPayload",
49
- value: function renderPayload(event) {
54
+ value: function renderPayload(event, validationErrors, currentEventData) {
50
55
  switch (event.eventType) {
51
56
  case _quizCommon.RESPONSE:
52
- return this.renderResponseEvent(event);
57
+ return this.renderResponseEvent(event, validationErrors, currentEventData);
53
58
  case _quizCommon.SESSION_STARTED_OR_RESUMED_EVENT:
54
59
  return /*#__PURE__*/_react.default.createElement(_SessionStartEvent.default, {
55
- event: event
60
+ validationErrors: validationErrors,
61
+ currentEventData: currentEventData
62
+ });
63
+ case _quizCommon.QUIZ_SUBMISSION_EVENT:
64
+ return /*#__PURE__*/_react.default.createElement(_SessionSubmitEvent.SessionSubmitEvent, {
65
+ validationErrors: validationErrors,
66
+ currentEventData: currentEventData
56
67
  });
57
68
  case _quizCommon.RCE_EVENT:
58
69
  return /*#__PURE__*/_react.default.createElement(_RCEEvent.default, {
@@ -72,8 +83,12 @@ var Event = /*#__PURE__*/function (_Component) {
72
83
  value: function render() {
73
84
  var _this$props = this.props,
74
85
  event = _this$props.event,
75
- startTime = _this$props.startTime;
76
- var payloadNode = this.renderPayload(event);
86
+ startTime = _this$props.startTime,
87
+ firstEvent = _this$props.firstEvent;
88
+ var currentEventData = (0, _extractSessionData.extractSessionData)(event);
89
+ var firstEventData = (0, _extractSessionData.extractSessionData)(firstEvent);
90
+ var validationErrors = (0, _checkIsBreach.checkIsBreach)(firstEventData, currentEventData);
91
+ var payloadNode = this.renderPayload(event, validationErrors, currentEventData);
77
92
  if (!payloadNode) return null;
78
93
  return /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, /*#__PURE__*/_react.default.createElement(_ElapsedTime.default, {
79
94
  eventTime: event.createdDate(),
@@ -91,11 +106,13 @@ Event.displayName = 'Row';
91
106
  Event.componentId = "Quizzes".concat(_Event.displayName);
92
107
  Event.propTypes = {
93
108
  event: _reactImmutableProptypes.default.record,
94
- startTime: _propTypes.default.instanceOf(Date)
109
+ startTime: _propTypes.default.instanceOf(Date),
110
+ firstEvent: _reactImmutableProptypes.default.record
95
111
  };
96
112
  Event.defaultProps = {
97
113
  event: void 0,
98
- startTime: void 0
114
+ startTime: void 0,
115
+ firstEvent: void 0
99
116
  };
100
117
  var _default = Event;
101
118
  exports.default = _default;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
4
5
  Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
@@ -9,7 +10,7 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
9
10
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
11
  var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
11
12
  var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper"));
12
- var _react = require("react");
13
+ var _react = _interopRequireWildcard(require("react"));
13
14
  var _reactImmutableProptypes = _interopRequireDefault(require("react-immutable-proptypes"));
14
15
  var _propTypes = _interopRequireDefault(require("prop-types"));
15
16
  var _uiIcons = require("@instructure/ui-icons");
@@ -19,9 +20,11 @@ var _uiToggleDetails = require("@instructure/ui-toggle-details");
19
20
  var _emotion = require("@instructure/emotion");
20
21
  var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
21
22
  var _quizInteractions = require("@instructure/quiz-interactions");
23
+ var _EventDetails = require("../resources/EventDetails.js");
22
24
  var _styles = _interopRequireDefault(require("./styles.js"));
23
25
  var _theme = _interopRequireDefault(require("./theme.js"));
24
26
  var _quizCommon = require("@instructure/quiz-common");
27
+ var _propTypes2 = require("../../../reporting/components/resources/common/propTypes.js");
25
28
  var _dec, _class, _ResponseEvent;
26
29
  /** @jsx jsx */
27
30
  var imgRegex = /<img.*?src=['"](.+)['"]/g;
@@ -51,13 +54,16 @@ var ResponseEvent = (_dec = (0, _quizCommon.withStyleOverrides)(_styles.default,
51
54
  }, {
52
55
  key: "renderTextSummary",
53
56
  value: function renderTextSummary() {
57
+ var isBreach = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
54
58
  var strippedItemBody = (0, _quizInteractions.extractTextFromHtml)(this.itemBody);
55
59
  return (0, _emotion.jsx)("span", null, this.hasMedia() && (0, _emotion.jsx)(_uiIcons.IconImageSolid, {
56
60
  css: this.props.styles.answerMediaIcon
57
- }), (0, _formatMessage.default)('Answered question {position}: {question}', {
61
+ }), (0, _emotion.jsx)(_uiText.Text, {
62
+ color: isBreach ? 'danger' : 'primary'
63
+ }, (0, _formatMessage.default)('Answered question {position}: {question}', {
58
64
  position: this.props.event.getIn(['eventData', 'position']),
59
65
  question: strippedItemBody
60
- }));
66
+ })));
61
67
  }
62
68
  }, {
63
69
  key: "renderMedia",
@@ -85,16 +91,26 @@ var ResponseEvent = (_dec = (0, _quizCommon.withStyleOverrides)(_styles.default,
85
91
  }, {
86
92
  key: "render",
87
93
  value: function render() {
94
+ var _this$props = this.props,
95
+ validationErrors = _this$props.validationErrors,
96
+ currentEventData = _this$props.currentEventData;
88
97
  var responseText = this.getReadableResponseText();
89
98
  if (responseText) {
90
99
  // If this returns falsey, then we know to just display the stem
91
100
  return (0, _emotion.jsx)(_uiToggleDetails.ToggleDetails, {
92
- summary: this.renderTextSummary()
93
- }, this.renderMedia(), responseText);
101
+ summary: this.renderTextSummary(validationErrors.isBreach)
102
+ }, this.renderMedia(), (0, _emotion.jsx)(_EventDetails.EventDetails, {
103
+ currentEventData: currentEventData,
104
+ validationErrors: validationErrors,
105
+ answerValue: responseText
106
+ }));
94
107
  } else {
95
108
  return (0, _emotion.jsx)(_uiText.Text, {
96
109
  size: "small"
97
- }, this.renderTextSummary(), this.renderMedia());
110
+ }, this.renderTextSummary(validationErrors.isBreach), (0, _emotion.jsx)(_EventDetails.EventDetails, {
111
+ currentEventData: currentEventData,
112
+ validationErrors: validationErrors
113
+ }), this.renderMedia());
98
114
  }
99
115
  }
100
116
  }, {
@@ -108,7 +124,9 @@ var ResponseEvent = (_dec = (0, _quizCommon.withStyleOverrides)(_styles.default,
108
124
  }(_react.Component), _ResponseEvent.displayName = 'ResponseEvent', _ResponseEvent.componentId = "Quizzes".concat(_ResponseEvent.displayName), _ResponseEvent.propTypes = {
109
125
  event: _reactImmutableProptypes.default.record.isRequired,
110
126
  item: _reactImmutableProptypes.default.record.isRequired,
111
- styles: _propTypes.default.object
127
+ styles: _propTypes.default.object,
128
+ validationErrors: _propTypes2.sessionValidationErrorsPropType,
129
+ currentEventData: _propTypes2.eventDataPropType
112
130
  }, _ResponseEvent)) || _class);
113
131
  exports.ResponseEvent = ResponseEvent;
114
132
  var _default = ResponseEvent;
@@ -11,11 +11,11 @@ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/creat
11
11
  var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
12
12
  var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper"));
13
13
  var _react = _interopRequireWildcard(require("react"));
14
- var _reactImmutableProptypes = _interopRequireDefault(require("react-immutable-proptypes"));
15
- var _platform = _interopRequireDefault(require("platform"));
14
+ var _EventDetails = require("../resources/EventDetails.js");
16
15
  var _uiToggleDetails = require("@instructure/ui-toggle-details");
17
- var _uiTable = require("@instructure/ui-table");
18
16
  var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
17
+ var _uiText = require("@instructure/ui-text");
18
+ var _propTypes = require("../../../reporting/components/resources/common/propTypes.js");
19
19
  var SessionStartEvent = /*#__PURE__*/function (_Component) {
20
20
  (0, _inherits2.default)(SessionStartEvent, _Component);
21
21
  var _super = (0, _createSuper2.default)(SessionStartEvent);
@@ -26,18 +26,18 @@ var SessionStartEvent = /*#__PURE__*/function (_Component) {
26
26
  (0, _createClass2.default)(SessionStartEvent, [{
27
27
  key: "render",
28
28
  value: function render() {
29
- var event = this.props.event;
30
- var userPlatform = _platform.default.parse(event.getIn(['eventData', 'userAgent']));
29
+ var _this$props = this.props,
30
+ validationErrors = _this$props.validationErrors,
31
+ currentEventData = _this$props.currentEventData;
32
+ var summary = /*#__PURE__*/_react.default.createElement(_uiText.Text, {
33
+ color: validationErrors.isBreach ? 'danger' : 'primary'
34
+ }, (0, _formatMessage.default)('Session started'));
31
35
  return /*#__PURE__*/_react.default.createElement(_uiToggleDetails.ToggleDetails, {
32
- summary: (0, _formatMessage.default)('Session started')
33
- }, /*#__PURE__*/_react.default.createElement(_uiTable.Table, {
34
- caption: (0, _formatMessage.default)('System details')
35
- }, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Head, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.ColHeader, {
36
- id: "system-details-attribute"
37
- }, (0, _formatMessage.default)('attribute')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.ColHeader, {
38
- id: "system-details-value"
39
- }, (0, _formatMessage.default)('value')))), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Body, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, (0, _formatMessage.default)('Browser')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, // eslint-disable-next-line react/jsx-no-literals
40
- "".concat(userPlatform.name, " ").concat(userPlatform.version))), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, (0, _formatMessage.default)('Operating System')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, userPlatform.os.toString())))));
36
+ summary: summary
37
+ }, /*#__PURE__*/_react.default.createElement(_EventDetails.EventDetails, {
38
+ currentEventData: currentEventData,
39
+ validationErrors: validationErrors
40
+ }));
41
41
  }
42
42
  }]);
43
43
  SessionStartEvent.displayName = "SessionStartEvent";
@@ -45,7 +45,8 @@ var SessionStartEvent = /*#__PURE__*/function (_Component) {
45
45
  }(_react.Component);
46
46
  exports.SessionStartEvent = SessionStartEvent;
47
47
  SessionStartEvent.propTypes = {
48
- event: _reactImmutableProptypes.default.record.isRequired
48
+ validationErrors: _propTypes.sessionValidationErrorsPropType,
49
+ currentEventData: _propTypes.eventDataPropType
49
50
  };
50
51
  var _default = SessionStartEvent;
51
52
  exports.default = _default;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = exports.SessionSubmitEvent = void 0;
9
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
11
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
12
+ var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper"));
13
+ var _react = _interopRequireWildcard(require("react"));
14
+ var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
15
+ var _EventDetails = require("../resources/EventDetails.js");
16
+ var _uiToggleDetails = require("@instructure/ui-toggle-details");
17
+ var _uiText = require("@instructure/ui-text");
18
+ var _propTypes = require("../../../reporting/components/resources/common/propTypes.js");
19
+ var SessionSubmitEvent = /*#__PURE__*/function (_Component) {
20
+ (0, _inherits2.default)(SessionSubmitEvent, _Component);
21
+ var _super = (0, _createSuper2.default)(SessionSubmitEvent);
22
+ function SessionSubmitEvent() {
23
+ (0, _classCallCheck2.default)(this, SessionSubmitEvent);
24
+ return _super.apply(this, arguments);
25
+ }
26
+ (0, _createClass2.default)(SessionSubmitEvent, [{
27
+ key: "render",
28
+ value: function render() {
29
+ var _this$props = this.props,
30
+ validationErrors = _this$props.validationErrors,
31
+ currentEventData = _this$props.currentEventData;
32
+ var summary = /*#__PURE__*/_react.default.createElement(_uiText.Text, {
33
+ color: validationErrors.isBreach ? 'danger' : 'primary'
34
+ }, (0, _formatMessage.default)('Session submitted'));
35
+ return /*#__PURE__*/_react.default.createElement(_uiToggleDetails.ToggleDetails, {
36
+ summary: summary
37
+ }, /*#__PURE__*/_react.default.createElement(_EventDetails.EventDetails, {
38
+ currentEventData: currentEventData,
39
+ validationErrors: validationErrors
40
+ }));
41
+ }
42
+ }]);
43
+ SessionSubmitEvent.displayName = "SessionSubmitEvent";
44
+ return SessionSubmitEvent;
45
+ }(_react.Component);
46
+ exports.SessionSubmitEvent = SessionSubmitEvent;
47
+ SessionSubmitEvent.propTypes = {
48
+ validationErrors: _propTypes.sessionValidationErrorsPropType,
49
+ currentEventData: _propTypes.eventDataPropType
50
+ };
51
+ var _default = SessionSubmitEvent;
52
+ exports.default = _default;
@@ -91,8 +91,8 @@ var ExtraTimeMultiplier = /*#__PURE__*/function (_withI18nSupport) {
91
91
  return _this;
92
92
  }
93
93
  (0, _createClass2.default)(ExtraTimeMultiplier, [{
94
- key: "componentWillMount",
95
- value: function componentWillMount() {
94
+ key: "UNSAFE_componentWillMount",
95
+ value: function UNSAFE_componentWillMount() {
96
96
  var multiplierValue = Math.max(this.props.timerMultiplierValue, this.props.minMultiplier);
97
97
  var multiplierValueString = this.formatDecimal2FractionDigits(multiplierValue);
98
98
  this.setState({
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.EventDetails = void 0;
8
+ var _uiTable = require("@instructure/ui-table");
9
+ var _uiText = require("@instructure/ui-text");
10
+ var _uiButtons = require("@instructure/ui-buttons");
11
+ var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
12
+ var _react = _interopRequireDefault(require("react"));
13
+ var _SessionBreachAlert = require("./SessionBreachAlert.js");
14
+ var _uiIcons = require("@instructure/ui-icons");
15
+ var _uiTooltip = require("@instructure/ui-tooltip");
16
+ var _ref2 = /*#__PURE__*/_react.default.createElement(_SessionBreachAlert.SessionBreachAlert, null);
17
+ var EventDetails = function EventDetails(_ref) {
18
+ var currentEventData = _ref.currentEventData,
19
+ validationErrors = _ref.validationErrors,
20
+ _ref$answerValue = _ref.answerValue,
21
+ answerValue = _ref$answerValue === void 0 ? null : _ref$answerValue;
22
+ var eventTimeString = "".concat((0, _formatMessage.default)('Event time'), ": ").concat(currentEventData.eventDate);
23
+ var renderTooltip = function renderTooltip(message) {
24
+ return /*#__PURE__*/_react.default.createElement(_uiTooltip.Tooltip, {
25
+ renderTip: message,
26
+ placement: "end",
27
+ on: ['click', 'hover', 'focus']
28
+ }, /*#__PURE__*/_react.default.createElement(_uiButtons.IconButton, {
29
+ screenReaderLabel: message,
30
+ renderIcon: _uiIcons.IconInfoLine,
31
+ withBackground: false,
32
+ withBorder: false
33
+ }));
34
+ };
35
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, validationErrors.isBreach && _ref2, /*#__PURE__*/_react.default.createElement("h4", null, eventTimeString), /*#__PURE__*/_react.default.createElement(_uiTable.Table, {
36
+ caption: (0, _formatMessage.default)('System details')
37
+ }, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Head, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.ColHeader, {
38
+ id: "system-details-attribute"
39
+ }, (0, _formatMessage.default)('Attribute')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.ColHeader, {
40
+ id: "system-details-value"
41
+ }, (0, _formatMessage.default)('Value')))), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Body, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, (0, _formatMessage.default)('Client IP address')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, /*#__PURE__*/_react.default.createElement(_uiText.Text, {
42
+ color: validationErrors.ipAddress ? 'danger' : 'primary'
43
+ }, currentEventData.ipAddress), validationErrors.ipAddress && renderTooltip(validationErrors.ipAddress))), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, (0, _formatMessage.default)('Browser session ID')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, /*#__PURE__*/_react.default.createElement(_uiText.Text, {
44
+ color: validationErrors.browserSessionID ? 'danger' : 'primary'
45
+ }, currentEventData.browserSessionID), validationErrors.browserSessionID && renderTooltip(validationErrors.browserSessionID))), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, (0, _formatMessage.default)('Browser')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, /*#__PURE__*/_react.default.createElement(_uiText.Text, {
46
+ color: validationErrors.browserString ? 'danger' : 'primary'
47
+ }, currentEventData.browserString), validationErrors.browserString && renderTooltip(validationErrors.browserString))), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, (0, _formatMessage.default)('Operating System')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, /*#__PURE__*/_react.default.createElement(_uiText.Text, {
48
+ color: validationErrors.userPlatform ? 'danger' : 'primary'
49
+ }, currentEventData.userPlatform), validationErrors.userPlatform && renderTooltip(validationErrors.userPlatform))), answerValue && /*#__PURE__*/_react.default.createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, (0, _formatMessage.default)('Answer value')), /*#__PURE__*/_react.default.createElement(_uiTable.Table.Cell, null, answerValue)))));
50
+ };
51
+ exports.EventDetails = EventDetails;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.SessionBreachAlert = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _uiAlerts = require("@instructure/ui-alerts");
10
+ var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
11
+ var _ref = /*#__PURE__*/_react.default.createElement("br", null);
12
+ var SessionBreachAlert = function SessionBreachAlert() {
13
+ return /*#__PURE__*/_react.default.createElement(_uiAlerts.Alert, {
14
+ variant: "warning",
15
+ margin: "small"
16
+ }, (0, _formatMessage.default)('Potential breach: This Quiz appears to have been accessed from multiple devices or browsers.'), _ref, (0, _formatMessage.default)('Review the activity log and take appropriate action.'));
17
+ };
18
+ exports.SessionBreachAlert = SessionBreachAlert;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.checkIsBreach = void 0;
8
+ var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
9
+ var checkIsBreach = function checkIsBreach(firstEventData, currentEventData) {
10
+ var result = {
11
+ isBreach: false
12
+ };
13
+ var checks = [{
14
+ key: 'ipAddress',
15
+ message: (0, _formatMessage.default)('Client IP address is different from initial address')
16
+ }, {
17
+ key: 'browserSessionID',
18
+ message: (0, _formatMessage.default)('Browser session ID is different from initial id')
19
+ }, {
20
+ key: 'browserString',
21
+ message: (0, _formatMessage.default)('Browser is different from initial browser')
22
+ }, {
23
+ key: 'userPlatform',
24
+ message: (0, _formatMessage.default)('Operating system is different from initial system')
25
+ }];
26
+ checks.forEach(function (_ref) {
27
+ var key = _ref.key,
28
+ message = _ref.message;
29
+ if (currentEventData[key] !== firstEventData[key]) {
30
+ result.isBreach = true;
31
+ result[key] = message;
32
+ }
33
+ });
34
+ return result;
35
+ };
36
+ exports.checkIsBreach = checkIsBreach;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.extractSessionData = void 0;
8
+ var _platform = _interopRequireDefault(require("platform"));
9
+ var _quizI18n = require("@instructure/quiz-i18n");
10
+ var extractSessionData = function extractSessionData(sourceData) {
11
+ if (!sourceData) return {
12
+ ipAddress: '',
13
+ browserSessionID: '',
14
+ eventDate: '',
15
+ browserString: '',
16
+ userPlatform: ''
17
+ };
18
+ var clientTimestamp = sourceData.getIn(['eventData', 'clientTimestamp']);
19
+ var userPlatform = _platform.default.parse(sourceData.getIn(['eventData', 'userAgent']));
20
+ return {
21
+ ipAddress: sourceData.getIn(['eventData', 'ipAddress']),
22
+ browserSessionID: sourceData.getIn(['eventData', 'browserSessionId']),
23
+ eventDate: clientTimestamp ? (0, _quizI18n.formatDateTimeSeconds)(clientTimestamp) : '',
24
+ browserString: "".concat(userPlatform.name, " ").concat(userPlatform.version),
25
+ userPlatform: userPlatform.os.toString()
26
+ };
27
+ };
28
+ exports.extractSessionData = extractSessionData;
@@ -47,8 +47,8 @@ var QuizAndItemAnalysis = (_dec = (0, _quizCommon.withStyleOverrides)(_styles.de
47
47
  this.getAnalyses(this.props.activeQuizId);
48
48
  }
49
49
  }, {
50
- key: "componentWillUpdate",
51
- value: function componentWillUpdate(nextProps) {
50
+ key: "UNSAFE_componentWillUpdate",
51
+ value: function UNSAFE_componentWillUpdate(nextProps) {
52
52
  if (this.props.activeQuizId !== nextProps.activeQuizId) {
53
53
  this.getAnalyses(nextProps.activeQuizId);
54
54
  }
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.afsFlags = exports.itemAnalysisPropType = exports.answerSummaryPropType = exports.numericTypeAnswerSummaryPropType = exports.richFillBlankTypeAnswerSummaryPropType = exports.matchingTypeAnswerSummaryPropType = exports.scoreDistributionType = exports.scoreDistributionTypeAnswerSummaryPropType = exports.choiceTypeAnswerSummaryPropType = exports.choiceTypeObject = exports.onlyAggregatePropType = exports.aggregatePropType = exports.aggregateDetailPropType = exports.studentAnalysesPropType = exports.quizAnalysisPropType = exports.quizAnalysisMetadata = void 0;
7
+ exports.eventDataPropType = exports.sessionValidationErrorsPropType = exports.afsFlags = exports.itemAnalysisPropType = exports.answerSummaryPropType = exports.numericTypeAnswerSummaryPropType = exports.richFillBlankTypeAnswerSummaryPropType = exports.matchingTypeAnswerSummaryPropType = exports.scoreDistributionType = exports.scoreDistributionTypeAnswerSummaryPropType = exports.choiceTypeAnswerSummaryPropType = exports.choiceTypeObject = exports.onlyAggregatePropType = exports.aggregatePropType = exports.aggregateDetailPropType = exports.studentAnalysesPropType = exports.quizAnalysisPropType = exports.quizAnalysisMetadata = void 0;
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var quizAnalysisMetadata = _propTypes.default.shape({
10
10
  quiz_title: _propTypes.default.string,
@@ -186,4 +186,20 @@ var afsFlags = _propTypes.default.shape({
186
186
  essayEnabled: _propTypes.default.bool.isRequired,
187
187
  fileUploadEnabled: _propTypes.default.bool.isRequired
188
188
  });
189
- exports.afsFlags = afsFlags;
189
+ exports.afsFlags = afsFlags;
190
+ var sessionValidationErrorsPropType = _propTypes.default.shape({
191
+ isBreach: _propTypes.default.bool,
192
+ ipAddress: _propTypes.default.string,
193
+ browserSessionID: _propTypes.default.string,
194
+ browserString: _propTypes.default.string,
195
+ userPlatform: _propTypes.default.string
196
+ });
197
+ exports.sessionValidationErrorsPropType = sessionValidationErrorsPropType;
198
+ var eventDataPropType = _propTypes.default.shape({
199
+ ipAddress: _propTypes.default.string,
200
+ browserSessionID: _propTypes.default.string,
201
+ eventDate: _propTypes.default.string,
202
+ browserString: _propTypes.default.string,
203
+ userPlatform: _propTypes.default.string
204
+ });
205
+ exports.eventDataPropType = eventDataPropType;
@@ -17,6 +17,8 @@ exports.postQuizSession = postQuizSession;
17
17
  exports.getTimeRemaining = getTimeRemaining;
18
18
  exports.recordQuizTime = recordQuizTime;
19
19
  exports.messageForSubmitModal = exports.nextQuestion = exports.submitStudentAccessCode = exports.makeSessionItemCall = exports.getResumeData = void 0;
20
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
21
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
20
22
  var _react = _interopRequireDefault(require("react"));
21
23
  var _partial = _interopRequireDefault(require("lodash/partial"));
22
24
  var _immutable = require("immutable");
@@ -34,6 +36,7 @@ var _quizSessions2 = require("../../common/actions/quizSessions.js");
34
36
  var _callHandlers = require("../../common/api/callHandlers.js");
35
37
  var modalActions = _interopRequireWildcard(require("../../common/actions/modal.js"));
36
38
  var _taking = require("../../common/actions/taking.js");
39
+ var _getClientIpAddress = require("../../common/util/getClientIpAddress.js");
37
40
  // =============================================
38
41
  // =============================================
39
42
 
@@ -167,9 +170,29 @@ function newQuizTakingSession(quizSessionId) {
167
170
  };
168
171
  }
169
172
  function onQuizSessionReadyForTaking(quizSession) {
170
- return function (dispatch) {
171
- dispatch([makeSessionItemCall(quizSession), getResumeData(quizSession.id), (0, _taking.sessionStartOrResumeEvent)(navigator.userAgent), (0, _taking.updateQuizSessionStatusOnPageLoad)(quizSession.status)]);
172
- };
173
+ return /*#__PURE__*/function () {
174
+ var _ref = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(dispatch) {
175
+ var ipAddress;
176
+ return _regenerator.default.wrap(function _callee$(_context) {
177
+ while (1) {
178
+ switch (_context.prev = _context.next) {
179
+ case 0:
180
+ _context.next = 2;
181
+ return (0, _getClientIpAddress.getClientIpAddress)(quizSession.id);
182
+ case 2:
183
+ ipAddress = _context.sent;
184
+ dispatch([makeSessionItemCall(quizSession), getResumeData(quizSession.id), (0, _taking.sessionStartOrResumeEvent)(navigator.userAgent, ipAddress), (0, _taking.updateQuizSessionStatusOnPageLoad)(quizSession.status)]);
185
+ case 4:
186
+ case "end":
187
+ return _context.stop();
188
+ }
189
+ }
190
+ }, _callee);
191
+ }));
192
+ return function (_x) {
193
+ return _ref.apply(this, arguments);
194
+ };
195
+ }();
173
196
  }
174
197
 
175
198
  // ====================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/quiz-core",
3
- "version": "21.0.0",
3
+ "version": "21.0.1-rc.11+83669feb2",
4
4
  "license": "MIT",
5
5
  "description": "The Quiz React SDK by Instructure Inc.",
6
6
  "author": "Instructure, Inc. Engineering and Product Design",
@@ -10,6 +10,27 @@
10
10
  "type": "git",
11
11
  "url": "https://gerrit.instructure.com/quizzes-ui.git"
12
12
  },
13
+ "scripts": {
14
+ "clean": "ui-build --clean",
15
+ "build": "build-if-changed",
16
+ "build:all": "ui-build --modules es,cjs",
17
+ "build:watch": "ui-build --watch",
18
+ "extract": "extract-translations",
19
+ "lint": "ui-test --lint",
20
+ "lint:fix": "ui-test --lint --fix",
21
+ "eslint:fix": "eslint --fix .",
22
+ "prelint": "pnpm build",
23
+ "pretest": "pnpm build",
24
+ "test": "pnpm test:karma",
25
+ "test:karma": "ui-test",
26
+ "test:watch": "ui-test --watch",
27
+ "snyk:monitor": "snyk monitor",
28
+ "postbuild": "cp src/banks/components/noResults.svg lib/banks/components/; cp src/banks/components/noResults.svg es/banks/components/; pnpm postbuild:errorImage",
29
+ "postbuild:all": "pnpm postbuild",
30
+ "postbuild:errorImage": "cp src/reporting/components/resources/NewQuizAndItemAnalysis/downForRepair.svg es/reporting/components/resources/NewQuizAndItemAnalysis/; cp src/reporting/components/resources/NewQuizAndItemAnalysis/downForRepair.svg lib/reporting/components/resources/NewQuizAndItemAnalysis/",
31
+ "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
32
+ "typecheck": "tsc --noEmit"
33
+ },
13
34
  "keywords": [
14
35
  "react",
15
36
  "react-component",
@@ -25,6 +46,11 @@
25
46
  "@instructure/emotion": "^9.11.1",
26
47
  "@instructure/grading-utils": "^1.0.0",
27
48
  "@instructure/outcomes-ui": "^3.2.2",
49
+ "@instructure/quiz-common": "21.0.1-rc.11+83669feb2",
50
+ "@instructure/quiz-i18n": "21.0.1-rc.11+83669feb2",
51
+ "@instructure/quiz-interactions": "21.0.1-rc.11+83669feb2",
52
+ "@instructure/quiz-number-input": "21.0.1-rc.11+83669feb2",
53
+ "@instructure/quiz-rce": "21.0.1-rc.11+83669feb2",
28
54
  "@instructure/ui-a11y-content": "^9.11.1",
29
55
  "@instructure/ui-alerts": "^9.11.1",
30
56
  "@instructure/ui-avatar": "^9.11.1",
@@ -83,6 +109,7 @@
83
109
  "file-saver": "~2.0.5",
84
110
  "humps": "^2.0.0",
85
111
  "immutable": "^3.8.1",
112
+ "instructure-validations": "21.0.1-rc.11+83669feb2",
86
113
  "ipaddr.js": "^1.5.4",
87
114
  "isomorphic-fetch": "^2.2.0",
88
115
  "isuuid": "^0.1.0",
@@ -110,15 +137,10 @@
110
137
  "scriptjs": "^2.5.8",
111
138
  "store": "^1.3.20",
112
139
  "striptags": "^2.0.0",
113
- "uuid": "^3.2.1",
114
- "@instructure/quiz-common": "21.0.0",
115
- "@instructure/quiz-interactions": "21.0.0",
116
- "@instructure/quiz-i18n": "21.0.0",
117
- "@instructure/quiz-rce": "21.0.0",
118
- "instructure-validations": "21.0.0",
119
- "@instructure/quiz-number-input": "21.0.0"
140
+ "uuid": "^3.2.1"
120
141
  },
121
142
  "devDependencies": {
143
+ "@instructure/quiz-scripts": "21.0.0",
122
144
  "@instructure/ui-axe-check": "^9.11.1",
123
145
  "@instructure/ui-babel-preset": "^7.22.1",
124
146
  "@instructure/ui-test-utils": "^7.22.1",
@@ -137,6 +159,7 @@
137
159
  "jquery": "^2.2.3",
138
160
  "karma-junit-reporter": "^2.0.1",
139
161
  "most-subject": "^5.3.0",
162
+ "quiz-presets": "21.0.1-rc.11+83669feb2",
140
163
  "react": "^16.8.6",
141
164
  "react-addons-test-utils": "^15.6.2",
142
165
  "react-dom": "^16.8.6",
@@ -144,9 +167,7 @@
144
167
  "redux-mock-store": "^1.3.0",
145
168
  "request": "^2.74.0",
146
169
  "sinon": "^6.1.3",
147
- "sinon-chai": "^3.3.0",
148
- "@instructure/quiz-scripts": "21.0.0",
149
- "quiz-presets": "21.0.0"
170
+ "sinon-chai": "^3.3.0"
150
171
  },
151
172
  "peerDependencies": {
152
173
  "react": "^15 || ^16"
@@ -154,25 +175,5 @@
154
175
  "publishConfig": {
155
176
  "access": "public"
156
177
  },
157
- "scripts": {
158
- "clean": "ui-build --clean",
159
- "build": "build-if-changed",
160
- "build:all": "ui-build --modules es,cjs",
161
- "build:watch": "ui-build --watch",
162
- "extract": "extract-translations",
163
- "lint": "ui-test --lint",
164
- "lint:fix": "ui-test --lint --fix",
165
- "eslint:fix": "eslint --fix .",
166
- "prelint": "pnpm build",
167
- "pretest": "pnpm build",
168
- "test": "pnpm test:karma",
169
- "test:karma": "ui-test",
170
- "test:watch": "ui-test --watch",
171
- "snyk:monitor": "snyk monitor",
172
- "postbuild": "cp src/banks/components/noResults.svg lib/banks/components/; cp src/banks/components/noResults.svg es/banks/components/; pnpm postbuild:errorImage",
173
- "postbuild:all": "pnpm postbuild",
174
- "postbuild:errorImage": "cp src/reporting/components/resources/NewQuizAndItemAnalysis/downForRepair.svg es/reporting/components/resources/NewQuizAndItemAnalysis/; cp src/reporting/components/resources/NewQuizAndItemAnalysis/downForRepair.svg lib/reporting/components/resources/NewQuizAndItemAnalysis/",
175
- "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
176
- "typecheck": "tsc --noEmit"
177
- }
178
- }
178
+ "gitHead": "83669feb279b2098bf5bcfd63781ec115f670a9e"
179
+ }