@instructure/quiz-core 20.17.3-rc.10 → 20.17.3-rc.12

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.
@@ -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,
@@ -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;
@@ -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"; // reducers
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 baseMiddleware = [alertTimerMiddleware, crossDomainMessagingMiddleware, multi, kinesisMiddleware, thunkMiddleware];
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";
@@ -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());
@@ -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,
@@ -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;
@@ -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 baseMiddleware = [_alertTimerMiddleware.default, _crossDomainMessagingMiddleware.default, _reduxMulti.default, kinesisMiddleware, _reduxThunk.default];
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);
@@ -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.17.3-rc.10+8baf40578",
3
+ "version": "20.17.3-rc.12+3a1a91424",
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.17.3-rc.10+8baf40578",
48
- "@instructure/quiz-i18n": "20.17.3-rc.10+8baf40578",
49
- "@instructure/quiz-interactions": "20.17.3-rc.10+8baf40578",
50
- "@instructure/quiz-number-input": "20.17.3-rc.10+8baf40578",
51
- "@instructure/quiz-rce": "20.17.3-rc.10+8baf40578",
47
+ "@instructure/quiz-common": "20.17.3-rc.12+3a1a91424",
48
+ "@instructure/quiz-i18n": "20.17.3-rc.12+3a1a91424",
49
+ "@instructure/quiz-interactions": "20.17.3-rc.12+3a1a91424",
50
+ "@instructure/quiz-number-input": "20.17.3-rc.12+3a1a91424",
51
+ "@instructure/quiz-rce": "20.17.3-rc.12+3a1a91424",
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.17.3-rc.10+8baf40578",
114
+ "instructure-validations": "20.17.3-rc.12+3a1a91424",
115
115
  "ipaddr.js": "^1.5.4",
116
116
  "isomorphic-fetch": "^2.2.0",
117
117
  "isuuid": "^0.1.0",
@@ -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.17.3-rc.10+8baf40578",
164
+ "quiz-presets": "20.17.3-rc.12+3a1a91424",
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": "8baf40578c74bfe09a995e1ac9b91e76fc212d43"
180
+ "gitHead": "3a1a91424ba174b7f2a39cf2a8a4d669dae120ab"
181
181
  }