@instructure/quiz-core 17.41.1-rc.9 → 17.42.0

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 (42) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/es/building/components/resources/ActionButtons/presenter.js +2 -1
  3. package/es/building/components/resources/quizEntry/QuizEntry/presenter.js +4 -1
  4. package/es/building/components/resources/quizEntry/QuizEntryShow/index.js +1 -0
  5. package/es/building/components/resources/quizEntry/QuizEntryShow/presenter.js +15 -4
  6. package/es/common/actions/rce.js +17 -0
  7. package/es/common/components/SDKApp/index.js +2 -2
  8. package/es/common/components/resources/stimulus/Stimulus/index.js +1 -0
  9. package/es/common/components/resources/stimulus/Stimulus/presenter.js +20 -7
  10. package/es/common/components/resources/stimulus/StimulusShow/index.js +9 -3
  11. package/es/common/kinesis/config.js +3 -2
  12. package/es/common/kinesis/eventTypes.js +2 -1
  13. package/es/common/reducers/rce.js +19 -0
  14. package/es/common/selectors/rce.js +3 -0
  15. package/es/common/util/RceConfigProvider.js +63 -28
  16. package/es/common/util/serializeEvent.js +2 -2
  17. package/es/common/util/windowChecks.js +6 -0
  18. package/es/configureStore.js +3 -1
  19. package/es/index.js +2 -0
  20. package/es/moderating/components/events/Event.js +7 -1
  21. package/es/moderating/components/events/RCEEvent.js +34 -0
  22. package/lib/building/components/resources/ActionButtons/presenter.js +2 -1
  23. package/lib/building/components/resources/quizEntry/QuizEntry/presenter.js +4 -1
  24. package/lib/building/components/resources/quizEntry/QuizEntryShow/index.js +1 -0
  25. package/lib/building/components/resources/quizEntry/QuizEntryShow/presenter.js +15 -4
  26. package/lib/common/actions/rce.js +30 -0
  27. package/lib/common/components/SDKApp/index.js +2 -2
  28. package/lib/common/components/resources/stimulus/Stimulus/index.js +1 -0
  29. package/lib/common/components/resources/stimulus/Stimulus/presenter.js +20 -7
  30. package/lib/common/components/resources/stimulus/StimulusShow/index.js +9 -3
  31. package/lib/common/kinesis/config.js +2 -1
  32. package/lib/common/kinesis/eventTypes.js +4 -2
  33. package/lib/common/reducers/rce.js +29 -0
  34. package/lib/common/selectors/rce.js +12 -0
  35. package/lib/common/util/RceConfigProvider.js +68 -27
  36. package/lib/common/util/serializeEvent.js +1 -1
  37. package/lib/common/util/windowChecks.js +11 -2
  38. package/lib/configureStore.js +4 -1
  39. package/lib/index.js +18 -0
  40. package/lib/moderating/components/events/Event.js +7 -0
  41. package/lib/moderating/components/events/RCEEvent.js +53 -0
  42. package/package.json +10 -10
@@ -5,11 +5,12 @@ import _createSuper from "@babel/runtime/helpers/esm/createSuper";
5
5
  import React, { Component } from 'react';
6
6
  import PropTypes from 'prop-types';
7
7
  import ImmutablePropTypes from 'react-immutable-proptypes';
8
- import { RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT } from '@instructure/quiz-common';
8
+ import { RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, RCE_EVENT } from '@instructure/quiz-common';
9
9
  import { Table } from '@instructure/ui-table';
10
10
  import ElapsedTime from "../resources/ElapsedTime.js";
11
11
  import ResponseEvent from "./ResponseEvent.js";
12
12
  import SessionStartEvent from "./SessionStartEvent.js";
13
+ import RCEEvent from "./RCEEvent.js";
13
14
  export var Event = /*#__PURE__*/function (_Component) {
14
15
  _inherits(Event, _Component);
15
16
 
@@ -48,6 +49,11 @@ export var Event = /*#__PURE__*/function (_Component) {
48
49
  event: event
49
50
  });
50
51
 
52
+ case RCE_EVENT:
53
+ return /*#__PURE__*/React.createElement(RCEEvent, {
54
+ event: event
55
+ });
56
+
51
57
  default:
52
58
  return null;
53
59
  // unknown event
@@ -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) {
@@ -56,10 +64,10 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
56
64
  };
57
65
 
58
66
  var refreshToken = /*#__PURE__*/function () {
59
- var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(setTokenFn) {
67
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(setTokenFn, questionStem) {
60
68
  var _response$json;
61
69
 
62
- var response, refreshedToken;
70
+ var response, refreshedToken, normalizedStem, extractedText;
63
71
  return _regenerator.default.wrap(function _callee$(_context) {
64
72
  while (1) {
65
73
  switch (_context.prev = _context.next) {
@@ -81,18 +89,23 @@ 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
96
  handleErrorFunc('Unable to refresh RCS token');
97
+ normalizedStem = questionStem !== null && questionStem !== void 0 ? questionStem : 'Unknown stem';
98
+ extractedText = (0, _quizInteractions.extractTextFromHtml)(normalizedStem);
99
+ setErrorIfDuringTaking((0, _formatMessage.default)('Error while answering "{stem}": Full functionality of the Rich Content Editor may not have been available to the user.', {
100
+ stem: extractedText
101
+ }));
89
102
  return _context.abrupt("return");
90
103
 
91
- case 10:
104
+ case 13:
92
105
  setJwt(refreshedToken);
93
106
  setTokenFn(refreshedToken);
94
107
 
95
- case 12:
108
+ case 15:
96
109
  case "end":
97
110
  return _context.stop();
98
111
  }
@@ -100,7 +113,7 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
100
113
  }, _callee);
101
114
  }));
102
115
 
103
- return function refreshToken(_x) {
116
+ return function refreshToken(_x, _x2) {
104
117
  return _ref.apply(this, arguments);
105
118
  };
106
119
  }();
@@ -114,20 +127,28 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
114
127
 
115
128
  return {
116
129
  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)
130
+ rendererEnhancement: (_rendererEnhancement = {}, (0, _defineProperty2.default)(_rendererEnhancement, _quizCommon.RceConfigKeys.handleError, handleErrorFunc), (0, _defineProperty2.default)(_rendererEnhancement, _quizCommon.RceConfigKeys.canvasOrigin, props.canvasOrigin), _rendererEnhancement)
118
131
  };
119
132
  };
120
133
 
134
+ var setErrorIfDuringTaking = function setErrorIfDuringTaking(errorMessage) {
135
+ if (!(0, _windowChecks.isDuringQuizTake)()) {
136
+ return;
137
+ }
138
+
139
+ props.setRCEError(errorMessage);
140
+ };
141
+
121
142
  (0, _react.useEffect)(function () {
122
143
  (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
123
- var endpoint, response, json;
144
+ var host, base, url, response, json;
124
145
  return _regenerator.default.wrap(function _callee2$(_context2) {
125
146
  while (1) {
126
147
  switch (_context2.prev = _context2.next) {
127
148
  case 0:
128
149
  _context2.prev = 0;
129
150
 
130
- if (!(!props.useNewRce || !hasAllPropsForRcs())) {
151
+ if (props.useNewRce) {
131
152
  _context2.next = 3;
132
153
  break;
133
154
  }
@@ -135,41 +156,56 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
135
156
  return _context2.abrupt("return");
136
157
 
137
158
  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, {
159
+ if (hasAllPropsForRcs()) {
160
+ _context2.next = 6;
161
+ break;
162
+ }
163
+
164
+ setErrorIfDuringTaking((0, _formatMessage.default)('Error: Full functionality of the Rich Content Editor may not have been available to the user.'));
165
+ return _context2.abrupt("return");
166
+
167
+ case 6:
168
+ host = props.rcsHost;
169
+ base = host.match(/^https?:\/\//) ? host : "".concat(window.location.protocol, "//").concat(host);
170
+ url = new URL('/api/rceConfig', base);
171
+ url.searchParams.append('contextType', props.contextType);
172
+ url.searchParams.append('contextId', props.contextId);
173
+ _context2.next = 13;
174
+ return fetch(url.href, {
141
175
  headers: {
142
176
  'Authorization': "Bearer ".concat(props.rcsJwt)
143
177
  }
144
178
  });
145
179
 
146
- case 6:
180
+ case 13:
147
181
  response = _context2.sent;
148
- _context2.next = 9;
182
+ _context2.next = 16;
149
183
  return response.json();
150
184
 
151
- case 9:
185
+ case 16:
152
186
  json = _context2.sent;
153
187
  setCanvasConfig(json);
154
- _context2.next = 16;
188
+ setErrorIfDuringTaking(null);
189
+ _context2.next = 25;
155
190
  break;
156
191
 
157
- case 13:
158
- _context2.prev = 13;
192
+ case 21:
193
+ _context2.prev = 21;
159
194
  _context2.t0 = _context2["catch"](0);
160
195
  setCanvasConfig(null);
196
+ setErrorIfDuringTaking((0, _formatMessage.default)('Error: Full functionality of the Rich Content Editor including accessibility features may not have been available to the user.'));
161
197
 
162
- case 16:
163
- _context2.prev = 16;
198
+ case 25:
199
+ _context2.prev = 25;
164
200
  setCanvasConfigLoading(false);
165
- return _context2.finish(16);
201
+ return _context2.finish(25);
166
202
 
167
- case 19:
203
+ case 28:
168
204
  case "end":
169
205
  return _context2.stop();
170
206
  }
171
207
  }
172
- }, _callee2, null, [[0, 13, 16, 19]]);
208
+ }, _callee2, null, [[0, 21, 25, 28]]);
173
209
  }))();
174
210
  }, [props.useNewRce]);
175
211
  if (!props.useNewRce) return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, props.children);
@@ -178,16 +214,18 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
178
214
  }, props.children);
179
215
  };
180
216
 
217
+ exports.RceConfigProviderComponent = RceConfigProviderComponent;
181
218
  RceConfigProviderComponent.propTypes = {
182
219
  children: _propTypes.default.node.isRequired,
183
220
  useNewRce: _propTypes.default.bool.isRequired,
221
+ setRCEError: _propTypes.default.func.isRequired,
184
222
  contextId: _propTypes.default.string,
185
223
  contextType: _propTypes.default.string,
186
224
  canvasUserId: _propTypes.default.string,
187
225
  rcsHost: _propTypes.default.string,
188
226
  rcsJwt: _propTypes.default.string,
189
227
  rcsJwtRefreshFn: _propTypes.default.func,
190
- documentServiceHost: _propTypes.default.string
228
+ canvasOrigin: _propTypes.default.string
191
229
  };
192
230
  RceConfigProviderComponent.defaultProps = {
193
231
  contextId: null,
@@ -196,7 +234,7 @@ RceConfigProviderComponent.defaultProps = {
196
234
  rcsHost: null,
197
235
  rcsJwt: null,
198
236
  rcsJwtRefreshFn: null,
199
- documentServiceHost: null
237
+ canvasOrigin: null
200
238
  };
201
239
 
202
240
  var mapStateToProps = function mapStateToProps() {
@@ -205,5 +243,8 @@ var mapStateToProps = function mapStateToProps() {
205
243
  };
206
244
  };
207
245
 
208
- var RceConfigProvider = (0, _reactRedux.connect)(mapStateToProps)(RceConfigProviderComponent);
246
+ var mapDispatchToProps = {
247
+ setRCEError: _rce.setRCEError
248
+ };
249
+ var RceConfigProvider = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(RceConfigProviderComponent);
209
250
  exports.RceConfigProvider = RceConfigProvider;