@instructure/quiz-core 17.46.2-rc.7 → 17.47.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 (34) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/es/banks/components/AddToBankModal/index.js +6 -0
  3. package/es/banks/components/AddToBankModal/presenter.js +128 -6
  4. package/es/banks/components/BankEntry/presenter.js +4 -3
  5. package/es/building/api/items.js +21 -5
  6. package/es/building/api/stimuli.js +21 -5
  7. package/es/building/components/resources/quizEntry/QuizEntryEdit/presenter.js +1 -0
  8. package/es/common/actions/config.js +7 -1
  9. package/es/common/components/ConfirmationModal/presenter.js +1 -1
  10. package/es/common/components/SDKApp/index.js +10 -2
  11. package/es/common/components/resources/entry/EntrySave/index.js +11 -5
  12. package/es/common/components/resources/entry/EntrySave/presenter.js +95 -21
  13. package/es/common/components/resources/stimulus/StimulusEdit/presenter.js +1 -0
  14. package/es/common/reducers/config.js +4 -1
  15. package/es/common/util/RceConfigProvider.js +42 -26
  16. package/es/common/util/rceChecker.js +1 -1
  17. package/es/common/util/windowChecks.js +4 -1
  18. package/lib/banks/components/AddToBankModal/index.js +9 -0
  19. package/lib/banks/components/AddToBankModal/presenter.js +135 -6
  20. package/lib/banks/components/BankEntry/presenter.js +4 -3
  21. package/lib/building/api/items.js +23 -5
  22. package/lib/building/api/stimuli.js +23 -5
  23. package/lib/building/components/resources/quizEntry/QuizEntryEdit/presenter.js +1 -0
  24. package/lib/common/actions/config.js +8 -0
  25. package/lib/common/components/ConfirmationModal/presenter.js +1 -1
  26. package/lib/common/components/SDKApp/index.js +9 -1
  27. package/lib/common/components/resources/entry/EntrySave/index.js +15 -2
  28. package/lib/common/components/resources/entry/EntrySave/presenter.js +96 -21
  29. package/lib/common/components/resources/stimulus/StimulusEdit/presenter.js +1 -0
  30. package/lib/common/reducers/config.js +3 -0
  31. package/lib/common/util/RceConfigProvider.js +41 -25
  32. package/lib/common/util/rceChecker.js +1 -1
  33. package/lib/common/util/windowChecks.js +8 -2
  34. package/package.json +10 -10
@@ -6,6 +6,7 @@ import _inherits from "@babel/runtime/helpers/esm/inherits";
6
6
  import _createSuper from "@babel/runtime/helpers/esm/createSuper";
7
7
  import React, { Component } from 'react';
8
8
  import PropTypes from 'prop-types';
9
+ import ImmutablePropTypes from 'react-immutable-proptypes';
9
10
  import { Button } from '@instructure/ui-buttons';
10
11
  import { View } from '@instructure/ui-view';
11
12
  import { API_INPUT_VALIDATION_ERROR } from '@instructure/quiz-common';
@@ -39,11 +40,75 @@ export var EntrySave = /*#__PURE__*/function (_Component) {
39
40
  _this.props.screenreaderNotification(msg);
40
41
  };
41
42
 
43
+ _this.confirmShareableContent = function () {
44
+ var _this$props = _this.props,
45
+ canvasOrigin = _this$props.canvasOrigin,
46
+ checkContentShareability = _this$props.checkContentShareability,
47
+ entry = _this$props.entry,
48
+ withConfirm = _this$props.withConfirm;
49
+
50
+ _this.setState({
51
+ canSubmit: false
52
+ });
53
+
54
+ checkContentShareability(entry.getWorkingInstance(), canvasOrigin).then(function () {
55
+ _this.successfulSubmit();
56
+ }).catch( /*#__PURE__*/function () {
57
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(err) {
58
+ var _err$response, _err$response2;
59
+
60
+ var body, text;
61
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
62
+ while (1) {
63
+ switch (_context.prev = _context.next) {
64
+ case 0:
65
+ _context.next = 2;
66
+ return (_err$response = err.response) === null || _err$response === void 0 ? void 0 : _err$response.json();
67
+
68
+ case 2:
69
+ body = _context.sent;
70
+ text = t('There was an error attempting to validate shareability.');
71
+
72
+ if (((_err$response2 = err.response) === null || _err$response2 === void 0 ? void 0 : _err$response2.status) === 400 && body.shareable === false) {
73
+ text = t('You are attempting to save content containing course links which may not work when used in other courses.');
74
+ }
75
+
76
+ withConfirm(function () {
77
+ _this.successfulSubmit();
78
+ }, {
79
+ title: t('Are you sure?'),
80
+ text: text,
81
+ continueText: t('Save anyway'),
82
+ onCancel: function onCancel() {
83
+ _this.setState({
84
+ canSubmit: true
85
+ });
86
+ }
87
+ });
88
+
89
+ case 6:
90
+ case "end":
91
+ return _context.stop();
92
+ }
93
+ }
94
+ }, _callee);
95
+ }));
96
+
97
+ return function (_x) {
98
+ return _ref.apply(this, arguments);
99
+ };
100
+ }());
101
+ };
102
+
42
103
  _this.onSubmit = function (e) {
43
104
  e.preventDefault();
44
105
 
45
106
  if (_this.props.isValid) {
46
- _this.successfulSubmit();
107
+ if (_this.props.checkBankedContentShareabilityEnabled && _this.props.shouldValidateShareableContent) {
108
+ _this.confirmShareableContent();
109
+ } else {
110
+ _this.successfulSubmit();
111
+ }
47
112
  } else {
48
113
  _this.createScreenReaderNotification();
49
114
 
@@ -87,24 +152,24 @@ export var EntrySave = /*#__PURE__*/function (_Component) {
87
152
  }, {
88
153
  key: "successfulSubmit",
89
154
  value: function () {
90
- var _successfulSubmit = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
155
+ var _successfulSubmit = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
91
156
  var validationResult;
92
- return _regeneratorRuntime.wrap(function _callee$(_context) {
157
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
93
158
  while (1) {
94
- switch (_context.prev = _context.next) {
159
+ switch (_context2.prev = _context2.next) {
95
160
  case 0:
96
161
  this.setState({
97
162
  canSubmit: false
98
163
  });
99
- _context.prev = 1;
100
- _context.next = 4;
164
+ _context2.prev = 1;
165
+ _context2.next = 4;
101
166
  return this.props.submitHandler();
102
167
 
103
168
  case 4:
104
- validationResult = _context.sent;
169
+ validationResult = _context2.sent;
105
170
 
106
171
  if (!(validationResult === API_INPUT_VALIDATION_ERROR)) {
107
- _context.next = 8;
172
+ _context2.next = 8;
108
173
  break;
109
174
  }
110
175
 
@@ -112,16 +177,16 @@ export var EntrySave = /*#__PURE__*/function (_Component) {
112
177
  throw new Error('User input validation error received from API.');
113
178
 
114
179
  case 8:
115
- _context.next = 14;
180
+ _context2.next = 14;
116
181
  break;
117
182
 
118
183
  case 10:
119
- _context.prev = 10;
120
- _context.t0 = _context["catch"](1);
184
+ _context2.prev = 10;
185
+ _context2.t0 = _context2["catch"](1);
121
186
  this.setState({
122
187
  canSubmit: true
123
188
  });
124
- return _context.abrupt("return");
189
+ return _context2.abrupt("return");
125
190
 
126
191
  case 14:
127
192
  this.props.switchOffEditing();
@@ -130,10 +195,10 @@ export var EntrySave = /*#__PURE__*/function (_Component) {
130
195
 
131
196
  case 17:
132
197
  case "end":
133
- return _context.stop();
198
+ return _context2.stop();
134
199
  }
135
200
  }
136
- }, _callee, this, [[1, 10]]);
201
+ }, _callee2, this, [[1, 10]]);
137
202
  }));
138
203
 
139
204
  function successfulSubmit() {
@@ -168,28 +233,37 @@ export var EntrySave = /*#__PURE__*/function (_Component) {
168
233
  return EntrySave;
169
234
  }(Component);
170
235
  EntrySave.propTypes = {
171
- displayPosition: PropTypes.number,
172
- disableSubmit: PropTypes.bool,
173
- guid: PropTypes.string,
174
- submitHandler: PropTypes.func.isRequired,
175
236
  cancelHandler: PropTypes.func,
237
+ canvasOrigin: PropTypes.string,
238
+ checkBankedContentShareabilityEnabled: PropTypes.bool,
239
+ checkContentShareability: PropTypes.func.isRequired,
176
240
  clearChanges: PropTypes.func.isRequired,
177
241
  // From connected component
178
242
  clearNextQuizEntry: PropTypes.func.isRequired,
243
+ disableSubmit: PropTypes.bool,
244
+ displayPosition: PropTypes.number,
245
+ entry: ImmutablePropTypes.record.isRequired,
246
+ guid: PropTypes.string,
179
247
  hideError: PropTypes.func.isRequired,
248
+ initialFocusId: PropTypes.string,
180
249
  isValid: PropTypes.bool.isRequired,
181
250
  showError: PropTypes.func.isRequired,
182
251
  screenreaderNotification: PropTypes.func.isRequired,
252
+ shouldValidateShareableContent: PropTypes.bool,
253
+ submitHandler: PropTypes.func.isRequired,
183
254
  // from makescrollable / from props being passed in occasionally
184
255
  switchOnEditing: PropTypes.func.isRequired,
185
256
  switchOffEditing: PropTypes.func.isRequired,
186
- initialFocusId: PropTypes.string
257
+ withConfirm: PropTypes.func.isRequired
187
258
  };
188
259
  EntrySave.defaultProps = {
189
- displayPosition: null,
190
260
  cancelHandler: noop,
261
+ canvasOrigin: '',
262
+ checkBankedContentShareabilityEnabled: false,
263
+ displayPosition: null,
191
264
  disableSubmit: false,
192
265
  guid: null,
193
- initialFocusId: null
266
+ initialFocusId: null,
267
+ shouldValidateShareableContent: false
194
268
  };
195
269
  export default EntrySave;
@@ -376,6 +376,7 @@ export var StimulusEdit = (_dec = themeable(theme, styles), _dec(_class = (_temp
376
376
  onAdd: this.handleAddToBank,
377
377
  onContinue: this.handleAddToBankContinue,
378
378
  getEntry: this.getEntryForBank,
379
+ workingEntry: this.props.workingStimulus,
379
380
  entryId: this.props.guid,
380
381
  entryType: this.props.quizEntry.entryType
381
382
  });
@@ -1,5 +1,5 @@
1
1
  import { fromJS } from 'immutable';
2
- import { SET_API_ENDPOINT, SET_USER_TOKEN } from '@instructure/quiz-common';
2
+ import { SET_API_ENDPOINT, SET_CANVAS_ORIGIN, SET_USER_TOKEN } from '@instructure/quiz-common';
3
3
  var defaultState = fromJS({
4
4
  apiEndpoint: ''
5
5
  });
@@ -11,6 +11,9 @@ export default (function () {
11
11
  case SET_API_ENDPOINT:
12
12
  return state.set('apiEndpoint', action.payload);
13
13
 
14
+ case SET_CANVAS_ORIGIN:
15
+ return state.set('canvasOrigin', action.payload);
16
+
14
17
  case SET_USER_TOKEN:
15
18
  return state.set('userToken', action.payload);
16
19
 
@@ -14,7 +14,7 @@ import { RceConfigContext, RceConfigKeys } from '@instructure/quiz-common';
14
14
  import { addError } from "../actions/alerts.js";
15
15
  import t from '@instructure/quiz-i18n/es/format-message';
16
16
  import { extractTextFromHtml } from '@instructure/quiz-interactions';
17
- import { isQuizTaking } from "./windowChecks.js";
17
+ import { isQuizTaking, isQuizBuilding } from "./windowChecks.js";
18
18
 
19
19
  var _ref4 = /*#__PURE__*/React.createElement(Card, {
20
20
  wrapped: true
@@ -50,39 +50,37 @@ export var RceConfigProviderComponent = function RceConfigProviderComponent(prop
50
50
  switch (_context.prev = _context.next) {
51
51
  case 0:
52
52
  if (hasAllPropsForRcs()) {
53
- _context.next = 3;
53
+ _context.next = 2;
54
54
  break;
55
55
  }
56
56
 
57
- handleErrorFunc('Invalid RCS configuration');
58
57
  return _context.abrupt("return");
59
58
 
60
- case 3:
61
- _context.next = 5;
59
+ case 2:
60
+ _context.next = 4;
62
61
  return props.rcsJwtRefreshFn(jwt);
63
62
 
64
- case 5:
63
+ case 4:
65
64
  response = _context.sent;
66
65
  refreshedToken = response === null || response === void 0 ? void 0 : (_response$json = response.json) === null || _response$json === void 0 ? void 0 : _response$json.token; // inst-redux-service-middleware response structure
67
66
 
68
67
  if (refreshedToken) {
69
- _context.next = 13;
68
+ _context.next = 11;
70
69
  break;
71
70
  }
72
71
 
73
- handleErrorFunc('Unable to refresh RCS token');
74
72
  normalizedStem = questionStem !== null && questionStem !== void 0 ? questionStem : 'Unknown stem';
75
73
  extractedText = extractTextFromHtml(normalizedStem);
76
- setErrorIfDuringTaking(t('Error while answering "{stem}": Full functionality of the Rich Content Editor may not have been available to the user.', {
74
+ handleError(t('Error while answering "{stem}": Full functionality of the Rich Content Editor may not have been available to the user.', {
77
75
  stem: extractedText
78
76
  }));
79
77
  return _context.abrupt("return");
80
78
 
81
- case 13:
79
+ case 11:
82
80
  setJwt(refreshedToken);
83
81
  setTokenFn(refreshedToken);
84
82
 
85
- case 15:
83
+ case 13:
86
84
  case "end":
87
85
  return _context.stop();
88
86
  }
@@ -95,8 +93,34 @@ export var RceConfigProviderComponent = function RceConfigProviderComponent(prop
95
93
  };
96
94
  }();
97
95
 
98
- var handleErrorFunc = function handleErrorFunc(errorMessage) {
99
- store.dispatch(addError(errorMessage));
96
+ var handleError = function handleError(quizLogMessage) {
97
+ if (shouldAlertUser()) {
98
+ alertTheUser(alertMessage());
99
+ }
100
+
101
+ if (shouldsetEventToQuizLog()) {
102
+ setEventToQuizLog(quizLogMessage);
103
+ }
104
+ };
105
+
106
+ var alertTheUser = function alertTheUser(message) {
107
+ store.dispatch(addError(message));
108
+ };
109
+
110
+ var setEventToQuizLog = function setEventToQuizLog(message) {
111
+ props.setEventToQuizLog(message);
112
+ };
113
+
114
+ var alertMessage = function alertMessage() {
115
+ return isQuizTaking() ? t('The Rich Content Editor has encountered an issue. ' + 'It has been logged for your instructor to review. Please refresh and try again.') : t('The Rich Content Editor has encountered an issue. Please refresh and try again.');
116
+ };
117
+
118
+ var shouldAlertUser = function shouldAlertUser() {
119
+ return isQuizTaking() || isQuizBuilding();
120
+ };
121
+
122
+ var shouldsetEventToQuizLog = function shouldsetEventToQuizLog() {
123
+ return isQuizTaking();
100
124
  };
101
125
 
102
126
  var getConfig = function getConfig() {
@@ -109,14 +133,6 @@ export var RceConfigProviderComponent = function RceConfigProviderComponent(prop
109
133
  };
110
134
  };
111
135
 
112
- var setErrorIfDuringTaking = function setErrorIfDuringTaking(errorMessage) {
113
- if (!isQuizTaking()) {
114
- return;
115
- }
116
-
117
- props.setRCEError(errorMessage);
118
- };
119
-
120
136
  useEffect(function () {
121
137
  _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
122
138
  var host, base, url, response, json;
@@ -139,7 +155,7 @@ export var RceConfigProviderComponent = function RceConfigProviderComponent(prop
139
155
  break;
140
156
  }
141
157
 
142
- setErrorIfDuringTaking(t('Error: Full functionality of the Rich Content Editor may not have been available to the user.'));
158
+ handleError(t('Error: Full functionality of the Rich Content Editor may not have been available to the user.'));
143
159
  return _context2.abrupt("return");
144
160
 
145
161
  case 6:
@@ -163,7 +179,7 @@ export var RceConfigProviderComponent = function RceConfigProviderComponent(prop
163
179
  case 16:
164
180
  json = _context2.sent;
165
181
  setCanvasConfig(json);
166
- setErrorIfDuringTaking(null);
182
+ setEventToQuizLog(null);
167
183
  _context2.next = 25;
168
184
  break;
169
185
 
@@ -171,7 +187,7 @@ export var RceConfigProviderComponent = function RceConfigProviderComponent(prop
171
187
  _context2.prev = 21;
172
188
  _context2.t0 = _context2["catch"](2);
173
189
  setCanvasConfig(null);
174
- setErrorIfDuringTaking(t('Error: Full functionality of the Rich Content Editor including accessibility features may not have been available to the user.'));
190
+ handleError(t('Error: Full functionality of the Rich Content Editor including accessibility features may not have been available to the user.'));
175
191
 
176
192
  case 25:
177
193
  _context2.prev = 25;
@@ -206,7 +222,7 @@ RceConfigProviderComponent.propTypes = {
206
222
  isNewRCEEnabled: PropTypes.bool.isRequired,
207
223
  rce5Renderer: PropTypes.bool.isRequired,
208
224
  isNewRCEAppsEnabled: PropTypes.bool,
209
- setRCEError: PropTypes.func.isRequired,
225
+ setEventToQuizLog: PropTypes.func.isRequired,
210
226
  contextId: PropTypes.string,
211
227
  contextType: PropTypes.string,
212
228
  canvasUserId: PropTypes.string,
@@ -238,7 +254,7 @@ var mapStateToProps = function mapStateToProps(state, ownProps) {
238
254
  };
239
255
 
240
256
  var mapDispatchToProps = {
241
- setRCEError: setRCEError
257
+ setEventToQuizLog: setRCEError
242
258
  };
243
259
  var RceConfigProvider = connect(mapStateToProps, mapDispatchToProps)(RceConfigProviderComponent);
244
260
  export { RceConfigProvider };
@@ -1,6 +1,6 @@
1
1
  import { featureOn } from "./featureCheck.js";
2
2
  var newRCEFeatureName = 'use_new_rce';
3
- var newRCEAppsFeatureName = 'use_new_rce_apps';
3
+ var newRCEAppsFeatureName = 'rce5_apps';
4
4
  var rce5RendererFeatureName = 'rce5_renderer';
5
5
  export function isNewRCEEnabled() {
6
6
  return featureOn(newRCEFeatureName);
@@ -1,4 +1,4 @@
1
- import { isDuringQuizTake } from '@instructure/quiz-common';
1
+ import { isDuringQuizTake, isDuringQuizBuild } from '@instructure/quiz-common';
2
2
  export var media = {
3
3
  'phone-break-point': 'only screen and (max-width: 48rem)',
4
4
  'tablet-break-point': 'only screen and (max-width: 64rem)'
@@ -15,4 +15,7 @@ export var onTablet = function onTablet() {
15
15
  };
16
16
  export var isQuizTaking = function isQuizTaking() {
17
17
  return isDuringQuizTake();
18
+ };
19
+ export var isQuizBuilding = function isQuizBuilding() {
20
+ return isDuringQuizBuild();
18
21
  };
@@ -16,6 +16,10 @@ var _banks = require("../../api/banks.js");
16
16
 
17
17
  var _bankEntries = require("../../api/bankEntries.js");
18
18
 
19
+ var _items = require("../../../building/api/items.js");
20
+
21
+ var _stimuli = require("../../../building/api/stimuli.js");
22
+
19
23
  var _presenter = _interopRequireDefault(require("./presenter.js"));
20
24
 
21
25
  var modalActions = _interopRequireWildcard(require("../../../common/actions/modal.js"));
@@ -30,10 +34,15 @@ var _quizCommon = require("@instructure/quiz-common");
30
34
 
31
35
  var _modalHelpers = require("../../../common/util/modalHelpers.js");
32
36
 
37
+ var _featureCheck = require("../../../common/util/featureCheck.js");
38
+
33
39
  function mapStateToProps(state, props) {
34
40
  var selectedBankOption = state.getIn(['ui', _quizCommon.ADD_TO_BANK_MODAL_BANK_SELECTION]);
35
41
  var selectedBank = selectedBankOption && new _Bank.default(state.getIn(['banks', selectedBankOption]));
36
42
  return {
43
+ canvasOrigin: state.getIn(['config', 'canvasOrigin']),
44
+ checkBankedContentShareabilityEnabled: (0, _featureCheck.featureOn)('check_banked_content_shareability'),
45
+ checkContentShareability: props.entryType === 'Item' ? _items.checkItemShareability : _stimuli.checkStimulusShareability,
37
46
  selectedBank: selectedBank,
38
47
  modalTrigger: (0, _modalHelpers.getModalTrigger)(state),
39
48
  modalOpen: state.getIn(['modal', 'isOpen']) === [_quizCommon.ADD_TO_BANK_MODAL, props.entryType, props.entryId].join(':')
@@ -9,6 +9,10 @@ Object.defineProperty(exports, "__esModule", {
9
9
  });
10
10
  exports.default = exports.AddToBankModal = void 0;
11
11
 
12
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
13
+
14
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
15
+
12
16
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
17
 
14
18
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
@@ -37,11 +41,36 @@ var _Bank = _interopRequireDefault(require("../../../common/records/Bank.js"));
37
41
 
38
42
  var _index = _interopRequireDefault(require("../../../common/components/resources/BankSelection/index.js"));
39
43
 
44
+ var _uiSpinner = require("@instructure/ui-spinner");
45
+
46
+ var _uiText = require("@instructure/ui-text");
47
+
48
+ var _uiIcons = require("@instructure/ui-icons");
49
+
50
+ var _uiView = require("@instructure/ui-view");
51
+
52
+ var _uiFlex = require("@instructure/ui-flex");
53
+
40
54
  var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
41
55
 
42
56
  var _quizCommon = require("@instructure/quiz-common");
43
57
 
44
- var _ref = /*#__PURE__*/_react.default.createElement("br", null);
58
+ var _ref2 = /*#__PURE__*/_react.default.createElement(_uiIcons.IconCheckLine, {
59
+ color: "success"
60
+ });
61
+
62
+ var _ref3 = /*#__PURE__*/_react.default.createElement(_uiFlex.Flex.Item, {
63
+ padding: "0 small 0 0"
64
+ }, /*#__PURE__*/_react.default.createElement(_uiIcons.IconNoLine, {
65
+ color: "error",
66
+ size: "small"
67
+ }));
68
+
69
+ var _ref4 = /*#__PURE__*/_react.default.createElement(_uiIcons.IconWarningLine, {
70
+ color: "warning"
71
+ });
72
+
73
+ var _ref5 = /*#__PURE__*/_react.default.createElement("br", null);
45
74
 
46
75
  var AddToBankModal = /*#__PURE__*/function (_Component) {
47
76
  (0, _inherits2.default)(AddToBankModal, _Component);
@@ -60,6 +89,7 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
60
89
  _this = _super.call.apply(_super, [this].concat(args));
61
90
  _this.state = {
62
91
  bankType: 'existing',
92
+ contentShareable: 'loading',
63
93
  newBankTitle: ''
64
94
  };
65
95
 
@@ -124,6 +154,65 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
124
154
  }
125
155
 
126
156
  (0, _createClass2.default)(AddToBankModal, [{
157
+ key: "componentDidUpdate",
158
+ value: function componentDidUpdate(prevProps) {
159
+ var _this2 = this;
160
+
161
+ var _this$props = this.props,
162
+ canvasOrigin = _this$props.canvasOrigin,
163
+ checkBankedContentShareabilityEnabled = _this$props.checkBankedContentShareabilityEnabled,
164
+ modalOpen = _this$props.modalOpen,
165
+ checkContentShareability = _this$props.checkContentShareability,
166
+ workingEntry = _this$props.workingEntry;
167
+
168
+ if (checkBankedContentShareabilityEnabled && modalOpen && !prevProps.modalOpen) {
169
+ this.setState({
170
+ contentShareable: 'loading'
171
+ });
172
+ checkContentShareability(workingEntry, canvasOrigin).then(function () {
173
+ _this2.setState({
174
+ contentShareable: 'true'
175
+ });
176
+ }).catch( /*#__PURE__*/function () {
177
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(err) {
178
+ var _err$response, _err$response2;
179
+
180
+ var body;
181
+ return _regenerator.default.wrap(function _callee$(_context) {
182
+ while (1) {
183
+ switch (_context.prev = _context.next) {
184
+ case 0:
185
+ _context.next = 2;
186
+ return (_err$response = err.response) === null || _err$response === void 0 ? void 0 : _err$response.json();
187
+
188
+ case 2:
189
+ body = _context.sent;
190
+
191
+ if (((_err$response2 = err.response) === null || _err$response2 === void 0 ? void 0 : _err$response2.status) === 400 && body.shareable === false) {
192
+ _this2.setState({
193
+ contentShareable: 'false'
194
+ });
195
+ } else {
196
+ _this2.setState({
197
+ contentShareable: 'unknown'
198
+ });
199
+ }
200
+
201
+ case 4:
202
+ case "end":
203
+ return _context.stop();
204
+ }
205
+ }
206
+ }, _callee);
207
+ }));
208
+
209
+ return function (_x) {
210
+ return _ref.apply(this, arguments);
211
+ };
212
+ }());
213
+ }
214
+ }
215
+ }, {
127
216
  key: "cancelButton",
128
217
  value: function cancelButton() {
129
218
  return /*#__PURE__*/_react.default.createElement(_uiButtons.Button, {
@@ -136,8 +225,11 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
136
225
  value: function addToBankButton() {
137
226
  var _this$state = this.state,
138
227
  bankType = _this$state.bankType,
139
- newBankTitle = _this$state.newBankTitle;
140
- var disabled = bankType === 'existing' && !this.props.selectedBank || bankType === 'new' && (!newBankTitle || !newBankTitle.trim());
228
+ newBankTitle = _this$state.newBankTitle,
229
+ contentShareable = _this$state.contentShareable;
230
+ var checkBankedContentShareabilityEnabled = this.props.checkBankedContentShareabilityEnabled;
231
+ var contentShareableLoading = contentShareable === 'loading';
232
+ var disabled = bankType === 'existing' && !this.props.selectedBank || bankType === 'new' && (!newBankTitle || !newBankTitle.trim()) || checkBankedContentShareabilityEnabled && contentShareableLoading;
141
233
  return /*#__PURE__*/_react.default.createElement(_uiButtons.Button, {
142
234
  type: "button",
143
235
  variant: "primary",
@@ -145,7 +237,7 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
145
237
  disabled: disabled,
146
238
  margin: _quizCommon.XSMALL_SIDE_MARGIN,
147
239
  "data-automation": "sdk-add-to-bank-button"
148
- }, (0, _formatMessage.default)('Add'));
240
+ }, checkBankedContentShareabilityEnabled && !contentShareableLoading && contentShareable !== 'true' ? (0, _formatMessage.default)('Add anyway') : (0, _formatMessage.default)('Add'));
149
241
  }
150
242
  }, {
151
243
  key: "renderBankTypeContent",
@@ -165,6 +257,37 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
165
257
  type: "text"
166
258
  });
167
259
  }
260
+ }, {
261
+ key: "renderContentShareabilityMessage",
262
+ value: function renderContentShareabilityMessage() {
263
+ if (this.props.checkBankedContentShareabilityEnabled) {
264
+ var content = null;
265
+
266
+ if (this.state.contentShareable === 'loading') {
267
+ content = /*#__PURE__*/_react.default.createElement(_uiText.Text, null, /*#__PURE__*/_react.default.createElement(_uiSpinner.Spinner, {
268
+ size: "x-small",
269
+ renderTitle: (0, _formatMessage.default)('Checking content shareability...')
270
+ }), "\xA0", (0, _formatMessage.default)('Validating content...'));
271
+ } else if (this.state.contentShareable === 'true') {
272
+ content = /*#__PURE__*/_react.default.createElement(_uiText.Text, null, _ref2, "\xA0", (0, _formatMessage.default)('Good to go!'));
273
+ } else if (this.state.contentShareable === 'false') {
274
+ content = /*#__PURE__*/_react.default.createElement(_uiFlex.Flex, null, _ref3, /*#__PURE__*/_react.default.createElement(_uiFlex.Flex.Item, {
275
+ shouldShrink: true
276
+ }, /*#__PURE__*/_react.default.createElement(_uiText.Text, {
277
+ color: "error"
278
+ }, (0, _formatMessage.default)('You are attempting to add content containing course links which may not work when used in other courses.'))));
279
+ } else {
280
+ content = /*#__PURE__*/_react.default.createElement(_uiText.Text, {
281
+ color: "warning"
282
+ }, _ref4, "\xA0", (0, _formatMessage.default)('There was an error attempting to validate shareability.'));
283
+ }
284
+
285
+ return /*#__PURE__*/_react.default.createElement(_uiView.View, {
286
+ as: "div",
287
+ margin: "small 0 0 0"
288
+ }, content);
289
+ }
290
+ }
168
291
  }, {
169
292
  key: "renderContent",
170
293
  value: function renderContent() {
@@ -179,7 +302,7 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
179
302
  }), /*#__PURE__*/_react.default.createElement(_uiRadioInput.RadioInput, {
180
303
  value: "new",
181
304
  label: (0, _formatMessage.default)('New item bank')
182
- })), _ref, this.renderBankTypeContent());
305
+ })), _ref5, this.renderBankTypeContent(), this.renderContentShareabilityMessage());
183
306
  }
184
307
  }, {
185
308
  key: "render",
@@ -207,6 +330,9 @@ var AddToBankModal = /*#__PURE__*/function (_Component) {
207
330
 
208
331
  exports.AddToBankModal = AddToBankModal;
209
332
  AddToBankModal.propTypes = {
333
+ canvasOrigin: _propTypes.default.string,
334
+ checkBankedContentShareabilityEnabled: _propTypes.default.bool,
335
+ checkContentShareability: _propTypes.default.func.isRequired,
210
336
  closeModal: _propTypes.default.func.isRequired,
211
337
  createBank: _propTypes.default.func.isRequired,
212
338
  createBankEntry: _propTypes.default.func.isRequired,
@@ -218,15 +344,18 @@ AddToBankModal.propTypes = {
218
344
  entryType: _propTypes.default.string.isRequired,
219
345
  // Resolve to the bank entry's entry, or create it if it does not yet exist.
220
346
  getEntry: _propTypes.default.func.isRequired,
347
+ handleValidationErrorsFromApi: _propTypes.default.func.isRequired,
221
348
  label: _propTypes.default.string.isRequired,
222
349
  modalOpen: _propTypes.default.bool.isRequired,
223
350
  onAdd: _propTypes.default.func,
224
351
  onContinue: _propTypes.default.func,
225
352
  selectedBank: _reactImmutableProptypes.default.record,
226
353
  uiSet: _propTypes.default.func.isRequired,
227
- handleValidationErrorsFromApi: _propTypes.default.func.isRequired
354
+ workingEntry: _reactImmutableProptypes.default.record.isRequired
228
355
  };
229
356
  AddToBankModal.defaultProps = {
357
+ canvasOrigin: '',
358
+ checkBankedContentShareabilityEnabled: false,
230
359
  onAdd: function onAdd() {},
231
360
  onContinue: function onContinue() {},
232
361
  selectedBank: null
@@ -245,17 +245,18 @@ var BankEntry = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _de
245
245
  return {
246
246
  cancelHandler: _this.navigateToBank,
247
247
  clearChanges: _this.clearChanges,
248
+ clearValidationErrorsFromApi: _this.clearValidationErrorsFromApi,
248
249
  contextUuid: null,
250
+ disableSubmit: Boolean(_this.state.validationErrorsFromApi && Object.values(_this.state.validationErrorsFromApi).length),
249
251
  entry: entry,
250
252
  guid: "".concat(_this.props.bankEntry.id, "_bank_entry_edit"),
251
253
  handleQuizEntryPointsChange: _this.handlePointsChange,
252
254
  parentId: _this.props.bankId,
253
255
  parentType: _quizCommon.PARENT_TYPE_BANK,
256
+ shouldValidateShareableContent: true,
254
257
  stimulus: entry,
255
258
  submitHandler: _this.submitHandler,
256
- validationErrorsFromApi: _this.state.validationErrorsFromApi,
257
- clearValidationErrorsFromApi: _this.clearValidationErrorsFromApi,
258
- disableSubmit: Boolean(_this.state.validationErrorsFromApi && Object.values(_this.state.validationErrorsFromApi).length)
259
+ validationErrorsFromApi: _this.state.validationErrorsFromApi
259
260
  };
260
261
  };
261
262