summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/static/yaksh/js/course.js72
-rw-r--r--yaksh/templates/yaksh/course_detail.html64
-rw-r--r--yaksh/templates/yaksh/register.html3
-rw-r--r--yaksh/templatetags/custom_filters.py41
4 files changed, 167 insertions, 13 deletions
diff --git a/yaksh/static/yaksh/js/course.js b/yaksh/static/yaksh/js/course.js
index f0d03e2..162e0b8 100644
--- a/yaksh/static/yaksh/js/course.js
+++ b/yaksh/static/yaksh/js/course.js
@@ -66,4 +66,76 @@ $("#send_mail").click(function(){
return status;
});
+// Download course status as csv
+function exportTableToCSV($table, filename) {
+ var $headers = $table.find('tr:has(th)')
+ ,$rows = $table.find('tr:has(td)')
+
+ // Temporary delimiter characters unlikely to be typed by keyboard
+ // This is to avoid accidentally splitting the actual contents
+ ,tmpColDelim = String.fromCharCode(11) // vertical tab character
+ ,tmpRowDelim = String.fromCharCode(0) // null character
+
+ // actual delimiter characters for CSV format
+ ,colDelim = '","'
+ ,rowDelim = '"\r\n"';
+
+ // Grab text from table into CSV formatted string
+ var csv = '"';
+ csv += formatRows($headers.map(grabRow));
+ csv += rowDelim;
+ csv += formatRows($rows.map(grabRow)) + '"';
+
+ // Data URI
+ var csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);
+
+ // For IE (tested 10+)
+ if (window.navigator.msSaveOrOpenBlob) {
+ var blob = new Blob([decodeURIComponent(encodeURI(csv))], {
+ type: "text/csv;charset=utf-8;"
+ });
+ navigator.msSaveBlob(blob, filename);
+ } else {
+ $(this)
+ .attr({
+ 'download': filename,'href': csvData
+ });
+ }
+
+ function formatRows(rows){
+ return rows.get().join(tmpRowDelim)
+ .split(tmpRowDelim).join(rowDelim)
+ .split(tmpColDelim).join(colDelim);
+ }
+ // Grab and format a row from the table
+ function grabRow(i,row){
+ var $row = $(row);
+ var $cols = $row.find('td');
+ if(!$cols.length) $cols = $row.find('th');
+
+ return $cols.map(grabCol)
+ .get().join(tmpColDelim);
+ }
+ // Grab and format a column from the table
+ function grabCol(j,col){
+ var $col = $(col),
+ $text = $col.text();
+
+ return $text.replace('"', '""').replace("View Unit Status", ''); // escape double quotes
+
+ }
+}
+
+
+$("#export").click(function (event) {
+ var outputFile = $("#course_name").val().replace(" ", "_") + '.csv';
+
+ exportTableToCSV.apply(this, [$('#course_table'), outputFile]);
+});
+
});
+
+function view_status(unit){
+ title_list = $(unit).attr("title").split("/");
+ $(unit).attr("title", title_list.join("\n"));
+}
diff --git a/yaksh/templates/yaksh/course_detail.html b/yaksh/templates/yaksh/course_detail.html
index cf0ab18..cd9d149 100644
--- a/yaksh/templates/yaksh/course_detail.html
+++ b/yaksh/templates/yaksh/course_detail.html
@@ -1,5 +1,5 @@
{% extends "manage.html" %}
-
+{% load custom_filters %}
{% block title %} Course Details {% endblock title %}
<div class="col-md-9 col-md-offset-2 main">
@@ -35,6 +35,10 @@
<a href="{{URL_ROOT}}/exam/manage/send_mail/{{ course.id }}/">
Send Mail</a>
</li>
+ <li>
+ <a href="{{URL_ROOT}}/exam/manage/course_status/{{ course.id }}/">
+ View Course Status</a>
+ </li>
</ul>
</div>
</div>
@@ -116,6 +120,64 @@
{% endif %}
</form>
</div>
+ {% elif state == "course_status" %}
+ <div class="course_data">
+ <input type="hidden" id="course_name" value="{{course.name}}">
+ <a href="#" class="btn btn-info" id="export">Export to CSV</a>
+ <center><h2>Course Status</h2></center>
+ <table class="table table-bordered" id="course_table">
+ <tr>
+ <th>Sr No.</th>
+ <th>Students</th>
+ <th>Total</th>
+ <th colspan="{{modules|length}}">Modules</th>
+ </tr>
+ <tr>
+ <th scope="row"></th>
+ <th></th>
+ <th></th>
+ {% if modules %}
+ {% for module in modules %}
+ <th>
+ {{module.name}}
+ <br>
+ <a data-target="tooltip" title="{% for unit in module.get_learning_units %}{% if unit.type == 'quiz' %}{{unit.quiz.description}}{% else %}{{unit.lesson.name}}{% endif %} / {% endfor %}" id="unit_status{{module.id}}" onmouseover="view_status('#unit_status{{module.id}}')">
+ View Units</a>
+ </th>
+ {% endfor %}
+ {% else %}
+ <th></th>
+ {% endif %}
+ </tr>
+ {% for student in students %}
+ <tr>
+ <td width="5%">
+ {{forloop.counter}}.
+ </td>
+ <td>
+ {{ student.get_full_name|title }}
+ </td>
+ <td>
+ {% course_completion_percent course student as c_percent %}
+ {{c_percent}} %
+ </td>
+ {% if modules %}
+ {% for module in modules %}
+ <td>
+ {% module_completion_percent course module student as m_percent %}
+ {{m_percent}} %
+ <br>
+ <a data-target="tooltip" title="{% for unit in module.get_learning_units %}{% if unit.type == 'quiz' %}{{unit.quiz.description}}{% else %}{{unit.lesson.name}}{% endif %} - {% get_unit_status course module unit student as status %}{{status|title}} / {% endfor %}" id="unit_status{{module.id}}{{student.id}}" onmouseover="view_status('#unit_status{{module.id}}{{student.id}}')">
+ View Unit Status</a>
+ </td>
+ {% endfor %}
+ {% else %}
+ <td>-------</td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
{% else %}
<div id="student-requests">
<center><b><u>Requests</u></b></center><br>
diff --git a/yaksh/templates/yaksh/register.html b/yaksh/templates/yaksh/register.html
index 7cf15a6..13cd248 100644
--- a/yaksh/templates/yaksh/register.html
+++ b/yaksh/templates/yaksh/register.html
@@ -12,7 +12,8 @@
<table class="table">
{{ form.as_table }}
</table></center>
- <center><button class="btn btn-primary" type="submit">Register</button>&nbsp;&nbsp;<button class="btn btn-primary" type="reset">Cancel</button></center>
+ <center><button class="btn btn-primary" type="submit">Register</button>&nbsp;&nbsp;
+ <a href="{{URL_ROOT}}/exam" class="btn btn-danger">Cancel</a></center>
</form>
{% endblock content %}
diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py
index 6ddd213..0049836 100644
--- a/yaksh/templatetags/custom_filters.py
+++ b/yaksh/templatetags/custom_filters.py
@@ -8,43 +8,62 @@ except ImportError:
register = template.Library()
+
@stringfilter
@register.filter(name='escape_quotes')
def escape_quotes(value):
- value = value.decode("utf-8")
- escape_single_quotes = value.replace("'", "\\'")
- escape_single_and_double_quotes = escape_single_quotes.replace('"', '\\"')
+ value = value.decode("utf-8")
+ escape_single_quotes = value.replace("'", "\\'")
+ escape_single_and_double_quotes = escape_single_quotes.replace('"', '\\"')
+
+ return escape_single_and_double_quotes
- return escape_single_and_double_quotes
@register.assignment_tag(name="completed")
def completed(answerpaper):
- return answerpaper.filter(status="completed").count()
+ return answerpaper.filter(status="completed").count()
+
@register.assignment_tag(name="inprogress")
def inprogress(answerpaper):
- return answerpaper.filter(status="inprogress").count()
+ return answerpaper.filter(status="inprogress").count()
+
@register.filter(name='zip')
def zip_longest_out(a, b):
- return zip_longest(a, b)
+ return zip_longest(a, b)
@register.filter(name="file_title")
def file_title(name):
- return os.path.basename(name)
+ return os.path.basename(name)
@register.simple_tag
def get_unit_status(course, module, unit, user):
- return course.get_unit_completion_status(module, user, unit)
+ return course.get_unit_completion_status(module, user, unit)
@register.simple_tag
def get_module_status(user, module, course):
- return module.get_status(user, course)
+ return module.get_status(user, course)
@register.simple_tag
def get_course_details(course):
- return course.get_quiz_details()
+ return course.get_quiz_details()
+
+
+@register.simple_tag
+def current_unit(course, student):
+ return course.get_current_unit(student)
+
+
+@register.simple_tag
+def module_completion_percent(course, module, user):
+ return module.get_module_complete_percent(course, user)
+
+
+@register.simple_tag
+def course_completion_percent(course, user):
+ return course.percent_completed(user)