Commit e0f62ff8 by Tim Krones

Allow instructors to filter answers by content.

parent 3e4edf40
...@@ -13,6 +13,7 @@ function StudentAnswersDashboardBlock(runtime, element) { ...@@ -13,6 +13,7 @@ function StudentAnswersDashboardBlock(runtime, element) {
var $blockTypes = $element.find("select[name='block_types']"); var $blockTypes = $element.find("select[name='block_types']");
var $rootBlockId = $element.find("input[name='root_block_id']"); var $rootBlockId = $element.find("input[name='root_block_id']");
var $username = $element.find("input[name='username']"); var $username = $element.find("input[name='username']");
var $matchString = $element.find("input[name='match_string']");
var $resultTable = $element.find('.data-export-results'); var $resultTable = $element.find('.data-export-results');
var status; var status;
...@@ -139,7 +140,8 @@ function StudentAnswersDashboardBlock(runtime, element) { ...@@ -139,7 +140,8 @@ function StudentAnswersDashboardBlock(runtime, element) {
data = { data = {
block_types: $blockTypes.val(), block_types: $blockTypes.val(),
root_block_id: $rootBlockId.val(), root_block_id: $rootBlockId.val(),
username: $username.val() username: $username.val(),
match_string: $matchString.val()
}; };
data = JSON.stringify(data); data = JSON.stringify(data);
} else { } else {
......
...@@ -163,6 +163,7 @@ class StudentAnswersDashboardBlock(XBlock): ...@@ -163,6 +163,7 @@ class StudentAnswersDashboardBlock(XBlock):
block_types = data.get('block_types', None) block_types = data.get('block_types', None)
username = data.get('username', None) username = data.get('username', None)
root_block_id = data.get('root_block_id', None) root_block_id = data.get('root_block_id', None)
match_string = data.get('match_string', None)
if not root_block_id: if not root_block_id:
root_block_id = self.scope_ids.usage_id root_block_id = self.scope_ids.usage_id
# Block ID not in workbench runtime. # Block ID not in workbench runtime.
...@@ -190,7 +191,8 @@ class StudentAnswersDashboardBlock(XBlock): ...@@ -190,7 +191,8 @@ class StudentAnswersDashboardBlock(XBlock):
root_block_id, root_block_id,
block_types, block_types,
user_id, user_id,
get_root=get_root, match_string,
get_root=get_root
) )
if async_result.ready(): if async_result.ready():
# In development mode, the task may have executed synchronously. # In development mode, the task may have executed synchronously.
......
...@@ -21,7 +21,7 @@ logger = get_task_logger(__name__) ...@@ -21,7 +21,7 @@ logger = get_task_logger(__name__)
@task() @task()
def export_data(course_id, source_block_id_str, block_types, user_id, get_root=True): def export_data(course_id, source_block_id_str, block_types, user_id, match_string, get_root=True):
""" """
Exports student answers to all MCQ questions to a CSV file. Exports student answers to all MCQ questions to a CSV file.
""" """
...@@ -93,8 +93,10 @@ def export_data(course_id, source_block_id_str, block_types, user_id, get_root=T ...@@ -93,8 +93,10 @@ def export_data(course_id, source_block_id_str, block_types, user_id, get_root=T
student_id = submission.get('student_id', user_id) student_id = submission.get('student_id', user_id)
# Extract data for display # Extract data for display
row = _extract_data_for_display(submission, student_id, block_type) # "row" will be None if answer does not match "match_string"
rows.append(row) row = _extract_data_for_display(submission, student_id, block_type, match_string)
if row:
rows.append(row)
# Generate the CSV: # Generate the CSV:
filename = u"pb-data-export-{}.csv".format(time.strftime("%Y-%m-%d-%H%M%S", time.gmtime(start_timestamp))) filename = u"pb-data-export-{}.csv".format(time.strftime("%Y-%m-%d-%H%M%S", time.gmtime(start_timestamp)))
...@@ -113,7 +115,7 @@ def export_data(course_id, source_block_id_str, block_types, user_id, get_root=T ...@@ -113,7 +115,7 @@ def export_data(course_id, source_block_id_str, block_types, user_id, get_root=T
} }
def _extract_data_for_display(submission, student_id, block_type): def _extract_data_for_display(submission, student_id, block_type, match_string):
""" """
Extract data that will be displayed on Student Answers Dashboard Extract data that will be displayed on Student Answers Dashboard
from `submission`. from `submission`.
...@@ -143,6 +145,10 @@ def _extract_data_for_display(submission, student_id, block_type): ...@@ -143,6 +145,10 @@ def _extract_data_for_display(submission, student_id, block_type):
answer = choice_block.content answer = choice_block.content
break break
# Short-circuit if answer does not match search criteria
if not match_string.lower() in answer.lower():
return
# Unit # Unit
mentoring_block = modulestore().get_item(block.parent) mentoring_block = modulestore().get_item(block.parent)
unit = modulestore().get_item(mentoring_block.parent) unit = modulestore().get_item(mentoring_block.parent)
......
...@@ -41,6 +41,17 @@ ...@@ -41,6 +41,17 @@
{% trans "Input the username of a student if you wish to query for a specific one. Otherwise, it will grab all results for all students." %} {% trans "Input the username of a student if you wish to query for a specific one. Otherwise, it will grab all results for all students." %}
</div> </div>
</div> </div>
<div class="data-export-field-container">
<div class="data-export-field">
<label>
<span>{% trans "Match answers containing:" %}</span>
<input type="text" name="match_string" />
</label>
</div>
<div class="data-export-helptext">
{% trans "Input text that all answers must match (case will be ignored). Otherwise, answers will not be filtered by content." %}
</div>
</div>
</div> </div>
<div class="data-export-actions"> <div class="data-export-actions">
<button class="data-export-start">{% trans "Start a new export" %}</button> <button class="data-export-start">{% trans "Start a new export" %}</button>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment