@instructure/quiz-core 17.41.1-rc.2 → 17.41.1-rc.20
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.
- package/es/building/components/resources/ActionButtons/presenter.js +2 -1
- package/es/building/components/resources/quizEntry/QuizEntry/presenter.js +4 -1
- package/es/building/components/resources/quizEntry/QuizEntryShow/index.js +1 -0
- package/es/building/components/resources/quizEntry/QuizEntryShow/presenter.js +15 -4
- package/es/common/actions/rce.js +17 -0
- package/es/common/components/SDKApp/index.js +2 -2
- package/es/common/components/resources/stimulus/Stimulus/index.js +1 -0
- package/es/common/components/resources/stimulus/Stimulus/presenter.js +20 -7
- package/es/common/components/resources/stimulus/StimulusShow/index.js +9 -3
- package/es/common/kinesis/config.js +3 -2
- package/es/common/kinesis/eventTypes.js +2 -1
- package/es/common/reducers/rce.js +19 -0
- package/es/common/selectors/rce.js +3 -0
- package/es/common/util/RceConfigProvider.js +63 -27
- package/es/common/util/serializeEvent.js +2 -2
- package/es/common/util/windowChecks.js +6 -0
- package/es/configureStore.js +3 -1
- package/es/index.js +2 -0
- package/es/moderating/components/events/Event.js +7 -1
- package/es/moderating/components/events/RCEEvent.js +34 -0
- package/lib/building/components/resources/ActionButtons/presenter.js +2 -1
- package/lib/building/components/resources/quizEntry/QuizEntry/presenter.js +4 -1
- package/lib/building/components/resources/quizEntry/QuizEntryShow/index.js +1 -0
- package/lib/building/components/resources/quizEntry/QuizEntryShow/presenter.js +15 -4
- package/lib/common/actions/rce.js +30 -0
- package/lib/common/components/SDKApp/index.js +2 -2
- package/lib/common/components/resources/stimulus/Stimulus/index.js +1 -0
- package/lib/common/components/resources/stimulus/Stimulus/presenter.js +20 -7
- package/lib/common/components/resources/stimulus/StimulusShow/index.js +9 -3
- package/lib/common/kinesis/config.js +2 -1
- package/lib/common/kinesis/eventTypes.js +4 -2
- package/lib/common/reducers/rce.js +29 -0
- package/lib/common/selectors/rce.js +12 -0
- package/lib/common/util/RceConfigProvider.js +68 -26
- package/lib/common/util/serializeEvent.js +1 -1
- package/lib/common/util/windowChecks.js +11 -2
- package/lib/configureStore.js +4 -1
- package/lib/index.js +18 -0
- package/lib/moderating/components/events/Event.js +7 -0
- package/lib/moderating/components/events/RCEEvent.js +53 -0
- package/package.json +10 -10
|
@@ -121,7 +121,7 @@ export var ActionButtons = (_dec = themeable(theme, styles), _dec(_class = (_tem
|
|
|
121
121
|
quizEntry: this.props.quizEntry,
|
|
122
122
|
quizEntries: this.props.quizEntries,
|
|
123
123
|
disabled: this.props.shouldDisableDragHandle
|
|
124
|
-
}))), /*#__PURE__*/React.createElement(Button, {
|
|
124
|
+
}))), this.props.shouldRenderDelete && /*#__PURE__*/React.createElement(Button, {
|
|
125
125
|
as: "div",
|
|
126
126
|
onClick: this.props.onDelete,
|
|
127
127
|
disabled: this.props.shouldDisableDeleteButton,
|
|
@@ -149,6 +149,7 @@ export var ActionButtons = (_dec = themeable(theme, styles), _dec(_class = (_tem
|
|
|
149
149
|
shouldDisableDragHandle: PropTypes.bool,
|
|
150
150
|
shouldDisableDeleteButton: PropTypes.bool,
|
|
151
151
|
shouldRenderEdit: PropTypes.bool,
|
|
152
|
+
shouldRenderDelete: PropTypes.bool,
|
|
152
153
|
switchOnEditing: PropTypes.func,
|
|
153
154
|
shouldFocusOnMount: PropTypes.bool
|
|
154
155
|
}, _class2.defaultProps = {
|
|
@@ -176,7 +176,7 @@ export var QuizEntry = (_dec = themeable(theme, styles), _dec(_class = (_temp =
|
|
|
176
176
|
clearValidationErrorsFromApi: this.props.clearValidationErrorsFromApi,
|
|
177
177
|
haveValidationErrorsFromApi: Boolean(Object.values(this.props.validationErrorsFromApi).length),
|
|
178
178
|
useNewRce: isNewRCEEnabled()
|
|
179
|
-
}, pick(this.props, ['displayPosition', 'guid', 'draggingOnBuild', 'newHoverPosition', 'quizEntry', 'quizEntries', 'quizId', 'setUi', 'switchOffEditing', 'switchOnEditing', 'shouldClone', 'scrollKey', 'editQuizEntryToggle', 'onEditQuizEntryToggle', 'stimulusOrientation']));
|
|
179
|
+
}, pick(this.props, ['displayPosition', 'guid', 'draggingOnBuild', 'newHoverPosition', 'quizEntry', 'quizEntries', 'quizId', 'isContentLockedByBlueprint', 'setUi', 'switchOffEditing', 'switchOnEditing', 'shouldClone', 'scrollKey', 'editQuizEntryToggle', 'onEditQuizEntryToggle', 'stimulusOrientation']));
|
|
180
180
|
}
|
|
181
181
|
}, {
|
|
182
182
|
key: "isEditing",
|
|
@@ -262,6 +262,7 @@ export var QuizEntry = (_dec = themeable(theme, styles), _dec(_class = (_temp =
|
|
|
262
262
|
dndRef: this.storeDndComponentRef,
|
|
263
263
|
guid: this.props.guid,
|
|
264
264
|
isBankedContent: bankEntryWarningWrapperProps !== void 0,
|
|
265
|
+
isContentLockedByBlueprint: this.props.isContentLockedByBlueprint,
|
|
265
266
|
isEditing: this.isEditing(),
|
|
266
267
|
draggingOnBuild: this.props.draggingOnBuild,
|
|
267
268
|
newHoverPosition: this.props.newHoverPosition // used for DnD
|
|
@@ -358,6 +359,7 @@ export var QuizEntry = (_dec = themeable(theme, styles), _dec(_class = (_temp =
|
|
|
358
359
|
quizEntries: ImmutablePropTypes.listOf(ImmutablePropTypes.record).isRequired,
|
|
359
360
|
quizEntry: ImmutablePropTypes.record.isRequired,
|
|
360
361
|
quizId: PropTypes.string.isRequired,
|
|
362
|
+
isContentLockedByBlueprint: PropTypes.bool.isRequired,
|
|
361
363
|
regradingOn: PropTypes.bool.isRequired,
|
|
362
364
|
screenreaderNotification: PropTypes.func.isRequired,
|
|
363
365
|
scrollKey: PropTypes.string,
|
|
@@ -384,6 +386,7 @@ export var QuizEntry = (_dec = themeable(theme, styles), _dec(_class = (_temp =
|
|
|
384
386
|
draggingOnBuild: false,
|
|
385
387
|
draggingOver: false,
|
|
386
388
|
initialFocusId: null,
|
|
389
|
+
isContentLockedByBlueprint: false,
|
|
387
390
|
isEditing: false,
|
|
388
391
|
partialDeepScoringEnabled: false,
|
|
389
392
|
partialScoringEnabled: false,
|
|
@@ -25,6 +25,7 @@ function mapStateToProps(state, props) {
|
|
|
25
25
|
modificationsClear: itemModsClear && quizEntryModsClear,
|
|
26
26
|
quizEntryWithErrorsShowing: getQuizEntryWithErrorsShowing(state) || props.haveValidationErrorsFromApi,
|
|
27
27
|
richFITBEnabled: featureOn('interaction_type_rich_fill_blank'),
|
|
28
|
+
lockBlueprintContentEnabled: featureOn('lock_blueprint_content'),
|
|
28
29
|
richFITBInteractionID: (richFITBInteraction || Map()).get('id'),
|
|
29
30
|
updateItemCallStatus: state.getIn(['calls', UPDATE_ITEM_CALL, 'requestStatus'], '')
|
|
30
31
|
};
|
|
@@ -263,7 +263,9 @@ var QuizEntryShow = (_dec = themeable(theme, styles), _dec(_class = (_temp = _cl
|
|
|
263
263
|
draggingOver = _this$props2.draggingOver,
|
|
264
264
|
draggingAboveHalf = _this$props2.draggingAboveHalf,
|
|
265
265
|
quizEntry = _this$props2.quizEntry,
|
|
266
|
-
stimulusOrientation = _this$props2.stimulusOrientation
|
|
266
|
+
stimulusOrientation = _this$props2.stimulusOrientation,
|
|
267
|
+
isContentLockedByBlueprint = _this$props2.isContentLockedByBlueprint,
|
|
268
|
+
lockBlueprintContentEnabled = _this$props2.lockBlueprintContentEnabled;
|
|
267
269
|
var positionToDisplay = this.props.quizEntry.positionToDisplay(displayPosition);
|
|
268
270
|
var positionText = t('Preview of question at position {position}', {
|
|
269
271
|
position: positionToDisplay
|
|
@@ -272,13 +274,15 @@ var QuizEntryShow = (_dec = themeable(theme, styles), _dec(_class = (_temp = _cl
|
|
|
272
274
|
var propsForDnDZone = {
|
|
273
275
|
draggingOver: draggingOver,
|
|
274
276
|
draggingAboveHalf: draggingAboveHalf
|
|
275
|
-
};
|
|
277
|
+
};
|
|
278
|
+
var shouldLockQuizEntry = lockBlueprintContentEnabled && isContentLockedByBlueprint; // Overlay gets tabIndex === "-1" so that the drag handle is tabbable before
|
|
276
279
|
// the Overlay get focus and opens the quizEntry in edit mode
|
|
277
280
|
|
|
278
281
|
return /*#__PURE__*/React.createElement(Overlay, {
|
|
279
282
|
onClick: this.editingOn,
|
|
280
283
|
wrapperClassName: styles.quizEntryWrapper,
|
|
281
|
-
tabIndex: "-1"
|
|
284
|
+
tabIndex: "-1",
|
|
285
|
+
hideOverlay: shouldLockQuizEntry
|
|
282
286
|
}, /*#__PURE__*/React.createElement(DragAndDropZone, Object.assign({}, propsForDnDZone, {
|
|
283
287
|
location: "above"
|
|
284
288
|
})), connectDragPreview( /*#__PURE__*/React.createElement("div", {
|
|
@@ -303,7 +307,10 @@ var QuizEntryShow = (_dec = themeable(theme, styles), _dec(_class = (_temp = _cl
|
|
|
303
307
|
scrollKey: this.props.scrollKey,
|
|
304
308
|
shouldDisableDragHandle: this.shouldDisableDragHandle(),
|
|
305
309
|
switchOnEditing: this.editingOn,
|
|
306
|
-
shouldFocusOnMount: this.props.editQuizEntryToggle
|
|
310
|
+
shouldFocusOnMount: this.props.editQuizEntryToggle,
|
|
311
|
+
shouldDisableCopy: shouldLockQuizEntry,
|
|
312
|
+
shouldRenderEdit: !shouldLockQuizEntry,
|
|
313
|
+
shouldRenderDelete: !shouldLockQuizEntry
|
|
307
314
|
}), /*#__PURE__*/React.createElement(ScreenReaderContent, null, srMsg)), /*#__PURE__*/React.createElement("div", {
|
|
308
315
|
className: styles.itemHolder,
|
|
309
316
|
ref: this.setInert,
|
|
@@ -331,10 +338,12 @@ var QuizEntryShow = (_dec = themeable(theme, styles), _dec(_class = (_temp = _cl
|
|
|
331
338
|
// only used in index.js
|
|
332
339
|
interactionTypeName: PropTypes.string,
|
|
333
340
|
modificationsClear: PropTypes.bool.isRequired,
|
|
341
|
+
lockBlueprintContentEnabled: PropTypes.bool.isRequired,
|
|
334
342
|
quizEntryWithErrorsShowing: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
|
335
343
|
quizEntries: ImmutablePropTypes.listOf(ImmutablePropTypes.record).isRequired,
|
|
336
344
|
quizEntry: ImmutablePropTypes.record.isRequired,
|
|
337
345
|
quizId: PropTypes.string.isRequired,
|
|
346
|
+
isContentLockedByBlueprint: PropTypes.bool.isRequired,
|
|
338
347
|
removeQuizEntry: PropTypes.func.isRequired,
|
|
339
348
|
// from connected component
|
|
340
349
|
richFITBEnabled: PropTypes.bool,
|
|
@@ -351,11 +360,13 @@ var QuizEntryShow = (_dec = themeable(theme, styles), _dec(_class = (_temp = _cl
|
|
|
351
360
|
children: null,
|
|
352
361
|
draggingOver: false,
|
|
353
362
|
draggingAboveHalf: false,
|
|
363
|
+
lockBlueprintContentEnabled: false,
|
|
354
364
|
quizEntryWithErrorsShowing: null,
|
|
355
365
|
scrollKey: void 0,
|
|
356
366
|
editQuizEntryToggle: false,
|
|
357
367
|
haveValidationErrorsFromApi: false,
|
|
358
368
|
interactionTypeName: null,
|
|
369
|
+
isContentLockedByBlueprint: false,
|
|
359
370
|
richFITBEnabled: false,
|
|
360
371
|
richFITBInteractionID: '',
|
|
361
372
|
stimulusOrientation: null
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RCE_EVENT, SET_RCE_ERROR } from '@instructure/quiz-common';
|
|
2
|
+
export var setRCEError = function setRCEError(rceError) {
|
|
3
|
+
return {
|
|
4
|
+
type: SET_RCE_ERROR,
|
|
5
|
+
payload: rceError
|
|
6
|
+
};
|
|
7
|
+
}; // This is not consumed by its reducer
|
|
8
|
+
// Instead it is processed by the eventLoggerMiddleware
|
|
9
|
+
|
|
10
|
+
export var reportRCEEvent = function reportRCEEvent(eventMessage) {
|
|
11
|
+
return {
|
|
12
|
+
type: RCE_EVENT,
|
|
13
|
+
payload: {
|
|
14
|
+
message: eventMessage
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -159,11 +159,11 @@ export var SDKApp = (_dec = themeable(theme, styles), _dec(_class = (_temp = _cl
|
|
|
159
159
|
rceConfig: PropTypes.shape({
|
|
160
160
|
contextId: PropTypes.string.isRequired,
|
|
161
161
|
contextType: PropTypes.string.isRequired,
|
|
162
|
+
canvasOrigin: PropTypes.string.isRequired,
|
|
162
163
|
canvasUserId: PropTypes.string.isRequired,
|
|
163
164
|
rcsHost: PropTypes.string.isRequired,
|
|
164
165
|
rcsJwt: PropTypes.string.isRequired,
|
|
165
|
-
rcsJwtRefreshFn: PropTypes.func.isRequired
|
|
166
|
-
documentServiceHost: PropTypes.string.isRequired
|
|
166
|
+
rcsJwtRefreshFn: PropTypes.func.isRequired
|
|
167
167
|
}),
|
|
168
168
|
timeZone: PropTypes.string,
|
|
169
169
|
translations: PropTypes.objectOf(PropTypes.shape({
|
|
@@ -15,6 +15,7 @@ var mapStateToProps = function mapStateToProps(state, props) {
|
|
|
15
15
|
dropIntoEmptyStimulus: draggingOver && dropIntoEmptyStimulus,
|
|
16
16
|
draggingOver: draggingOver,
|
|
17
17
|
draggingAboveHalf: draggingOver && draggingAboveHalf,
|
|
18
|
+
lockBlueprintContentEnabled: featureOn('lock_blueprint_content'),
|
|
18
19
|
stimulusOrientationEnabled: featureOn('customizable_stimulus_orientation')
|
|
19
20
|
};
|
|
20
21
|
};
|
|
@@ -75,6 +75,14 @@ export var Stimulus = (_dec = themeable(theme, styles), _dec(_class = (_temp = _
|
|
|
75
75
|
quizEntry = _this$props.quizEntry;
|
|
76
76
|
return quizEntries.size === quizEntry.positionSlots + 1;
|
|
77
77
|
}
|
|
78
|
+
}, {
|
|
79
|
+
key: "isQuizContentLocked",
|
|
80
|
+
value: function isQuizContentLocked() {
|
|
81
|
+
var _this$props2 = this.props,
|
|
82
|
+
isContentLockedByBlueprint = _this$props2.isContentLockedByBlueprint,
|
|
83
|
+
lockBlueprintContentEnabled = _this$props2.lockBlueprintContentEnabled;
|
|
84
|
+
return lockBlueprintContentEnabled && isContentLockedByBlueprint;
|
|
85
|
+
}
|
|
78
86
|
}, {
|
|
79
87
|
key: "renderChildQuizEntries",
|
|
80
88
|
value: function renderChildQuizEntries() {
|
|
@@ -89,7 +97,7 @@ export var Stimulus = (_dec = themeable(theme, styles), _dec(_class = (_temp = _
|
|
|
89
97
|
key: childEntry.id
|
|
90
98
|
}, /*#__PURE__*/React.createElement(ConnectedQuizEntry, Object.assign({}, _this2.props.propsForQuizEntry(childEntry, displayPosition), {
|
|
91
99
|
stimulusOrientation: _this2.props.stimulusOrientationEnabled ? _this2.props.stimulus.orientation : null
|
|
92
|
-
})), !_this2.props.draggingOnBuild && /*#__PURE__*/React.createElement(AddContentPopover, {
|
|
100
|
+
})), !_this2.props.draggingOnBuild && !_this2.isQuizContentLocked() && /*#__PURE__*/React.createElement(AddContentPopover, {
|
|
93
101
|
allowStimulusCreation: false,
|
|
94
102
|
stimulusId: _this2.props.stimulus.id,
|
|
95
103
|
parentEntryId: _this2.props.quizEntry.id,
|
|
@@ -123,7 +131,8 @@ export var Stimulus = (_dec = themeable(theme, styles), _dec(_class = (_temp = _
|
|
|
123
131
|
switchOnEditing: this.props.switchOnEditing,
|
|
124
132
|
switchOffEditing: this.props.switchOffEditing,
|
|
125
133
|
onEditToggle: this.props.onEditStimulusToggle,
|
|
126
|
-
shouldFocusOnMount: this.props.editStimulusToggle
|
|
134
|
+
shouldFocusOnMount: this.props.editStimulusToggle,
|
|
135
|
+
isQuizContentLocked: this.isQuizContentLocked()
|
|
127
136
|
})));
|
|
128
137
|
}
|
|
129
138
|
}, {
|
|
@@ -131,9 +140,9 @@ export var Stimulus = (_dec = themeable(theme, styles), _dec(_class = (_temp = _
|
|
|
131
140
|
value: function renderPanels(propsForDnDZone) {
|
|
132
141
|
var _classnames2;
|
|
133
142
|
|
|
134
|
-
var _this$
|
|
135
|
-
stimulus = _this$
|
|
136
|
-
stimulusOrientationEnabled = _this$
|
|
143
|
+
var _this$props3 = this.props,
|
|
144
|
+
stimulus = _this$props3.stimulus,
|
|
145
|
+
stimulusOrientationEnabled = _this$props3.stimulusOrientationEnabled;
|
|
137
146
|
var shouldSetHorizontalOrientation = stimulus.orientation === LEFT || !stimulusOrientationEnabled;
|
|
138
147
|
var stimulusPanelClass = classnames(styles.leftPanel, _defineProperty({}, styles.horizontallyAligned, shouldSetHorizontalOrientation));
|
|
139
148
|
var itemsPanelClass = classnames((_classnames2 = {}, _defineProperty(_classnames2, styles.horizontallyAligned, shouldSetHorizontalOrientation), _defineProperty(_classnames2, styles.hidden, stimulus.isTemporary()), _defineProperty(_classnames2, styles.rightPanel, !stimulus.isTemporary()), _classnames2));
|
|
@@ -147,7 +156,7 @@ export var Stimulus = (_dec = themeable(theme, styles), _dec(_class = (_temp = _
|
|
|
147
156
|
className: itemsPanelClass
|
|
148
157
|
}, /*#__PURE__*/React.createElement("div", null), this.renderChildQuizEntries(), /*#__PURE__*/React.createElement(DragAndDropZone, Object.assign({}, propsForDnDZone, {
|
|
149
158
|
location: "in"
|
|
150
|
-
})), this.props.childEntries.size === 0 && /*#__PURE__*/React.createElement(AddContentPopover, {
|
|
159
|
+
})), this.props.childEntries.size === 0 && !this.isQuizContentLocked() && /*#__PURE__*/React.createElement(AddContentPopover, {
|
|
151
160
|
allowStimulusCreation: false,
|
|
152
161
|
stimulusId: this.props.stimulus.id,
|
|
153
162
|
parentEntryId: this.props.quizEntry.id,
|
|
@@ -189,8 +198,10 @@ export var Stimulus = (_dec = themeable(theme, styles), _dec(_class = (_temp = _
|
|
|
189
198
|
dropIntoEmptyStimulus: PropTypes.bool,
|
|
190
199
|
displayPosition: PropTypes.number.isRequired,
|
|
191
200
|
isBankedContent: PropTypes.bool,
|
|
201
|
+
isContentLockedByBlueprint: PropTypes.bool.isRequired,
|
|
192
202
|
isEditing: PropTypes.bool,
|
|
193
203
|
guid: PropTypes.string.isRequired,
|
|
204
|
+
lockBlueprintContentEnabled: PropTypes.bool.isRequired,
|
|
194
205
|
openDeleteStimulusModal: PropTypes.func.isRequired,
|
|
195
206
|
propsForQuizEntry: PropTypes.func.isRequired,
|
|
196
207
|
quizEntry: ImmutablePropTypes.record.isRequired,
|
|
@@ -215,7 +226,9 @@ export var Stimulus = (_dec = themeable(theme, styles), _dec(_class = (_temp = _
|
|
|
215
226
|
dropIntoEmptyStimulus: false,
|
|
216
227
|
isBankedContent: false,
|
|
217
228
|
isEditing: false,
|
|
229
|
+
lockBlueprintContentEnabled: false,
|
|
218
230
|
onEditStimulusToggle: function onEditStimulusToggle() {},
|
|
219
|
-
scrollKey: ''
|
|
231
|
+
scrollKey: '',
|
|
232
|
+
isContentLockedByBlueprint: false
|
|
220
233
|
}, _temp)) || _class);
|
|
221
234
|
export default DragSource(ItemTypes.QUIZ_ENTRY, dragSource, collectDrag)(wrapWithOutsideClick(Stimulus));
|
|
@@ -66,7 +66,8 @@ export var StimulusShow = (_dec = themeable(theme, styles), _dec(_class = (_temp
|
|
|
66
66
|
return /*#__PURE__*/React.createElement(Overlay, {
|
|
67
67
|
onClick: this.switchOnEditing,
|
|
68
68
|
wrapperClassName: styles.stimulusWrapper,
|
|
69
|
-
tabIndex: "-1"
|
|
69
|
+
tabIndex: "-1",
|
|
70
|
+
hideOverlay: this.props.isQuizContentLocked
|
|
70
71
|
}, /*#__PURE__*/React.createElement("div", {
|
|
71
72
|
className: styles.stimulus
|
|
72
73
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -84,10 +85,13 @@ export var StimulusShow = (_dec = themeable(theme, styles), _dec(_class = (_temp
|
|
|
84
85
|
scrollKey: this.props.scrollKey,
|
|
85
86
|
shouldDisableDragHandle: this.props.shouldDisableDragHandle,
|
|
86
87
|
switchOnEditing: this.props.switchOnEditing,
|
|
87
|
-
shouldFocusOnMount: this.props.shouldFocusOnMount
|
|
88
|
+
shouldFocusOnMount: this.props.shouldFocusOnMount,
|
|
89
|
+
shouldDisableCopy: this.props.isQuizContentLocked,
|
|
90
|
+
shouldRenderEdit: !this.props.isQuizContentLocked,
|
|
91
|
+
shouldRenderDelete: !this.props.isQuizContentLocked
|
|
88
92
|
})), /*#__PURE__*/React.createElement("div", {
|
|
89
93
|
role: "presentation",
|
|
90
|
-
onClick: this.switchOnEditing,
|
|
94
|
+
onClick: this.props.isQuizContentLocked ? null : this.switchOnEditing,
|
|
91
95
|
className: styles.stimulusContent
|
|
92
96
|
}, /*#__PURE__*/React.createElement(StimulusShowInfo, {
|
|
93
97
|
stimulus: this.props.stimulus
|
|
@@ -101,6 +105,7 @@ export var StimulusShow = (_dec = themeable(theme, styles), _dec(_class = (_temp
|
|
|
101
105
|
connectDragSource: PropTypes.func.isRequired,
|
|
102
106
|
displayPosition: PropTypes.number.isRequired,
|
|
103
107
|
isBankedContent: PropTypes.bool,
|
|
108
|
+
isQuizContentLocked: PropTypes.bool.isRequired,
|
|
104
109
|
openDeleteStimulusModal: PropTypes.func.isRequired,
|
|
105
110
|
quizEntries: ImmutablePropTypes.listOf(ImmutablePropTypes.record).isRequired,
|
|
106
111
|
quizEntry: ImmutablePropTypes.record.isRequired,
|
|
@@ -111,6 +116,7 @@ export var StimulusShow = (_dec = themeable(theme, styles), _dec(_class = (_temp
|
|
|
111
116
|
shouldFocusOnMount: PropTypes.bool.isRequired
|
|
112
117
|
}, _class2.defaultProps = {
|
|
113
118
|
isBankedContent: false,
|
|
119
|
+
isQuizContentLocked: false,
|
|
114
120
|
scrollKey: '',
|
|
115
121
|
shouldDisableDragHandle: false,
|
|
116
122
|
shouldFocusOnMount: false
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EVENT_RESPONSE, QUIZ_SUBMISSION_EVENT, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT } from "./eventTypes.js";
|
|
1
|
+
import { EVENT_RESPONSE, QUIZ_SUBMISSION_EVENT, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, RCE_EVENT } from "./eventTypes.js";
|
|
2
2
|
export var assembleKinesisConfig = function assembleKinesisConfig(apiConfig) {
|
|
3
3
|
return Object.assign({
|
|
4
4
|
apiVersion: '2013-12-02'
|
|
@@ -19,7 +19,8 @@ export var eventStreamConfig = function eventStreamConfig(defaultStreamConfig, s
|
|
|
19
19
|
eventTypes: {
|
|
20
20
|
RESPONSE: EVENT_RESPONSE,
|
|
21
21
|
SESSION_STARTED_OR_RESUMED_EVENT: SESSION_STARTED_OR_RESUMED_EVENT,
|
|
22
|
-
QUIZ_SUBMISSION_EVENT: QUIZ_SUBMISSION_EVENT
|
|
22
|
+
QUIZ_SUBMISSION_EVENT: QUIZ_SUBMISSION_EVENT,
|
|
23
|
+
RCE_EVENT: RCE_EVENT
|
|
23
24
|
},
|
|
24
25
|
stream: stream
|
|
25
26
|
});
|
|
@@ -34,4 +34,5 @@ export var RESPONSE = eventType(function (data) {
|
|
|
34
34
|
});
|
|
35
35
|
export var EVENT_RESPONSE = eventType();
|
|
36
36
|
export var SESSION_STARTED_OR_RESUMED_EVENT = eventType();
|
|
37
|
-
export var QUIZ_SUBMISSION_EVENT = eventType();
|
|
37
|
+
export var QUIZ_SUBMISSION_EVENT = eventType();
|
|
38
|
+
export var RCE_EVENT = eventType();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Map } from 'immutable';
|
|
2
|
+
import { SET_RCE_ERROR } from '@instructure/quiz-common';
|
|
3
|
+
|
|
4
|
+
var setRceError = function setRceError(state, payload) {
|
|
5
|
+
return state.set('rceError', payload);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default (function () {
|
|
9
|
+
var state = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : Map();
|
|
10
|
+
var action = arguments.length > 1 ? arguments[1] : void 0;
|
|
11
|
+
|
|
12
|
+
switch (action.type) {
|
|
13
|
+
case SET_RCE_ERROR:
|
|
14
|
+
return setRceError(state, action.payload);
|
|
15
|
+
|
|
16
|
+
default:
|
|
17
|
+
return state;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
@@ -6,14 +6,18 @@ import React, { useEffect, useState } from 'react';
|
|
|
6
6
|
import PropTypes from 'prop-types';
|
|
7
7
|
import { connect } from "../../common/react-redux.js";
|
|
8
8
|
import store from "../../reduxStore.js";
|
|
9
|
+
import { setRCEError } from "../actions/rce.js";
|
|
9
10
|
import isNewRCEEnabled from "./rceChecker.js";
|
|
10
11
|
import { QuizzesSpinner as Spinner } from "../components/shared/spinner/Spinner.js";
|
|
11
12
|
import { RceConfigContext, RceConfigKeys } from '@instructure/quiz-common';
|
|
12
13
|
import { addError } from "../actions/alerts.js";
|
|
14
|
+
import t from '@instructure/quiz-i18n/es/format-message';
|
|
15
|
+
import { extractTextFromHtml } from '@instructure/quiz-interactions';
|
|
16
|
+
import { isDuringQuizTake } from "./windowChecks.js";
|
|
13
17
|
|
|
14
18
|
var _ref4 = /*#__PURE__*/React.createElement(Spinner, null);
|
|
15
19
|
|
|
16
|
-
var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
|
|
20
|
+
export var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
|
|
17
21
|
var _useState = useState(props.rcsJwt),
|
|
18
22
|
_useState2 = _slicedToArray(_useState, 2),
|
|
19
23
|
jwt = _useState2[0],
|
|
@@ -37,7 +41,7 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
|
|
|
37
41
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(setTokenFn) {
|
|
38
42
|
var _response$json;
|
|
39
43
|
|
|
40
|
-
var response, refreshedToken;
|
|
44
|
+
var response, refreshedToken, stemPlaceholder, extractedText;
|
|
41
45
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
42
46
|
while (1) {
|
|
43
47
|
switch (_context.prev = _context.next) {
|
|
@@ -59,18 +63,24 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
|
|
|
59
63
|
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
|
|
60
64
|
|
|
61
65
|
if (refreshedToken) {
|
|
62
|
-
_context.next =
|
|
66
|
+
_context.next = 13;
|
|
63
67
|
break;
|
|
64
68
|
}
|
|
65
69
|
|
|
66
|
-
handleErrorFunc('Unable to refresh RCS token');
|
|
70
|
+
handleErrorFunc('Unable to refresh RCS token'); // TODO: provide question context for this function so it can actually get the question stem / instruction text
|
|
71
|
+
|
|
72
|
+
stemPlaceholder = 'Example question stem text';
|
|
73
|
+
extractedText = extractTextFromHtml(stemPlaceholder);
|
|
74
|
+
setErrorIfDuringTaking(t('Error while answering: {stem}: Full functionality of the Rich Content Editor may not have been available to the user.', {
|
|
75
|
+
stem: extractedText
|
|
76
|
+
}));
|
|
67
77
|
return _context.abrupt("return");
|
|
68
78
|
|
|
69
|
-
case
|
|
79
|
+
case 13:
|
|
70
80
|
setJwt(refreshedToken);
|
|
71
81
|
setTokenFn(refreshedToken);
|
|
72
82
|
|
|
73
|
-
case
|
|
83
|
+
case 15:
|
|
74
84
|
case "end":
|
|
75
85
|
return _context.stop();
|
|
76
86
|
}
|
|
@@ -92,20 +102,28 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
|
|
|
92
102
|
|
|
93
103
|
return {
|
|
94
104
|
rcs: hasAllPropsForRcs() && canvasConfig ? (_ref2 = {}, _defineProperty(_ref2, RceConfigKeys.useNewRce, props.useNewRce), _defineProperty(_ref2, RceConfigKeys.canvasUserId, props.canvasUserId), _defineProperty(_ref2, RceConfigKeys.contextId, props.contextId), _defineProperty(_ref2, RceConfigKeys.contextType, props.contextType), _defineProperty(_ref2, RceConfigKeys.rcsHost, props.rcsHost), _defineProperty(_ref2, RceConfigKeys.rcsJwt, jwt), _defineProperty(_ref2, RceConfigKeys.rcsJwtRefreshFn, refreshToken), _defineProperty(_ref2, RceConfigKeys.canvasConfig, canvasConfig), _ref2) : null,
|
|
95
|
-
rendererEnhancement: (_rendererEnhancement = {}, _defineProperty(_rendererEnhancement, RceConfigKeys.handleError, handleErrorFunc), _defineProperty(_rendererEnhancement, RceConfigKeys.
|
|
105
|
+
rendererEnhancement: (_rendererEnhancement = {}, _defineProperty(_rendererEnhancement, RceConfigKeys.handleError, handleErrorFunc), _defineProperty(_rendererEnhancement, RceConfigKeys.canvasOrigin, props.canvasOrigin), _rendererEnhancement)
|
|
96
106
|
};
|
|
97
107
|
};
|
|
98
108
|
|
|
109
|
+
var setErrorIfDuringTaking = function setErrorIfDuringTaking(errorMessage) {
|
|
110
|
+
if (!isDuringQuizTake()) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
props.setRCEError(errorMessage);
|
|
115
|
+
};
|
|
116
|
+
|
|
99
117
|
useEffect(function () {
|
|
100
118
|
_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
101
|
-
var
|
|
119
|
+
var host, base, url, response, json;
|
|
102
120
|
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
103
121
|
while (1) {
|
|
104
122
|
switch (_context2.prev = _context2.next) {
|
|
105
123
|
case 0:
|
|
106
124
|
_context2.prev = 0;
|
|
107
125
|
|
|
108
|
-
if (
|
|
126
|
+
if (props.useNewRce) {
|
|
109
127
|
_context2.next = 3;
|
|
110
128
|
break;
|
|
111
129
|
}
|
|
@@ -113,41 +131,56 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
|
|
|
113
131
|
return _context2.abrupt("return");
|
|
114
132
|
|
|
115
133
|
case 3:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
134
|
+
if (hasAllPropsForRcs()) {
|
|
135
|
+
_context2.next = 6;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
setErrorIfDuringTaking(t('Error: Full functionality of the Rich Content Editor may not have been available to the user.'));
|
|
140
|
+
return _context2.abrupt("return");
|
|
141
|
+
|
|
142
|
+
case 6:
|
|
143
|
+
host = props.rcsHost;
|
|
144
|
+
base = host.match(/^https?:\/\//) ? host : "".concat(window.location.protocol, "//").concat(host);
|
|
145
|
+
url = new URL('/api/rceConfig', base);
|
|
146
|
+
url.searchParams.append('contextType', props.contextType);
|
|
147
|
+
url.searchParams.append('contextId', props.contextId);
|
|
148
|
+
_context2.next = 13;
|
|
149
|
+
return fetch(url.href, {
|
|
119
150
|
headers: {
|
|
120
151
|
'Authorization': "Bearer ".concat(props.rcsJwt)
|
|
121
152
|
}
|
|
122
153
|
});
|
|
123
154
|
|
|
124
|
-
case
|
|
155
|
+
case 13:
|
|
125
156
|
response = _context2.sent;
|
|
126
|
-
_context2.next =
|
|
157
|
+
_context2.next = 16;
|
|
127
158
|
return response.json();
|
|
128
159
|
|
|
129
|
-
case
|
|
160
|
+
case 16:
|
|
130
161
|
json = _context2.sent;
|
|
131
162
|
setCanvasConfig(json);
|
|
132
|
-
|
|
163
|
+
setErrorIfDuringTaking(null);
|
|
164
|
+
_context2.next = 25;
|
|
133
165
|
break;
|
|
134
166
|
|
|
135
|
-
case
|
|
136
|
-
_context2.prev =
|
|
167
|
+
case 21:
|
|
168
|
+
_context2.prev = 21;
|
|
137
169
|
_context2.t0 = _context2["catch"](0);
|
|
138
170
|
setCanvasConfig(null);
|
|
171
|
+
setErrorIfDuringTaking(t('Error: Full functionality of the Rich Content Editor including accessibility features may not have been available to the user.'));
|
|
139
172
|
|
|
140
|
-
case
|
|
141
|
-
_context2.prev =
|
|
173
|
+
case 25:
|
|
174
|
+
_context2.prev = 25;
|
|
142
175
|
setCanvasConfigLoading(false);
|
|
143
|
-
return _context2.finish(
|
|
176
|
+
return _context2.finish(25);
|
|
144
177
|
|
|
145
|
-
case
|
|
178
|
+
case 28:
|
|
146
179
|
case "end":
|
|
147
180
|
return _context2.stop();
|
|
148
181
|
}
|
|
149
182
|
}
|
|
150
|
-
}, _callee2, null, [[0,
|
|
183
|
+
}, _callee2, null, [[0, 21, 25, 28]]);
|
|
151
184
|
}))();
|
|
152
185
|
}, [props.useNewRce]);
|
|
153
186
|
if (!props.useNewRce) return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
@@ -155,17 +188,17 @@ var RceConfigProviderComponent = function RceConfigProviderComponent(props) {
|
|
|
155
188
|
value: getConfig()
|
|
156
189
|
}, props.children);
|
|
157
190
|
};
|
|
158
|
-
|
|
159
191
|
RceConfigProviderComponent.propTypes = {
|
|
160
192
|
children: PropTypes.node.isRequired,
|
|
161
193
|
useNewRce: PropTypes.bool.isRequired,
|
|
194
|
+
setRCEError: PropTypes.func.isRequired,
|
|
162
195
|
contextId: PropTypes.string,
|
|
163
196
|
contextType: PropTypes.string,
|
|
164
197
|
canvasUserId: PropTypes.string,
|
|
165
198
|
rcsHost: PropTypes.string,
|
|
166
199
|
rcsJwt: PropTypes.string,
|
|
167
200
|
rcsJwtRefreshFn: PropTypes.func,
|
|
168
|
-
|
|
201
|
+
canvasOrigin: PropTypes.string
|
|
169
202
|
};
|
|
170
203
|
RceConfigProviderComponent.defaultProps = {
|
|
171
204
|
contextId: null,
|
|
@@ -174,7 +207,7 @@ RceConfigProviderComponent.defaultProps = {
|
|
|
174
207
|
rcsHost: null,
|
|
175
208
|
rcsJwt: null,
|
|
176
209
|
rcsJwtRefreshFn: null,
|
|
177
|
-
|
|
210
|
+
canvasOrigin: null
|
|
178
211
|
};
|
|
179
212
|
|
|
180
213
|
var mapStateToProps = function mapStateToProps() {
|
|
@@ -183,5 +216,8 @@ var mapStateToProps = function mapStateToProps() {
|
|
|
183
216
|
};
|
|
184
217
|
};
|
|
185
218
|
|
|
186
|
-
var
|
|
219
|
+
var mapDispatchToProps = {
|
|
220
|
+
setRCEError: setRCEError
|
|
221
|
+
};
|
|
222
|
+
var RceConfigProvider = connect(mapStateToProps, mapDispatchToProps)(RceConfigProviderComponent);
|
|
187
223
|
export { RceConfigProvider };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { QUIZ_SUBMISSION_EVENT, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT } from '@instructure/quiz-common';
|
|
1
|
+
import { QUIZ_SUBMISSION_EVENT, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, RCE_EVENT } from '@instructure/quiz-common';
|
|
2
2
|
import { getBrowserSessionId } from "../selectors/taking.js";
|
|
3
3
|
import { getActiveQuizSession } from "../selectors/quizSessions.js";
|
|
4
|
-
var whitelist = [QUIZ_SUBMISSION_EVENT, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT];
|
|
4
|
+
var whitelist = [QUIZ_SUBMISSION_EVENT, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, RCE_EVENT];
|
|
5
5
|
export function serializeEvent(action, store) {
|
|
6
6
|
var type = action.type;
|
|
7
7
|
|
|
@@ -11,4 +11,10 @@ export var onTablet = function onTablet() {
|
|
|
11
11
|
var windowObj = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : window;
|
|
12
12
|
var mediaQueryString = media['tablet-break-point'];
|
|
13
13
|
return !onPhone(windowObj) && windowObj.matchMedia(mediaQueryString).matches;
|
|
14
|
+
};
|
|
15
|
+
export var isDuringQuizTake = function isDuringQuizTake() {
|
|
16
|
+
var windowObj = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : window;
|
|
17
|
+
var locationPath = windowObj.location.pathname;
|
|
18
|
+
var patternOfQuizTakingPath = /taking\/\d+\/take/;
|
|
19
|
+
return !!locationPath.match(patternOfQuizTakingPath);
|
|
14
20
|
};
|
package/es/configureStore.js
CHANGED
|
@@ -44,6 +44,7 @@ import ui from "./common/reducers/ui.js";
|
|
|
44
44
|
import upload from "./common/reducers/upload.js";
|
|
45
45
|
import qtiImports from "./common/reducers/qtiImports.js";
|
|
46
46
|
import printing from "./common/reducers/printing.js";
|
|
47
|
+
import rce from "./common/reducers/rce.js";
|
|
47
48
|
import dragAndDrop from "./common/reducers/dragAndDrop.js";
|
|
48
49
|
import sharedBanks from "./common/reducers/sharedBanks.js";
|
|
49
50
|
export function configureStore(_ref) {
|
|
@@ -110,7 +111,8 @@ export function configureStore(_ref) {
|
|
|
110
111
|
tagAssociations: tagAssociations,
|
|
111
112
|
taking: taking,
|
|
112
113
|
ui: ui,
|
|
113
|
-
upload: upload
|
|
114
|
+
upload: upload,
|
|
115
|
+
rce: rce
|
|
114
116
|
});
|
|
115
117
|
return createStoreWithMiddlewareApplied(rootReducer, initialState);
|
|
116
118
|
}
|
package/es/index.js
CHANGED
|
@@ -113,6 +113,7 @@ export { showError, hideError, clearErrorsShowing } from "./common/actions/error
|
|
|
113
113
|
export { changeItemState, changeQuizEntryPoints, changeQuizEntryProperties, clearModifications, moveTemporaryQuizEntry, changeQuizOutcomeAlignmentSetGuid, changeFudgePoints, sessionItemResultsModification } from "./common/actions/modifications.js";
|
|
114
114
|
export { previousQuestion, editResponse, previewResponse, setCurrentSessionItemPosition, clearFocusCurrentSessionItem } from "./common/actions/taking.js";
|
|
115
115
|
export { scrollToItem } from "./common/actions/scrolling.js";
|
|
116
|
+
export { reportRCEEvent } from "./common/actions/rce.js";
|
|
116
117
|
export { toggleSidebar } from "./common/actions/sidebar.js";
|
|
117
118
|
export { newHoverPosition } from "./common/actions/dragAndDrop.js";
|
|
118
119
|
export { set, setActiveCalculatorId } from "./common/actions/ui.js";
|
|
@@ -129,6 +130,7 @@ export { getItemById } from "./common/selectors/items.js";
|
|
|
129
130
|
export { fileUploading } from "./common/selectors/calls.js";
|
|
130
131
|
export { isTimeUp, getTimerData, getResponseDataByPosition } from "./common/selectors/taking.js";
|
|
131
132
|
export { getActiveCalculatorId } from "./common/selectors/ui.js";
|
|
133
|
+
export { getRCEError } from "./common/selectors/rce.js";
|
|
132
134
|
export { getQuizSessionById, getActiveQuizSession, getBacktrackingIsAllowed, isOneQuestionAtATime } from "./common/selectors/quizSessions.js";
|
|
133
135
|
export { getGradingSessionItems } from "./common/selectors/sessionItems.js";
|
|
134
136
|
export { getGradingSessionItemResults } from "./common/selectors/sessionItemResults.js"; // Records
|
|
@@ -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
|