@instructure/quiz-core 17.63.1-rc.1 → 17.63.1-rc.4

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 (23) hide show
  1. package/es/common/actions/analyses.js +7 -1
  2. package/es/common/components/shared/spinner/Spinner.js +33 -18
  3. package/es/common/components/shared/spinner/theme.js +2 -5
  4. package/es/common/reducers/analyses.js +10 -8
  5. package/es/common/selectors/analyses.js +3 -0
  6. package/es/reporting/components/resources/NewQuizAndItemAnalysis/ReportCard/presenter.js +80 -30
  7. package/es/reporting/components/resources/NewQuizAndItemAnalysis/ReportCard/theme.js +4 -2
  8. package/es/reporting/components/resources/NewQuizAndItemAnalysis/fetchReports.js +15 -12
  9. package/es/reporting/components/resources/NewQuizAndItemAnalysis/fetchReportsStatus.js +45 -0
  10. package/es/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisState.js +10 -4
  11. package/es/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisStatePresenter.js +53 -13
  12. package/lib/common/actions/analyses.js +8 -0
  13. package/lib/common/components/shared/spinner/Spinner.js +34 -19
  14. package/lib/common/components/shared/spinner/theme.js +2 -5
  15. package/lib/common/reducers/analyses.js +13 -8
  16. package/lib/common/selectors/analyses.js +7 -1
  17. package/lib/reporting/components/resources/NewQuizAndItemAnalysis/ReportCard/presenter.js +79 -29
  18. package/lib/reporting/components/resources/NewQuizAndItemAnalysis/ReportCard/theme.js +4 -2
  19. package/lib/reporting/components/resources/NewQuizAndItemAnalysis/fetchReports.js +15 -12
  20. package/lib/reporting/components/resources/NewQuizAndItemAnalysis/fetchReportsStatus.js +59 -0
  21. package/lib/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisState.js +10 -2
  22. package/lib/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisStatePresenter.js +53 -12
  23. package/package.json +9 -9
@@ -1,4 +1,4 @@
1
- import { SET_QUIZ_ANALYSIS, SET_ITEM_ANALYSES, SET_ANALYSIS_FETCH_IN_PROGRESS, SET_ANALYSIS_GENERATION_IN_PROGRESS, SET_ANALYSIS_ERROR } from '@instructure/quiz-common';
1
+ import { SET_QUIZ_ANALYSIS, SET_ITEM_ANALYSES, SET_ANALYSIS_FETCH_IN_PROGRESS, SET_ANALYSIS_GENERATION_IN_PROGRESS, SET_ANALYSIS_ERROR, SET_STATUS_POLLING_IN_PROGRESS } from '@instructure/quiz-common';
2
2
  export function setQuizAnalysis(quizAnalysis) {
3
3
  return {
4
4
  type: SET_QUIZ_ANALYSIS,
@@ -17,6 +17,12 @@ export function setFetchInProgress(inProgress) {
17
17
  payload: inProgress
18
18
  };
19
19
  }
20
+ export function setStatusPollingInProgress(inProgress) {
21
+ return {
22
+ type: SET_STATUS_POLLING_IN_PROGRESS,
23
+ payload: inProgress
24
+ };
25
+ }
20
26
  export function setGenerationInProgress(inProgress) {
21
27
  return {
22
28
  type: SET_ANALYSIS_GENERATION_IN_PROGRESS,
@@ -7,20 +7,19 @@ var _dec, _class, _class2, _temp;
7
7
 
8
8
  import React, { Component } from 'react';
9
9
  import PropTypes from 'prop-types';
10
+ import { Text } from '@instructure/ui-text';
10
11
  import { Spinner } from '@instructure/ui-spinner';
11
- import { Heading } from '@instructure/ui-heading';
12
12
  import { PresentationContent } from '@instructure/ui-a11y-content';
13
13
  import { themeable } from '@instructure/ui-themeable';
14
14
  import t from '@instructure/quiz-i18n/es/format-message';
15
15
  var styles = {
16
- componentId: 'ebGcj',
16
+ componentId: 'cJgyM',
17
17
  template: function template(theme) {
18
- return "\n\n.ebGcj_gasz{align-items:center;display:inline-flex;flex:1 1 auto;height:100%;justify-content:center;min-height:500px;width:100%}\n\n:root .ebGcj_gasz,_:-ms-fullscreen{height:10rem}\n\n.ebGcj_bZBM .ebGcj_qrQc{flex:1 1 auto}\n\n.ebGcj_fBqo{font-size:".concat(theme.mainTextFontSize || 'inherit', "}");
18
+ return "\n\n.cJgyM_gasz{align-items:center;column-gap:10px;display:inline-flex;flex:1 1 auto;height:100%;justify-content:center;width:100%}\n\n:root .cJgyM_gasz,_:-ms-fullscreen{height:10rem}\n\n.cJgyM_bZBM .cJgyM_qrQc{flex:1 1 auto}";
19
19
  },
20
- 'wrapper': 'ebGcj_gasz',
21
- 'left': 'ebGcj_bZBM',
22
- 'right': 'ebGcj_qrQc',
23
- 'mainText': 'ebGcj_fBqo'
20
+ 'wrapper': 'cJgyM_gasz',
21
+ 'left': 'cJgyM_bZBM',
22
+ 'right': 'cJgyM_qrQc'
24
23
  };
25
24
  import theme from "./theme.js";
26
25
  export var QuizzesSpinner = (_dec = themeable(theme, styles), _dec(_class = (_temp = _class2 = /*#__PURE__*/function (_Component) {
@@ -37,34 +36,50 @@ export var QuizzesSpinner = (_dec = themeable(theme, styles), _dec(_class = (_te
37
36
  _createClass(QuizzesSpinner, [{
38
37
  key: "mainText",
39
38
  value: function mainText() {
40
- return this.props.mainText || t('Loading...');
39
+ var _this$props = this.props,
40
+ color = _this$props.color,
41
+ mainText = _this$props.mainText,
42
+ fontSize = _this$props.fontSize;
43
+ return /*#__PURE__*/React.createElement(Text, {
44
+ size: fontSize,
45
+ color: color
46
+ }, mainText || t('Loading...'));
41
47
  }
42
48
  }, {
43
49
  key: "render",
44
50
  value: function render() {
51
+ var _this$props2 = this.props,
52
+ size = _this$props2.size,
53
+ minHeight = _this$props2.minHeight;
45
54
  return /*#__PURE__*/React.createElement("div", {
46
- className: styles.wrapper
55
+ className: styles.wrapper,
56
+ style: {
57
+ minHeight: minHeight
58
+ }
47
59
  }, /*#__PURE__*/React.createElement("div", {
48
60
  className: styles.left
49
61
  }, /*#__PURE__*/React.createElement(Spinner, {
50
62
  renderTitle: this.mainText(),
51
- size: "large"
63
+ size: size
52
64
  })), /*#__PURE__*/React.createElement("div", {
53
65
  className: styles.right
54
- }, /*#__PURE__*/React.createElement(PresentationContent, null, /*#__PURE__*/React.createElement(Heading, {
55
- level: "h2",
56
- as: "h1"
57
- }, /*#__PURE__*/React.createElement("div", {
58
- className: styles.mainText
59
- }, this.mainText())))));
66
+ }, /*#__PURE__*/React.createElement(PresentationContent, null, this.mainText())));
60
67
  }
61
68
  }]);
62
69
 
63
70
  QuizzesSpinner.displayName = "QuizzesSpinner";
64
71
  return QuizzesSpinner;
65
72
  }(Component), _class2.propTypes = {
66
- mainText: PropTypes.string
73
+ mainText: PropTypes.string,
74
+ fontSize: PropTypes.oneOf(['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large']),
75
+ size: PropTypes.oneOf(['x-small', 'small', 'medium', 'large']),
76
+ color: PropTypes.string,
77
+ minHeight: PropTypes.string
67
78
  }, _class2.defaultProps = {
68
- mainText: null
79
+ mainText: null,
80
+ size: 'large',
81
+ fontSize: 'xx-large',
82
+ minHeight: '500px',
83
+ color: 'primary'
69
84
  }, _temp)) || _class);
70
85
  export default QuizzesSpinner;
@@ -1,6 +1,3 @@
1
- export default function generator(_ref) {
2
- var typography = _ref.typography;
3
- return {
4
- mainTextFontSize: typography.fontSizeXXLarge
5
- };
1
+ export default function generator() {
2
+ return {};
6
3
  }
@@ -1,17 +1,16 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
+
3
+ var _fromJS;
4
+
1
5
  import { fromJS } from 'immutable';
2
- import { SET_QUIZ_ANALYSIS, SET_ITEM_ANALYSES, SET_ANALYSIS_FETCH_IN_PROGRESS, SET_ANALYSIS_GENERATION_IN_PROGRESS, SET_ANALYSIS_ERROR } from '@instructure/quiz-common';
6
+ import { SET_QUIZ_ANALYSIS, SET_ITEM_ANALYSES, SET_ANALYSIS_FETCH_IN_PROGRESS, SET_ANALYSIS_GENERATION_IN_PROGRESS, SET_STATUS_POLLING_IN_PROGRESS, SET_ANALYSIS_ERROR } from '@instructure/quiz-common';
3
7
  export var quizAnalysisKey = 'quizAnalysis';
4
8
  export var itemAnalysesKey = 'itemAnalyses';
5
9
  export var fetchInProgressKey = 'fetchInProgress';
6
10
  export var generationInProgressKey = 'generationInProgress';
11
+ export var statusPollingInProgressKey = 'statusPollingInProgress';
7
12
  export var errorKey = 'analysisError';
8
- export var defaultState = fromJS({
9
- quizAnalysisKey: void 0,
10
- itemAnalysesKey: void 0,
11
- fetchStateKey: false,
12
- generationStateKey: false,
13
- errorKey: void 0
14
- });
13
+ export var defaultState = fromJS((_fromJS = {}, _defineProperty(_fromJS, quizAnalysisKey, void 0), _defineProperty(_fromJS, itemAnalysesKey, void 0), _defineProperty(_fromJS, fetchInProgressKey, false), _defineProperty(_fromJS, generationInProgressKey, false), _defineProperty(_fromJS, statusPollingInProgressKey, false), _defineProperty(_fromJS, errorKey, void 0), _fromJS));
15
14
  export default (function () {
16
15
  var state = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : defaultState;
17
16
  var action = arguments.length > 1 ? arguments[1] : void 0;
@@ -29,6 +28,9 @@ export default (function () {
29
28
  case SET_ANALYSIS_GENERATION_IN_PROGRESS:
30
29
  return state.set(generationInProgressKey, action.payload);
31
30
 
31
+ case SET_STATUS_POLLING_IN_PROGRESS:
32
+ return state.set(statusPollingInProgressKey, action.payload);
33
+
32
34
  case SET_ANALYSIS_ERROR:
33
35
  return state.set(errorKey, action.payload);
34
36
 
@@ -12,6 +12,9 @@ export var getItemAnalyses = function getItemAnalyses(state) {
12
12
  export var getFetchInProgress = function getFetchInProgress(state) {
13
13
  return state.getIn([path, 'fetchInProgress'], false);
14
14
  };
15
+ export var getStatusPollingInProgress = function getStatusPollingInProgress(state) {
16
+ return state.getIn([path, 'statusPollingInProgress'], false);
17
+ };
15
18
  export var getGenerationInProgress = function getGenerationInProgress(state) {
16
19
  return state.getIn([path, 'generationInProgress'], false);
17
20
  };
@@ -14,22 +14,22 @@ import { Flex } from '@instructure/ui-flex';
14
14
  import { themeable } from '@instructure/ui-themeable';
15
15
  import Card from "../../../../../common/components/shared/Card/index.js";
16
16
  var styles = {
17
- componentId: 'eJSiT',
17
+ componentId: 'boQPo',
18
18
  template: function template(theme) {
19
- return "\n\n.eJSiT_bqdH{column-gap:5px;display:flex;justify-content:space-between;padding:".concat(theme.metricsPadding || 'inherit', " 0}\n\n.eJSiT_fbIL{border-radius:").concat(theme.cardBorderRadius || 'inherit', ";box-shadow:").concat(theme.cardBoxShadow || 'inherit', ";display:inline-flex;flex-direction:column;margin:").concat(theme.cardMargin || 'inherit', ";padding:").concat(theme.cardPadding || 'inherit', ";width:").concat(theme.cardWidth || 'inherit', "}\n\n.eJSiT_blRb{max-width:160px;padding-right:10px}");
19
+ return "\n\n.boQPo_bqdH{column-gap:5px;display:flex;justify-content:space-between;padding-bottom:".concat(theme.metricsPadding || 'inherit', "}\n\n.boQPo_PFlN{border-radius:").concat(theme.cardBorderRadius || 'inherit', ";box-shadow:").concat(theme.cardBoxShadow || 'inherit', ";display:inline-flex;flex-direction:column;margin:").concat(theme.cardMargin || 'inherit', ";padding:").concat(theme.cardPadding || 'inherit', ";width:").concat(theme.cardWidth || 'inherit', "}\n\n.boQPo_blRb{max-width:160px;padding-right:10px}\n\n.boQPo_bxzy{border-bottom:1px solid ").concat(theme.quizSummaryBorderBottomColor || 'inherit', ";margin-bottom:15px;padding-bottom:15px}\n\n.boQPo_dKIc{padding-bottom:15px}\n\n.boQPo_cGHR{align-self:flex-end}");
20
20
  },
21
- 'metricsContainer': 'eJSiT_bqdH',
22
- 'card': 'eJSiT_fbIL',
23
- 'dateContainer': 'eJSiT_blRb'
21
+ 'metricsContainer': 'boQPo_bqdH',
22
+ 'reportCard': 'boQPo_PFlN',
23
+ 'dateContainer': 'boQPo_blRb',
24
+ 'quizAnalysisSummary': 'boQPo_bxzy',
25
+ 'titleContainer': 'boQPo_dKIc',
26
+ 'spinnerContainer': 'boQPo_cGHR'
24
27
  };
25
28
  import theme from "./theme.js";
26
29
  import AnalysisMetric from "../AnalysisMetric/index.js";
27
30
  import Spinner from "../../../../../common/components/shared/spinner/Spinner.js";
28
31
  import { AnalysisUpdateDate } from "../AnalysisUpdateDate/index.js";
29
- import { quizAnalysisPropType } from "../propTypes.js";
30
-
31
- var _ref = /*#__PURE__*/React.createElement(Spinner, null);
32
-
32
+ import { itemAnalysisPropType, quizAnalysisPropType } from "../propTypes.js";
33
33
  export var NewQuizAndItemAnalysisReportCardPresenter = (_dec = themeable(theme, styles), _dec(_class = (_temp = _class2 = /*#__PURE__*/function (_Component) {
34
34
  _inherits(NewQuizAndItemAnalysisReportCardPresenter, _Component);
35
35
 
@@ -70,20 +70,14 @@ export var NewQuizAndItemAnalysisReportCardPresenter = (_dec = themeable(theme,
70
70
  }));
71
71
  };
72
72
 
73
- return _this;
74
- }
75
-
76
- _createClass(NewQuizAndItemAnalysisReportCardPresenter, [{
77
- key: "renderContent",
78
- value: function renderContent() {
79
- var _this$props = this.props,
80
- name = _this$props.name,
81
- href = _this$props.href,
82
- quizAnalysis = _this$props.quizAnalysis;
83
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
84
- size: "medium",
85
- weight: "bold"
86
- }, name), this.renderMetrics(), /*#__PURE__*/React.createElement(Flex, {
73
+ _this.renderQuizAnalysisSummary = function () {
74
+ var _this$props = _this.props,
75
+ quizAnalysis = _this$props.quizAnalysis,
76
+ itemAnalyses = _this$props.itemAnalyses,
77
+ href = _this$props.href;
78
+ return /*#__PURE__*/React.createElement("div", {
79
+ className: styles.quizAnalysisSummary
80
+ }, _this.renderMetrics(), /*#__PURE__*/React.createElement(Flex, {
87
81
  direction: "row",
88
82
  justifyItems: "space-between"
89
83
  }, /*#__PURE__*/React.createElement("div", {
@@ -91,18 +85,66 @@ export var NewQuizAndItemAnalysisReportCardPresenter = (_dec = themeable(theme,
91
85
  }, /*#__PURE__*/React.createElement(AnalysisUpdateDate, {
92
86
  date: quizAnalysis.created_timestamp,
93
87
  multiline: true
94
- })), /*#__PURE__*/React.createElement(Link, {
88
+ })), quizAnalysis && itemAnalyses && /*#__PURE__*/React.createElement(Link, {
95
89
  href: href
96
90
  }, /*#__PURE__*/React.createElement(Text, {
97
91
  size: "small"
98
92
  }, t('View Report')))));
99
- }
100
- }, {
93
+ };
94
+
95
+ _this.renderSpinner = function (mainText) {
96
+ return /*#__PURE__*/React.createElement(Spinner, {
97
+ size: "x-small",
98
+ color: "brand",
99
+ minHeight: "0",
100
+ mainText: mainText,
101
+ fontSize: "x-small"
102
+ });
103
+ };
104
+
105
+ _this.renderReportCardFooter = function () {
106
+ var _this$props2 = _this.props,
107
+ generationInProgress = _this$props2.generationInProgress,
108
+ generateReports = _this$props2.generateReports,
109
+ analysisError = _this$props2.analysisError;
110
+ return /*#__PURE__*/React.createElement(Flex, {
111
+ direction: "row",
112
+ justifyItems: "space-between"
113
+ }, /*#__PURE__*/React.createElement(Flex.Item, {
114
+ shouldShrink: true
115
+ }, analysisError && !generationInProgress && /*#__PURE__*/React.createElement(Text, {
116
+ size: "x-small",
117
+ lineHeight: "fit",
118
+ weight: "bold",
119
+ color: "danger"
120
+ }, analysisError)), /*#__PURE__*/React.createElement(Flex.Item, null, generationInProgress ? _this.renderSpinner(t('Generation In Progress')) : /*#__PURE__*/React.createElement(Link, {
121
+ onClick: generateReports,
122
+ role: "button"
123
+ }, /*#__PURE__*/React.createElement(Text, {
124
+ size: "small"
125
+ }, t('Generate Report')))));
126
+ };
127
+
128
+ return _this;
129
+ }
130
+
131
+ _createClass(NewQuizAndItemAnalysisReportCardPresenter, [{
101
132
  key: "render",
102
133
  value: function render() {
134
+ var _this$props3 = this.props,
135
+ fetchInProgress = _this$props3.fetchInProgress,
136
+ name = _this$props3.name,
137
+ quizAnalysis = _this$props3.quizAnalysis;
103
138
  return /*#__PURE__*/React.createElement(Card, {
104
- className: styles.card
105
- }, this.props.quizAnalysis ? this.renderContent() : _ref);
139
+ className: styles.reportCard
140
+ }, /*#__PURE__*/React.createElement("div", {
141
+ className: styles.titleContainer
142
+ }, /*#__PURE__*/React.createElement(Text, {
143
+ size: "medium",
144
+ weight: "bold"
145
+ }, name)), !fetchInProgress && quizAnalysis && this.renderQuizAnalysisSummary(), fetchInProgress && /*#__PURE__*/React.createElement("div", {
146
+ className: styles.spinnerContainer
147
+ }, this.renderSpinner()), !fetchInProgress && this.renderReportCardFooter());
106
148
  }
107
149
  }]);
108
150
 
@@ -111,9 +153,17 @@ export var NewQuizAndItemAnalysisReportCardPresenter = (_dec = themeable(theme,
111
153
  }(Component), _class2.propTypes = {
112
154
  name: PropTypes.node,
113
155
  href: PropTypes.string,
114
- quizAnalysis: quizAnalysisPropType
156
+ quizAnalysis: quizAnalysisPropType,
157
+ itemAnalyses: PropTypes.arrayOf(itemAnalysisPropType),
158
+ fetchInProgress: PropTypes.bool.isRequired,
159
+ generationInProgress: PropTypes.bool.isRequired,
160
+ analysisError: PropTypes.string,
161
+ generateReports: PropTypes.func.isRequired
115
162
  }, _class2.defaultProps = {
116
163
  name: void 0,
117
164
  href: void 0,
118
- quizAnalysis: void 0
165
+ analysisError: void 0,
166
+ generationInProgress: void 0,
167
+ quizAnalysis: void 0,
168
+ itemAnalyses: void 0
119
169
  }, _temp)) || _class);
@@ -1,12 +1,14 @@
1
1
  export default function generator(_ref) {
2
2
  var spacing = _ref.spacing,
3
- borders = _ref.borders;
3
+ borders = _ref.borders,
4
+ colors = _ref.colors;
4
5
  return {
5
6
  metricsPadding: spacing.medium,
6
7
  cardWidth: '16rem',
7
8
  cardPadding: spacing.medium,
8
9
  cardMargin: spacing.xSmall,
9
10
  cardBoxShadow: '1px 1px 3px 0 #ddd',
10
- cardBorderRadius: borders.radiusMedium
11
+ cardBorderRadius: borders.radiusMedium,
12
+ quizSummaryBorderBottomColor: colors.tiara
11
13
  };
12
14
  }
@@ -4,13 +4,13 @@ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
4
4
  import { getFailedToFetchReports, getLastReportGenerationFailed } from "./errorMessages.js";
5
5
  export var fetchReports = /*#__PURE__*/function () {
6
6
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
7
- var activeQuizId, setFetchInProgress, setQuizAnalysis, setItemAnalyses, setAnalysisError, setGenerationInProgress, addError, fetchQuizAnalysis, fetchItemAnalyses, _yield$Promise$all, _yield$Promise$all2, quizAnalysis, itemAnalyses;
7
+ var activeQuizId, setFetchInProgress, setQuizAnalysis, setItemAnalyses, setStatusPollingInProgress, setAnalysisError, setGenerationInProgress, addError, fetchQuizAnalysis, fetchItemAnalyses, _yield$Promise$all, _yield$Promise$all2, quizAnalysis, itemAnalyses, areAnalysesInProgress, areAnalysesFailed;
8
8
 
9
9
  return _regeneratorRuntime.wrap(function _callee$(_context) {
10
10
  while (1) {
11
11
  switch (_context.prev = _context.next) {
12
12
  case 0:
13
- activeQuizId = _ref.activeQuizId, setFetchInProgress = _ref.setFetchInProgress, setQuizAnalysis = _ref.setQuizAnalysis, setItemAnalyses = _ref.setItemAnalyses, setAnalysisError = _ref.setAnalysisError, setGenerationInProgress = _ref.setGenerationInProgress, addError = _ref.addError, fetchQuizAnalysis = _ref.fetchQuizAnalysis, fetchItemAnalyses = _ref.fetchItemAnalyses;
13
+ activeQuizId = _ref.activeQuizId, setFetchInProgress = _ref.setFetchInProgress, setQuizAnalysis = _ref.setQuizAnalysis, setItemAnalyses = _ref.setItemAnalyses, setStatusPollingInProgress = _ref.setStatusPollingInProgress, setAnalysisError = _ref.setAnalysisError, setGenerationInProgress = _ref.setGenerationInProgress, addError = _ref.addError, fetchQuizAnalysis = _ref.fetchQuizAnalysis, fetchItemAnalyses = _ref.fetchItemAnalyses;
14
14
  _context.prev = 1;
15
15
  setFetchInProgress(true);
16
16
  _context.next = 5;
@@ -21,33 +21,36 @@ export var fetchReports = /*#__PURE__*/function () {
21
21
  _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
22
22
  quizAnalysis = _yield$Promise$all2[0];
23
23
  itemAnalyses = _yield$Promise$all2[1];
24
+ areAnalysesInProgress = quizAnalysis.new_analysis_in_progress || itemAnalyses.new_analysis_in_progress;
25
+ areAnalysesFailed = quizAnalysis.last_analysis_failed || itemAnalyses.last_analysis_failed;
26
+ setGenerationInProgress(areAnalysesInProgress);
27
+ setStatusPollingInProgress(areAnalysesInProgress);
24
28
  setQuizAnalysis(quizAnalysis.last_successful_analysis);
25
29
  setItemAnalyses(itemAnalyses.last_successful_analysis);
26
- setGenerationInProgress(quizAnalysis.new_analysis_in_progress || itemAnalyses.new_analysis_in_progress);
27
30
 
28
- if (quizAnalysis.last_analysis_failed || itemAnalyses.last_analysis_failed) {
31
+ if (areAnalysesFailed) {
29
32
  setAnalysisError(getLastReportGenerationFailed());
30
33
  }
31
34
 
32
- _context.next = 18;
35
+ _context.next = 21;
33
36
  break;
34
37
 
35
- case 15:
36
- _context.prev = 15;
38
+ case 18:
39
+ _context.prev = 18;
37
40
  _context.t0 = _context["catch"](1);
38
41
  addError(getFailedToFetchReports());
39
42
 
40
- case 18:
41
- _context.prev = 18;
43
+ case 21:
44
+ _context.prev = 21;
42
45
  setFetchInProgress(false);
43
- return _context.finish(18);
46
+ return _context.finish(21);
44
47
 
45
- case 21:
48
+ case 24:
46
49
  case "end":
47
50
  return _context.stop();
48
51
  }
49
52
  }
50
- }, _callee, null, [[1, 15, 18, 21]]);
53
+ }, _callee, null, [[1, 18, 21, 24]]);
51
54
  }));
52
55
 
53
56
  return function fetchReports(_x) {
@@ -0,0 +1,45 @@
1
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
+ import { getFailedToFetchReports } from "./errorMessages.js";
4
+ export var fetchReportsStatus = /*#__PURE__*/function () {
5
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
6
+ var activeQuizId, addError, fetchAnalysesStatus, instrumentedFetchReports, setStatusPollingInProgress, setGenerationInProgress, status, isReportGenerationReady;
7
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
8
+ while (1) {
9
+ switch (_context.prev = _context.next) {
10
+ case 0:
11
+ activeQuizId = _ref.activeQuizId, addError = _ref.addError, fetchAnalysesStatus = _ref.fetchAnalysesStatus, instrumentedFetchReports = _ref.instrumentedFetchReports, setStatusPollingInProgress = _ref.setStatusPollingInProgress, setGenerationInProgress = _ref.setGenerationInProgress;
12
+ _context.prev = 1;
13
+ _context.next = 4;
14
+ return fetchAnalysesStatus(activeQuizId);
15
+
16
+ case 4:
17
+ status = _context.sent;
18
+ isReportGenerationReady = !status.quiz_analysis_in_progress && !status.item_analyses_in_progress;
19
+
20
+ if (isReportGenerationReady) {
21
+ instrumentedFetchReports();
22
+ }
23
+
24
+ _context.next = 14;
25
+ break;
26
+
27
+ case 9:
28
+ _context.prev = 9;
29
+ _context.t0 = _context["catch"](1);
30
+ addError(getFailedToFetchReports());
31
+ setStatusPollingInProgress(false);
32
+ setGenerationInProgress(false);
33
+
34
+ case 14:
35
+ case "end":
36
+ return _context.stop();
37
+ }
38
+ }
39
+ }, _callee, null, [[1, 9]]);
40
+ }));
41
+
42
+ return function fetchReportsStatus(_x) {
43
+ return _ref2.apply(this, arguments);
44
+ };
45
+ }();
@@ -1,22 +1,27 @@
1
1
  import { withAnalysisStatePresenter } from "./withAnalysisStatePresenter.js";
2
- import { getQuizAnalysis, getItemAnalyses, getFetchInProgress, getGenerationInProgress, getAnalysisError } from "../../../../common/selectors/analyses.js";
3
- import { setQuizAnalysis, setItemAnalyses, setFetchInProgress, setGenerationInProgress, setAnalysisError } from "../../../../common/actions/analyses.js";
2
+ import { getQuizAnalysis, getItemAnalyses, getFetchInProgress, getGenerationInProgress, getAnalysisError, getStatusPollingInProgress } from "../../../../common/selectors/analyses.js";
3
+ import { setQuizAnalysis, setItemAnalyses, setFetchInProgress, setGenerationInProgress, setAnalysisError, setStatusPollingInProgress } from "../../../../common/actions/analyses.js";
4
4
  import { getQuizAnalysis as fetchQuizAnalysis } from "../../../api/getQuizAnalysis.js";
5
5
  import { getItemAnalyses as fetchItemAnalyses } from "../../../api/getItemAnalyses.js";
6
+ import { getAnalysesStatus as fetchAnalysesStatus } from "../../../api/getAnalysesStatus.js";
6
7
  import { connect } from "../../../../common/react-redux.js";
7
8
  import { compose } from 'redux';
8
9
  import { getActiveQuizId } from "../../../../common/selectors/quizzes.js";
9
10
  import { addError } from "../../../../common/actions/alerts.js";
11
+ var DEFAULT_POLLING_INTERVAL = 3000;
10
12
  export function mapStateToProps(state, ownProps) {
11
13
  return {
12
14
  quizAnalysis: getQuizAnalysis(state),
13
15
  itemAnalyses: getItemAnalyses(state),
14
16
  fetchInProgress: getFetchInProgress(state),
15
17
  generationInProgress: getGenerationInProgress(state),
18
+ statusPollingInProgress: getStatusPollingInProgress(state),
16
19
  analysisError: getAnalysisError(state),
17
20
  activeQuizId: ownProps.activeQuizId || getActiveQuizId(state),
18
21
  fetchQuizAnalysis: fetchQuizAnalysis,
19
- fetchItemAnalyses: fetchItemAnalyses
22
+ fetchItemAnalyses: fetchItemAnalyses,
23
+ fetchAnalysesStatus: fetchAnalysesStatus,
24
+ pollingInterval: ownProps.pollingInterval || DEFAULT_POLLING_INTERVAL
20
25
  };
21
26
  }
22
27
  var mapDispatchToProps = {
@@ -25,7 +30,8 @@ var mapDispatchToProps = {
25
30
  setFetchInProgress: setFetchInProgress,
26
31
  setGenerationInProgress: setGenerationInProgress,
27
32
  setAnalysisError: setAnalysisError,
28
- addError: addError
33
+ addError: addError,
34
+ setStatusPollingInProgress: setStatusPollingInProgress
29
35
  };
30
36
  export var withAnalysisState = compose(connect(mapStateToProps, mapDispatchToProps), withAnalysisStatePresenter);
31
37
  export default withAnalysisState;
@@ -1,10 +1,11 @@
1
1
  import _regeneratorRuntime from "@babel/runtime/regenerator";
2
2
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
3
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
4
- import React, { useEffect } from 'react';
4
+ import React, { useEffect, useRef } from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import { itemAnalysisPropType, quizAnalysisPropType } from "./propTypes.js";
7
7
  import { fetchReports } from "./fetchReports.js";
8
+ import { fetchReportsStatus } from "./fetchReportsStatus.js";
8
9
  export var withAnalysisStatePresenter = function withAnalysisStatePresenter(OriginalComponent) {
9
10
  var WithAnalysisStatePresenter = function WithAnalysisStatePresenter(_ref) {
10
11
  var quizAnalysis = _ref.quizAnalysis,
@@ -22,19 +23,39 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
22
23
  generateReport = _ref.generateReport,
23
24
  fetchQuizAnalysis = _ref.fetchQuizAnalysis,
24
25
  fetchItemAnalyses = _ref.fetchItemAnalyses,
25
- passThroughProps = _objectWithoutProperties(_ref, ["quizAnalysis", "itemAnalyses", "fetchInProgress", "generationInProgress", "analysisError", "setQuizAnalysis", "addError", "setItemAnalyses", "setFetchInProgress", "setGenerationInProgress", "setAnalysisError", "activeQuizId", "generateReport", "fetchQuizAnalysis", "fetchItemAnalyses"]);
26
+ fetchAnalysesStatus = _ref.fetchAnalysesStatus,
27
+ statusPollingInProgress = _ref.statusPollingInProgress,
28
+ setStatusPollingInProgress = _ref.setStatusPollingInProgress,
29
+ pollingInterval = _ref.pollingInterval,
30
+ passThroughProps = _objectWithoutProperties(_ref, ["quizAnalysis", "itemAnalyses", "fetchInProgress", "generationInProgress", "analysisError", "setQuizAnalysis", "addError", "setItemAnalyses", "setFetchInProgress", "setGenerationInProgress", "setAnalysisError", "activeQuizId", "generateReport", "fetchQuizAnalysis", "fetchItemAnalyses", "fetchAnalysesStatus", "statusPollingInProgress", "setStatusPollingInProgress", "pollingInterval"]);
26
31
 
27
32
  WithAnalysisStatePresenter.displayName = "WithAnalysisStatePresenter(".concat(OriginalComponent.displayName || OriginalComponent.name, ")");
28
- var reportFetchingConfig = {
29
- activeQuizId: activeQuizId,
30
- addError: addError,
31
- fetchQuizAnalysis: fetchQuizAnalysis,
32
- fetchItemAnalyses: fetchItemAnalyses,
33
- setAnalysisError: setAnalysisError,
34
- setItemAnalyses: setItemAnalyses,
35
- setGenerationInProgress: setGenerationInProgress,
36
- setFetchInProgress: setFetchInProgress,
37
- setQuizAnalysis: setQuizAnalysis
33
+ var runningInterval = useRef(null);
34
+
35
+ var instrumentedFetchReports = function instrumentedFetchReports() {
36
+ return fetchReports({
37
+ activeQuizId: activeQuizId,
38
+ addError: addError,
39
+ fetchQuizAnalysis: fetchQuizAnalysis,
40
+ fetchItemAnalyses: fetchItemAnalyses,
41
+ setAnalysisError: setAnalysisError,
42
+ setStatusPollingInProgress: setStatusPollingInProgress,
43
+ setItemAnalyses: setItemAnalyses,
44
+ setGenerationInProgress: setGenerationInProgress,
45
+ setFetchInProgress: setFetchInProgress,
46
+ setQuizAnalysis: setQuizAnalysis
47
+ });
48
+ };
49
+
50
+ var instrumentedStatusFetching = function instrumentedStatusFetching() {
51
+ return fetchReportsStatus({
52
+ activeQuizId: activeQuizId,
53
+ addError: addError,
54
+ setGenerationInProgress: setGenerationInProgress,
55
+ setStatusPollingInProgress: setStatusPollingInProgress,
56
+ fetchAnalysesStatus: fetchAnalysesStatus,
57
+ instrumentedFetchReports: instrumentedFetchReports
58
+ });
38
59
  };
39
60
 
40
61
  function generateReports() {
@@ -72,7 +93,7 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
72
93
  }
73
94
 
74
95
  _context.next = 4;
75
- return fetchReports(reportFetchingConfig);
96
+ return instrumentedFetchReports();
76
97
 
77
98
  case 4:
78
99
  case "end":
@@ -89,6 +110,21 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
89
110
 
90
111
  fetchIfNeeded();
91
112
  }, []);
113
+ useEffect(function () {
114
+ if (statusPollingInProgress && !runningInterval.current) {
115
+ runningInterval.current = setInterval(instrumentedStatusFetching, pollingInterval);
116
+ }
117
+
118
+ if (!statusPollingInProgress && runningInterval.current) {
119
+ clearInterval(runningInterval.current);
120
+ runningInterval.current = null;
121
+ } // unmount cleanup
122
+
123
+
124
+ return function () {
125
+ return clearInterval(runningInterval.current);
126
+ };
127
+ }, [statusPollingInProgress]);
92
128
  return /*#__PURE__*/React.createElement(OriginalComponent, Object.assign({
93
129
  quizAnalysis: quizAnalysis,
94
130
  itemAnalyses: itemAnalyses,
@@ -104,16 +140,20 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
104
140
  itemAnalyses: PropTypes.arrayOf(itemAnalysisPropType),
105
141
  fetchInProgress: PropTypes.bool.isRequired,
106
142
  generationInProgress: PropTypes.bool.isRequired,
143
+ statusPollingInProgress: PropTypes.bool.isRequired,
107
144
  analysisError: PropTypes.string,
108
145
  setQuizAnalysis: PropTypes.func.isRequired,
109
146
  setItemAnalyses: PropTypes.func.isRequired,
110
147
  setFetchInProgress: PropTypes.func.isRequired,
111
148
  setGenerationInProgress: PropTypes.func.isRequired,
112
149
  setAnalysisError: PropTypes.func.isRequired,
150
+ setStatusPollingInProgress: PropTypes.func.isRequired,
113
151
  activeQuizId: PropTypes.string.isRequired,
114
152
  fetchQuizAnalysis: PropTypes.func.isRequired,
115
153
  fetchItemAnalyses: PropTypes.func.isRequired,
154
+ fetchAnalysesStatus: PropTypes.func.isRequired,
116
155
  addError: PropTypes.func.isRequired,
156
+ pollingInterval: PropTypes.number.isRequired,
117
157
  // can be required after passed from LTI
118
158
  generateReport: PropTypes.func
119
159
  };
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.setQuizAnalysis = setQuizAnalysis;
7
7
  exports.setItemAnalyses = setItemAnalyses;
8
8
  exports.setFetchInProgress = setFetchInProgress;
9
+ exports.setStatusPollingInProgress = setStatusPollingInProgress;
9
10
  exports.setGenerationInProgress = setGenerationInProgress;
10
11
  exports.setAnalysisError = setAnalysisError;
11
12
 
@@ -32,6 +33,13 @@ function setFetchInProgress(inProgress) {
32
33
  };
33
34
  }
34
35
 
36
+ function setStatusPollingInProgress(inProgress) {
37
+ return {
38
+ type: _quizCommon.SET_STATUS_POLLING_IN_PROGRESS,
39
+ payload: inProgress
40
+ };
41
+ }
42
+
35
43
  function setGenerationInProgress(inProgress) {
36
44
  return {
37
45
  type: _quizCommon.SET_ANALYSIS_GENERATION_IN_PROGRESS,