@instructure/quiz-core 18.5.1-rc.7 → 18.5.1-rc.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/NewQuizAnalysis/presenter.js +20 -1
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/charts/ScoreDistribution/presenter.js +16 -3
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/errorMessages.js +3 -0
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/exportReports.js +65 -0
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/propTypes.js +8 -3
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/utils.js +4 -0
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisState.js +2 -0
- package/es/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisStatePresenter.js +41 -1
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/NewQuizAnalysis/presenter.js +20 -1
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/charts/ScoreDistribution/presenter.js +16 -3
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/errorMessages.js +7 -1
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/exportReports.js +80 -0
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/propTypes.js +12 -4
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/utils.js +10 -2
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisState.js +3 -0
- package/lib/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisStatePresenter.js +43 -1
- package/package.json +10 -9
package/es/reporting/components/resources/NewQuizAndItemAnalysis/NewQuizAnalysis/presenter.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
1
2
|
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
2
3
|
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
3
4
|
import _inherits from "@babel/runtime/helpers/esm/inherits";
|
|
@@ -120,7 +121,7 @@ export var NewQuizAnalysis = (_dec = themeable(theme, styles), _dec(_class = (_t
|
|
|
120
121
|
title: expanded ? t('collapse quiz analysis') : t('expand quiz analysis'),
|
|
121
122
|
isExpanded: expanded
|
|
122
123
|
}))), expanded && _this.renderExpanded(), /*#__PURE__*/React.createElement(ScoreDistribution, {
|
|
123
|
-
decileDistribution:
|
|
124
|
+
decileDistribution: _this.getPreparedDecileDistribution()
|
|
124
125
|
}));
|
|
125
126
|
};
|
|
126
127
|
|
|
@@ -128,6 +129,24 @@ export var NewQuizAnalysis = (_dec = themeable(theme, styles), _dec(_class = (_t
|
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
_createClass(NewQuizAnalysis, [{
|
|
132
|
+
key: "getPreparedDecileDistribution",
|
|
133
|
+
value: function getPreparedDecileDistribution() {
|
|
134
|
+
var quizAnalysis = this.props.quizAnalysis;
|
|
135
|
+
var scores = quizAnalysis.scores,
|
|
136
|
+
metadata = quizAnalysis.metadata;
|
|
137
|
+
|
|
138
|
+
var decileDistribution = _toConsumableArray(scores === null || scores === void 0 ? void 0 : scores.decile_distribution);
|
|
139
|
+
|
|
140
|
+
if (metadata.decile_distribution && (metadata.decile_distribution.high_extreme_values_count > 0 || metadata.decile_distribution.low_extreme_values_count > 0)) {
|
|
141
|
+
var _metadata$decile_dist, _metadata$decile_dist2;
|
|
142
|
+
|
|
143
|
+
decileDistribution.unshift((_metadata$decile_dist = metadata.decile_distribution) === null || _metadata$decile_dist === void 0 ? void 0 : _metadata$decile_dist.low_extreme_values_count);
|
|
144
|
+
decileDistribution.push((_metadata$decile_dist2 = metadata.decile_distribution) === null || _metadata$decile_dist2 === void 0 ? void 0 : _metadata$decile_dist2.high_extreme_values_count);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return decileDistribution;
|
|
148
|
+
}
|
|
149
|
+
}, {
|
|
131
150
|
key: "render",
|
|
132
151
|
value: function render() {
|
|
133
152
|
var fetchInProgress = this.props.fetchInProgress;
|
|
@@ -39,7 +39,19 @@ export var ScoreDistribution = (_dec = themeable(theme, styles), _dec(_class = (
|
|
|
39
39
|
|
|
40
40
|
_this = _super.call.apply(_super, [this].concat(args));
|
|
41
41
|
|
|
42
|
-
_this.
|
|
42
|
+
_this.calculateLabelForColumnsWithExtremeValues = function (index, length) {
|
|
43
|
+
if (index === 0) {
|
|
44
|
+
return t('< 0%');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (index === length - 1) {
|
|
48
|
+
return t('> 100%');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return _this.calculateLabelForColumns(index - 1, length - 2);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
_this.calculateLabelForColumns = function (index, length) {
|
|
43
55
|
var label = Math.floor(index * 100 / length);
|
|
44
56
|
return t('{label, number}%', {
|
|
45
57
|
label: label
|
|
@@ -52,6 +64,7 @@ export var ScoreDistribution = (_dec = themeable(theme, styles), _dec(_class = (
|
|
|
52
64
|
_createClass(ScoreDistribution, [{
|
|
53
65
|
key: "render",
|
|
54
66
|
value: function render() {
|
|
67
|
+
var decileDistribution = this.props.decileDistribution;
|
|
55
68
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
56
69
|
className: styles.headingContainer
|
|
57
70
|
}, /*#__PURE__*/React.createElement(Heading, {
|
|
@@ -62,8 +75,8 @@ export var ScoreDistribution = (_dec = themeable(theme, styles), _dec(_class = (
|
|
|
62
75
|
}, t('Score Distribution'))), /*#__PURE__*/React.createElement(QuintileDistribution, {
|
|
63
76
|
animateDelay: 1000,
|
|
64
77
|
animateDuration: 1000,
|
|
65
|
-
visualDistribution:
|
|
66
|
-
calculateLabelForColumn: this.
|
|
78
|
+
visualDistribution: decileDistribution || [],
|
|
79
|
+
calculateLabelForColumn: decileDistribution.length > 10 ? this.calculateLabelForColumnsWithExtremeValues : this.calculateLabelForColumns
|
|
67
80
|
}), /*#__PURE__*/React.createElement("div", {
|
|
68
81
|
"aria-hidden": "true",
|
|
69
82
|
className: styles.chartLabel
|
|
@@ -2,6 +2,9 @@ import t from '@instructure/quiz-i18n/es/format-message';
|
|
|
2
2
|
export var getFailedToFetchReports = function getFailedToFetchReports() {
|
|
3
3
|
return t('An error has occurred while loading this report. Please refresh the page.');
|
|
4
4
|
};
|
|
5
|
+
export var getFailedToExportReports = function getFailedToExportReports() {
|
|
6
|
+
return t('An error has occurred while exporting this report. Please try again.');
|
|
7
|
+
};
|
|
5
8
|
export var getLastReportGenerationFailed = function getLastReportGenerationFailed() {
|
|
6
9
|
return t('Report generation failed. Please try again.');
|
|
7
10
|
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
2
|
+
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
3
|
+
import { getFailedToExportReports } from "./errorMessages.js";
|
|
4
|
+
import contentDisposition from 'content-disposition';
|
|
5
|
+
export var exportReports = /*#__PURE__*/function () {
|
|
6
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
|
|
7
|
+
var getAnalysesExport, activeQuizId, filter, format, saveFile, addError, response, dispositionHeader, disposition, filename, blob;
|
|
8
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
9
|
+
while (1) {
|
|
10
|
+
switch (_context.prev = _context.next) {
|
|
11
|
+
case 0:
|
|
12
|
+
getAnalysesExport = _ref.getAnalysesExport, activeQuizId = _ref.activeQuizId, filter = _ref.filter, format = _ref.format, saveFile = _ref.saveFile, addError = _ref.addError;
|
|
13
|
+
_context.prev = 1;
|
|
14
|
+
_context.next = 4;
|
|
15
|
+
return getAnalysesExport(activeQuizId, format, filter);
|
|
16
|
+
|
|
17
|
+
case 4:
|
|
18
|
+
response = _context.sent;
|
|
19
|
+
dispositionHeader = response.headers.get('Content-Disposition');
|
|
20
|
+
|
|
21
|
+
if (dispositionHeader) {
|
|
22
|
+
_context.next = 8;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
throw new Error('Response contains no Content-Disposition header.');
|
|
27
|
+
|
|
28
|
+
case 8:
|
|
29
|
+
disposition = contentDisposition.parse(dispositionHeader);
|
|
30
|
+
filename = disposition.parameters.filename;
|
|
31
|
+
|
|
32
|
+
if (filename) {
|
|
33
|
+
_context.next = 12;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
throw new Error('Cannot determine filename to save.');
|
|
38
|
+
|
|
39
|
+
case 12:
|
|
40
|
+
_context.next = 14;
|
|
41
|
+
return response.blob();
|
|
42
|
+
|
|
43
|
+
case 14:
|
|
44
|
+
blob = _context.sent;
|
|
45
|
+
saveFile(blob, filename);
|
|
46
|
+
_context.next = 21;
|
|
47
|
+
break;
|
|
48
|
+
|
|
49
|
+
case 18:
|
|
50
|
+
_context.prev = 18;
|
|
51
|
+
_context.t0 = _context["catch"](1);
|
|
52
|
+
addError(getFailedToExportReports());
|
|
53
|
+
|
|
54
|
+
case 21:
|
|
55
|
+
case "end":
|
|
56
|
+
return _context.stop();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}, _callee, null, [[1, 18]]);
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
return function exportReports(_x) {
|
|
63
|
+
return _ref2.apply(this, arguments);
|
|
64
|
+
};
|
|
65
|
+
}();
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
|
+
export var quizAnalysisMetadata = PropTypes.shape({
|
|
3
|
+
quiz_title: PropTypes.string,
|
|
4
|
+
decile_distribution: PropTypes.shape({
|
|
5
|
+
high_extreme_values_count: PropTypes.number,
|
|
6
|
+
low_extreme_values_count: PropTypes.number
|
|
7
|
+
})
|
|
8
|
+
});
|
|
2
9
|
export var quizAnalysisPropType = PropTypes.shape({
|
|
3
10
|
created_timestamp: PropTypes.string.isRequired,
|
|
4
|
-
metadata:
|
|
5
|
-
quiz_title: PropTypes.string
|
|
6
|
-
}).isRequired,
|
|
11
|
+
metadata: quizAnalysisMetadata.isRequired,
|
|
7
12
|
scores: PropTypes.shape({
|
|
8
13
|
decile_distribution: PropTypes.arrayOf(PropTypes.number),
|
|
9
14
|
cronbachs_alpha: PropTypes.number,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import t from '@instructure/quiz-i18n/es/format-message';
|
|
2
|
+
import { saveAs } from 'file-saver';
|
|
2
3
|
|
|
3
4
|
var formatNumbers = function formatNumbers(value) {
|
|
4
5
|
if (typeof value === 'number') {
|
|
@@ -17,4 +18,7 @@ var getSanitizedMetricValue = function getSanitizedMetricValue(value, suffix) {
|
|
|
17
18
|
return suffix ? formattedValue + suffix : formattedValue;
|
|
18
19
|
};
|
|
19
20
|
|
|
21
|
+
export var saveFile = function saveFile(file, fileName) {
|
|
22
|
+
saveAs(file, fileName);
|
|
23
|
+
};
|
|
20
24
|
export { getSanitizedMetricValue };
|
|
@@ -4,6 +4,7 @@ import { setQuizAnalysis, setItemAnalyses, setFetchInProgress, setGenerationInPr
|
|
|
4
4
|
import { getQuizAnalysis as fetchQuizAnalysis } from "../../../api/getQuizAnalysis.js";
|
|
5
5
|
import { getItemAnalyses as fetchItemAnalyses } from "../../../api/getItemAnalyses.js";
|
|
6
6
|
import { getAnalysesStatus as fetchAnalysesStatus } from "../../../api/getAnalysesStatus.js";
|
|
7
|
+
import { getAnalysesExport } from "../../../api/getAnalysesExport.js";
|
|
7
8
|
import { connect } from "../../../../common/react-redux.js";
|
|
8
9
|
import { compose } from 'redux';
|
|
9
10
|
import { getActiveQuizId } from "../../../../common/selectors/quizzes.js";
|
|
@@ -21,6 +22,7 @@ export function mapStateToProps(state, ownProps) {
|
|
|
21
22
|
fetchQuizAnalysis: fetchQuizAnalysis,
|
|
22
23
|
fetchItemAnalyses: fetchItemAnalyses,
|
|
23
24
|
fetchAnalysesStatus: fetchAnalysesStatus,
|
|
25
|
+
getAnalysesExport: getAnalysesExport,
|
|
24
26
|
pollingInterval: ownProps.pollingInterval || DEFAULT_POLLING_INTERVAL
|
|
25
27
|
};
|
|
26
28
|
}
|
package/es/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisStatePresenter.js
CHANGED
|
@@ -9,6 +9,8 @@ import { fetchReports } from "./fetchReports.js";
|
|
|
9
9
|
import { fetchReportsStatus } from "./fetchReportsStatus.js";
|
|
10
10
|
import { getErrorMessageForCode } from "./errorCodes.js";
|
|
11
11
|
import { generateReports as triggerReportGeneration } from "./generateReports.js";
|
|
12
|
+
import { exportReports as triggerExportReports } from "./exportReports.js";
|
|
13
|
+
import { saveFile } from "./utils.js";
|
|
12
14
|
export var withAnalysisStatePresenter = function withAnalysisStatePresenter(OriginalComponent) {
|
|
13
15
|
var WithAnalysisStatePresenter = function WithAnalysisStatePresenter(_ref) {
|
|
14
16
|
var quizAnalysis = _ref.quizAnalysis,
|
|
@@ -26,11 +28,12 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
|
|
|
26
28
|
generateAnalysis = _ref.generateAnalysis,
|
|
27
29
|
fetchQuizAnalysis = _ref.fetchQuizAnalysis,
|
|
28
30
|
fetchItemAnalyses = _ref.fetchItemAnalyses,
|
|
31
|
+
getAnalysesExport = _ref.getAnalysesExport,
|
|
29
32
|
fetchAnalysesStatus = _ref.fetchAnalysesStatus,
|
|
30
33
|
statusPollingInProgress = _ref.statusPollingInProgress,
|
|
31
34
|
setStatusPollingInProgress = _ref.setStatusPollingInProgress,
|
|
32
35
|
pollingInterval = _ref.pollingInterval,
|
|
33
|
-
passThroughProps = _objectWithoutProperties(_ref, ["quizAnalysis", "itemAnalyses", "fetchInProgress", "generationInProgress", "analysisError", "setQuizAnalysis", "addError", "setItemAnalyses", "setFetchInProgress", "setGenerationInProgress", "setAnalysisError", "activeQuizId", "generateAnalysis", "fetchQuizAnalysis", "fetchItemAnalyses", "fetchAnalysesStatus", "statusPollingInProgress", "setStatusPollingInProgress", "pollingInterval"]);
|
|
36
|
+
passThroughProps = _objectWithoutProperties(_ref, ["quizAnalysis", "itemAnalyses", "fetchInProgress", "generationInProgress", "analysisError", "setQuizAnalysis", "addError", "setItemAnalyses", "setFetchInProgress", "setGenerationInProgress", "setAnalysisError", "activeQuizId", "generateAnalysis", "fetchQuizAnalysis", "fetchItemAnalyses", "getAnalysesExport", "fetchAnalysesStatus", "statusPollingInProgress", "setStatusPollingInProgress", "pollingInterval"]);
|
|
34
37
|
|
|
35
38
|
WithAnalysisStatePresenter.displayName = "WithAnalysisStatePresenter(".concat(OriginalComponent.displayName || OriginalComponent.name, ")");
|
|
36
39
|
|
|
@@ -101,6 +104,41 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
|
|
|
101
104
|
return _generateReports.apply(this, arguments);
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
function exportReports(_x) {
|
|
108
|
+
return _exportReports.apply(this, arguments);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function _exportReports() {
|
|
112
|
+
_exportReports = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(format) {
|
|
113
|
+
var filter,
|
|
114
|
+
exportConfig,
|
|
115
|
+
_args4 = arguments;
|
|
116
|
+
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
117
|
+
while (1) {
|
|
118
|
+
switch (_context4.prev = _context4.next) {
|
|
119
|
+
case 0:
|
|
120
|
+
filter = _args4.length > 1 && _args4[1] !== void 0 ? _args4[1] : 'last_attempt';
|
|
121
|
+
exportConfig = {
|
|
122
|
+
getAnalysesExport: getAnalysesExport,
|
|
123
|
+
format: format,
|
|
124
|
+
filter: filter,
|
|
125
|
+
activeQuizId: activeQuizId,
|
|
126
|
+
addError: addError,
|
|
127
|
+
saveFile: saveFile
|
|
128
|
+
};
|
|
129
|
+
_context4.next = 4;
|
|
130
|
+
return triggerExportReports(exportConfig);
|
|
131
|
+
|
|
132
|
+
case 4:
|
|
133
|
+
case "end":
|
|
134
|
+
return _context4.stop();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}, _callee4);
|
|
138
|
+
}));
|
|
139
|
+
return _exportReports.apply(this, arguments);
|
|
140
|
+
}
|
|
141
|
+
|
|
104
142
|
useEffect(function () {
|
|
105
143
|
var fetchIfNeeded = /*#__PURE__*/function () {
|
|
106
144
|
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
@@ -172,6 +210,7 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
|
|
|
172
210
|
generationInProgress: generationInProgress,
|
|
173
211
|
analysisError: analysisError,
|
|
174
212
|
generateReports: generateReports,
|
|
213
|
+
exportReports: exportReports,
|
|
175
214
|
analysisFetchError: analysisFetchError
|
|
176
215
|
}, passThroughProps));
|
|
177
216
|
};
|
|
@@ -193,6 +232,7 @@ export var withAnalysisStatePresenter = function withAnalysisStatePresenter(Orig
|
|
|
193
232
|
fetchQuizAnalysis: PropTypes.func.isRequired,
|
|
194
233
|
fetchItemAnalyses: PropTypes.func.isRequired,
|
|
195
234
|
fetchAnalysesStatus: PropTypes.func.isRequired,
|
|
235
|
+
getAnalysesExport: PropTypes.func.isRequired,
|
|
196
236
|
addError: PropTypes.func.isRequired,
|
|
197
237
|
pollingInterval: PropTypes.number.isRequired,
|
|
198
238
|
generateAnalysis: PropTypes.func.isRequired // from LTI, f(filter: string, onError?: func(error))
|
package/lib/reporting/components/resources/NewQuizAndItemAnalysis/NewQuizAnalysis/presenter.js
CHANGED
|
@@ -9,6 +9,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
9
9
|
});
|
|
10
10
|
exports.NewQuizAnalysis = void 0;
|
|
11
11
|
|
|
12
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
13
|
+
|
|
12
14
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
13
15
|
|
|
14
16
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
@@ -148,7 +150,7 @@ var NewQuizAnalysis = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles
|
|
|
148
150
|
title: expanded ? (0, _formatMessage.default)('collapse quiz analysis') : (0, _formatMessage.default)('expand quiz analysis'),
|
|
149
151
|
isExpanded: expanded
|
|
150
152
|
}))), expanded && _this.renderExpanded(), /*#__PURE__*/_react.default.createElement(_presenter.ScoreDistribution, {
|
|
151
|
-
decileDistribution:
|
|
153
|
+
decileDistribution: _this.getPreparedDecileDistribution()
|
|
152
154
|
}));
|
|
153
155
|
};
|
|
154
156
|
|
|
@@ -156,6 +158,23 @@ var NewQuizAnalysis = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles
|
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
(0, _createClass2.default)(NewQuizAnalysis, [{
|
|
161
|
+
key: "getPreparedDecileDistribution",
|
|
162
|
+
value: function getPreparedDecileDistribution() {
|
|
163
|
+
var quizAnalysis = this.props.quizAnalysis;
|
|
164
|
+
var scores = quizAnalysis.scores,
|
|
165
|
+
metadata = quizAnalysis.metadata;
|
|
166
|
+
var decileDistribution = (0, _toConsumableArray2.default)(scores === null || scores === void 0 ? void 0 : scores.decile_distribution);
|
|
167
|
+
|
|
168
|
+
if (metadata.decile_distribution && (metadata.decile_distribution.high_extreme_values_count > 0 || metadata.decile_distribution.low_extreme_values_count > 0)) {
|
|
169
|
+
var _metadata$decile_dist, _metadata$decile_dist2;
|
|
170
|
+
|
|
171
|
+
decileDistribution.unshift((_metadata$decile_dist = metadata.decile_distribution) === null || _metadata$decile_dist === void 0 ? void 0 : _metadata$decile_dist.low_extreme_values_count);
|
|
172
|
+
decileDistribution.push((_metadata$decile_dist2 = metadata.decile_distribution) === null || _metadata$decile_dist2 === void 0 ? void 0 : _metadata$decile_dist2.high_extreme_values_count);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return decileDistribution;
|
|
176
|
+
}
|
|
177
|
+
}, {
|
|
159
178
|
key: "render",
|
|
160
179
|
value: function render() {
|
|
161
180
|
var fetchInProgress = this.props.fetchInProgress;
|
|
@@ -61,7 +61,19 @@ var ScoreDistribution = (_dec = (0, _uiThemeable.themeable)(_theme.default, styl
|
|
|
61
61
|
|
|
62
62
|
_this = _super.call.apply(_super, [this].concat(args));
|
|
63
63
|
|
|
64
|
-
_this.
|
|
64
|
+
_this.calculateLabelForColumnsWithExtremeValues = function (index, length) {
|
|
65
|
+
if (index === 0) {
|
|
66
|
+
return (0, _formatMessage.default)('< 0%');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (index === length - 1) {
|
|
70
|
+
return (0, _formatMessage.default)('> 100%');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return _this.calculateLabelForColumns(index - 1, length - 2);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
_this.calculateLabelForColumns = function (index, length) {
|
|
65
77
|
var label = Math.floor(index * 100 / length);
|
|
66
78
|
return (0, _formatMessage.default)('{label, number}%', {
|
|
67
79
|
label: label
|
|
@@ -74,6 +86,7 @@ var ScoreDistribution = (_dec = (0, _uiThemeable.themeable)(_theme.default, styl
|
|
|
74
86
|
(0, _createClass2.default)(ScoreDistribution, [{
|
|
75
87
|
key: "render",
|
|
76
88
|
value: function render() {
|
|
89
|
+
var decileDistribution = this.props.decileDistribution;
|
|
77
90
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
78
91
|
className: styles.headingContainer
|
|
79
92
|
}, /*#__PURE__*/_react.default.createElement(_uiHeading.Heading, {
|
|
@@ -84,8 +97,8 @@ var ScoreDistribution = (_dec = (0, _uiThemeable.themeable)(_theme.default, styl
|
|
|
84
97
|
}, (0, _formatMessage.default)('Score Distribution'))), /*#__PURE__*/_react.default.createElement(_index.default, {
|
|
85
98
|
animateDelay: 1000,
|
|
86
99
|
animateDuration: 1000,
|
|
87
|
-
visualDistribution:
|
|
88
|
-
calculateLabelForColumn: this.
|
|
100
|
+
visualDistribution: decileDistribution || [],
|
|
101
|
+
calculateLabelForColumn: decileDistribution.length > 10 ? this.calculateLabelForColumnsWithExtremeValues : this.calculateLabelForColumns
|
|
89
102
|
}), /*#__PURE__*/_react.default.createElement("div", {
|
|
90
103
|
"aria-hidden": "true",
|
|
91
104
|
className: styles.chartLabel
|
|
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.getNotEnoughDataAvailableError = exports.getMinimumThreeGradedSubmissionError = exports.getOngoingReportGenerationError = exports.getInsufficentSubmissionNumberError = exports.getReportGenerationFailure = exports.getLastReportGenerationFailed = exports.getFailedToFetchReports = void 0;
|
|
8
|
+
exports.getNotEnoughDataAvailableError = exports.getMinimumThreeGradedSubmissionError = exports.getOngoingReportGenerationError = exports.getInsufficentSubmissionNumberError = exports.getReportGenerationFailure = exports.getLastReportGenerationFailed = exports.getFailedToExportReports = exports.getFailedToFetchReports = void 0;
|
|
9
9
|
|
|
10
10
|
var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
|
|
11
11
|
|
|
@@ -15,6 +15,12 @@ var getFailedToFetchReports = function getFailedToFetchReports() {
|
|
|
15
15
|
|
|
16
16
|
exports.getFailedToFetchReports = getFailedToFetchReports;
|
|
17
17
|
|
|
18
|
+
var getFailedToExportReports = function getFailedToExportReports() {
|
|
19
|
+
return (0, _formatMessage.default)('An error has occurred while exporting this report. Please try again.');
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
exports.getFailedToExportReports = getFailedToExportReports;
|
|
23
|
+
|
|
18
24
|
var getLastReportGenerationFailed = function getLastReportGenerationFailed() {
|
|
19
25
|
return (0, _formatMessage.default)('Report generation failed. Please try again.');
|
|
20
26
|
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.exportReports = void 0;
|
|
9
|
+
|
|
10
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
11
|
+
|
|
12
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
13
|
+
|
|
14
|
+
var _errorMessages = require("./errorMessages.js");
|
|
15
|
+
|
|
16
|
+
var _contentDisposition = _interopRequireDefault(require("content-disposition"));
|
|
17
|
+
|
|
18
|
+
var exportReports = /*#__PURE__*/function () {
|
|
19
|
+
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(_ref) {
|
|
20
|
+
var getAnalysesExport, activeQuizId, filter, format, saveFile, addError, response, dispositionHeader, disposition, filename, blob;
|
|
21
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
22
|
+
while (1) {
|
|
23
|
+
switch (_context.prev = _context.next) {
|
|
24
|
+
case 0:
|
|
25
|
+
getAnalysesExport = _ref.getAnalysesExport, activeQuizId = _ref.activeQuizId, filter = _ref.filter, format = _ref.format, saveFile = _ref.saveFile, addError = _ref.addError;
|
|
26
|
+
_context.prev = 1;
|
|
27
|
+
_context.next = 4;
|
|
28
|
+
return getAnalysesExport(activeQuizId, format, filter);
|
|
29
|
+
|
|
30
|
+
case 4:
|
|
31
|
+
response = _context.sent;
|
|
32
|
+
dispositionHeader = response.headers.get('Content-Disposition');
|
|
33
|
+
|
|
34
|
+
if (dispositionHeader) {
|
|
35
|
+
_context.next = 8;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
throw new Error('Response contains no Content-Disposition header.');
|
|
40
|
+
|
|
41
|
+
case 8:
|
|
42
|
+
disposition = _contentDisposition.default.parse(dispositionHeader);
|
|
43
|
+
filename = disposition.parameters.filename;
|
|
44
|
+
|
|
45
|
+
if (filename) {
|
|
46
|
+
_context.next = 12;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw new Error('Cannot determine filename to save.');
|
|
51
|
+
|
|
52
|
+
case 12:
|
|
53
|
+
_context.next = 14;
|
|
54
|
+
return response.blob();
|
|
55
|
+
|
|
56
|
+
case 14:
|
|
57
|
+
blob = _context.sent;
|
|
58
|
+
saveFile(blob, filename);
|
|
59
|
+
_context.next = 21;
|
|
60
|
+
break;
|
|
61
|
+
|
|
62
|
+
case 18:
|
|
63
|
+
_context.prev = 18;
|
|
64
|
+
_context.t0 = _context["catch"](1);
|
|
65
|
+
addError((0, _errorMessages.getFailedToExportReports)());
|
|
66
|
+
|
|
67
|
+
case 21:
|
|
68
|
+
case "end":
|
|
69
|
+
return _context.stop();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, _callee, null, [[1, 18]]);
|
|
73
|
+
}));
|
|
74
|
+
|
|
75
|
+
return function exportReports(_x) {
|
|
76
|
+
return _ref2.apply(this, arguments);
|
|
77
|
+
};
|
|
78
|
+
}();
|
|
79
|
+
|
|
80
|
+
exports.exportReports = exportReports;
|
|
@@ -5,15 +5,23 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.afsFlags = exports.answerSummaryPropType = exports.matchingTypeAnswerSummaryPropType = exports.choiceTypeAnswerSummaryPropType = exports.onlyAggregatePropType = exports.itemAnalysisPropType = exports.quizAnalysisPropType = void 0;
|
|
8
|
+
exports.afsFlags = exports.answerSummaryPropType = exports.matchingTypeAnswerSummaryPropType = exports.choiceTypeAnswerSummaryPropType = exports.onlyAggregatePropType = exports.itemAnalysisPropType = exports.quizAnalysisPropType = exports.quizAnalysisMetadata = void 0;
|
|
9
9
|
|
|
10
10
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
11
|
|
|
12
|
+
var quizAnalysisMetadata = _propTypes.default.shape({
|
|
13
|
+
quiz_title: _propTypes.default.string,
|
|
14
|
+
decile_distribution: _propTypes.default.shape({
|
|
15
|
+
high_extreme_values_count: _propTypes.default.number,
|
|
16
|
+
low_extreme_values_count: _propTypes.default.number
|
|
17
|
+
})
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
exports.quizAnalysisMetadata = quizAnalysisMetadata;
|
|
21
|
+
|
|
12
22
|
var quizAnalysisPropType = _propTypes.default.shape({
|
|
13
23
|
created_timestamp: _propTypes.default.string.isRequired,
|
|
14
|
-
metadata:
|
|
15
|
-
quiz_title: _propTypes.default.string
|
|
16
|
-
}).isRequired,
|
|
24
|
+
metadata: quizAnalysisMetadata.isRequired,
|
|
17
25
|
scores: _propTypes.default.shape({
|
|
18
26
|
decile_distribution: _propTypes.default.arrayOf(_propTypes.default.number),
|
|
19
27
|
cronbachs_alpha: _propTypes.default.number,
|
|
@@ -5,10 +5,12 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.getSanitizedMetricValue = void 0;
|
|
8
|
+
exports.getSanitizedMetricValue = exports.saveFile = void 0;
|
|
9
9
|
|
|
10
10
|
var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
|
|
11
11
|
|
|
12
|
+
var _fileSaver = require("file-saver");
|
|
13
|
+
|
|
12
14
|
var formatNumbers = function formatNumbers(value) {
|
|
13
15
|
if (typeof value === 'number') {
|
|
14
16
|
return _formatMessage.default.number(value);
|
|
@@ -26,4 +28,10 @@ var getSanitizedMetricValue = function getSanitizedMetricValue(value, suffix) {
|
|
|
26
28
|
return suffix ? formattedValue + suffix : formattedValue;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
|
-
exports.getSanitizedMetricValue = getSanitizedMetricValue;
|
|
31
|
+
exports.getSanitizedMetricValue = getSanitizedMetricValue;
|
|
32
|
+
|
|
33
|
+
var saveFile = function saveFile(file, fileName) {
|
|
34
|
+
(0, _fileSaver.saveAs)(file, fileName);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
exports.saveFile = saveFile;
|
|
@@ -18,6 +18,8 @@ var _getItemAnalyses = require("../../../api/getItemAnalyses.js");
|
|
|
18
18
|
|
|
19
19
|
var _getAnalysesStatus = require("../../../api/getAnalysesStatus.js");
|
|
20
20
|
|
|
21
|
+
var _getAnalysesExport = require("../../../api/getAnalysesExport.js");
|
|
22
|
+
|
|
21
23
|
var _reactRedux = require("../../../../common/react-redux.js");
|
|
22
24
|
|
|
23
25
|
var _redux = require("redux");
|
|
@@ -40,6 +42,7 @@ function mapStateToProps(state, ownProps) {
|
|
|
40
42
|
fetchQuizAnalysis: _getQuizAnalysis.getQuizAnalysis,
|
|
41
43
|
fetchItemAnalyses: _getItemAnalyses.getItemAnalyses,
|
|
42
44
|
fetchAnalysesStatus: _getAnalysesStatus.getAnalysesStatus,
|
|
45
|
+
getAnalysesExport: _getAnalysesExport.getAnalysesExport,
|
|
43
46
|
pollingInterval: ownProps.pollingInterval || DEFAULT_POLLING_INTERVAL
|
|
44
47
|
};
|
|
45
48
|
}
|
package/lib/reporting/components/resources/NewQuizAndItemAnalysis/withAnalysisStatePresenter.js
CHANGED
|
@@ -31,6 +31,10 @@ var _errorCodes = require("./errorCodes.js");
|
|
|
31
31
|
|
|
32
32
|
var _generateReports2 = require("./generateReports.js");
|
|
33
33
|
|
|
34
|
+
var _exportReports2 = require("./exportReports.js");
|
|
35
|
+
|
|
36
|
+
var _utils = require("./utils.js");
|
|
37
|
+
|
|
34
38
|
var withAnalysisStatePresenter = function withAnalysisStatePresenter(OriginalComponent) {
|
|
35
39
|
var WithAnalysisStatePresenter = function WithAnalysisStatePresenter(_ref) {
|
|
36
40
|
var quizAnalysis = _ref.quizAnalysis,
|
|
@@ -48,11 +52,12 @@ var withAnalysisStatePresenter = function withAnalysisStatePresenter(OriginalCom
|
|
|
48
52
|
generateAnalysis = _ref.generateAnalysis,
|
|
49
53
|
fetchQuizAnalysis = _ref.fetchQuizAnalysis,
|
|
50
54
|
fetchItemAnalyses = _ref.fetchItemAnalyses,
|
|
55
|
+
getAnalysesExport = _ref.getAnalysesExport,
|
|
51
56
|
fetchAnalysesStatus = _ref.fetchAnalysesStatus,
|
|
52
57
|
statusPollingInProgress = _ref.statusPollingInProgress,
|
|
53
58
|
setStatusPollingInProgress = _ref.setStatusPollingInProgress,
|
|
54
59
|
pollingInterval = _ref.pollingInterval,
|
|
55
|
-
passThroughProps = (0, _objectWithoutProperties2.default)(_ref, ["quizAnalysis", "itemAnalyses", "fetchInProgress", "generationInProgress", "analysisError", "setQuizAnalysis", "addError", "setItemAnalyses", "setFetchInProgress", "setGenerationInProgress", "setAnalysisError", "activeQuizId", "generateAnalysis", "fetchQuizAnalysis", "fetchItemAnalyses", "fetchAnalysesStatus", "statusPollingInProgress", "setStatusPollingInProgress", "pollingInterval"]);
|
|
60
|
+
passThroughProps = (0, _objectWithoutProperties2.default)(_ref, ["quizAnalysis", "itemAnalyses", "fetchInProgress", "generationInProgress", "analysisError", "setQuizAnalysis", "addError", "setItemAnalyses", "setFetchInProgress", "setGenerationInProgress", "setAnalysisError", "activeQuizId", "generateAnalysis", "fetchQuizAnalysis", "fetchItemAnalyses", "getAnalysesExport", "fetchAnalysesStatus", "statusPollingInProgress", "setStatusPollingInProgress", "pollingInterval"]);
|
|
56
61
|
WithAnalysisStatePresenter.displayName = "WithAnalysisStatePresenter(".concat(OriginalComponent.displayName || OriginalComponent.name, ")");
|
|
57
62
|
|
|
58
63
|
var _useState = (0, _react.useState)(false),
|
|
@@ -122,6 +127,41 @@ var withAnalysisStatePresenter = function withAnalysisStatePresenter(OriginalCom
|
|
|
122
127
|
return _generateReports.apply(this, arguments);
|
|
123
128
|
}
|
|
124
129
|
|
|
130
|
+
function exportReports(_x) {
|
|
131
|
+
return _exportReports.apply(this, arguments);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function _exportReports() {
|
|
135
|
+
_exportReports = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(format) {
|
|
136
|
+
var filter,
|
|
137
|
+
exportConfig,
|
|
138
|
+
_args4 = arguments;
|
|
139
|
+
return _regenerator.default.wrap(function _callee4$(_context4) {
|
|
140
|
+
while (1) {
|
|
141
|
+
switch (_context4.prev = _context4.next) {
|
|
142
|
+
case 0:
|
|
143
|
+
filter = _args4.length > 1 && _args4[1] !== void 0 ? _args4[1] : 'last_attempt';
|
|
144
|
+
exportConfig = {
|
|
145
|
+
getAnalysesExport: getAnalysesExport,
|
|
146
|
+
format: format,
|
|
147
|
+
filter: filter,
|
|
148
|
+
activeQuizId: activeQuizId,
|
|
149
|
+
addError: addError,
|
|
150
|
+
saveFile: _utils.saveFile
|
|
151
|
+
};
|
|
152
|
+
_context4.next = 4;
|
|
153
|
+
return (0, _exportReports2.exportReports)(exportConfig);
|
|
154
|
+
|
|
155
|
+
case 4:
|
|
156
|
+
case "end":
|
|
157
|
+
return _context4.stop();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}, _callee4);
|
|
161
|
+
}));
|
|
162
|
+
return _exportReports.apply(this, arguments);
|
|
163
|
+
}
|
|
164
|
+
|
|
125
165
|
(0, _react.useEffect)(function () {
|
|
126
166
|
var fetchIfNeeded = /*#__PURE__*/function () {
|
|
127
167
|
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
@@ -193,6 +233,7 @@ var withAnalysisStatePresenter = function withAnalysisStatePresenter(OriginalCom
|
|
|
193
233
|
generationInProgress: generationInProgress,
|
|
194
234
|
analysisError: analysisError,
|
|
195
235
|
generateReports: generateReports,
|
|
236
|
+
exportReports: exportReports,
|
|
196
237
|
analysisFetchError: analysisFetchError
|
|
197
238
|
}, passThroughProps));
|
|
198
239
|
};
|
|
@@ -214,6 +255,7 @@ var withAnalysisStatePresenter = function withAnalysisStatePresenter(OriginalCom
|
|
|
214
255
|
fetchQuizAnalysis: _propTypes.default.func.isRequired,
|
|
215
256
|
fetchItemAnalyses: _propTypes.default.func.isRequired,
|
|
216
257
|
fetchAnalysesStatus: _propTypes.default.func.isRequired,
|
|
258
|
+
getAnalysesExport: _propTypes.default.func.isRequired,
|
|
217
259
|
addError: _propTypes.default.func.isRequired,
|
|
218
260
|
pollingInterval: _propTypes.default.number.isRequired,
|
|
219
261
|
generateAnalysis: _propTypes.default.func.isRequired // from LTI, f(filter: string, onError?: func(error))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/quiz-core",
|
|
3
|
-
"version": "18.5.1-rc.
|
|
3
|
+
"version": "18.5.1-rc.9+7684e8663",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The Quiz React SDK by Instructure Inc.",
|
|
6
6
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@instructure/grading-utils": "^1.0.0",
|
|
45
45
|
"@instructure/outcomes-ui": "^2.1.9",
|
|
46
|
-
"@instructure/quiz-common": "18.5.1-rc.
|
|
47
|
-
"@instructure/quiz-i18n": "18.5.1-rc.
|
|
48
|
-
"@instructure/quiz-interactions": "18.5.1-rc.
|
|
49
|
-
"@instructure/quiz-number-input": "18.5.1-rc.
|
|
50
|
-
"@instructure/quiz-rce": "18.5.1-rc.
|
|
46
|
+
"@instructure/quiz-common": "18.5.1-rc.9+7684e8663",
|
|
47
|
+
"@instructure/quiz-i18n": "18.5.1-rc.9+7684e8663",
|
|
48
|
+
"@instructure/quiz-interactions": "18.5.1-rc.9+7684e8663",
|
|
49
|
+
"@instructure/quiz-number-input": "18.5.1-rc.9+7684e8663",
|
|
50
|
+
"@instructure/quiz-rce": "18.5.1-rc.9+7684e8663",
|
|
51
51
|
"@instructure/ui-a11y-content": "^7.22.1",
|
|
52
52
|
"@instructure/ui-alerts": "^7.22.1",
|
|
53
53
|
"@instructure/ui-avatar": "^7.22.1",
|
|
@@ -106,9 +106,10 @@
|
|
|
106
106
|
"d3-transition": "^1",
|
|
107
107
|
"date-fns": "^1.28.0",
|
|
108
108
|
"eventemitter3": "^3.1.0",
|
|
109
|
+
"file-saver": "~2.0.5",
|
|
109
110
|
"humps": "^2.0.0",
|
|
110
111
|
"immutable": "^3.8.1",
|
|
111
|
-
"instructure-validations": "18.5.1-rc.
|
|
112
|
+
"instructure-validations": "18.5.1-rc.9+7684e8663",
|
|
112
113
|
"ipaddr.js": "^1.5.4",
|
|
113
114
|
"isomorphic-fetch": "^2.2.0",
|
|
114
115
|
"isuuid": "^0.1.0",
|
|
@@ -159,7 +160,7 @@
|
|
|
159
160
|
"intl": "^1.2.4",
|
|
160
161
|
"jquery": "^2.2.3",
|
|
161
162
|
"most-subject": "^5.3.0",
|
|
162
|
-
"quiz-presets": "18.5.1-rc.
|
|
163
|
+
"quiz-presets": "18.5.1-rc.9+7684e8663",
|
|
163
164
|
"react": "^16.8.6",
|
|
164
165
|
"react-addons-test-utils": "^15.6.2",
|
|
165
166
|
"react-dom": "^16.8.6",
|
|
@@ -175,5 +176,5 @@
|
|
|
175
176
|
"publishConfig": {
|
|
176
177
|
"access": "public"
|
|
177
178
|
},
|
|
178
|
-
"gitHead": "
|
|
179
|
+
"gitHead": "7684e8663eece2857d4f080e80563f2a6f31de33"
|
|
179
180
|
}
|