@instructure/quiz-core 22.10.2 → 22.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/es/banks/api/banks.js +18 -97
  2. package/es/banks/components/SharingModal/index.js +6 -3
  3. package/es/banks/components/SharingModal/presenter.js +207 -131
  4. package/es/building/api/items.js +120 -24
  5. package/es/building/api/quizEntries.js +78 -15
  6. package/es/building/components/resources/quizEntry/QuizEntryShow/presenter.js +11 -2
  7. package/es/common/actions/sharedBanks.js +13 -1
  8. package/es/common/actions/sharingModal.js +7 -0
  9. package/es/common/components/resources/quiz/AddContent/Body/index.js +1 -1
  10. package/es/common/components/resources/quiz/AddContent/Body/presenter.js +129 -141
  11. package/es/common/components/resources/quiz/AddContent/Popover/presenter.js +126 -119
  12. package/es/common/components/shared/InteractionTypes/index.js +1 -4
  13. package/es/common/components/shared/InteractionTypes/presenter.js +1 -3
  14. package/es/common/middleware/sharedBanksMiddleware.js +243 -0
  15. package/es/common/records/Item.js +2 -1
  16. package/es/common/records/QuizEntry.js +7 -0
  17. package/es/common/reducers/sharingModal.js +17 -0
  18. package/es/common/util/useRemoteComponent.js +127 -0
  19. package/es/configureStore.js +4 -1
  20. package/es/index.js +3 -2
  21. package/lib/banks/api/banks.js +17 -96
  22. package/lib/banks/components/SharingModal/index.js +5 -2
  23. package/lib/banks/components/SharingModal/presenter.js +205 -129
  24. package/lib/building/api/items.js +120 -23
  25. package/lib/building/api/quizEntries.js +78 -14
  26. package/lib/building/components/resources/quizEntry/QuizEntryShow/presenter.js +10 -1
  27. package/lib/common/actions/sharedBanks.js +13 -1
  28. package/lib/common/actions/sharingModal.js +13 -0
  29. package/lib/common/components/resources/quiz/AddContent/Body/index.js +1 -1
  30. package/lib/common/components/resources/quiz/AddContent/Body/presenter.js +132 -141
  31. package/lib/common/components/resources/quiz/AddContent/Popover/presenter.js +127 -119
  32. package/lib/common/components/shared/InteractionTypes/index.js +1 -4
  33. package/lib/common/components/shared/InteractionTypes/presenter.js +1 -3
  34. package/lib/common/middleware/sharedBanksMiddleware.js +250 -0
  35. package/lib/common/records/Item.js +2 -1
  36. package/lib/common/records/QuizEntry.js +7 -0
  37. package/lib/common/reducers/sharingModal.js +23 -0
  38. package/lib/common/util/useRemoteComponent.js +134 -0
  39. package/lib/configureStore.js +4 -1
  40. package/lib/index.js +22 -0
  41. package/package.json +8 -8
@@ -4,6 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
+ exports.createBulkItems = createBulkItems;
7
8
  exports.createItem = createItem;
8
9
  exports.getItem = getItem;
9
10
  exports.updateItem = updateItem;
@@ -130,6 +131,102 @@ function createItem(item, parentId, parentType) {
130
131
  };
131
132
  }
132
133
 
134
+ /**
135
+ * Creates multiple items in bulk. The input data must consist of question groups and questions
136
+ * using a Learnosity format.
137
+ *
138
+ * @param {{
139
+ * question_type: string,
140
+ * questions: unknown[]
141
+ * }} items
142
+ * @param {object} options - Options for the bulk creation.
143
+ * @param {string} options.parentId - The ID of the parent resource (quiz or bank).
144
+ * @param {string} options.parentType - The type of the parent resource, either 'bank' or 'quiz'.
145
+ * @returns {function} - A thunk function that dispatches the action to create items.
146
+ */
147
+ function createBulkItems(items, _ref3) {
148
+ var parentId = _ref3.parentId,
149
+ parentType = _ref3.parentType;
150
+ var resource = parentType === 'bank' ? 'banks' : 'quizzes';
151
+ var url = "/api/".concat(resource, "/").concat(parentId, "/items/bulk");
152
+ var body = {
153
+ body: JSON.stringify({
154
+ items: items
155
+ })
156
+ };
157
+ return /*#__PURE__*/function () {
158
+ var _ref4 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee3(dispatch) {
159
+ var fetcher;
160
+ return _regenerator["default"].wrap(function _callee3$(_context3) {
161
+ while (1) switch (_context3.prev = _context3.next) {
162
+ case 0:
163
+ fetcher = new _Fetcher["default"]({
164
+ callType: _quizCommon.CREATE_BULK_ITEMS_CALL,
165
+ cloneResponseForError: true,
166
+ onError: function onError(_ref5) {
167
+ var response = _ref5.response;
168
+ return /*#__PURE__*/function () {
169
+ var _ref6 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(dispatch) {
170
+ var _yield$response$json2, errors;
171
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
172
+ while (1) switch (_context2.prev = _context2.next) {
173
+ case 0:
174
+ if (!(response && response.status === 422)) {
175
+ _context2.next = 12;
176
+ break;
177
+ }
178
+ _context2.prev = 1;
179
+ _context2.next = 4;
180
+ return response.json();
181
+ case 4:
182
+ _yield$response$json2 = _context2.sent;
183
+ errors = _yield$response$json2.errors;
184
+ if (!(0, _helpers.errorsAllFromValidation)(errors)) {
185
+ _context2.next = 8;
186
+ break;
187
+ }
188
+ return _context2.abrupt("return");
189
+ case 8:
190
+ _context2.next = 12;
191
+ break;
192
+ case 10:
193
+ _context2.prev = 10;
194
+ _context2.t0 = _context2["catch"](1);
195
+ case 12:
196
+ return _context2.abrupt("return", dispatch((0, _alerts.addError)((0, _formatMessage["default"])('Failed to create items.'))));
197
+ case 13:
198
+ case "end":
199
+ return _context2.stop();
200
+ }
201
+ }, _callee2, null, [[1, 10]]);
202
+ }));
203
+ return function (_x2) {
204
+ return _ref6.apply(this, arguments);
205
+ };
206
+ }();
207
+ }
208
+ });
209
+ return _context3.abrupt("return", fetcher.post(url, body).then(function (_ref7) {
210
+ var items = _ref7.items,
211
+ errors = _ref7.errors;
212
+ dispatch((0, _callHandlers.handleItemsResponse)(items));
213
+ return {
214
+ items: items,
215
+ errors: errors
216
+ };
217
+ })["catch"](_helpers.processApiError));
218
+ case 2:
219
+ case "end":
220
+ return _context3.stop();
221
+ }
222
+ }, _callee3);
223
+ }));
224
+ return function (_x) {
225
+ return _ref4.apply(this, arguments);
226
+ };
227
+ }();
228
+ }
229
+
133
230
  // =====================
134
231
  // =====================
135
232
  // UPDATE
@@ -163,53 +260,53 @@ function updateItem(item, parentId, parentType) {
163
260
  var fetcher = new _Fetcher["default"]({
164
261
  callType: _quizCommon.UPDATE_ITEM_CALL,
165
262
  cloneResponseForError: true,
166
- onError: function onError(_ref3) {
167
- var response = _ref3.response;
263
+ onError: function onError(_ref8) {
264
+ var response = _ref8.response;
168
265
  return /*#__PURE__*/function () {
169
- var _ref4 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(dispatch) {
170
- var _yield$response$json2, errors;
171
- return _regenerator["default"].wrap(function _callee2$(_context2) {
172
- while (1) switch (_context2.prev = _context2.next) {
266
+ var _ref9 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee4(dispatch) {
267
+ var _yield$response$json3, errors;
268
+ return _regenerator["default"].wrap(function _callee4$(_context4) {
269
+ while (1) switch (_context4.prev = _context4.next) {
173
270
  case 0:
174
271
  if (!(response && response.status === 422)) {
175
- _context2.next = 14;
272
+ _context4.next = 14;
176
273
  break;
177
274
  }
178
- _context2.prev = 1;
179
- _context2.next = 4;
275
+ _context4.prev = 1;
276
+ _context4.next = 4;
180
277
  return response.json();
181
278
  case 4:
182
- _yield$response$json2 = _context2.sent;
183
- errors = _yield$response$json2.errors;
279
+ _yield$response$json3 = _context4.sent;
280
+ errors = _yield$response$json3.errors;
184
281
  if (!(errors.base && errors.base.some(function (message) {
185
282
  return message.includes('cannot update an immutable item');
186
283
  }))) {
187
- _context2.next = 8;
284
+ _context4.next = 8;
188
285
  break;
189
286
  }
190
- return _context2.abrupt("return", dispatch((0, _alerts.addError)((0, _formatMessage["default"])('This item has now been viewed by a student, so your edits were not saved. ' + 'Please refresh the page and try again.'))));
287
+ return _context4.abrupt("return", dispatch((0, _alerts.addError)((0, _formatMessage["default"])('This item has now been viewed by a student, so your edits were not saved. ' + 'Please refresh the page and try again.'))));
191
288
  case 8:
192
289
  if (!(0, _helpers.errorsAllFromValidation)(errors)) {
193
- _context2.next = 10;
290
+ _context4.next = 10;
194
291
  break;
195
292
  }
196
- return _context2.abrupt("return");
293
+ return _context4.abrupt("return");
197
294
  case 10:
198
- _context2.next = 14;
295
+ _context4.next = 14;
199
296
  break;
200
297
  case 12:
201
- _context2.prev = 12;
202
- _context2.t0 = _context2["catch"](1);
298
+ _context4.prev = 12;
299
+ _context4.t0 = _context4["catch"](1);
203
300
  case 14:
204
- return _context2.abrupt("return", dispatch((0, _alerts.addError)((0, _formatMessage["default"])('Failed to update item.'))));
301
+ return _context4.abrupt("return", dispatch((0, _alerts.addError)((0, _formatMessage["default"])('Failed to update item.'))));
205
302
  case 15:
206
303
  case "end":
207
- return _context2.stop();
304
+ return _context4.stop();
208
305
  }
209
- }, _callee2, null, [[1, 12]]);
306
+ }, _callee4, null, [[1, 12]]);
210
307
  }));
211
- return function (_x) {
212
- return _ref4.apply(this, arguments);
308
+ return function (_x3) {
309
+ return _ref9.apply(this, arguments);
213
310
  };
214
311
  }();
215
312
  }
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.cloneQuizEntry = cloneQuizEntry;
8
+ exports.createBulkQuizEntries = createBulkQuizEntries;
8
9
  exports.createItemAndQuizEntry = void 0;
9
10
  exports.createQuizEntry = createQuizEntry;
10
11
  exports.createStimulusAndQuizEntry = void 0;
@@ -18,6 +19,7 @@ exports.removeStimulusQuizEntry = removeStimulusQuizEntry;
18
19
  exports.updateQuizEntry = updateQuizEntry;
19
20
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
20
21
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
22
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
21
23
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
22
24
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
23
25
  var _pick = _interopRequireDefault(require("lodash/pick"));
@@ -150,6 +152,68 @@ function createQuizEntry(quizId, entryId, entryType, entryProperties) {
150
152
  });
151
153
  };
152
154
  }
155
+ function createBulkQuizEntries(items, _ref) {
156
+ var quizId = _ref.quizId,
157
+ startPosition = _ref.startPosition,
158
+ _ref$pointsPossible = _ref.pointsPossible,
159
+ pointsPossible = _ref$pointsPossible === void 0 ? 1 : _ref$pointsPossible,
160
+ _ref$requireFocus = _ref.requireFocus,
161
+ requireFocus = _ref$requireFocus === void 0 ? true : _ref$requireFocus;
162
+ var url = "/api/quizzes/".concat(quizId, "/quiz_entries/bulk");
163
+ var quizEntries = items.map(function (item, index) {
164
+ return {
165
+ quizId: quizId,
166
+ entryId: item.id,
167
+ entryType: 'Item',
168
+ points_possible: pointsPossible,
169
+ position: Math.max(startPosition, 1) + index,
170
+ stimulus_quiz_entry_id: null
171
+ };
172
+ });
173
+ var body = {
174
+ body: JSON.stringify({
175
+ quiz_entries: quizEntries
176
+ })
177
+ };
178
+ return /*#__PURE__*/function () {
179
+ var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(dispatch) {
180
+ var fetcher;
181
+ return _regenerator["default"].wrap(function _callee$(_context) {
182
+ while (1) switch (_context.prev = _context.next) {
183
+ case 0:
184
+ fetcher = new _Fetcher["default"]({
185
+ callType: _quizCommon.CREATE_BULK_QUIZ_ENTRIES_CALL,
186
+ onError: function onError() {
187
+ return (0, _alerts.addError)((0, _formatMessage["default"])('Failed to create quiz entries.'));
188
+ }
189
+ });
190
+ return _context.abrupt("return", fetcher.post(url, body).then(function (response) {
191
+ var quizEntries = response.quiz_entries;
192
+ if (!Array.isArray(quizEntries)) {
193
+ throw new Error((0, _formatMessage["default"])('Expected an array of quiz entries.'));
194
+ }
195
+ var _ref3 = quizEntries || [],
196
+ _ref4 = (0, _slicedToArray2["default"])(_ref3, 1),
197
+ firstQuizEntry = _ref4[0];
198
+ if (quizEntries.length === 0 || !(firstQuizEntry !== null && firstQuizEntry !== void 0 && firstQuizEntry.id)) {
199
+ return dispatch(getQuizEntries(quizId));
200
+ }
201
+ var scrollCallback = function scrollCallback() {
202
+ return dispatch((0, _scrolling.scrollToItem)(String(firstQuizEntry.id), requireFocus));
203
+ };
204
+ return dispatch(getQuizEntries(quizId, scrollCallback));
205
+ }));
206
+ case 2:
207
+ case "end":
208
+ return _context.stop();
209
+ }
210
+ }, _callee);
211
+ }));
212
+ return function (_x) {
213
+ return _ref2.apply(this, arguments);
214
+ };
215
+ }();
216
+ }
153
217
 
154
218
  // =====================
155
219
  // =====================
@@ -185,9 +249,9 @@ function updateBody(updatedProperties) {
185
249
  // be updated with response data when it comes back. You may want to set
186
250
  // handleResponse to false for some optimistic update flows.
187
251
  function updateQuizEntry(quizId, quizEntryId, updatedProperties) {
188
- var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
189
- _ref$handleResponse = _ref.handleResponse,
190
- handleResponse = _ref$handleResponse === void 0 ? true : _ref$handleResponse;
252
+ var _ref5 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
253
+ _ref5$handleResponse = _ref5.handleResponse,
254
+ handleResponse = _ref5$handleResponse === void 0 ? true : _ref5$handleResponse;
191
255
  var url = "/api/quizzes/".concat(quizId, "/quiz_entries/").concat(quizEntryId);
192
256
  var fetcher = new _Fetcher["default"]({
193
257
  callType: _quizCommon.UPDATE_QUIZ_ENTRY_CALL,
@@ -197,28 +261,28 @@ function updateQuizEntry(quizId, quizEntryId, updatedProperties) {
197
261
  });
198
262
  var body = updateBody(updatedProperties);
199
263
  return /*#__PURE__*/function () {
200
- var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(dispatch, getState) {
264
+ var _ref6 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(dispatch, getState) {
201
265
  var response;
202
- return _regenerator["default"].wrap(function _callee$(_context) {
203
- while (1) switch (_context.prev = _context.next) {
266
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
267
+ while (1) switch (_context2.prev = _context2.next) {
204
268
  case 0:
205
- _context.next = 2;
269
+ _context2.next = 2;
206
270
  return fetcher.patch(url, {
207
271
  body: body
208
272
  });
209
273
  case 2:
210
- response = _context.sent;
274
+ response = _context2.sent;
211
275
  if (handleResponse) {
212
276
  dispatch((0, _callHandlers.handleQuizEntryResponse)(response));
213
277
  }
214
278
  case 4:
215
279
  case "end":
216
- return _context.stop();
280
+ return _context2.stop();
217
281
  }
218
- }, _callee);
282
+ }, _callee2);
219
283
  }));
220
- return function (_x, _x2) {
221
- return _ref2.apply(this, arguments);
284
+ return function (_x2, _x3) {
285
+ return _ref6.apply(this, arguments);
222
286
  };
223
287
  }();
224
288
  }
@@ -283,8 +347,8 @@ var createItemAndMoveQuizEntry = queue.wrapActionCreator(function (quizId, posit
283
347
  return function (dispatch, getState) {
284
348
  var quizEntry = _QuizEntry["default"].create(getState().getIn(['quizEntries', quizEntryId]));
285
349
  var workingItem = quizEntry.getEntry().getWorkingInstance();
286
- return dispatch(createItemAction(workingItem, quizId, 'quiz', workingItem.id)).then(function (_ref3) {
287
- var id = _ref3.id;
350
+ return dispatch(createItemAction(workingItem, quizId, 'quiz', workingItem.id)).then(function (_ref7) {
351
+ var id = _ref7.id;
288
352
  return dispatch(updateAction(quizId, quizEntryId, {
289
353
  entryId: id,
290
354
  position: position,
@@ -214,12 +214,21 @@ var QuizEntryShow = (_dec = (0, _quizCommon.withStyleOverrides)(_styles["default
214
214
  return (0, _emotion.jsx)(_uiIcons.IconBankLine, null);
215
215
  }
216
216
  }
217
+ }, {
218
+ key: "renderAiGeneratedContent",
219
+ value: function renderAiGeneratedContent() {
220
+ if (this.props.quizEntry.isAiGenerated) {
221
+ return (0, _emotion.jsx)(_uiIcons.IconAiLine, {
222
+ title: (0, _formatMessage["default"])('AI generated')
223
+ });
224
+ }
225
+ }
217
226
  }, {
218
227
  key: "renderLeftHeader",
219
228
  value: function renderLeftHeader() {
220
229
  return (0, _emotion.jsx)("div", {
221
230
  css: this.props.styles.leftHeader
222
- }, this.renderBankedContent(), this.renderInteractionType(), this.renderPointsPossible(), (0, _emotion.jsx)("div", {
231
+ }, this.renderBankedContent(), this.renderAiGeneratedContent(), this.renderInteractionType(), this.renderPointsPossible(), (0, _emotion.jsx)("div", {
223
232
  css: this.props.styles.title,
224
233
  "data-automation": "sdk-quiz-entry-title-div"
225
234
  }, this.props.entry.title));
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.updateSharedBankPermission = exports.removeSharedBank = exports.addSharedBanks = void 0;
6
+ exports.updateSharedBankPermission = exports.removeSharedBank = exports.getSharedBanksAction = exports.getAllSharedItems = exports.addSharedBanks = void 0;
7
7
  var _quizCommon = require("@instructure/quiz-common");
8
8
  var addSharedBanks = exports.addSharedBanks = function addSharedBanks(sharedBank) {
9
9
  return {
@@ -11,6 +11,18 @@ var addSharedBanks = exports.addSharedBanks = function addSharedBanks(sharedBank
11
11
  payload: sharedBank
12
12
  };
13
13
  };
14
+ var getSharedBanksAction = exports.getSharedBanksAction = function getSharedBanksAction(props) {
15
+ return {
16
+ type: _quizCommon.GET_SHARED_BANKS,
17
+ payload: props
18
+ };
19
+ };
20
+ var getAllSharedItems = exports.getAllSharedItems = function getAllSharedItems(props) {
21
+ return {
22
+ type: _quizCommon.GET_ALL_SHARED_ITEMS,
23
+ payload: props
24
+ };
25
+ };
14
26
  var updateSharedBankPermission = exports.updateSharedBankPermission = function updateSharedBankPermission(sharedBankId, permission) {
15
27
  return {
16
28
  type: _quizCommon.UPDATE_SHARED_BANK_PERMISSION,
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.sharedBankLoadingAction = void 0;
7
+ var _quizCommon = require("@instructure/quiz-common");
8
+ var sharedBankLoadingAction = exports.sharedBankLoadingAction = function sharedBankLoadingAction(props) {
9
+ return {
10
+ type: _quizCommon.CHANGE_MODAL_LOADING,
11
+ payload: props
12
+ };
13
+ };
@@ -12,7 +12,7 @@ var _alerts = require("../../../../../actions/alerts");
12
12
  var _presenter = _interopRequireDefault(require("./presenter"));
13
13
  var _interactionTypes = require("../../../../../selectors/interactionTypes");
14
14
  var _quizzes = require("../../../../../selectors/quizzes");
15
- var mapStateToProps = function mapStateToProps(state, props) {
15
+ var mapStateToProps = function mapStateToProps(state) {
16
16
  return {
17
17
  editingQuizEntry: (0, _quizzes.isEditingQuizEntry)(state),
18
18
  interactionTypes: (0, _interactionTypes.getInteractionTypes)(state),