Commit 940d24bc by Muhammad Shoaib

added the pagination for the student attempts

parent a7f4c56a
......@@ -26,7 +26,17 @@ var edx = edx || {};
this.loadTemplateData();
},
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 () {
var cookieValue = null;
......@@ -73,7 +83,11 @@ var edx = edx || {};
},
render: function () {
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.show();
}
......
<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">
<thead>
<tr class="exam-attempt-headings">
<th class="username"><%- gettext("Username") %></th>
<th class="attempt-exam-name"><%- gettext("Exam Name") %></th>
<th class="attempt-allowed-time"><%- gettext("Allowed Time for Student") %> </th>
<th class="attempt-started-at"><%- gettext("started At") %></th>
<th class="attempt-completed-at"><%- gettext("Completed At") %> </th>
<th class="attempt-status"><%- gettext("Status") %> </th>
<th class="attempt-action"><%- gettext("Action") %> </th>
</tr>
</thead>
<tbody>
<% _.each(proctored_exam_attempts, function(proctored_exam_attempt){ %>
<tr class="allowance-items">
<td>
<%- interpolate(gettext(' %(username)s '), { username: proctored_exam_attempt.user.username }, true) %>
</td>
<td>
<%- interpolate(gettext(' %(exam_display_name)s '), { exam_display_name: proctored_exam_attempt.proctored_exam.exam_name }, true) %>
</td>
<td> <%= proctored_exam_attempt.allowed_time_limit_mins %></td>
<td>
<% if (proctored_exam_attempt.started_at){ %>
<%= proctored_exam_attempt.started_at %>
<% } else { %>
N/A
<% } %>
</td>
<td>
<% if (proctored_exam_attempt.completed_at){ %>
<%= proctored_exam_attempt.completed_at %> </td>
<% } else { %>
N/A
<% } %>
<td>
<% if (proctored_exam_attempt.status){ %>
<%= proctored_exam_attempt.status %> </td>
<% } else { %>
N/A
<% } %>
<td>
<% if (proctored_exam_attempt.status){ %>
<button type="button" class="remove-attempt blue-button" data-attempt-id="<%= proctored_exam_attempt.id %>" ><%- gettext("Remove") %></button>
<% } else { %>
N/A
<% } %>
</td>
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>
<tr class="exam-attempt-headings">
<th class="username"><%- gettext("Username") %></th>
<th class="exam-name"><%- gettext("Exam Name") %></th>
<th class="attempt-allowed-time"><%- gettext("Allowed Time for Student") %> </th>
<th class="attempt-started-at"><%- gettext("started At") %></th>
<th class="attempt-completed-at"><%- gettext("Completed At") %> </th>
<th class="attempt-status"><%- gettext("Status") %> </th>
<th class="c_action"><%- gettext("Action") %> </th>
</tr>
<% }); %>
</tbody>
</table>
</section>
</thead>
<tbody>
<% _.each(proctored_exam_attempts, function(proctored_exam_attempt){ %>
<tr class="allowance-items">
<td>
<%- interpolate(gettext(' %(username)s '), { username: proctored_exam_attempt.user.username }, true) %>
</td>
<td>
<%- interpolate(gettext(' %(exam_display_name)s '), { exam_display_name: proctored_exam_attempt.proctored_exam.exam_name }, true) %>
</td>
<td> <%= humanized_time(proctored_exam_attempt.allowed_time_limit_mins) %></td>
<td>
<% if (proctored_exam_attempt.started_at){ %>
<%= new Date(proctored_exam_attempt.started_at).toString("MMMM dd, yyyy HH:MM") %>
<% } else { %>
N/A
<% } %>
</td>
<td>
<% if (proctored_exam_attempt.completed_at){ %>
<%= new Date(proctored_exam_attempt.completed_at).toString("MMMM dd, yyyy HH:MM") %>
<% } else { %>
N/A
<% } %>
<td>
<% if (proctored_exam_attempt.status){ %>
<%= proctored_exam_attempt.status %> </td>
<% } else { %>
N/A
<% } %>
<td>
<% if (proctored_exam_attempt.status){ %>
<td><button type="button" class="remove-attempt blue-button" data-attempt-id="<%= proctored_exam_attempt.id %>" ><%- gettext("Remove") %></button></td>
<% } else { %>
N/A
<% } %>
</td>
</tr>
<% }); %>
</tbody>
</table>
</section>
</div>
\ No newline at end of file
......@@ -22,7 +22,9 @@ from edx_proctoring.api import (
get_allowances_for_course,
get_all_exams_for_course,
get_exam_attempt_by_id,
remove_exam_attempt_by_id)
remove_exam_attempt_by_id,
get_all_exam_attempts
)
from edx_proctoring.exceptions import (
ProctoredExamAlreadyExists,
ProctoredExamNotFoundException,
......@@ -384,6 +386,26 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.assertEqual(len(student_active_exams[0]['allowances']), 2)
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):
"""
Test for get_student_view promting the user to take the exam
......
......@@ -587,6 +587,36 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
response_data = json.loads(response.content)
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):
"""
Start an exam (create an exam attempt)
......
......@@ -5,6 +5,7 @@ Proctored Exams HTTP-based API endpoints
import logging
import pytz
from datetime import datetime, timedelta
from django.core.urlresolvers import reverse
from django.utils.decorators import method_decorator
from django.conf import settings
......@@ -393,6 +394,8 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView):
"""
if course_id is not None:
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
page = request.GET.get('page')
try:
......@@ -411,7 +414,9 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView):
'has_next': exam_attempts_page.has_next(),
'current_page': exam_attempts_page.number,
'total_pages': exam_attempts_page.paginator.num_pages,
}
},
'attempt_url': reverse('edx_proctoring.proctored_exam.attempt', args=[course_id])
}
return Response(
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