Commit 940d24bc by Muhammad Shoaib

added the pagination for the student attempts

parent a7f4c56a
...@@ -26,7 +26,17 @@ var edx = edx || {}; ...@@ -26,7 +26,17 @@ var edx = edx || {};
this.loadTemplateData(); this.loadTemplateData();
}, },
events: { events: {
"click .remove-attempt": "onRemoveAttempt" "click .remove-attempt": "onRemoveAttempt",
'click li > a.target-link': 'getPaginatedAttempts'
},
getPaginatedAttempts: function(event) {
var target = $(event.currentTarget);
var url = target.data('target-url');
this.collection.url = url;
this.hydrate();
event.stopPropagation();
event.preventDefault();
}, },
getCSRFToken: function () { getCSRFToken: function () {
var cookieValue = null; var cookieValue = null;
...@@ -73,7 +83,11 @@ var edx = edx || {}; ...@@ -73,7 +83,11 @@ var edx = edx || {};
}, },
render: function () { render: function () {
if (this.template !== null) { if (this.template !== null) {
var html = this.template({proctored_exam_attempts: this.collection.toJSON()[0].proctored_exam_attempts}); var html = this.template({
proctored_exam_attempts: this.collection.toJSON()[0].proctored_exam_attempts,
pagination_info: this.collection.toJSON()[0].pagination_info,
attempt_url: this.collection.toJSON()[0].attempt_url
});
this.$el.html(html); this.$el.html(html);
this.$el.show(); this.$el.show();
} }
......
<div class="wrapper-content wrapper"> <div class="wrapper-content wrapper">
<section class="content"> <section class="content">
<%
var humanized_time = function(time_in_minutes) {
var hours = parseInt(time_in_minutes / 60);
var minutes = time_in_minutes % 60;
<table class="allowance-table"> var hours_present = false;
if (hours == 0) {
hours_present = false;
var template = ""
}
else if (hours == 1) {
template = hours + " Hour ";
hours_present = true;
}
else if (hours >= 2) {
console.log(hours);
template = hours + " Hours ";
hours_present = true
}
else {
template = "error";
}
if (template !== "error") {
if (minutes == 0) {
if (!hours_present) {
template = minutes + " Minutes";
}
}
else if ( minutes == 1 ) {
if (hours_present) {
template = template + " and " +minutes + " Minute";
}
else {
template = template + minutes + " Minute";
}
}
else {
if (hours_present) {
template = template + " and " + minutes + " Minutes";
}
else {
template = template + minutes + " Minutes";
}
}
}
return template;
}
%>
<ul class="pagination">
<% if (!pagination_info.has_previous){ %>
<li class="disabled">
<a aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<% } else { %>
<li>
<a class="target-link " data-target-url="
<%- interpolate(
'%(attempt_url)s?page=%(count)s ',
{
attempt_url: attempt_url,
count: pagination_info.current_page - 1
},
true
) %> "
href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<% }%>
<% for(var n = 1; n <= pagination_info.total_pages; n++) { %>
<li>
<a class="target-link <% if (pagination_info.current_page == n){ %> active <% } %>"
data-target-url="
<%- interpolate(
'%(attempt_url)s?page=%(count)s ',
{
attempt_url: attempt_url,
count: n
},
true
) %>
"
href="#"><%= n %>
</a>
</li>
<% } %>
<% if (!pagination_info.has_next){ %>
<li class="disabled">
<a aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
<% } else { %>
<li>
<a class="target-link" href="#" aria-label="Next" data-target-url="
<%- interpolate(
'%(attempt_url)s?page=%(count)s ',
{
attempt_url: attempt_url,
count: pagination_info.current_page + 1
},
true
) %> "
>
<span aria-hidden="true">&raquo;</span>
</a>
</li>
<% }%>
</ul>
<table class="exam-attempts-table">
<thead> <thead>
<tr class="exam-attempt-headings"> <tr class="exam-attempt-headings">
<th class="username"><%- gettext("Username") %></th> <th class="username"><%- gettext("Username") %></th>
<th class="attempt-exam-name"><%- gettext("Exam Name") %></th> <th class="exam-name"><%- gettext("Exam Name") %></th>
<th class="attempt-allowed-time"><%- gettext("Allowed Time for Student") %> </th> <th class="attempt-allowed-time"><%- gettext("Allowed Time for Student") %> </th>
<th class="attempt-started-at"><%- gettext("started At") %></th> <th class="attempt-started-at"><%- gettext("started At") %></th>
<th class="attempt-completed-at"><%- gettext("Completed At") %> </th> <th class="attempt-completed-at"><%- gettext("Completed At") %> </th>
<th class="attempt-status"><%- gettext("Status") %> </th> <th class="attempt-status"><%- gettext("Status") %> </th>
<th class="attempt-action"><%- gettext("Action") %> </th> <th class="c_action"><%- gettext("Action") %> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
...@@ -22,17 +135,17 @@ ...@@ -22,17 +135,17 @@
<td> <td>
<%- interpolate(gettext(' %(exam_display_name)s '), { exam_display_name: proctored_exam_attempt.proctored_exam.exam_name }, true) %> <%- interpolate(gettext(' %(exam_display_name)s '), { exam_display_name: proctored_exam_attempt.proctored_exam.exam_name }, true) %>
</td> </td>
<td> <%= proctored_exam_attempt.allowed_time_limit_mins %></td> <td> <%= humanized_time(proctored_exam_attempt.allowed_time_limit_mins) %></td>
<td> <td>
<% if (proctored_exam_attempt.started_at){ %> <% if (proctored_exam_attempt.started_at){ %>
<%= proctored_exam_attempt.started_at %> <%= new Date(proctored_exam_attempt.started_at).toString("MMMM dd, yyyy HH:MM") %>
<% } else { %> <% } else { %>
N/A N/A
<% } %> <% } %>
</td> </td>
<td> <td>
<% if (proctored_exam_attempt.completed_at){ %> <% if (proctored_exam_attempt.completed_at){ %>
<%= proctored_exam_attempt.completed_at %> </td> <%= new Date(proctored_exam_attempt.completed_at).toString("MMMM dd, yyyy HH:MM") %>
<% } else { %> <% } else { %>
N/A N/A
<% } %> <% } %>
...@@ -44,7 +157,7 @@ ...@@ -44,7 +157,7 @@
<% } %> <% } %>
<td> <td>
<% if (proctored_exam_attempt.status){ %> <% if (proctored_exam_attempt.status){ %>
<button type="button" class="remove-attempt blue-button" data-attempt-id="<%= proctored_exam_attempt.id %>" ><%- gettext("Remove") %></button> <td><button type="button" class="remove-attempt blue-button" data-attempt-id="<%= proctored_exam_attempt.id %>" ><%- gettext("Remove") %></button></td>
<% } else { %> <% } else { %>
N/A N/A
<% } %> <% } %>
......
...@@ -22,7 +22,9 @@ from edx_proctoring.api import ( ...@@ -22,7 +22,9 @@ from edx_proctoring.api import (
get_allowances_for_course, get_allowances_for_course,
get_all_exams_for_course, get_all_exams_for_course,
get_exam_attempt_by_id, get_exam_attempt_by_id,
remove_exam_attempt_by_id) remove_exam_attempt_by_id,
get_all_exam_attempts
)
from edx_proctoring.exceptions import ( from edx_proctoring.exceptions import (
ProctoredExamAlreadyExists, ProctoredExamAlreadyExists,
ProctoredExamNotFoundException, ProctoredExamNotFoundException,
...@@ -384,6 +386,26 @@ class ProctoredExamApiTests(LoggedInTestCase): ...@@ -384,6 +386,26 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.assertEqual(len(student_active_exams[0]['allowances']), 2) self.assertEqual(len(student_active_exams[0]['allowances']), 2)
self.assertEqual(len(student_active_exams[1]['allowances']), 0) self.assertEqual(len(student_active_exams[1]['allowances']), 0)
def test_get_all_exam_attempts(self):
"""
Test to get all the exam attempts.
"""
exam_attempt = self._create_started_exam_attempt()
exam_id = create_exam(
course_id=self.course_id,
content_id='test_content_2',
exam_name='Final Test Exam',
time_limit_mins=self.default_time_limit
)
updated_exam_attempt_id = create_exam_attempt(
exam_id=exam_id,
user_id=self.user_id
)
all_exams = get_all_exam_attempts(self.course_id)
self.assertEqual(len(all_exams), 2)
self.assertEqual(all_exams[0]['id'], exam_attempt.id)
self.assertEqual(all_exams[1]['id'], updated_exam_attempt_id)
def test_get_student_view(self): def test_get_student_view(self):
""" """
Test for get_student_view promting the user to take the exam Test for get_student_view promting the user to take the exam
......
...@@ -587,6 +587,36 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase): ...@@ -587,6 +587,36 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
response_data = json.loads(response.content) response_data = json.loads(response.content)
self.assertEqual(response_data['exam_attempt_id'], old_attempt_id) self.assertEqual(response_data['exam_attempt_id'], old_attempt_id)
def test_get_exam_attempts_in_a_course(self):
"""
Test to get the exam attempts in a course.
"""
# Create an exam.
proctored_exam = ProctoredExam.objects.create(
course_id='a/b/c',
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90
)
attempt_data = {
'exam_id': proctored_exam.id,
'user_id': self.student_taking_exam.id,
'external_id': proctored_exam.external_id
}
response = self.client.post(
reverse('edx_proctoring.proctored_exam.attempt.collection'),
attempt_data
)
self.assertEqual(response.status_code, 200)
response = self.client.get(
reverse('edx_proctoring.proctored_exam.attempt', kwargs={'course_id': proctored_exam.course_id})
)
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
self.assertEqual(len(response_data['proctored_exam_attempts']), 1)
def test_stop_others_attempt(self): def test_stop_others_attempt(self):
""" """
Start an exam (create an exam attempt) Start an exam (create an exam attempt)
......
...@@ -5,6 +5,7 @@ Proctored Exams HTTP-based API endpoints ...@@ -5,6 +5,7 @@ Proctored Exams HTTP-based API endpoints
import logging import logging
import pytz import pytz
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.core.urlresolvers import reverse
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.conf import settings from django.conf import settings
...@@ -393,6 +394,8 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView): ...@@ -393,6 +394,8 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView):
""" """
if course_id is not None: if course_id is not None:
exam_attempts = get_all_exam_attempts(course_id) exam_attempts = get_all_exam_attempts(course_id)
# TODO have to change the default attempts per page
paginator = Paginator(exam_attempts, 1) # Show 1 attempts per page paginator = Paginator(exam_attempts, 1) # Show 1 attempts per page
page = request.GET.get('page') page = request.GET.get('page')
try: try:
...@@ -411,7 +414,9 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView): ...@@ -411,7 +414,9 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView):
'has_next': exam_attempts_page.has_next(), 'has_next': exam_attempts_page.has_next(),
'current_page': exam_attempts_page.number, 'current_page': exam_attempts_page.number,
'total_pages': exam_attempts_page.paginator.num_pages, 'total_pages': exam_attempts_page.paginator.num_pages,
} },
'attempt_url': reverse('edx_proctoring.proctored_exam.attempt', args=[course_id])
} }
return Response( return Response(
data=data, data=data,
......
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