@instructure/quiz-core 20.17.3-rc.9 → 20.18.1-rc.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.
- package/CHANGELOG.md +20 -0
- package/es/banks/api/bankEntries.js +45 -1
- package/es/banks/components/AddToBankModal/index.js +2 -1
- package/es/banks/components/AddToBankModal/presenter.js +13 -2
- package/es/banks/components/CopyMoveBankEntryModal/index.js +3 -1
- package/es/banks/components/CopyMoveBankEntryModal/presenter.js +26 -7
- package/es/building/components/resources/quizEntry/QuizEntryEdit/presenter.js +1 -0
- package/es/common/actions/taking.js +9 -1
- package/es/common/components/resources/stimulus/StimulusEdit/presenter.js +1 -0
- package/es/common/middleware/quizTimerWebSocketMiddleware.js +91 -0
- package/es/common/reducers/taking.js +8 -1
- package/es/common/util/TimerService.js +6 -1
- package/es/configureStore.js +4 -2
- package/es/index.js +8 -0
- package/es/taking/api/taking.js +18 -2
- package/lib/banks/api/bankEntries.js +57 -1
- package/lib/banks/components/AddToBankModal/index.js +1 -0
- package/lib/banks/components/AddToBankModal/presenter.js +14 -2
- package/lib/banks/components/CopyMoveBankEntryModal/index.js +2 -0
- package/lib/banks/components/CopyMoveBankEntryModal/presenter.js +27 -7
- package/lib/building/components/resources/quizEntry/QuizEntryEdit/presenter.js +1 -0
- package/lib/common/actions/taking.js +12 -1
- package/lib/common/components/resources/stimulus/StimulusEdit/presenter.js +1 -0
- package/lib/common/middleware/quizTimerWebSocketMiddleware.js +121 -0
- package/lib/common/reducers/taking.js +7 -0
- package/lib/common/util/TimerService.js +6 -1
- package/lib/configureStore.js +4 -1
- package/lib/taking/api/taking.js +20 -0
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [20.18.0](https://gerrit.instructure.com/quizzes-ui/compare/v20.17.2...v20.18.0) (2024-09-26)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **quizzes-ui:** Add data-automation tags for impact integration ([9b710b8](https://gerrit.instructure.com/quizzes-ui/commits/9b710b87929cc2d203de0f9f68e75a5e2b1a3150))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* update remaining time in quiz session ([3a1a914](https://gerrit.instructure.com/quizzes-ui/commits/3a1a91424ba174b7f2a39cf2a8a4d669dae120ab))
|
|
17
|
+
* **quizzes-ui:** add 2-minute alert to timed quiz ([6bb83e9](https://gerrit.instructure.com/quizzes-ui/commits/6bb83e953ae989bc88975922051044bef9e4d7ce))
|
|
18
|
+
* **quizzes-ui:** add page_blurred/page_focused events ([2c6b692](https://gerrit.instructure.com/quizzes-ui/commits/2c6b6928b7a2f7926ab1757884ee63bcff6c4c37))
|
|
19
|
+
* add Cancel and Close button to ModerateTray ([e41ad88](https://gerrit.instructure.com/quizzes-ui/commits/e41ad88aaef2af576f53ff0e212c6d793db74bf4))
|
|
20
|
+
* refactor ingress for AccommodationModal and ModerateTray ([7c49355](https://gerrit.instructure.com/quizzes-ui/commits/7c49355a8b03cd20dabf480c2ba6c8c616a7eb65))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
6
26
|
## [20.17.2](https://gerrit.instructure.com/quizzes-ui/compare/v20.17.1...v20.17.2) (2024-09-05)
|
|
7
27
|
|
|
8
28
|
|
|
@@ -9,7 +9,7 @@ import { archiveBankEntry } from "../../common/actions/bankEntries.js";
|
|
|
9
9
|
import { getBank } from "./banks.js";
|
|
10
10
|
import { handleError } from "../../common/api/helpers.js";
|
|
11
11
|
import get from 'lodash/get';
|
|
12
|
-
import { BANKS_BANK_ENTRY_PAGINATION, GET_BANK_ENTRIES_CALL, GET_BANK_ENTRY_CALL, UPDATE_BANK_ENTRY_CALL, CREATE_BANK_ENTRY_CALL, REMOVE_BANK_ENTRY_CALL } from '@instructure/quiz-common';
|
|
12
|
+
import { BANKS_BANK_ENTRY_PAGINATION, GET_BANK_ENTRIES_CALL, GET_BANK_ENTRY_CALL, UPDATE_BANK_ENTRY_CALL, CREATE_BANK_ENTRY_CALL, COPY_BANK_ENTRY_CALL, REMOVE_BANK_ENTRY_CALL } from '@instructure/quiz-common';
|
|
13
13
|
import t from '@instructure/quiz-i18n/es/format-message';
|
|
14
14
|
export var getBankEntries = function getBankEntries(bankId, useBankSearch) {
|
|
15
15
|
var params = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
@@ -98,6 +98,50 @@ export var createEntryAndBankEntry = function createEntryAndBankEntry(bankId, en
|
|
|
98
98
|
});
|
|
99
99
|
};
|
|
100
100
|
};
|
|
101
|
+
export var moveBankEntryFromQuizEntry = function moveBankEntryFromQuizEntry(sourceQuizId, sourceEntryId, sourceEntryType, destinationBankId) {
|
|
102
|
+
var body = {
|
|
103
|
+
source_entry_id: sourceEntryId,
|
|
104
|
+
source_entry_type: sourceEntryType
|
|
105
|
+
};
|
|
106
|
+
var query_params = {
|
|
107
|
+
source_quiz_id: sourceQuizId
|
|
108
|
+
};
|
|
109
|
+
return copyOrMoveBankEntry(body, destinationBankId, 'move_from_quiz_entry', query_params);
|
|
110
|
+
};
|
|
111
|
+
export var copyBankEntry = function copyBankEntry(sourceBankId, bankEntryId, destinationBankId) {
|
|
112
|
+
var body = {
|
|
113
|
+
source_bank_id: sourceBankId,
|
|
114
|
+
source_bank_entry_id: bankEntryId
|
|
115
|
+
};
|
|
116
|
+
return copyOrMoveBankEntry(body, destinationBankId, 'copy');
|
|
117
|
+
};
|
|
118
|
+
export var moveBankEntry = function moveBankEntry(sourceBankId, bankEntryId, destinationBankId) {
|
|
119
|
+
var body = {
|
|
120
|
+
source_bank_id: sourceBankId,
|
|
121
|
+
source_bank_entry_id: bankEntryId
|
|
122
|
+
};
|
|
123
|
+
return copyOrMoveBankEntry(body, destinationBankId, 'move');
|
|
124
|
+
};
|
|
125
|
+
export var copyOrMoveBankEntry = function copyOrMoveBankEntry(body, destinationBankId, operation, query_params) {
|
|
126
|
+
var url = "/api/banks/".concat(destinationBankId, "/bank_entries/").concat(operation);
|
|
127
|
+
return function (dispatch, getState) {
|
|
128
|
+
var fetcher = new Fetcher({
|
|
129
|
+
callType: COPY_BANK_ENTRY_CALL,
|
|
130
|
+
onError: handleError(dispatch, t('Failed to copy bank entry.'))
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (query_params) {
|
|
134
|
+
url = fetcher.appendQueryParams(url, query_params);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return fetcher.post(url, {
|
|
138
|
+
body: JSON.stringify(body)
|
|
139
|
+
}).then(function (response) {
|
|
140
|
+
dispatch([handleBankEntryResponse(response), associateEntries(destinationBankId, [response.id]), getBank(destinationBankId)]);
|
|
141
|
+
return response;
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
};
|
|
101
145
|
export var createBankEntry = function createBankEntry(bankId, entryType, entryId) {
|
|
102
146
|
var url = "/api/banks/".concat(bankId, "/bank_entries");
|
|
103
147
|
return function (dispatch, getState) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { connect } from "../../../common/react-redux.js";
|
|
2
2
|
import { createBank } from "../../api/banks.js";
|
|
3
|
-
import { createBankEntry } from "../../api/bankEntries.js";
|
|
3
|
+
import { createBankEntry, moveBankEntryFromQuizEntry } from "../../api/bankEntries.js";
|
|
4
4
|
import { checkItemShareability } from "../../../building/api/items.js";
|
|
5
5
|
import { checkStimulusShareability } from "../../../building/api/stimuli.js";
|
|
6
6
|
import AddToBankModal from "./presenter.js";
|
|
@@ -27,6 +27,7 @@ var mapDispatchToProps = {
|
|
|
27
27
|
closeModal: modalActions.closeModal,
|
|
28
28
|
createBank: createBank,
|
|
29
29
|
createBankEntry: createBankEntry,
|
|
30
|
+
moveBankEntryFromQuizEntry: moveBankEntryFromQuizEntry,
|
|
30
31
|
disassociateBankEntry: disassociateEntry,
|
|
31
32
|
uiSet: uiActions.set
|
|
32
33
|
};
|
|
@@ -21,6 +21,7 @@ import { View } from '@instructure/ui-view';
|
|
|
21
21
|
import { Flex } from '@instructure/ui-flex';
|
|
22
22
|
import t from '@instructure/quiz-i18n/es/format-message';
|
|
23
23
|
import { Modal, ModalHeader, ModalBody, ModalFooter, ADD_TO_BANK_MODAL_BANK_SELECTION, XSMALL_SIDE_MARGIN } from '@instructure/quiz-common';
|
|
24
|
+
import { featureOn } from "../../../common/util/featureCheck.js";
|
|
24
25
|
|
|
25
26
|
var _ref2 = /*#__PURE__*/React.createElement(IconCheckLine, {
|
|
26
27
|
color: "success"
|
|
@@ -60,9 +61,17 @@ export var AddToBankModal = /*#__PURE__*/function (_Component) {
|
|
|
60
61
|
newBankTitle: ''
|
|
61
62
|
};
|
|
62
63
|
|
|
64
|
+
_this.copyBankEntry = function (entryId, bankId) {
|
|
65
|
+
if (featureOn('instfs_bank_entry_movement_endpoints')) {
|
|
66
|
+
return _this.props.moveBankEntryFromQuizEntry(_this.props.quizId, entryId, _this.props.entryType, bankId);
|
|
67
|
+
} else {
|
|
68
|
+
return _this.props.createBankEntry(bankId, _this.props.entryType, entryId);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
63
72
|
_this.addToBank = function (bankId) {
|
|
64
73
|
_this.props.getEntry().then(function (entry) {
|
|
65
|
-
return _this.
|
|
74
|
+
return _this.copyBankEntry(entry.id, bankId);
|
|
66
75
|
}).then(_this.props.onAdd).catch(function (e) {
|
|
67
76
|
if (e.validationErrorsFromApi) {
|
|
68
77
|
// Close the modal so the user can view the input validation errors and correct them
|
|
@@ -301,6 +310,7 @@ AddToBankModal.propTypes = {
|
|
|
301
310
|
checkContentShareability: PropTypes.func.isRequired,
|
|
302
311
|
closeModal: PropTypes.func.isRequired,
|
|
303
312
|
createBank: PropTypes.func.isRequired,
|
|
313
|
+
moveBankEntryFromQuizEntry: PropTypes.func.isRequired,
|
|
304
314
|
createBankEntry: PropTypes.func.isRequired,
|
|
305
315
|
// Create the bank entry's entry, or clone it if it already exists. Should
|
|
306
316
|
// always be provided when a source is provided.
|
|
@@ -318,7 +328,8 @@ AddToBankModal.propTypes = {
|
|
|
318
328
|
onContinue: PropTypes.func,
|
|
319
329
|
selectedBank: ImmutablePropTypes.record,
|
|
320
330
|
uiSet: PropTypes.func.isRequired,
|
|
321
|
-
workingEntry: ImmutablePropTypes.record.isRequired
|
|
331
|
+
workingEntry: ImmutablePropTypes.record.isRequired,
|
|
332
|
+
quizId: PropTypes.string.isRequired
|
|
322
333
|
};
|
|
323
334
|
AddToBankModal.defaultProps = {
|
|
324
335
|
canvasOrigin: '',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { connect } from "../../../common/react-redux.js";
|
|
2
2
|
import { createBank } from "../../api/banks.js";
|
|
3
|
-
import { createBankEntry, updateBankEntry } from "../../api/bankEntries.js";
|
|
3
|
+
import { createBankEntry, updateBankEntry, moveBankEntry, copyBankEntry } from "../../api/bankEntries.js";
|
|
4
4
|
import CopyMoveBankModal from "./presenter.js";
|
|
5
5
|
import * as modalActions from "../../../common/actions/modal.js";
|
|
6
6
|
import { disassociateEntry } from "../../../common/actions/banks.js";
|
|
@@ -22,8 +22,10 @@ export function mapStateToProps(state, props) {
|
|
|
22
22
|
var mapDispatchToProps = {
|
|
23
23
|
closeModal: modalActions.closeModal,
|
|
24
24
|
createBank: createBank,
|
|
25
|
+
copyBankEntry: copyBankEntry,
|
|
25
26
|
createBankEntry: createBankEntry,
|
|
26
27
|
updateBankEntry: updateBankEntry,
|
|
28
|
+
moveBankEntry: moveBankEntry,
|
|
27
29
|
disassociateBankEntry: disassociateEntry,
|
|
28
30
|
uiSet: uiActions.set
|
|
29
31
|
};
|
|
@@ -15,6 +15,7 @@ import t from '@instructure/quiz-i18n/es/format-message';
|
|
|
15
15
|
import Bank from "../../../common/records/Bank.js";
|
|
16
16
|
import BankSelection from "../../../common/components/resources/BankSelection/index.js";
|
|
17
17
|
import { Modal, ModalHeader, ModalBody, ModalFooter, COPY_MOVE_BANK_ENTRY_MODAL_BANK_SELECTION, COPY_MOVE_BANK_ENTRY_MODAL_KEEP_COPY, XSMALL_SIDE_MARGIN } from '@instructure/quiz-common';
|
|
18
|
+
import { featureOn } from "../../../common/util/featureCheck.js";
|
|
18
19
|
|
|
19
20
|
var _ref = /*#__PURE__*/React.createElement("br", null);
|
|
20
21
|
|
|
@@ -65,20 +66,36 @@ export var CopyMoveBankEntryModal = /*#__PURE__*/function (_Component) {
|
|
|
65
66
|
}
|
|
66
67
|
};
|
|
67
68
|
|
|
69
|
+
_this.initiateMove = function (newBankId) {
|
|
70
|
+
if (featureOn('instfs_bank_entry_movement_endpoints')) {
|
|
71
|
+
return _this.props.moveBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId, newBankId);
|
|
72
|
+
} else {
|
|
73
|
+
return _this.props.updateBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId, {
|
|
74
|
+
bankId: newBankId
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
68
79
|
_this.moveBankEntry = function (newBankId) {
|
|
69
|
-
return _this.
|
|
70
|
-
bankId: newBankId
|
|
71
|
-
}).then(function (bankEntry) {
|
|
80
|
+
return _this.initiateMove(newBankId).then(function (bankEntry) {
|
|
72
81
|
_this.props.disassociateBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId);
|
|
73
82
|
|
|
74
83
|
return bankEntry;
|
|
75
84
|
}).then(_this.props.onAdd);
|
|
76
85
|
};
|
|
77
86
|
|
|
87
|
+
_this.initiateCopy = function (newBankId) {
|
|
88
|
+
if (featureOn('instfs_bank_entry_movement_endpoints')) {
|
|
89
|
+
return _this.props.copyBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId, newBankId);
|
|
90
|
+
} else {
|
|
91
|
+
return _this.props.createEntry().then(function (entry) {
|
|
92
|
+
return _this.props.createBankEntry(newBankId, _this.props.entryType, entry.id);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
78
97
|
_this.copyBankEntry = function (newBankId) {
|
|
79
|
-
return _this.
|
|
80
|
-
return _this.props.createBankEntry(newBankId, _this.props.entryType, entry.id);
|
|
81
|
-
}).then(_this.props.onAdd);
|
|
98
|
+
return _this.initiateCopy(newBankId).then(_this.props.onAdd);
|
|
82
99
|
};
|
|
83
100
|
|
|
84
101
|
_this.closeAction = function () {
|
|
@@ -202,6 +219,7 @@ export var CopyMoveBankEntryModal = /*#__PURE__*/function (_Component) {
|
|
|
202
219
|
CopyMoveBankEntryModal.propTypes = {
|
|
203
220
|
closeModal: PropTypes.func.isRequired,
|
|
204
221
|
createBank: PropTypes.func.isRequired,
|
|
222
|
+
copyBankEntry: PropTypes.func.isRequired,
|
|
205
223
|
createBankEntry: PropTypes.func.isRequired,
|
|
206
224
|
// Create the bank entry's entry, or clone it if it already exists. Should
|
|
207
225
|
// always be provided when a source is provided.
|
|
@@ -221,7 +239,8 @@ CopyMoveBankEntryModal.propTypes = {
|
|
|
221
239
|
sourceBankEntryId: PropTypes.string.isRequired,
|
|
222
240
|
sourceBankId: PropTypes.string.isRequired,
|
|
223
241
|
uiSet: PropTypes.func.isRequired,
|
|
224
|
-
updateBankEntry: PropTypes.func.isRequired
|
|
242
|
+
updateBankEntry: PropTypes.func.isRequired,
|
|
243
|
+
moveBankEntry: PropTypes.func.isRequired
|
|
225
244
|
};
|
|
226
245
|
CopyMoveBankEntryModal.contextTypes = {
|
|
227
246
|
locale: PropTypes.string
|
|
@@ -394,6 +394,7 @@ var QuizEntryEdit = (_dec = withStyle(generateStyle, generateComponentTheme), _d
|
|
|
394
394
|
workingEntry: this.props.workingEntry,
|
|
395
395
|
entryId: this.props.guid,
|
|
396
396
|
entryType: this.props.quizEntry.entryType,
|
|
397
|
+
quizId: this.props.quizId,
|
|
397
398
|
handleValidationErrorsFromApi: this.props.handleValidationErrorsFromApi
|
|
398
399
|
});
|
|
399
400
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v4 as uuid } from 'uuid';
|
|
2
|
-
import { BACKTRACKING_NEXT_QUESTION, CLEAR_FOCUS_CURRENT_SESSION_ITEM, LOAD_RESUME_DATA, PREVIEW_RESPONSE, PREVIOUS_QUESTION, QUIZ_SUBMISSION_EVENT, UPDATE_QUIZ_SUBMIT_FLAG, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, SET_CURRENT_SESSION_ITEM_POSITION, SET_FOCUS_TITLE_AND_INSTRUCTIONS, UPDATE_IS_TAKING, UPDATE_QUIZ_SESSION_STATUS_ON_PAGE_LOAD, UPDATE_TIMER_MINIMIZED, UPDATE_TIMER_INFO, PAGE_BLURRED_EVENT, PAGE_FOCUSED_EVENT } from '@instructure/quiz-common';
|
|
2
|
+
import { BACKTRACKING_NEXT_QUESTION, CLEAR_FOCUS_CURRENT_SESSION_ITEM, LOAD_RESUME_DATA, PREVIEW_RESPONSE, PREVIOUS_QUESTION, QUIZ_SUBMISSION_EVENT, UPDATE_QUIZ_SUBMIT_FLAG, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, SET_CURRENT_SESSION_ITEM_POSITION, SET_FOCUS_TITLE_AND_INSTRUCTIONS, UPDATE_IS_TAKING, UPDATE_QUIZ_SESSION_STATUS_ON_PAGE_LOAD, UPDATE_TIMER_MINIMIZED, UPDATE_TIMER_INFO, SET_WS_TOKEN, PAGE_BLURRED_EVENT, PAGE_FOCUSED_EVENT } from '@instructure/quiz-common';
|
|
3
3
|
export var setCurrentSessionItemPosition = function setCurrentSessionItemPosition(position) {
|
|
4
4
|
return {
|
|
5
5
|
type: SET_CURRENT_SESSION_ITEM_POSITION,
|
|
@@ -135,6 +135,14 @@ export var submitQuizSessionEvent = function submitQuizSessionEvent() {
|
|
|
135
135
|
payload: {}
|
|
136
136
|
};
|
|
137
137
|
};
|
|
138
|
+
export var setWSToken = function setWSToken(wsToken) {
|
|
139
|
+
return {
|
|
140
|
+
type: SET_WS_TOKEN,
|
|
141
|
+
payload: {
|
|
142
|
+
wsToken: wsToken
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
};
|
|
138
146
|
export var updateQuizSubmitFlag = function updateQuizSubmitFlag(value) {
|
|
139
147
|
return {
|
|
140
148
|
type: UPDATE_QUIZ_SUBMIT_FLAG,
|
|
@@ -382,6 +382,7 @@ export var StimulusEdit = (_dec = withStyle(generateStyle, generateComponentThem
|
|
|
382
382
|
onContinue: this.handleAddToBankContinue,
|
|
383
383
|
getEntry: this.getEntryForBank,
|
|
384
384
|
workingEntry: this.props.workingStimulus,
|
|
385
|
+
quizId: this.props.quizId,
|
|
385
386
|
entryId: this.props.guid,
|
|
386
387
|
entryType: this.props.quizEntry.entryType
|
|
387
388
|
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { SET_WS_TOKEN, QUIZ_SUBMISSION_EVENT } from '@instructure/quiz-common';
|
|
2
|
+
import { featureOn } from "../../common/util/featureCheck.js";
|
|
3
|
+
import { formatTime } from "../../common/util/formatTimespan.js";
|
|
4
|
+
import { updateTime, notifyTimeAdded } from "../../taking/api/taking.js";
|
|
5
|
+
import { bindActionCreators } from 'redux';
|
|
6
|
+
var takingApiActions = {
|
|
7
|
+
updateTime: updateTime,
|
|
8
|
+
notifyTimeAdded: notifyTimeAdded
|
|
9
|
+
};
|
|
10
|
+
export var createWebsocket = function createWebsocket(url, token) {
|
|
11
|
+
return new WebSocket("".concat(url, "?token=").concat(token));
|
|
12
|
+
};
|
|
13
|
+
export var handleExtraTime = function handleExtraTime(extraTimeInSeconds, endAt, updateTimeAction, notifyTimeAdded) {
|
|
14
|
+
var remainingTimeInMs = new Date(endAt) - Date.now();
|
|
15
|
+
var remainingTimeInSeconds = Math.floor(remainingTimeInMs / 1000);
|
|
16
|
+
var formattedExtraTimeText = formatTime(extraTimeInSeconds);
|
|
17
|
+
updateTimeAction(remainingTimeInSeconds);
|
|
18
|
+
notifyTimeAdded(formattedExtraTimeText);
|
|
19
|
+
};
|
|
20
|
+
export var parseJwt = function parseJwt(token) {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export var initializeWebSocket = function initializeWebSocket(token, createWebsocketFn) {
|
|
28
|
+
var jwt = parseJwt(token);
|
|
29
|
+
|
|
30
|
+
if (!jwt) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return createWebsocketFn(jwt['aud'], token);
|
|
35
|
+
};
|
|
36
|
+
export var handleWebSocketMessage = function handleWebSocketMessage(webSocketMessage, boundTakingApiActions, handleExtraTimeFn) {
|
|
37
|
+
var _webSocketMessageData, _webSocketMessageData2, _webSocketMessageData3;
|
|
38
|
+
|
|
39
|
+
var webSocketMessageData = JSON.parse(webSocketMessage.data);
|
|
40
|
+
webSocketMessageData = ((_webSocketMessageData = webSocketMessageData) === null || _webSocketMessageData === void 0 ? void 0 : (_webSocketMessageData2 = _webSocketMessageData.message) === null || _webSocketMessageData2 === void 0 ? void 0 : _webSocketMessageData2.data) || ((_webSocketMessageData3 = webSocketMessageData) === null || _webSocketMessageData3 === void 0 ? void 0 : _webSocketMessageData3.data);
|
|
41
|
+
|
|
42
|
+
if (!webSocketMessageData) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
var extra_time_in_seconds = webSocketMessageData.extra_time_in_seconds;
|
|
47
|
+
var end_at = webSocketMessageData.end_at;
|
|
48
|
+
|
|
49
|
+
if (!extra_time_in_seconds || !end_at) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
handleExtraTimeFn(extra_time_in_seconds, end_at, boundTakingApiActions.updateTime, boundTakingApiActions.notifyTimeAdded);
|
|
54
|
+
};
|
|
55
|
+
export var createQuizTimerWebSocketMiddleware = function createQuizTimerWebSocketMiddleware() {
|
|
56
|
+
var createWebsocketFn = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : createWebsocket;
|
|
57
|
+
var featureOnFn = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : featureOn;
|
|
58
|
+
var socket = null;
|
|
59
|
+
return function (store) {
|
|
60
|
+
return function (next) {
|
|
61
|
+
return function (action) {
|
|
62
|
+
var addTimeToExistingQuizSessionsEnabled = featureOnFn('add_time_to_existing_quiz_sessions');
|
|
63
|
+
|
|
64
|
+
if (!addTimeToExistingQuizSessionsEnabled) {
|
|
65
|
+
return next(action);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (action.type === SET_WS_TOKEN && socket === null) {
|
|
69
|
+
var token = action.payload.wsToken;
|
|
70
|
+
socket = initializeWebSocket(token, createWebsocketFn);
|
|
71
|
+
|
|
72
|
+
if (!socket) {
|
|
73
|
+
return next(action);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
var boundTakingApiActions = bindActionCreators(takingApiActions, store.dispatch);
|
|
77
|
+
socket.addEventListener('message', function (webSocketMessage) {
|
|
78
|
+
handleWebSocketMessage(webSocketMessage, boundTakingApiActions, handleExtraTime);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (action.type === QUIZ_SUBMISSION_EVENT && socket !== null) {
|
|
83
|
+
socket.close();
|
|
84
|
+
socket = null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return next(action);
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Map } from 'immutable';
|
|
2
|
-
import { ACTIVE_QUIZ_SESSION_CHANGE, UPDATE_TIMER_INFO, UPDATE_IS_TAKING, UPDATE_QUIZ_SESSION_STATUS_ON_PAGE_LOAD, UPDATE_TIMER_MINIMIZED, LOAD_RESUME_DATA, PREVIEW_RESPONSE, PREVIOUS_QUESTION, BACKTRACKING_NEXT_QUESTION, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, SET_CURRENT_SESSION_ITEM_POSITION, CLEAR_FOCUS_CURRENT_SESSION_ITEM, SET_FOCUS_TITLE_AND_INSTRUCTIONS, UPDATE_QUIZ_SUBMIT_FLAG } from '@instructure/quiz-common';
|
|
2
|
+
import { ACTIVE_QUIZ_SESSION_CHANGE, UPDATE_TIMER_INFO, UPDATE_IS_TAKING, UPDATE_QUIZ_SESSION_STATUS_ON_PAGE_LOAD, UPDATE_TIMER_MINIMIZED, LOAD_RESUME_DATA, PREVIEW_RESPONSE, PREVIOUS_QUESTION, BACKTRACKING_NEXT_QUESTION, RESPONSE, SESSION_STARTED_OR_RESUMED_EVENT, SET_CURRENT_SESSION_ITEM_POSITION, CLEAR_FOCUS_CURRENT_SESSION_ITEM, SET_FOCUS_TITLE_AND_INSTRUCTIONS, UPDATE_QUIZ_SUBMIT_FLAG, SET_WS_TOKEN } from '@instructure/quiz-common';
|
|
3
3
|
|
|
4
4
|
var defaultResponse = function defaultResponse(payload) {
|
|
5
5
|
return Map({
|
|
@@ -53,6 +53,10 @@ var updateTimerInfo = function updateTimerInfo(state, payload) {
|
|
|
53
53
|
return state.mergeIn(['timerData'], payload);
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
+
var setWSToken = function setWSToken(state, payload) {
|
|
57
|
+
return state.set('wsToken', payload === null || payload === void 0 ? void 0 : payload.wsToken);
|
|
58
|
+
};
|
|
59
|
+
|
|
56
60
|
var updateTimerMinimized = function updateTimerMinimized(state, payload) {
|
|
57
61
|
return state.setIn(['timerData', 'timerMinimized'], payload.timerMinimized);
|
|
58
62
|
};
|
|
@@ -126,6 +130,9 @@ export default (function () {
|
|
|
126
130
|
case UPDATE_TIMER_INFO:
|
|
127
131
|
return updateTimerInfo(state, action.payload);
|
|
128
132
|
|
|
133
|
+
case SET_WS_TOKEN:
|
|
134
|
+
return setWSToken(state, action.payload);
|
|
135
|
+
|
|
129
136
|
case SET_CURRENT_SESSION_ITEM_POSITION:
|
|
130
137
|
return setCurrentSessionItemPosition(state, action.payload);
|
|
131
138
|
|
|
@@ -5,7 +5,7 @@ import reduxStore from "../../reduxStore.js";
|
|
|
5
5
|
export var MAX_SETTIMEOUT_IN_MILLISECONDS = 20 * 24 * 3600 * 1000; // ms of 20 days
|
|
6
6
|
|
|
7
7
|
export var TimerService = /*#__PURE__*/function () {
|
|
8
|
-
function TimerService(getTimeRemaining, updateTimeRemaining, getTimerData, submitQuiz, alert) {
|
|
8
|
+
function TimerService(getTimeRemaining, updateTimeRemaining, getTimerData, submitQuiz, alert, setWsToken) {
|
|
9
9
|
var _this = this;
|
|
10
10
|
|
|
11
11
|
_classCallCheck(this, TimerService);
|
|
@@ -23,6 +23,10 @@ export var TimerService = /*#__PURE__*/function () {
|
|
|
23
23
|
_this.__onTimerChange(data);
|
|
24
24
|
|
|
25
25
|
_this.__setApiCallIntervalTime(data.timeLeftInSeconds);
|
|
26
|
+
|
|
27
|
+
if (_this._setWsToken) {
|
|
28
|
+
_this._setWsToken(data.wsToken);
|
|
29
|
+
}
|
|
26
30
|
});
|
|
27
31
|
};
|
|
28
32
|
|
|
@@ -31,6 +35,7 @@ export var TimerService = /*#__PURE__*/function () {
|
|
|
31
35
|
this._getTimerData = getTimerData;
|
|
32
36
|
this._submitQuiz = submitQuiz;
|
|
33
37
|
this._alert = alert;
|
|
38
|
+
this._setWsToken = setWsToken;
|
|
34
39
|
this._stopped = false;
|
|
35
40
|
this._apiInterval = null;
|
|
36
41
|
this._clockInterval = null;
|
package/es/configureStore.js
CHANGED
|
@@ -9,7 +9,8 @@ import multi from 'redux-multi';
|
|
|
9
9
|
import thunkMiddleware from 'redux-thunk';
|
|
10
10
|
import alertTimerMiddleware from "./common/middleware/alertTimerMiddleware.js";
|
|
11
11
|
import crossDomainMessagingMiddleware from "./common/middleware/crossDomainMessagingMiddleware.js";
|
|
12
|
-
import eventLoggerMiddlewareCreator from "./common/middleware/eventLoggerMiddleware.js";
|
|
12
|
+
import eventLoggerMiddlewareCreator from "./common/middleware/eventLoggerMiddleware.js";
|
|
13
|
+
import { createQuizTimerWebSocketMiddleware } from "./common/middleware/quizTimerWebSocketMiddleware.js"; // reducers
|
|
13
14
|
|
|
14
15
|
import alerts from "./common/reducers/alerts.js";
|
|
15
16
|
import banks from "./common/reducers/banks.js";
|
|
@@ -69,7 +70,8 @@ export function configureStore(_ref) {
|
|
|
69
70
|
}
|
|
70
71
|
});
|
|
71
72
|
var kinesisMiddleware = eventLoggerMiddlewareCreator();
|
|
72
|
-
var
|
|
73
|
+
var websocketMiddleware = createQuizTimerWebSocketMiddleware();
|
|
74
|
+
var baseMiddleware = [alertTimerMiddleware, crossDomainMessagingMiddleware, multi, kinesisMiddleware, thunkMiddleware, websocketMiddleware];
|
|
73
75
|
var devMiddleware = [loggerMiddleware];
|
|
74
76
|
var middlewareToApply = inDevelopment ? union(baseMiddleware, devMiddleware) : baseMiddleware;
|
|
75
77
|
middlewareToApply = union(middlewareToApply, extraMiddleware);
|
package/es/index.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
/* eslint "import/newline-after-import": "warn" */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* In g/356542 we tried importing takingApiActions from here, and it caused a weird karma issue.
|
|
6
|
+
* Nothing from this file should be imported from within quiz-core!
|
|
7
|
+
* These exports are for other packages to use.
|
|
8
|
+
* We should look into configuring an import/no-restricted-paths eslint rule to prevent this.
|
|
9
|
+
*/
|
|
2
10
|
// Components
|
|
3
11
|
export { DragDroppableSDKApp as SDKApp } from "./common/components/SDKApp/index.js";
|
|
4
12
|
export { ModerateTable } from "./moderating/components/resources/ModerateTable/index.js";
|
package/es/taking/api/taking.js
CHANGED
|
@@ -11,7 +11,7 @@ import { Map } from 'immutable';
|
|
|
11
11
|
import { camelizeKeys } from 'humps';
|
|
12
12
|
import t from '@instructure/quiz-i18n/es/format-message';
|
|
13
13
|
import noop from "../../common/util/noop.js";
|
|
14
|
-
import { screenreaderNotification } from "../../common/actions/alerts.js";
|
|
14
|
+
import { addInfo, screenreaderNotification } from "../../common/actions/alerts.js";
|
|
15
15
|
import Item from "../../common/records/Item.js";
|
|
16
16
|
import { featureOn } from "../../common/util/featureCheck.js";
|
|
17
17
|
import { fetchLogger } from "../../common/kinesis/QuizEventsLogger.js";
|
|
@@ -21,7 +21,7 @@ import { fetchQuizSession, fetchResumeData, fetchTime, recordTime, singleRespons
|
|
|
21
21
|
import { getSessionItems, handleQuizSessionFetch } from "../../common/actions/quizSessions.js";
|
|
22
22
|
import { handleSessionItemsResponse, handleResumeDataResponse, handleQuizSessionResponse } from "../../common/api/callHandlers.js";
|
|
23
23
|
import * as modalActions from "../../common/actions/modal.js";
|
|
24
|
-
import { backtrackingNextQuestion, sessionStartOrResumeEvent, setCurrentSessionItemPosition, submitQuizSessionEvent, updateQuizSubmitFlag, updateQuizSessionStatusOnPageLoad } from "../../common/actions/taking.js";
|
|
24
|
+
import { backtrackingNextQuestion, sessionStartOrResumeEvent, setCurrentSessionItemPosition, submitQuizSessionEvent, updateQuizSubmitFlag, updateQuizSessionStatusOnPageLoad, updateTimerInfo } from "../../common/actions/taking.js";
|
|
25
25
|
|
|
26
26
|
var getQuizSessionConfig = function getQuizSessionConfig(quizSession) {
|
|
27
27
|
// these should be handled by existing functions
|
|
@@ -244,6 +244,22 @@ export function submitQuiz(quizSessionId) {
|
|
|
244
244
|
}
|
|
245
245
|
};
|
|
246
246
|
}
|
|
247
|
+
export function notifyTimeAdded(extraTime) {
|
|
248
|
+
return function (dispatch) {
|
|
249
|
+
return dispatch(addInfo(t('Your original time limit has been extended by { extraTime }', {
|
|
250
|
+
extraTime: extraTime
|
|
251
|
+
})));
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
export function updateTime(timeInSeconds) {
|
|
255
|
+
return function (dispatch) {
|
|
256
|
+
return dispatch(updateTimerInfo({
|
|
257
|
+
timeLeftInSeconds: timeInSeconds,
|
|
258
|
+
timerRunning: true,
|
|
259
|
+
timeRecording: true
|
|
260
|
+
}));
|
|
261
|
+
};
|
|
262
|
+
}
|
|
247
263
|
|
|
248
264
|
function getQuestionsNeedingAResponse(state, quizSessionId) {
|
|
249
265
|
var responses = state.getIn(['taking', 'responses'], Map());
|
|
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.removeBankEntry = exports.updateBankEntry = exports.createBankEntry = exports.createEntryAndBankEntry = exports.cloneBankEntry = exports.getBankEntry = exports.getBankEntries = void 0;
|
|
8
|
+
exports.removeBankEntry = exports.updateBankEntry = exports.createBankEntry = exports.copyOrMoveBankEntry = exports.moveBankEntry = exports.copyBankEntry = exports.moveBankEntryFromQuizEntry = exports.createEntryAndBankEntry = exports.cloneBankEntry = exports.getBankEntry = exports.getBankEntries = void 0;
|
|
9
9
|
|
|
10
10
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
11
11
|
|
|
@@ -132,6 +132,62 @@ var createEntryAndBankEntry = function createEntryAndBankEntry(bankId, entry, ba
|
|
|
132
132
|
|
|
133
133
|
exports.createEntryAndBankEntry = createEntryAndBankEntry;
|
|
134
134
|
|
|
135
|
+
var moveBankEntryFromQuizEntry = function moveBankEntryFromQuizEntry(sourceQuizId, sourceEntryId, sourceEntryType, destinationBankId) {
|
|
136
|
+
var body = {
|
|
137
|
+
source_entry_id: sourceEntryId,
|
|
138
|
+
source_entry_type: sourceEntryType
|
|
139
|
+
};
|
|
140
|
+
var query_params = {
|
|
141
|
+
source_quiz_id: sourceQuizId
|
|
142
|
+
};
|
|
143
|
+
return copyOrMoveBankEntry(body, destinationBankId, 'move_from_quiz_entry', query_params);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
exports.moveBankEntryFromQuizEntry = moveBankEntryFromQuizEntry;
|
|
147
|
+
|
|
148
|
+
var copyBankEntry = function copyBankEntry(sourceBankId, bankEntryId, destinationBankId) {
|
|
149
|
+
var body = {
|
|
150
|
+
source_bank_id: sourceBankId,
|
|
151
|
+
source_bank_entry_id: bankEntryId
|
|
152
|
+
};
|
|
153
|
+
return copyOrMoveBankEntry(body, destinationBankId, 'copy');
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
exports.copyBankEntry = copyBankEntry;
|
|
157
|
+
|
|
158
|
+
var moveBankEntry = function moveBankEntry(sourceBankId, bankEntryId, destinationBankId) {
|
|
159
|
+
var body = {
|
|
160
|
+
source_bank_id: sourceBankId,
|
|
161
|
+
source_bank_entry_id: bankEntryId
|
|
162
|
+
};
|
|
163
|
+
return copyOrMoveBankEntry(body, destinationBankId, 'move');
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
exports.moveBankEntry = moveBankEntry;
|
|
167
|
+
|
|
168
|
+
var copyOrMoveBankEntry = function copyOrMoveBankEntry(body, destinationBankId, operation, query_params) {
|
|
169
|
+
var url = "/api/banks/".concat(destinationBankId, "/bank_entries/").concat(operation);
|
|
170
|
+
return function (dispatch, getState) {
|
|
171
|
+
var fetcher = new _Fetcher.default({
|
|
172
|
+
callType: _quizCommon.COPY_BANK_ENTRY_CALL,
|
|
173
|
+
onError: (0, _helpers.handleError)(dispatch, (0, _formatMessage.default)('Failed to copy bank entry.'))
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (query_params) {
|
|
177
|
+
url = fetcher.appendQueryParams(url, query_params);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return fetcher.post(url, {
|
|
181
|
+
body: JSON.stringify(body)
|
|
182
|
+
}).then(function (response) {
|
|
183
|
+
dispatch([(0, _callHandlers.handleBankEntryResponse)(response), (0, _banks.associateEntries)(destinationBankId, [response.id]), (0, _banks2.getBank)(destinationBankId)]);
|
|
184
|
+
return response;
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
exports.copyOrMoveBankEntry = copyOrMoveBankEntry;
|
|
190
|
+
|
|
135
191
|
var createBankEntry = function createBankEntry(bankId, entryType, entryId) {
|
|
136
192
|
var url = "/api/banks/".concat(bankId, "/bank_entries");
|
|
137
193
|
return function (dispatch, getState) {
|
|
@@ -53,6 +53,7 @@ var mapDispatchToProps = {
|
|
|
53
53
|
closeModal: modalActions.closeModal,
|
|
54
54
|
createBank: _banks.createBank,
|
|
55
55
|
createBankEntry: _bankEntries.createBankEntry,
|
|
56
|
+
moveBankEntryFromQuizEntry: _bankEntries.moveBankEntryFromQuizEntry,
|
|
56
57
|
disassociateBankEntry: _banks2.disassociateEntry,
|
|
57
58
|
uiSet: uiActions.set
|
|
58
59
|
};
|
|
@@ -55,6 +55,8 @@ var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/f
|
|
|
55
55
|
|
|
56
56
|
var _quizCommon = require("@instructure/quiz-common");
|
|
57
57
|
|
|
58
|
+
var _featureCheck = require("../../../common/util/featureCheck.js");
|
|
59
|
+
|
|
58
60
|
var _ref2 = /*#__PURE__*/_react.default.createElement(_uiIcons.IconCheckLine, {
|
|
59
61
|
color: "success"
|
|
60
62
|
});
|
|
@@ -93,9 +95,17 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
|
|
|
93
95
|
newBankTitle: ''
|
|
94
96
|
};
|
|
95
97
|
|
|
98
|
+
_this.copyBankEntry = function (entryId, bankId) {
|
|
99
|
+
if ((0, _featureCheck.featureOn)('instfs_bank_entry_movement_endpoints')) {
|
|
100
|
+
return _this.props.moveBankEntryFromQuizEntry(_this.props.quizId, entryId, _this.props.entryType, bankId);
|
|
101
|
+
} else {
|
|
102
|
+
return _this.props.createBankEntry(bankId, _this.props.entryType, entryId);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
96
106
|
_this.addToBank = function (bankId) {
|
|
97
107
|
_this.props.getEntry().then(function (entry) {
|
|
98
|
-
return _this.
|
|
108
|
+
return _this.copyBankEntry(entry.id, bankId);
|
|
99
109
|
}).then(_this.props.onAdd).catch(function (e) {
|
|
100
110
|
if (e.validationErrorsFromApi) {
|
|
101
111
|
// Close the modal so the user can view the input validation errors and correct them
|
|
@@ -335,6 +345,7 @@ AddToBankModal.propTypes = {
|
|
|
335
345
|
checkContentShareability: _propTypes.default.func.isRequired,
|
|
336
346
|
closeModal: _propTypes.default.func.isRequired,
|
|
337
347
|
createBank: _propTypes.default.func.isRequired,
|
|
348
|
+
moveBankEntryFromQuizEntry: _propTypes.default.func.isRequired,
|
|
338
349
|
createBankEntry: _propTypes.default.func.isRequired,
|
|
339
350
|
// Create the bank entry's entry, or clone it if it already exists. Should
|
|
340
351
|
// always be provided when a source is provided.
|
|
@@ -352,7 +363,8 @@ AddToBankModal.propTypes = {
|
|
|
352
363
|
onContinue: _propTypes.default.func,
|
|
353
364
|
selectedBank: _reactImmutableProptypes.default.record,
|
|
354
365
|
uiSet: _propTypes.default.func.isRequired,
|
|
355
|
-
workingEntry: _reactImmutableProptypes.default.record.isRequired
|
|
366
|
+
workingEntry: _reactImmutableProptypes.default.record.isRequired,
|
|
367
|
+
quizId: _propTypes.default.string.isRequired
|
|
356
368
|
};
|
|
357
369
|
AddToBankModal.defaultProps = {
|
|
358
370
|
canvasOrigin: '',
|
|
@@ -45,8 +45,10 @@ function mapStateToProps(state, props) {
|
|
|
45
45
|
var mapDispatchToProps = {
|
|
46
46
|
closeModal: modalActions.closeModal,
|
|
47
47
|
createBank: _banks.createBank,
|
|
48
|
+
copyBankEntry: _bankEntries.copyBankEntry,
|
|
48
49
|
createBankEntry: _bankEntries.createBankEntry,
|
|
49
50
|
updateBankEntry: _bankEntries.updateBankEntry,
|
|
51
|
+
moveBankEntry: _bankEntries.moveBankEntry,
|
|
50
52
|
disassociateBankEntry: _banks2.disassociateEntry,
|
|
51
53
|
uiSet: uiActions.set
|
|
52
54
|
};
|
|
@@ -43,6 +43,8 @@ var _index = _interopRequireDefault(require("../../../common/components/resource
|
|
|
43
43
|
|
|
44
44
|
var _quizCommon = require("@instructure/quiz-common");
|
|
45
45
|
|
|
46
|
+
var _featureCheck = require("../../../common/util/featureCheck.js");
|
|
47
|
+
|
|
46
48
|
var _ref = /*#__PURE__*/_react.default.createElement("br", null);
|
|
47
49
|
|
|
48
50
|
var _ref2 = /*#__PURE__*/_react.default.createElement("br", null);
|
|
@@ -92,20 +94,36 @@ var CopyMoveBankEntryModal = /*#__PURE__*/function (_Component) {
|
|
|
92
94
|
}
|
|
93
95
|
};
|
|
94
96
|
|
|
97
|
+
_this.initiateMove = function (newBankId) {
|
|
98
|
+
if ((0, _featureCheck.featureOn)('instfs_bank_entry_movement_endpoints')) {
|
|
99
|
+
return _this.props.moveBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId, newBankId);
|
|
100
|
+
} else {
|
|
101
|
+
return _this.props.updateBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId, {
|
|
102
|
+
bankId: newBankId
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
95
107
|
_this.moveBankEntry = function (newBankId) {
|
|
96
|
-
return _this.
|
|
97
|
-
bankId: newBankId
|
|
98
|
-
}).then(function (bankEntry) {
|
|
108
|
+
return _this.initiateMove(newBankId).then(function (bankEntry) {
|
|
99
109
|
_this.props.disassociateBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId);
|
|
100
110
|
|
|
101
111
|
return bankEntry;
|
|
102
112
|
}).then(_this.props.onAdd);
|
|
103
113
|
};
|
|
104
114
|
|
|
115
|
+
_this.initiateCopy = function (newBankId) {
|
|
116
|
+
if ((0, _featureCheck.featureOn)('instfs_bank_entry_movement_endpoints')) {
|
|
117
|
+
return _this.props.copyBankEntry(_this.props.sourceBankId, _this.props.sourceBankEntryId, newBankId);
|
|
118
|
+
} else {
|
|
119
|
+
return _this.props.createEntry().then(function (entry) {
|
|
120
|
+
return _this.props.createBankEntry(newBankId, _this.props.entryType, entry.id);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
105
125
|
_this.copyBankEntry = function (newBankId) {
|
|
106
|
-
return _this.
|
|
107
|
-
return _this.props.createBankEntry(newBankId, _this.props.entryType, entry.id);
|
|
108
|
-
}).then(_this.props.onAdd);
|
|
126
|
+
return _this.initiateCopy(newBankId).then(_this.props.onAdd);
|
|
109
127
|
};
|
|
110
128
|
|
|
111
129
|
_this.closeAction = function () {
|
|
@@ -230,6 +248,7 @@ exports.CopyMoveBankEntryModal = CopyMoveBankEntryModal;
|
|
|
230
248
|
CopyMoveBankEntryModal.propTypes = {
|
|
231
249
|
closeModal: _propTypes.default.func.isRequired,
|
|
232
250
|
createBank: _propTypes.default.func.isRequired,
|
|
251
|
+
copyBankEntry: _propTypes.default.func.isRequired,
|
|
233
252
|
createBankEntry: _propTypes.default.func.isRequired,
|
|
234
253
|
// Create the bank entry's entry, or clone it if it already exists. Should
|
|
235
254
|
// always be provided when a source is provided.
|
|
@@ -249,7 +268,8 @@ CopyMoveBankEntryModal.propTypes = {
|
|
|
249
268
|
sourceBankEntryId: _propTypes.default.string.isRequired,
|
|
250
269
|
sourceBankId: _propTypes.default.string.isRequired,
|
|
251
270
|
uiSet: _propTypes.default.func.isRequired,
|
|
252
|
-
updateBankEntry: _propTypes.default.func.isRequired
|
|
271
|
+
updateBankEntry: _propTypes.default.func.isRequired,
|
|
272
|
+
moveBankEntry: _propTypes.default.func.isRequired
|
|
253
273
|
};
|
|
254
274
|
CopyMoveBankEntryModal.contextTypes = {
|
|
255
275
|
locale: _propTypes.default.string
|
|
@@ -426,6 +426,7 @@ var QuizEntryEdit = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defa
|
|
|
426
426
|
workingEntry: this.props.workingEntry,
|
|
427
427
|
entryId: this.props.guid,
|
|
428
428
|
entryType: this.props.quizEntry.entryType,
|
|
429
|
+
quizId: this.props.quizId,
|
|
429
430
|
handleValidationErrorsFromApi: this.props.handleValidationErrorsFromApi
|
|
430
431
|
});
|
|
431
432
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.updateQuizSubmitFlag = exports.submitQuizSessionEvent = exports.reportPageFocusedEvent = exports.reportPageBlurredEvent = exports.sessionStartOrResumeEvent = exports.loadResumeData = exports.editResponse = exports.previewResponse = exports.updateTimerInfo = exports.updateQuizSessionStatusOnPageLoad = exports.updateIsTaking = exports.updateTimerMinimized = exports.backtrackingNextQuestion = exports.previousQuestion = exports.setFocusTitleAndInstructions = exports.clearFocusCurrentSessionItem = exports.setCurrentSessionItemPosition = void 0;
|
|
6
|
+
exports.updateQuizSubmitFlag = exports.setWSToken = exports.submitQuizSessionEvent = exports.reportPageFocusedEvent = exports.reportPageBlurredEvent = exports.sessionStartOrResumeEvent = exports.loadResumeData = exports.editResponse = exports.previewResponse = exports.updateTimerInfo = exports.updateQuizSessionStatusOnPageLoad = exports.updateIsTaking = exports.updateTimerMinimized = exports.backtrackingNextQuestion = exports.previousQuestion = exports.setFocusTitleAndInstructions = exports.clearFocusCurrentSessionItem = exports.setCurrentSessionItemPosition = void 0;
|
|
7
7
|
|
|
8
8
|
var _uuid = require("uuid");
|
|
9
9
|
|
|
@@ -192,6 +192,17 @@ var submitQuizSessionEvent = function submitQuizSessionEvent() {
|
|
|
192
192
|
|
|
193
193
|
exports.submitQuizSessionEvent = submitQuizSessionEvent;
|
|
194
194
|
|
|
195
|
+
var setWSToken = function setWSToken(wsToken) {
|
|
196
|
+
return {
|
|
197
|
+
type: _quizCommon.SET_WS_TOKEN,
|
|
198
|
+
payload: {
|
|
199
|
+
wsToken: wsToken
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
exports.setWSToken = setWSToken;
|
|
205
|
+
|
|
195
206
|
var updateQuizSubmitFlag = function updateQuizSubmitFlag(value) {
|
|
196
207
|
return {
|
|
197
208
|
type: _quizCommon.UPDATE_QUIZ_SUBMIT_FLAG,
|
|
@@ -419,6 +419,7 @@ var StimulusEdit = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
419
419
|
onContinue: this.handleAddToBankContinue,
|
|
420
420
|
getEntry: this.getEntryForBank,
|
|
421
421
|
workingEntry: this.props.workingStimulus,
|
|
422
|
+
quizId: this.props.quizId,
|
|
422
423
|
entryId: this.props.guid,
|
|
423
424
|
entryType: this.props.quizEntry.entryType
|
|
424
425
|
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createQuizTimerWebSocketMiddleware = exports.handleWebSocketMessage = exports.initializeWebSocket = exports.parseJwt = exports.handleExtraTime = exports.createWebsocket = void 0;
|
|
7
|
+
|
|
8
|
+
var _quizCommon = require("@instructure/quiz-common");
|
|
9
|
+
|
|
10
|
+
var _featureCheck = require("../../common/util/featureCheck.js");
|
|
11
|
+
|
|
12
|
+
var _formatTimespan = require("../../common/util/formatTimespan.js");
|
|
13
|
+
|
|
14
|
+
var _taking = require("../../taking/api/taking.js");
|
|
15
|
+
|
|
16
|
+
var _redux = require("redux");
|
|
17
|
+
|
|
18
|
+
var takingApiActions = {
|
|
19
|
+
updateTime: _taking.updateTime,
|
|
20
|
+
notifyTimeAdded: _taking.notifyTimeAdded
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
var createWebsocket = function createWebsocket(url, token) {
|
|
24
|
+
return new WebSocket("".concat(url, "?token=").concat(token));
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
exports.createWebsocket = createWebsocket;
|
|
28
|
+
|
|
29
|
+
var handleExtraTime = function handleExtraTime(extraTimeInSeconds, endAt, updateTimeAction, notifyTimeAdded) {
|
|
30
|
+
var remainingTimeInMs = new Date(endAt) - Date.now();
|
|
31
|
+
var remainingTimeInSeconds = Math.floor(remainingTimeInMs / 1000);
|
|
32
|
+
var formattedExtraTimeText = (0, _formatTimespan.formatTime)(extraTimeInSeconds);
|
|
33
|
+
updateTimeAction(remainingTimeInSeconds);
|
|
34
|
+
notifyTimeAdded(formattedExtraTimeText);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
exports.handleExtraTime = handleExtraTime;
|
|
38
|
+
|
|
39
|
+
var parseJwt = function parseJwt(token) {
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
|
|
42
|
+
} catch (e) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
exports.parseJwt = parseJwt;
|
|
48
|
+
|
|
49
|
+
var initializeWebSocket = function initializeWebSocket(token, createWebsocketFn) {
|
|
50
|
+
var jwt = parseJwt(token);
|
|
51
|
+
|
|
52
|
+
if (!jwt) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return createWebsocketFn(jwt['aud'], token);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
exports.initializeWebSocket = initializeWebSocket;
|
|
60
|
+
|
|
61
|
+
var handleWebSocketMessage = function handleWebSocketMessage(webSocketMessage, boundTakingApiActions, handleExtraTimeFn) {
|
|
62
|
+
var _webSocketMessageData, _webSocketMessageData2, _webSocketMessageData3;
|
|
63
|
+
|
|
64
|
+
var webSocketMessageData = JSON.parse(webSocketMessage.data);
|
|
65
|
+
webSocketMessageData = ((_webSocketMessageData = webSocketMessageData) === null || _webSocketMessageData === void 0 ? void 0 : (_webSocketMessageData2 = _webSocketMessageData.message) === null || _webSocketMessageData2 === void 0 ? void 0 : _webSocketMessageData2.data) || ((_webSocketMessageData3 = webSocketMessageData) === null || _webSocketMessageData3 === void 0 ? void 0 : _webSocketMessageData3.data);
|
|
66
|
+
|
|
67
|
+
if (!webSocketMessageData) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var extra_time_in_seconds = webSocketMessageData.extra_time_in_seconds;
|
|
72
|
+
var end_at = webSocketMessageData.end_at;
|
|
73
|
+
|
|
74
|
+
if (!extra_time_in_seconds || !end_at) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
handleExtraTimeFn(extra_time_in_seconds, end_at, boundTakingApiActions.updateTime, boundTakingApiActions.notifyTimeAdded);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
exports.handleWebSocketMessage = handleWebSocketMessage;
|
|
82
|
+
|
|
83
|
+
var createQuizTimerWebSocketMiddleware = function createQuizTimerWebSocketMiddleware() {
|
|
84
|
+
var createWebsocketFn = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : createWebsocket;
|
|
85
|
+
var featureOnFn = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : _featureCheck.featureOn;
|
|
86
|
+
var socket = null;
|
|
87
|
+
return function (store) {
|
|
88
|
+
return function (next) {
|
|
89
|
+
return function (action) {
|
|
90
|
+
var addTimeToExistingQuizSessionsEnabled = featureOnFn('add_time_to_existing_quiz_sessions');
|
|
91
|
+
|
|
92
|
+
if (!addTimeToExistingQuizSessionsEnabled) {
|
|
93
|
+
return next(action);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (action.type === _quizCommon.SET_WS_TOKEN && socket === null) {
|
|
97
|
+
var token = action.payload.wsToken;
|
|
98
|
+
socket = initializeWebSocket(token, createWebsocketFn);
|
|
99
|
+
|
|
100
|
+
if (!socket) {
|
|
101
|
+
return next(action);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
var boundTakingApiActions = (0, _redux.bindActionCreators)(takingApiActions, store.dispatch);
|
|
105
|
+
socket.addEventListener('message', function (webSocketMessage) {
|
|
106
|
+
handleWebSocketMessage(webSocketMessage, boundTakingApiActions, handleExtraTime);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (action.type === _quizCommon.QUIZ_SUBMISSION_EVENT && socket !== null) {
|
|
111
|
+
socket.close();
|
|
112
|
+
socket = null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return next(action);
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
exports.createQuizTimerWebSocketMiddleware = createQuizTimerWebSocketMiddleware;
|
|
@@ -61,6 +61,10 @@ var updateTimerInfo = function updateTimerInfo(state, payload) {
|
|
|
61
61
|
return state.mergeIn(['timerData'], payload);
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
+
var setWSToken = function setWSToken(state, payload) {
|
|
65
|
+
return state.set('wsToken', payload === null || payload === void 0 ? void 0 : payload.wsToken);
|
|
66
|
+
};
|
|
67
|
+
|
|
64
68
|
var updateTimerMinimized = function updateTimerMinimized(state, payload) {
|
|
65
69
|
return state.setIn(['timerData', 'timerMinimized'], payload.timerMinimized);
|
|
66
70
|
};
|
|
@@ -134,6 +138,9 @@ var _default = function _default() {
|
|
|
134
138
|
case _quizCommon.UPDATE_TIMER_INFO:
|
|
135
139
|
return updateTimerInfo(state, action.payload);
|
|
136
140
|
|
|
141
|
+
case _quizCommon.SET_WS_TOKEN:
|
|
142
|
+
return setWSToken(state, action.payload);
|
|
143
|
+
|
|
137
144
|
case _quizCommon.SET_CURRENT_SESSION_ITEM_POSITION:
|
|
138
145
|
return setCurrentSessionItemPosition(state, action.payload);
|
|
139
146
|
|
|
@@ -20,7 +20,7 @@ var MAX_SETTIMEOUT_IN_MILLISECONDS = 20 * 24 * 3600 * 1000; // ms of 20 days
|
|
|
20
20
|
exports.MAX_SETTIMEOUT_IN_MILLISECONDS = MAX_SETTIMEOUT_IN_MILLISECONDS;
|
|
21
21
|
|
|
22
22
|
var TimerService = /*#__PURE__*/function () {
|
|
23
|
-
function TimerService(getTimeRemaining, updateTimeRemaining, getTimerData, submitQuiz, alert) {
|
|
23
|
+
function TimerService(getTimeRemaining, updateTimeRemaining, getTimerData, submitQuiz, alert, setWsToken) {
|
|
24
24
|
var _this = this;
|
|
25
25
|
|
|
26
26
|
(0, _classCallCheck2.default)(this, TimerService);
|
|
@@ -38,6 +38,10 @@ var TimerService = /*#__PURE__*/function () {
|
|
|
38
38
|
_this.__onTimerChange(data);
|
|
39
39
|
|
|
40
40
|
_this.__setApiCallIntervalTime(data.timeLeftInSeconds);
|
|
41
|
+
|
|
42
|
+
if (_this._setWsToken) {
|
|
43
|
+
_this._setWsToken(data.wsToken);
|
|
44
|
+
}
|
|
41
45
|
});
|
|
42
46
|
};
|
|
43
47
|
|
|
@@ -46,6 +50,7 @@ var TimerService = /*#__PURE__*/function () {
|
|
|
46
50
|
this._getTimerData = getTimerData;
|
|
47
51
|
this._submitQuiz = submitQuiz;
|
|
48
52
|
this._alert = alert;
|
|
53
|
+
this._setWsToken = setWsToken;
|
|
49
54
|
this._stopped = false;
|
|
50
55
|
this._apiInterval = null;
|
|
51
56
|
this._clockInterval = null;
|
package/lib/configureStore.js
CHANGED
|
@@ -30,6 +30,8 @@ var _crossDomainMessagingMiddleware = _interopRequireDefault(require("./common/m
|
|
|
30
30
|
|
|
31
31
|
var _eventLoggerMiddleware = _interopRequireDefault(require("./common/middleware/eventLoggerMiddleware.js"));
|
|
32
32
|
|
|
33
|
+
var _quizTimerWebSocketMiddleware = require("./common/middleware/quizTimerWebSocketMiddleware.js");
|
|
34
|
+
|
|
33
35
|
var _alerts = _interopRequireDefault(require("./common/reducers/alerts.js"));
|
|
34
36
|
|
|
35
37
|
var _banks = _interopRequireDefault(require("./common/reducers/banks.js"));
|
|
@@ -129,7 +131,8 @@ function configureStore(_ref) {
|
|
|
129
131
|
}
|
|
130
132
|
});
|
|
131
133
|
var kinesisMiddleware = (0, _eventLoggerMiddleware.default)();
|
|
132
|
-
var
|
|
134
|
+
var websocketMiddleware = (0, _quizTimerWebSocketMiddleware.createQuizTimerWebSocketMiddleware)();
|
|
135
|
+
var baseMiddleware = [_alertTimerMiddleware.default, _crossDomainMessagingMiddleware.default, _reduxMulti.default, kinesisMiddleware, _reduxThunk.default, websocketMiddleware];
|
|
133
136
|
var devMiddleware = [loggerMiddleware];
|
|
134
137
|
var middlewareToApply = inDevelopment ? (0, _union.default)(baseMiddleware, devMiddleware) : baseMiddleware;
|
|
135
138
|
middlewareToApply = (0, _union.default)(middlewareToApply, extraMiddleware);
|
package/lib/taking/api/taking.js
CHANGED
|
@@ -13,6 +13,8 @@ exports.onQuizSessionReadyForTaking = onQuizSessionReadyForTaking;
|
|
|
13
13
|
exports.showSubmitConfirmModal = showSubmitConfirmModal;
|
|
14
14
|
exports.closeSubmitConfirmModal = closeSubmitConfirmModal;
|
|
15
15
|
exports.submitQuiz = submitQuiz;
|
|
16
|
+
exports.notifyTimeAdded = notifyTimeAdded;
|
|
17
|
+
exports.updateTime = updateTime;
|
|
16
18
|
exports.postQuizSession = postQuizSession;
|
|
17
19
|
exports.getTimeRemaining = getTimeRemaining;
|
|
18
20
|
exports.recordQuizTime = recordQuizTime;
|
|
@@ -299,6 +301,24 @@ function submitQuiz(quizSessionId) {
|
|
|
299
301
|
};
|
|
300
302
|
}
|
|
301
303
|
|
|
304
|
+
function notifyTimeAdded(extraTime) {
|
|
305
|
+
return function (dispatch) {
|
|
306
|
+
return dispatch((0, _alerts.addInfo)((0, _formatMessage.default)('Your original time limit has been extended by { extraTime }', {
|
|
307
|
+
extraTime: extraTime
|
|
308
|
+
})));
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function updateTime(timeInSeconds) {
|
|
313
|
+
return function (dispatch) {
|
|
314
|
+
return dispatch((0, _taking.updateTimerInfo)({
|
|
315
|
+
timeLeftInSeconds: timeInSeconds,
|
|
316
|
+
timerRunning: true,
|
|
317
|
+
timeRecording: true
|
|
318
|
+
}));
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
302
322
|
function getQuestionsNeedingAResponse(state, quizSessionId) {
|
|
303
323
|
var responses = state.getIn(['taking', 'responses'], (0, _immutable.Map)());
|
|
304
324
|
var sessionItems = state.get('sessionItems', (0, _immutable.Map)()).filter(function (record) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/quiz-core",
|
|
3
|
-
"version": "20.
|
|
3
|
+
"version": "20.18.1-rc.0+392e66e66",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The Quiz React SDK by Instructure Inc.",
|
|
6
6
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"@instructure/emotion": "^8.51.0",
|
|
45
45
|
"@instructure/grading-utils": "^1.0.0",
|
|
46
46
|
"@instructure/outcomes-ui": "^3.2.2",
|
|
47
|
-
"@instructure/quiz-common": "20.
|
|
48
|
-
"@instructure/quiz-i18n": "20.
|
|
49
|
-
"@instructure/quiz-interactions": "20.
|
|
50
|
-
"@instructure/quiz-number-input": "20.
|
|
51
|
-
"@instructure/quiz-rce": "20.
|
|
47
|
+
"@instructure/quiz-common": "20.18.1-rc.0+392e66e66",
|
|
48
|
+
"@instructure/quiz-i18n": "20.18.1-rc.0+392e66e66",
|
|
49
|
+
"@instructure/quiz-interactions": "20.18.1-rc.0+392e66e66",
|
|
50
|
+
"@instructure/quiz-number-input": "20.18.1-rc.0+392e66e66",
|
|
51
|
+
"@instructure/quiz-rce": "20.18.1-rc.0+392e66e66",
|
|
52
52
|
"@instructure/ui-a11y-content": "^8.51.0",
|
|
53
53
|
"@instructure/ui-alerts": "^8.51.0",
|
|
54
54
|
"@instructure/ui-avatar": "^8.51.0",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"file-saver": "~2.0.5",
|
|
112
112
|
"humps": "^2.0.0",
|
|
113
113
|
"immutable": "^3.8.1",
|
|
114
|
-
"instructure-validations": "20.
|
|
114
|
+
"instructure-validations": "20.18.1-rc.0+392e66e66",
|
|
115
115
|
"ipaddr.js": "^1.5.4",
|
|
116
116
|
"isomorphic-fetch": "^2.2.0",
|
|
117
117
|
"isuuid": "^0.1.0",
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
"uuid": "^3.2.1"
|
|
143
143
|
},
|
|
144
144
|
"devDependencies": {
|
|
145
|
-
"@instructure/quiz-scripts": "20.
|
|
145
|
+
"@instructure/quiz-scripts": "20.18.0",
|
|
146
146
|
"@instructure/ui-axe-check": "^8.51.0",
|
|
147
147
|
"@instructure/ui-babel-preset": "^7.22.1",
|
|
148
148
|
"@instructure/ui-scripts": "^7.22.1",
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
"jquery": "^2.2.3",
|
|
162
162
|
"karma-junit-reporter": "^2.0.1",
|
|
163
163
|
"most-subject": "^5.3.0",
|
|
164
|
-
"quiz-presets": "20.
|
|
164
|
+
"quiz-presets": "20.18.1-rc.0+392e66e66",
|
|
165
165
|
"react": "^16.8.6",
|
|
166
166
|
"react-addons-test-utils": "^15.6.2",
|
|
167
167
|
"react-dom": "^16.8.6",
|
|
@@ -177,5 +177,5 @@
|
|
|
177
177
|
"publishConfig": {
|
|
178
178
|
"access": "public"
|
|
179
179
|
},
|
|
180
|
-
"gitHead": "
|
|
180
|
+
"gitHead": "392e66e66be84e073171f29b85edaf54330b3b8f"
|
|
181
181
|
}
|