diff --git a/common/static/common/js/components/BlockBrowser/data/reducers/index.js b/common/static/common/js/components/BlockBrowser/data/reducers/index.js
index 7d14e63052cd..365e9153edd5 100644
--- a/common/static/common/js/components/BlockBrowser/data/reducers/index.js
+++ b/common/static/common/js/components/BlockBrowser/data/reducers/index.js
@@ -18,7 +18,7 @@ export const buildBlockTree = (blocks, excludeBlockTypes) => {
return blockTree(blocks.root, null);
};
-const blocks = (state = {}, action) => {
+export const blocks = (state = {}, action) => {
switch (action.type) {
case courseBlocksActions.fetch.SUCCESS:
return buildBlockTree(action.blocks, action.excludeBlockTypes);
@@ -27,7 +27,7 @@ const blocks = (state = {}, action) => {
}
};
-const selectedBlock = (state = null, action) => {
+export const selectedBlock = (state = null, action) => {
switch (action.type) {
case courseBlocksActions.SELECT_BLOCK:
return action.blockId;
@@ -37,7 +37,7 @@ const selectedBlock = (state = null, action) => {
};
-const rootBlock = (state = null, action) => {
+export const rootBlock = (state = null, action) => {
switch (action.type) {
case courseBlocksActions.fetch.SUCCESS:
return action.blocks.root;
diff --git a/lms/djangoapps/instructor/static/instructor/ProblemBrowser/.eslintrc.js b/lms/djangoapps/instructor/static/instructor/.eslintrc.js
similarity index 100%
rename from lms/djangoapps/instructor/static/instructor/ProblemBrowser/.eslintrc.js
rename to lms/djangoapps/instructor/static/instructor/.eslintrc.js
diff --git a/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/Main.jsx b/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/Main.jsx
index aca0041c9948..bbc7c8efeebb 100644
--- a/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/Main.jsx
+++ b/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/Main.jsx
@@ -1,15 +1,20 @@
/* global gettext */
import { Button } from '@edx/paragon';
-import { BlockBrowser } from 'BlockBrowser';
+import BlockBrowserContainer from 'BlockBrowser/components/BlockBrowser/BlockBrowserContainer';
import * as PropTypes from 'prop-types';
import * as React from 'react';
+import { PopupModalContainer } from '../Popup/PopupModalContainer';
export default class Main extends React.Component {
constructor(props) {
super(props);
this.handleToggleDropdown = this.handleToggleDropdown.bind(this);
+ this.showPopup = this.showPopup.bind(this);
+ this.hidePopup = this.hidePopup.bind(this);
this.state = {
+ popupOpen: false,
showDropdown: false,
+ taskForBlock: null,
};
}
@@ -22,19 +27,51 @@ export default class Main extends React.Component {
this.setState({ showDropdown: false });
}
+ showPopup() {
+ if (this.state.taskForBlock !== this.props.selectedBlock) {
+ this.props.createProblemResponsesReportTask(
+ this.props.initialEndpoint,
+ this.props.taskStatusEndpoint,
+ this.props.selectedBlock,
+ );
+ }
+ this.setState({ popupOpen: true, taskForBlock: this.props.selectedBlock });
+ }
+
+ hidePopup() {
+ if (this.props.timeout != null) {
+ clearTimeout(this.props.timeout);
+ }
+ this.setState({ popupOpen: false, taskForBlock: null });
+ this.props.resetProblemResponsesReportTask();
+ }
+
render() {
const { selectedBlock, onSelectBlock } = this.props;
return (
-
+
{this.state.showDropdown &&
-
{
- this.hideDropdown();
- onSelectBlock(blockId);
- }}
+ {
+ this.hideDropdown();
+ onSelectBlock(blockId);
+ }}
/>}
+
+
);
}
@@ -42,13 +79,19 @@ export default class Main extends React.Component {
Main.propTypes = {
courseId: PropTypes.string.isRequired,
+ createProblemResponsesReportTask: PropTypes.func.isRequired,
excludeBlockTypes: PropTypes.arrayOf(PropTypes.string),
fetchCourseBlocks: PropTypes.func.isRequired,
+ initialEndpoint: PropTypes.string.isRequired,
onSelectBlock: PropTypes.func.isRequired,
selectedBlock: PropTypes.string,
+ resetProblemResponsesReportTask: PropTypes.func.isRequired,
+ taskStatusEndpoint: PropTypes.string.isRequired,
+ timeout: PropTypes.number,
};
Main.defaultProps = {
excludeBlockTypes: null,
selectedBlock: null,
+ timeout: null,
};
diff --git a/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/MainContainer.jsx b/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/MainContainer.jsx
index a36b31978be9..6257b7130f70 100644
--- a/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/MainContainer.jsx
+++ b/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Main/MainContainer.jsx
@@ -1,17 +1,25 @@
import { fetchCourseBlocks, selectBlock } from 'BlockBrowser/data/actions/courseBlocks';
import { connect } from 'react-redux';
-
+import { createProblemResponsesReportTask, reset } from '../../data/actions/problemResponses';
import Main from './Main';
const mapStateToProps = state => ({
selectedBlock: state.selectedBlock,
+ timeout: state.popupTask.timeout,
});
const mapDispatchToProps = dispatch => ({
onSelectBlock: blockId => dispatch(selectBlock(blockId)),
- fetchCourseBlocks: (courseId, excludeBlockTypes) =>
- dispatch(fetchCourseBlocks(courseId, excludeBlockTypes)),
+ fetchCourseBlocks:
+ (courseId, excludeBlockTypes) =>
+ dispatch(fetchCourseBlocks(courseId, excludeBlockTypes)),
+ createProblemResponsesReportTask:
+ (initialEndpoint, taskStatusEndpoint, problemLocation) =>
+ dispatch(
+ createProblemResponsesReportTask(initialEndpoint, taskStatusEndpoint, problemLocation),
+ ),
+ resetProblemResponsesReportTask: () => dispatch(reset),
});
const MainContainer = connect(
diff --git a/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Popup/PopupModal.jsx b/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Popup/PopupModal.jsx
new file mode 100644
index 000000000000..691e92c6fe79
--- /dev/null
+++ b/lms/djangoapps/instructor/static/instructor/ProblemBrowser/components/Popup/PopupModal.jsx
@@ -0,0 +1,82 @@
+/* global gettext */
+import { Button, Modal } from '@edx/paragon/static';
+import * as classNames from 'classnames';
+import * as PropTypes from 'prop-types';
+import * as React from 'react';
+
+const PopupModal = ({ open, onHide, message, error, succeeded, reportPath, reportPreview }) => {
+ const previewButton = (
+