@instructure/quiz-core 17.41.1-rc.2 → 17.41.1-rc.21

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 (41) hide show
  1. package/es/building/components/resources/ActionButtons/presenter.js +2 -1
  2. package/es/building/components/resources/quizEntry/QuizEntry/presenter.js +4 -1
  3. package/es/building/components/resources/quizEntry/QuizEntryShow/index.js +1 -0
  4. package/es/building/components/resources/quizEntry/QuizEntryShow/presenter.js +15 -4
  5. package/es/common/actions/rce.js +17 -0
  6. package/es/common/components/SDKApp/index.js +2 -2
  7. package/es/common/components/resources/stimulus/Stimulus/index.js +1 -0
  8. package/es/common/components/resources/stimulus/Stimulus/presenter.js +20 -7
  9. package/es/common/components/resources/stimulus/StimulusShow/index.js +9 -3
  10. package/es/common/kinesis/config.js +3 -2
  11. package/es/common/kinesis/eventTypes.js +2 -1
  12. package/es/common/reducers/rce.js +19 -0
  13. package/es/common/selectors/rce.js +3 -0
  14. package/es/common/util/RceConfigProvider.js +63 -27
  15. package/es/common/util/serializeEvent.js +2 -2
  16. package/es/common/util/windowChecks.js +6 -0
  17. package/es/configureStore.js +3 -1
  18. package/es/index.js +2 -0
  19. package/es/moderating/components/events/Event.js +7 -1
  20. package/es/moderating/components/events/RCEEvent.js +34 -0
  21. package/lib/building/components/resources/ActionButtons/presenter.js +2 -1
  22. package/lib/building/components/resources/quizEntry/QuizEntry/presenter.js +4 -1
  23. package/lib/building/components/resources/quizEntry/QuizEntryShow/index.js +1 -0
  24. package/lib/building/components/resources/quizEntry/QuizEntryShow/presenter.js +15 -4
  25. package/lib/common/actions/rce.js +30 -0
  26. package/lib/common/components/SDKApp/index.js +2 -2
  27. package/lib/common/components/resources/stimulus/Stimulus/index.js +1 -0
  28. package/lib/common/components/resources/stimulus/Stimulus/presenter.js +20 -7
  29. package/lib/common/components/resources/stimulus/StimulusShow/index.js +9 -3
  30. package/lib/common/kinesis/config.js +2 -1
  31. package/lib/common/kinesis/eventTypes.js +4 -2
  32. package/lib/common/reducers/rce.js +29 -0
  33. package/lib/common/selectors/rce.js +12 -0
  34. package/lib/common/util/RceConfigProvider.js +68 -26
  35. package/lib/common/util/serializeEvent.js +1 -1
  36. package/lib/common/util/windowChecks.js +11 -2
  37. package/lib/configureStore.js +4 -1
  38. package/lib/index.js +18 -0
  39. package/lib/moderating/components/events/Event.js +7 -0
  40. package/lib/moderating/components/events/RCEEvent.js +53 -0
  41. package/package.json +10 -10
@@ -0,0 +1,34 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/esm/createClass";
3
+ import _inherits from "@babel/runtime/helpers/esm/inherits";
4
+ import _createSuper from "@babel/runtime/helpers/esm/createSuper";
5
+ import React, { Component } from 'react';
6
+ import ImmutablePropTypes from 'react-immutable-proptypes';
7
+ import { Text } from '@instructure/ui-text';
8
+ export var RCEEvent = /*#__PURE__*/function (_Component) {
9
+ _inherits(RCEEvent, _Component);
10
+
11
+ var _super = _createSuper(RCEEvent);
12
+
13
+ function RCEEvent() {
14
+ _classCallCheck(this, RCEEvent);
15
+
16
+ return _super.apply(this, arguments);
17
+ }
18
+
19
+ _createClass(RCEEvent, [{
20
+ key: "render",
21
+ value: function render() {
22
+ var event = this.props.event;
23
+ var message = event.getIn(['eventData', 'message']);
24
+ return /*#__PURE__*/React.createElement(Text, null, message);
25
+ }
26
+ }]);
27
+
28
+ RCEEvent.displayName = "RCEEvent";
29
+ return RCEEvent;
30
+ }(Component);
31
+ RCEEvent.propTypes = {
32
+ event: ImmutablePropTypes.record.isRequired
33
+ };
34
+ export default RCEEvent;
@@ -149,7 +149,7 @@ var ActionButtons = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
149
149
  quizEntry: this.props.quizEntry,
150
150
  quizEntries: this.props.quizEntries,
151
151
  disabled: this.props.shouldDisableDragHandle
152
- }))), /*#__PURE__*/_react.default.createElement(_uiButtons.Button, {
152
+ }))), this.props.shouldRenderDelete && /*#__PURE__*/_react.default.createElement(_uiButtons.Button, {
153
153
  as: "div",
154
154
  onClick: this.props.onDelete,
155
155
  disabled: this.props.shouldDisableDeleteButton,
@@ -176,6 +176,7 @@ var ActionButtons = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
176
176
  shouldDisableDragHandle: _propTypes.default.bool,
177
177
  shouldDisableDeleteButton: _propTypes.default.bool,
178
178
  shouldRenderEdit: _propTypes.default.bool,
179
+ shouldRenderDelete: _propTypes.default.bool,
179
180
  switchOnEditing: _propTypes.default.func,
180
181
  shouldFocusOnMount: _propTypes.default.bool
181
182
  }, _class2.defaultProps = {
@@ -218,7 +218,7 @@ var QuizEntry = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _de
218
218
  clearValidationErrorsFromApi: this.props.clearValidationErrorsFromApi,
219
219
  haveValidationErrorsFromApi: Boolean(Object.values(this.props.validationErrorsFromApi).length),
220
220
  useNewRce: (0, _rceChecker.isNewRCEEnabled)()
221
- }, (0, _pick.default)(this.props, ['displayPosition', 'guid', 'draggingOnBuild', 'newHoverPosition', 'quizEntry', 'quizEntries', 'quizId', 'setUi', 'switchOffEditing', 'switchOnEditing', 'shouldClone', 'scrollKey', 'editQuizEntryToggle', 'onEditQuizEntryToggle', 'stimulusOrientation']));
221
+ }, (0, _pick.default)(this.props, ['displayPosition', 'guid', 'draggingOnBuild', 'newHoverPosition', 'quizEntry', 'quizEntries', 'quizId', 'isContentLockedByBlueprint', 'setUi', 'switchOffEditing', 'switchOnEditing', 'shouldClone', 'scrollKey', 'editQuizEntryToggle', 'onEditQuizEntryToggle', 'stimulusOrientation']));
222
222
  }
223
223
  }, {
224
224
  key: "isEditing",
@@ -304,6 +304,7 @@ var QuizEntry = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _de
304
304
  dndRef: this.storeDndComponentRef,
305
305
  guid: this.props.guid,
306
306
  isBankedContent: bankEntryWarningWrapperProps !== void 0,
307
+ isContentLockedByBlueprint: this.props.isContentLockedByBlueprint,
307
308
  isEditing: this.isEditing(),
308
309
  draggingOnBuild: this.props.draggingOnBuild,
309
310
  newHoverPosition: this.props.newHoverPosition // used for DnD
@@ -399,6 +400,7 @@ var QuizEntry = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _de
399
400
  quizEntries: _reactImmutableProptypes.default.listOf(_reactImmutableProptypes.default.record).isRequired,
400
401
  quizEntry: _reactImmutableProptypes.default.record.isRequired,
401
402
  quizId: _propTypes.default.string.isRequired,
403
+ isContentLockedByBlueprint: _propTypes.default.bool.isRequired,
402
404
  regradingOn: _propTypes.default.bool.isRequired,
403
405
  screenreaderNotification: _propTypes.default.func.isRequired,
404
406
  scrollKey: _propTypes.default.string,
@@ -425,6 +427,7 @@ var QuizEntry = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _de
425
427
  draggingOnBuild: false,
426
428
  draggingOver: false,
427
429
  initialFocusId: null,
430
+ isContentLockedByBlueprint: false,
428
431
  isEditing: false,
429
432
  partialDeepScoringEnabled: false,
430
433
  partialScoringEnabled: false,
@@ -41,6 +41,7 @@ function mapStateToProps(state, props) {
41
41
  modificationsClear: itemModsClear && quizEntryModsClear,
42
42
  quizEntryWithErrorsShowing: (0, _quizzes.getQuizEntryWithErrorsShowing)(state) || props.haveValidationErrorsFromApi,
43
43
  richFITBEnabled: (0, _featureCheck.featureOn)('interaction_type_rich_fill_blank'),
44
+ lockBlueprintContentEnabled: (0, _featureCheck.featureOn)('lock_blueprint_content'),
44
45
  richFITBInteractionID: (richFITBInteraction || (0, _immutable.Map)()).get('id'),
45
46
  updateItemCallStatus: state.getIn(['calls', _quizCommon.UPDATE_ITEM_CALL, 'requestStatus'], '')
46
47
  };
@@ -296,7 +296,9 @@ var QuizEntryShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
296
296
  draggingOver = _this$props2.draggingOver,
297
297
  draggingAboveHalf = _this$props2.draggingAboveHalf,
298
298
  quizEntry = _this$props2.quizEntry,
299
- stimulusOrientation = _this$props2.stimulusOrientation;
299
+ stimulusOrientation = _this$props2.stimulusOrientation,
300
+ isContentLockedByBlueprint = _this$props2.isContentLockedByBlueprint,
301
+ lockBlueprintContentEnabled = _this$props2.lockBlueprintContentEnabled;
300
302
  var positionToDisplay = this.props.quizEntry.positionToDisplay(displayPosition);
301
303
  var positionText = (0, _formatMessage.default)('Preview of question at position {position}', {
302
304
  position: positionToDisplay
@@ -305,13 +307,15 @@ var QuizEntryShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
305
307
  var propsForDnDZone = {
306
308
  draggingOver: draggingOver,
307
309
  draggingAboveHalf: draggingAboveHalf
308
- }; // Overlay gets tabIndex === "-1" so that the drag handle is tabbable before
310
+ };
311
+ var shouldLockQuizEntry = lockBlueprintContentEnabled && isContentLockedByBlueprint; // Overlay gets tabIndex === "-1" so that the drag handle is tabbable before
309
312
  // the Overlay get focus and opens the quizEntry in edit mode
310
313
 
311
314
  return /*#__PURE__*/_react.default.createElement(_Overlay.default, {
312
315
  onClick: this.editingOn,
313
316
  wrapperClassName: styles.quizEntryWrapper,
314
- tabIndex: "-1"
317
+ tabIndex: "-1",
318
+ hideOverlay: shouldLockQuizEntry
315
319
  }, /*#__PURE__*/_react.default.createElement(_index2.default, Object.assign({}, propsForDnDZone, {
316
320
  location: "above"
317
321
  })), connectDragPreview( /*#__PURE__*/_react.default.createElement("div", {
@@ -336,7 +340,10 @@ var QuizEntryShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
336
340
  scrollKey: this.props.scrollKey,
337
341
  shouldDisableDragHandle: this.shouldDisableDragHandle(),
338
342
  switchOnEditing: this.editingOn,
339
- shouldFocusOnMount: this.props.editQuizEntryToggle
343
+ shouldFocusOnMount: this.props.editQuizEntryToggle,
344
+ shouldDisableCopy: shouldLockQuizEntry,
345
+ shouldRenderEdit: !shouldLockQuizEntry,
346
+ shouldRenderDelete: !shouldLockQuizEntry
340
347
  }), /*#__PURE__*/_react.default.createElement(_uiA11yContent.ScreenReaderContent, null, srMsg)), /*#__PURE__*/_react.default.createElement("div", {
341
348
  className: styles.itemHolder,
342
349
  ref: this.setInert,
@@ -363,10 +370,12 @@ var QuizEntryShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
363
370
  // only used in index.js
364
371
  interactionTypeName: _propTypes.default.string,
365
372
  modificationsClear: _propTypes.default.bool.isRequired,
373
+ lockBlueprintContentEnabled: _propTypes.default.bool.isRequired,
366
374
  quizEntryWithErrorsShowing: _propTypes.default.oneOfType([_propTypes.default.bool, _propTypes.default.object]),
367
375
  quizEntries: _reactImmutableProptypes.default.listOf(_reactImmutableProptypes.default.record).isRequired,
368
376
  quizEntry: _reactImmutableProptypes.default.record.isRequired,
369
377
  quizId: _propTypes.default.string.isRequired,
378
+ isContentLockedByBlueprint: _propTypes.default.bool.isRequired,
370
379
  removeQuizEntry: _propTypes.default.func.isRequired,
371
380
  // from connected component
372
381
  richFITBEnabled: _propTypes.default.bool,
@@ -383,11 +392,13 @@ var QuizEntryShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
383
392
  children: null,
384
393
  draggingOver: false,
385
394
  draggingAboveHalf: false,
395
+ lockBlueprintContentEnabled: false,
386
396
  quizEntryWithErrorsShowing: null,
387
397
  scrollKey: void 0,
388
398
  editQuizEntryToggle: false,
389
399
  haveValidationErrorsFromApi: false,
390
400
  interactionTypeName: null,
401
+ isContentLockedByBlueprint: false,
391
402
  richFITBEnabled: false,
392
403
  richFITBInteractionID: '',
393
404
  stimulusOrientation: null
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.reportRCEEvent = exports.setRCEError = void 0;
7
+
8
+ var _quizCommon = require("@instructure/quiz-common");
9
+
10
+ var setRCEError = function setRCEError(rceError) {
11
+ return {
12
+ type: _quizCommon.SET_RCE_ERROR,
13
+ payload: rceError
14
+ };
15
+ }; // This is not consumed by its reducer
16
+ // Instead it is processed by the eventLoggerMiddleware
17
+
18
+
19
+ exports.setRCEError = setRCEError;
20
+
21
+ var reportRCEEvent = function reportRCEEvent(eventMessage) {
22
+ return {
23
+ type: _quizCommon.RCE_EVENT,
24
+ payload: {
25
+ message: eventMessage
26
+ }
27
+ };
28
+ };
29
+
30
+ exports.reportRCEEvent = reportRCEEvent;
@@ -188,11 +188,11 @@ var SDKApp = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec(_
188
188
  rceConfig: _propTypes.default.shape({
189
189
  contextId: _propTypes.default.string.isRequired,
190
190
  contextType: _propTypes.default.string.isRequired,
191
+ canvasOrigin: _propTypes.default.string.isRequired,
191
192
  canvasUserId: _propTypes.default.string.isRequired,
192
193
  rcsHost: _propTypes.default.string.isRequired,
193
194
  rcsJwt: _propTypes.default.string.isRequired,
194
- rcsJwtRefreshFn: _propTypes.default.func.isRequired,
195
- documentServiceHost: _propTypes.default.string.isRequired
195
+ rcsJwtRefreshFn: _propTypes.default.func.isRequired
196
196
  }),
197
197
  timeZone: _propTypes.default.string,
198
198
  translations: _propTypes.default.objectOf(_propTypes.default.shape({
@@ -29,6 +29,7 @@ var mapStateToProps = function mapStateToProps(state, props) {
29
29
  dropIntoEmptyStimulus: draggingOver && dropIntoEmptyStimulus,
30
30
  draggingOver: draggingOver,
31
31
  draggingAboveHalf: draggingOver && draggingAboveHalf,
32
+ lockBlueprintContentEnabled: (0, _featureCheck.featureOn)('lock_blueprint_content'),
32
33
  stimulusOrientationEnabled: (0, _featureCheck.featureOn)('customizable_stimulus_orientation')
33
34
  };
34
35
  };
@@ -106,6 +106,14 @@ var Stimulus = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec
106
106
  quizEntry = _this$props.quizEntry;
107
107
  return quizEntries.size === quizEntry.positionSlots + 1;
108
108
  }
109
+ }, {
110
+ key: "isQuizContentLocked",
111
+ value: function isQuizContentLocked() {
112
+ var _this$props2 = this.props,
113
+ isContentLockedByBlueprint = _this$props2.isContentLockedByBlueprint,
114
+ lockBlueprintContentEnabled = _this$props2.lockBlueprintContentEnabled;
115
+ return lockBlueprintContentEnabled && isContentLockedByBlueprint;
116
+ }
109
117
  }, {
110
118
  key: "renderChildQuizEntries",
111
119
  value: function renderChildQuizEntries() {
@@ -120,7 +128,7 @@ var Stimulus = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec
120
128
  key: childEntry.id
121
129
  }, /*#__PURE__*/_react.default.createElement(_index5.default, Object.assign({}, _this2.props.propsForQuizEntry(childEntry, displayPosition), {
122
130
  stimulusOrientation: _this2.props.stimulusOrientationEnabled ? _this2.props.stimulus.orientation : null
123
- })), !_this2.props.draggingOnBuild && /*#__PURE__*/_react.default.createElement(_index.default, {
131
+ })), !_this2.props.draggingOnBuild && !_this2.isQuizContentLocked() && /*#__PURE__*/_react.default.createElement(_index.default, {
124
132
  allowStimulusCreation: false,
125
133
  stimulusId: _this2.props.stimulus.id,
126
134
  parentEntryId: _this2.props.quizEntry.id,
@@ -154,7 +162,8 @@ var Stimulus = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec
154
162
  switchOnEditing: this.props.switchOnEditing,
155
163
  switchOffEditing: this.props.switchOffEditing,
156
164
  onEditToggle: this.props.onEditStimulusToggle,
157
- shouldFocusOnMount: this.props.editStimulusToggle
165
+ shouldFocusOnMount: this.props.editStimulusToggle,
166
+ isQuizContentLocked: this.isQuizContentLocked()
158
167
  })));
159
168
  }
160
169
  }, {
@@ -162,9 +171,9 @@ var Stimulus = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec
162
171
  value: function renderPanels(propsForDnDZone) {
163
172
  var _classnames2;
164
173
 
165
- var _this$props2 = this.props,
166
- stimulus = _this$props2.stimulus,
167
- stimulusOrientationEnabled = _this$props2.stimulusOrientationEnabled;
174
+ var _this$props3 = this.props,
175
+ stimulus = _this$props3.stimulus,
176
+ stimulusOrientationEnabled = _this$props3.stimulusOrientationEnabled;
168
177
  var shouldSetHorizontalOrientation = stimulus.orientation === _quizCommon.LEFT || !stimulusOrientationEnabled;
169
178
  var stimulusPanelClass = (0, _classnames4.default)(styles.leftPanel, (0, _defineProperty2.default)({}, styles.horizontallyAligned, shouldSetHorizontalOrientation));
170
179
  var itemsPanelClass = (0, _classnames4.default)((_classnames2 = {}, (0, _defineProperty2.default)(_classnames2, styles.horizontallyAligned, shouldSetHorizontalOrientation), (0, _defineProperty2.default)(_classnames2, styles.hidden, stimulus.isTemporary()), (0, _defineProperty2.default)(_classnames2, styles.rightPanel, !stimulus.isTemporary()), _classnames2));
@@ -178,7 +187,7 @@ var Stimulus = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec
178
187
  className: itemsPanelClass
179
188
  }, /*#__PURE__*/_react.default.createElement("div", null), this.renderChildQuizEntries(), /*#__PURE__*/_react.default.createElement(_index4.default, Object.assign({}, propsForDnDZone, {
180
189
  location: "in"
181
- })), this.props.childEntries.size === 0 && /*#__PURE__*/_react.default.createElement(_index.default, {
190
+ })), this.props.childEntries.size === 0 && !this.isQuizContentLocked() && /*#__PURE__*/_react.default.createElement(_index.default, {
182
191
  allowStimulusCreation: false,
183
192
  stimulusId: this.props.stimulus.id,
184
193
  parentEntryId: this.props.quizEntry.id,
@@ -219,8 +228,10 @@ var Stimulus = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec
219
228
  dropIntoEmptyStimulus: _propTypes.default.bool,
220
229
  displayPosition: _propTypes.default.number.isRequired,
221
230
  isBankedContent: _propTypes.default.bool,
231
+ isContentLockedByBlueprint: _propTypes.default.bool.isRequired,
222
232
  isEditing: _propTypes.default.bool,
223
233
  guid: _propTypes.default.string.isRequired,
234
+ lockBlueprintContentEnabled: _propTypes.default.bool.isRequired,
224
235
  openDeleteStimulusModal: _propTypes.default.func.isRequired,
225
236
  propsForQuizEntry: _propTypes.default.func.isRequired,
226
237
  quizEntry: _reactImmutableProptypes.default.record.isRequired,
@@ -245,8 +256,10 @@ var Stimulus = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec
245
256
  dropIntoEmptyStimulus: false,
246
257
  isBankedContent: false,
247
258
  isEditing: false,
259
+ lockBlueprintContentEnabled: false,
248
260
  onEditStimulusToggle: function onEditStimulusToggle() {},
249
- scrollKey: ''
261
+ scrollKey: '',
262
+ isContentLockedByBlueprint: false
250
263
  }, _temp)) || _class);
251
264
  exports.Stimulus = Stimulus;
252
265
 
@@ -89,7 +89,8 @@ var StimulusShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
89
89
  return /*#__PURE__*/_react.default.createElement(_Overlay.default, {
90
90
  onClick: this.switchOnEditing,
91
91
  wrapperClassName: styles.stimulusWrapper,
92
- tabIndex: "-1"
92
+ tabIndex: "-1",
93
+ hideOverlay: this.props.isQuizContentLocked
93
94
  }, /*#__PURE__*/_react.default.createElement("div", {
94
95
  className: styles.stimulus
95
96
  }, /*#__PURE__*/_react.default.createElement("div", {
@@ -107,10 +108,13 @@ var StimulusShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
107
108
  scrollKey: this.props.scrollKey,
108
109
  shouldDisableDragHandle: this.props.shouldDisableDragHandle,
109
110
  switchOnEditing: this.props.switchOnEditing,
110
- shouldFocusOnMount: this.props.shouldFocusOnMount
111
+ shouldFocusOnMount: this.props.shouldFocusOnMount,
112
+ shouldDisableCopy: this.props.isQuizContentLocked,
113
+ shouldRenderEdit: !this.props.isQuizContentLocked,
114
+ shouldRenderDelete: !this.props.isQuizContentLocked
111
115
  })), /*#__PURE__*/_react.default.createElement("div", {
112
116
  role: "presentation",
113
- onClick: this.switchOnEditing,
117
+ onClick: this.props.isQuizContentLocked ? null : this.switchOnEditing,
114
118
  className: styles.stimulusContent
115
119
  }, /*#__PURE__*/_react.default.createElement(_index.default, {
116
120
  stimulus: this.props.stimulus
@@ -123,6 +127,7 @@ var StimulusShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
123
127
  connectDragSource: _propTypes.default.func.isRequired,
124
128
  displayPosition: _propTypes.default.number.isRequired,
125
129
  isBankedContent: _propTypes.default.bool,
130
+ isQuizContentLocked: _propTypes.default.bool.isRequired,
126
131
  openDeleteStimulusModal: _propTypes.default.func.isRequired,
127
132
  quizEntries: _reactImmutableProptypes.default.listOf(_reactImmutableProptypes.default.record).isRequired,
128
133
  quizEntry: _reactImmutableProptypes.default.record.isRequired,
@@ -133,6 +138,7 @@ var StimulusShow = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles),
133
138
  shouldFocusOnMount: _propTypes.default.bool.isRequired
134
139
  }, _class2.defaultProps = {
135
140
  isBankedContent: false,
141
+ isQuizContentLocked: false,
136
142
  scrollKey: '',
137
143
  shouldDisableDragHandle: false,
138
144
  shouldFocusOnMount: false
@@ -33,7 +33,8 @@ var eventStreamConfig = function eventStreamConfig(defaultStreamConfig, stream)
33
33
  eventTypes: {
34
34
  RESPONSE: _eventTypes.EVENT_RESPONSE,
35
35
  SESSION_STARTED_OR_RESUMED_EVENT: _eventTypes.SESSION_STARTED_OR_RESUMED_EVENT,
36
- QUIZ_SUBMISSION_EVENT: _eventTypes.QUIZ_SUBMISSION_EVENT
36
+ QUIZ_SUBMISSION_EVENT: _eventTypes.QUIZ_SUBMISSION_EVENT,
37
+ RCE_EVENT: _eventTypes.RCE_EVENT
37
38
  },
38
39
  stream: stream
39
40
  });
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.QUIZ_SUBMISSION_EVENT = exports.SESSION_STARTED_OR_RESUMED_EVENT = exports.EVENT_RESPONSE = exports.RESPONSE = void 0;
6
+ exports.RCE_EVENT = exports.QUIZ_SUBMISSION_EVENT = exports.SESSION_STARTED_OR_RESUMED_EVENT = exports.EVENT_RESPONSE = exports.RESPONSE = void 0;
7
7
 
8
8
  var _humps = require("humps");
9
9
 
@@ -45,4 +45,6 @@ exports.EVENT_RESPONSE = EVENT_RESPONSE;
45
45
  var SESSION_STARTED_OR_RESUMED_EVENT = eventType();
46
46
  exports.SESSION_STARTED_OR_RESUMED_EVENT = SESSION_STARTED_OR_RESUMED_EVENT;
47
47
  var QUIZ_SUBMISSION_EVENT = eventType();
48
- exports.QUIZ_SUBMISSION_EVENT = QUIZ_SUBMISSION_EVENT;
48
+ exports.QUIZ_SUBMISSION_EVENT = QUIZ_SUBMISSION_EVENT;
49
+ var RCE_EVENT = eventType();
50
+ exports.RCE_EVENT = RCE_EVENT;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _immutable = require("immutable");
9
+
10
+ var _quizCommon = require("@instructure/quiz-common");
11
+
12
+ var setRceError = function setRceError(state, payload) {
13
+ return state.set('rceError', payload);
14
+ };
15
+
16
+ var _default = function _default() {
17
+ var state = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : (0, _immutable.Map)();
18
+ var action = arguments.length > 1 ? arguments[1] : void 0;
19
+
20
+ switch (action.type) {
21
+ case _quizCommon.SET_RCE_ERROR:
22
+ return setRceError(state, action.payload);
23
+
24
+ default:
25
+ return state;
26
+ }
27
+ };
28
+
29
+ exports.default = _default;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getRCEError = void 0;
7
+
8
+ var getRCEError = function getRCEError(state) {
9
+ return state.getIn(['rce', 'rceError'], null);
10
+ };
11
+
12
+ exports.getRCEError = getRCEError;
@@ -7,7 +7,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
7
7
  Object.defineProperty(exports, "__esModule", {
8
8
  value: true
9
9
  });
10
- exports.RceConfigProvider = void 0;
10
+ exports.RceConfigProvider = exports.RceConfigProviderComponent = void 0;
11
11
 
12
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
13
 
@@ -25,6 +25,8 @@ var _reactRedux = require("../../common/react-redux.js");
25
25
 
26
26
  var _reduxStore = _interopRequireDefault(require("../../reduxStore.js"));
27
27
 
28
+ var _rce = require("../actions/rce.js");
29
+
28
30
  var _rceChecker = _interopRequireDefault(require("./rceChecker.js"));
29
31
 
30
32
  var _Spinner = require("../components/shared/spinner/Spinner.js");
@@ -33,6 +35,12 @@ var _quizCommon = require("@instructure/quiz-common");
33
35
 
34
36
  var _alerts = require("../actions/alerts.js");
35
37
 
38
+ var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
39
+
40
+ var _quizInteractions = require("@instructure/quiz-interactions");
41
+
42
+ var _windowChecks = require("./windowChecks.js");
43
+
36
44
  var _ref4 = /*#__PURE__*/_react.default.createElement(_Spinner.QuizzesSpinner, null);
37
45
 
38
46
  var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
@@ -59,7 +67,7 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
59
67
  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(setTokenFn) {
60
68
  var _response$json;
61
69
 
62
- var response, refreshedToken;
70
+ var response, refreshedToken, stemPlaceholder, extractedText;
63
71
  return _regenerator.default.wrap(function _callee$(_context) {
64
72
  while (1) {
65
73
  switch (_context.prev = _context.next) {
@@ -81,18 +89,24 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
81
89
  refreshedToken = response === null || response === void 0 ? void 0 : (_response$json = response.json) === null || _response$json === void 0 ? void 0 : _response$json.token; // inst-redux-service-middleware response structure
82
90
 
83
91
  if (refreshedToken) {
84
- _context.next = 10;
92
+ _context.next = 13;
85
93
  break;
86
94
  }
87
95
 
88
- handleErrorFunc('Unable to refresh RCS token');
96
+ handleErrorFunc('Unable to refresh RCS token'); // TODO: provide question context for this function so it can actually get the question stem / instruction text
97
+
98
+ stemPlaceholder = 'Example question stem text';
99
+ extractedText = (0, _quizInteractions.extractTextFromHtml)(stemPlaceholder);
100
+ setErrorIfDuringTaking((0, _formatMessage.default)('Error while answering: {stem}: Full functionality of the Rich Content Editor may not have been available to the user.', {
101
+ stem: extractedText
102
+ }));
89
103
  return _context.abrupt("return");
90
104
 
91
- case 10:
105
+ case 13:
92
106
  setJwt(refreshedToken);
93
107
  setTokenFn(refreshedToken);
94
108
 
95
- case 12:
109
+ case 15:
96
110
  case "end":
97
111
  return _context.stop();
98
112
  }
@@ -114,20 +128,28 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
114
128
 
115
129
  return {
116
130
  rcs: hasAllPropsForRcs() && canvasConfig ? (_ref2 = {}, (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.useNewRce, props.useNewRce), (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.canvasUserId, props.canvasUserId), (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.contextId, props.contextId), (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.contextType, props.contextType), (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.rcsHost, props.rcsHost), (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.rcsJwt, jwt), (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.rcsJwtRefreshFn, refreshToken), (0, _defineProperty2.default)(_ref2, _quizCommon.RceConfigKeys.canvasConfig, canvasConfig), _ref2) : null,
117
- rendererEnhancement: (_rendererEnhancement = {}, (0, _defineProperty2.default)(_rendererEnhancement, _quizCommon.RceConfigKeys.handleError, handleErrorFunc), (0, _defineProperty2.default)(_rendererEnhancement, _quizCommon.RceConfigKeys.documentServiceHost, props.documentServiceHost), _rendererEnhancement)
131
+ rendererEnhancement: (_rendererEnhancement = {}, (0, _defineProperty2.default)(_rendererEnhancement, _quizCommon.RceConfigKeys.handleError, handleErrorFunc), (0, _defineProperty2.default)(_rendererEnhancement, _quizCommon.RceConfigKeys.canvasOrigin, props.canvasOrigin), _rendererEnhancement)
118
132
  };
119
133
  };
120
134
 
135
+ var setErrorIfDuringTaking = function setErrorIfDuringTaking(errorMessage) {
136
+ if (!(0, _windowChecks.isDuringQuizTake)()) {
137
+ return;
138
+ }
139
+
140
+ props.setRCEError(errorMessage);
141
+ };
142
+
121
143
  (0, _react.useEffect)(function () {
122
144
  (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
123
- var endpoint, response, json;
145
+ var host, base, url, response, json;
124
146
  return _regenerator.default.wrap(function _callee2$(_context2) {
125
147
  while (1) {
126
148
  switch (_context2.prev = _context2.next) {
127
149
  case 0:
128
150
  _context2.prev = 0;
129
151
 
130
- if (!(!props.useNewRce || !hasAllPropsForRcs())) {
152
+ if (props.useNewRce) {
131
153
  _context2.next = 3;
132
154
  break;
133
155
  }
@@ -135,41 +157,56 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
135
157
  return _context2.abrupt("return");
136
158
 
137
159
  case 3:
138
- endpoint = "".concat(props.rcsHost, "/api/rceConfig?contextType=").concat(props.contextType, "&contextId=").concat(props.contextId);
139
- _context2.next = 6;
140
- return fetch(endpoint, {
160
+ if (hasAllPropsForRcs()) {
161
+ _context2.next = 6;
162
+ break;
163
+ }
164
+
165
+ setErrorIfDuringTaking((0, _formatMessage.default)('Error: Full functionality of the Rich Content Editor may not have been available to the user.'));
166
+ return _context2.abrupt("return");
167
+
168
+ case 6:
169
+ host = props.rcsHost;
170
+ base = host.match(/^https?:\/\//) ? host : "".concat(window.location.protocol, "//").concat(host);
171
+ url = new URL('/api/rceConfig', base);
172
+ url.searchParams.append('contextType', props.contextType);
173
+ url.searchParams.append('contextId', props.contextId);
174
+ _context2.next = 13;
175
+ return fetch(url.href, {
141
176
  headers: {
142
177
  'Authorization': "Bearer ".concat(props.rcsJwt)
143
178
  }
144
179
  });
145
180
 
146
- case 6:
181
+ case 13:
147
182
  response = _context2.sent;
148
- _context2.next = 9;
183
+ _context2.next = 16;
149
184
  return response.json();
150
185
 
151
- case 9:
186
+ case 16:
152
187
  json = _context2.sent;
153
188
  setCanvasConfig(json);
154
- _context2.next = 16;
189
+ setErrorIfDuringTaking(null);
190
+ _context2.next = 25;
155
191
  break;
156
192
 
157
- case 13:
158
- _context2.prev = 13;
193
+ case 21:
194
+ _context2.prev = 21;
159
195
  _context2.t0 = _context2["catch"](0);
160
196
  setCanvasConfig(null);
197
+ setErrorIfDuringTaking((0, _formatMessage.default)('Error: Full functionality of the Rich Content Editor including accessibility features may not have been available to the user.'));
161
198
 
162
- case 16:
163
- _context2.prev = 16;
199
+ case 25:
200
+ _context2.prev = 25;
164
201
  setCanvasConfigLoading(false);
165
- return _context2.finish(16);
202
+ return _context2.finish(25);
166
203
 
167
- case 19:
204
+ case 28:
168
205
  case "end":
169
206
  return _context2.stop();
170
207
  }
171
208
  }
172
- }, _callee2, null, [[0, 13, 16, 19]]);
209
+ }, _callee2, null, [[0, 21, 25, 28]]);
173
210
  }))();
174
211
  }, [props.useNewRce]);
175
212
  if (!props.useNewRce) return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, props.children);
@@ -178,16 +215,18 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
178
215
  }, props.children);
179
216
  };
180
217
 
218
+ exports.RceConfigProviderComponent = RceConfigProviderComponent;
181
219
  RceConfigProviderComponent.propTypes = {
182
220
  children: _propTypes.default.node.isRequired,
183
221
  useNewRce: _propTypes.default.bool.isRequired,
222
+ setRCEError: _propTypes.default.func.isRequired,
184
223
  contextId: _propTypes.default.string,
185
224
  contextType: _propTypes.default.string,
186
225
  canvasUserId: _propTypes.default.string,
187
226
  rcsHost: _propTypes.default.string,
188
227
  rcsJwt: _propTypes.default.string,
189
228
  rcsJwtRefreshFn: _propTypes.default.func,
190
- documentServiceHost: _propTypes.default.string
229
+ canvasOrigin: _propTypes.default.string
191
230
  };
192
231
  RceConfigProviderComponent.defaultProps = {
193
232
  contextId: null,
@@ -196,7 +235,7 @@ RceConfigProviderComponent.defaultProps = {
196
235
  rcsHost: null,
197
236
  rcsJwt: null,
198
237
  rcsJwtRefreshFn: null,
199
- documentServiceHost: null
238
+ canvasOrigin: null
200
239
  };
201
240
 
202
241
  var mapStateToProps = function mapStateToProps() {
@@ -205,5 +244,8 @@ var mapStateToProps = function mapStateToProps() {
205
244
  };
206
245
  };
207
246
 
208
- var RceConfigProvider = (0, _reactRedux.connect)(mapStateToProps)(RceConfigProviderComponent);
247
+ var mapDispatchToProps = {
248
+ setRCEError: _rce.setRCEError
249
+ };
250
+ var RceConfigProvider = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(RceConfigProviderComponent);
209
251
  exports.RceConfigProvider = RceConfigProvider;
@@ -12,7 +12,7 @@ var _taking = require("../selectors/taking.js");
12
12
 
13
13
  var _quizSessions = require("../selectors/quizSessions.js");
14
14
 
15
- var whitelist = [_quizCommon.QUIZ_SUBMISSION_EVENT, _quizCommon.RESPONSE, _quizCommon.SESSION_STARTED_OR_RESUMED_EVENT];
15
+ var whitelist = [_quizCommon.QUIZ_SUBMISSION_EVENT, _quizCommon.RESPONSE, _quizCommon.SESSION_STARTED_OR_RESUMED_EVENT, _quizCommon.RCE_EVENT];
16
16
 
17
17
  function serializeEvent(action, store) {
18
18
  var type = action.type;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.onTablet = exports.onPhone = exports.media = void 0;
6
+ exports.isDuringQuizTake = exports.onTablet = exports.onPhone = exports.media = void 0;
7
7
  var media = {
8
8
  'phone-break-point': 'only screen and (max-width: 48rem)',
9
9
  'tablet-break-point': 'only screen and (max-width: 64rem)'
@@ -24,4 +24,13 @@ var onTablet = function onTablet() {
24
24
  return !onPhone(windowObj) && windowObj.matchMedia(mediaQueryString).matches;
25
25
  };
26
26
 
27
- exports.onTablet = onTablet;
27
+ exports.onTablet = onTablet;
28
+
29
+ var isDuringQuizTake = function isDuringQuizTake() {
30
+ var windowObj = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : window;
31
+ var locationPath = windowObj.location.pathname;
32
+ var patternOfQuizTakingPath = /taking\/\d+\/take/;
33
+ return !!locationPath.match(patternOfQuizTakingPath);
34
+ };
35
+
36
+ exports.isDuringQuizTake = isDuringQuizTake;