Commit 78f45512 by Filippo Valsorda

Remove the dataexport functionality and XBlock

parent e2924962
......@@ -9,7 +9,6 @@ It supports:
* **Self-assessment quizzes** (multiple choice), to display predetermined feedback to a student based on his choices in the self-assessment. Supports rating scales and arbitrary answers.
* **Progression tracking**, allowing to check that the student has completed the previous steps before allowing to complete a given XBlock instance. Provides a link to the next step to the student.
* **Tables**, which allow to present answers from the student to free-form answers in a concise way. Supports custom headers.
* **Data export**, to allow course authors to download a CSV file containing the free-form answers entered by the students
Examples
--------
......@@ -91,13 +90,6 @@ Second XBlock instance:
</mentoring-table>
```
### Data export
```xml
<vertical>
<mentoring-dataexport url_name="mentoring_dataexport"></mentoring-dataexport>
</vertical>
```
Installing dependencies
-----------------------
......
from .answer import AnswerBlock
from .dataexport import MentoringDataExportBlock
from .html import HTMLBlock
from .quizz import QuizzBlock, QuizzChoiceBlock, QuizzTipBlock
from .mentoring import MentoringBlock
......
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 Harvard
#
# Authors:
# Xavier Antoviaque <xavier@antoviaque.org>
#
# This software's license gives you freedom; you can copy, convey,
# propagate, redistribute and/or modify this program under the terms of
# the GNU Affero General Public License (AGPL) as published by the Free
# Software Foundation (FSF), either version 3 of the License, or (at your
# option) any later version of the AGPL published by the FSF.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
# General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program in a file in the toplevel directory called
# "AGPLv3". If not, see <http://www.gnu.org/licenses/>.
#
# Imports ###########################################################
import logging
from itertools import groupby
from operator import itemgetter
from webob import Response
from xblock.core import XBlock
from xblock.fragment import Fragment
from .models import Answer
from .utils import list2csv, render_template, serialize_opaque_key
# Globals ###########################################################
log = logging.getLogger(__name__)
# Classes ###########################################################
class MentoringDataExportBlock(XBlock):
"""
An XBlock allowing the instructor team to export all the student answers as a CSV file
"""
def student_view(self, context):
html = render_template('templates/html/dataexport.html', {
'self': self,
})
fragment = Fragment(html)
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/dataexport.js'))
fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/dataexport.css'))
fragment.initialize_js('MentoringDataExportBlock')
return fragment
def studio_view(self, context):
return Fragment(u'Studio view body')
@XBlock.handler
def download_csv(self, request, suffix=''):
response = Response(content_type='text/csv')
response.app_iter = self.get_csv()
response.content_disposition = 'attachment; filename=course_data.csv'
return response
def get_csv(self):
course_id = serialize_opaque_key(self.xmodule_runtime.course_id)
answers = Answer.objects.filter(course_id=course_id).order_by('student_id', 'name')
answers_names = answers.values_list('name', flat=True).distinct().order_by('name')
# Header line
yield list2csv([u'student_id'] + list(answers_names))
answers_list = answers.values_list('name', 'student_id', 'student_input')
if answers_names:
for k, student_answers in groupby(answers_list, itemgetter(1)):
row = []
next_answer_idx = 0
for answer in student_answers:
if not row:
row = [answer[1]]
while answer[0] != answers_names[next_answer_idx]:
# Still add answer row to CSV when they don't exist in DB
row.append('')
next_answer_idx += 1
row.append(answer[2])
next_answer_idx += 1
if row:
yield list2csv(row)
.mentoring-dataexport {
margin: 10px;
}
function MentoringDataExportBlock(runtime, element) {
var downloadUrl = runtime.handlerUrl(element, 'download_csv');
$('button.download', element).click(function(ev) {
ev.preventDefault();
window.location = downloadUrl;
});
}
<div class="mentoring-dataexport">
<h3>Answers data dump</h3>
<button class="download">Download CSV</button>
</div>
......@@ -26,9 +26,7 @@
import logging
import os
import pkg_resources
import unicodecsv
from cStringIO import StringIO
from django.template import Context, Template
from xblock.fragment import Fragment
......@@ -55,16 +53,6 @@ def render_template(template_path, context={}):
template = Template(template_str)
return template.render(Context(context))
def list2csv(row):
"""
Convert a list to a CSV string (single row)
"""
f = StringIO()
writer = unicodecsv.writer(f, encoding='utf-8')
writer.writerow(row)
f.seek(0)
return f.read()
def get_scenarios_from_path(scenarios_path, include_identifier=False):
"""
Returns an array of (title, xmlcontent) from files contained in a specified directory,
......
-e .
unicodecsv==0.9.4
-e git://github.com/nosedjango/nosedjango.git@ed7d7f9aa969252ff799ec159f828eaa8c1cbc5a#egg=nosedjango-dev
......@@ -44,7 +44,6 @@ def package_data(pkg, root_list):
BLOCKS = [
'mentoring = mentoring:MentoringBlock',
'mentoring-dataexport = mentoring:MentoringDataExportBlock',
]
BLOCKS_CHILDREN = [
......
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