Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-proctoring
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
edx-proctoring
Commits
3f2712e6
Commit
3f2712e6
authored
Jul 13, 2015
by
Muhammad Shoaib
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added the backbone structure and new endpoint for all the proctored exam attempts in a course.
parent
6f90af77
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
190 additions
and
6 deletions
+190
-6
edx_proctoring/serializers.py
+4
-4
edx_proctoring/static/proctoring/js/collections/proctored_exam_attempt_collection.js
+14
-0
edx_proctoring/static/proctoring/js/models/proctored_exam_attempt_model.js
+15
-0
edx_proctoring/static/proctoring/js/proctored_app.js
+5
-0
edx_proctoring/static/proctoring/js/views/proctored_exam_attempt_view.js
+81
-0
edx_proctoring/static/proctoring/templates/student-proctored-exam-attempts.underscore
+40
-0
edx_proctoring/tests/test_api.py
+2
-2
edx_proctoring/views.py
+29
-0
No files found.
edx_proctoring/serializers.py
View file @
3f2712e6
...
...
@@ -66,8 +66,8 @@ class ProctoredExamStudentAttemptSerializer(serializers.ModelSerializer):
"""
Serializer for the ProctoredExamStudentAttempt Model.
"""
proctored_exam
_id
=
serializers
.
IntegerField
(
source
=
"proctored_exam_id"
)
user
_id
=
serializers
.
IntegerField
(
required
=
False
)
proctored_exam
=
ProctoredExamSerializer
(
)
user
=
UserSerializer
(
)
class
Meta
:
"""
...
...
@@ -76,8 +76,8 @@ class ProctoredExamStudentAttemptSerializer(serializers.ModelSerializer):
model
=
ProctoredExamStudentAttempt
fields
=
(
"id"
,
"created"
,
"modified"
,
"user
_id
"
,
"started_at"
,
"completed_at"
,
"external_id"
,
"status"
,
"proctored_exam
_id
"
,
"allowed_time_limit_mins"
,
"id"
,
"created"
,
"modified"
,
"user"
,
"started_at"
,
"completed_at"
,
"external_id"
,
"status"
,
"proctored_exam"
,
"allowed_time_limit_mins"
,
"attempt_code"
,
"is_sample_attempt"
,
"taking_as_proctored"
)
...
...
edx_proctoring/static/proctoring/js/collections/proctored_exam_attempt_collection.js
0 → 100644
View file @
3f2712e6
var
edx
=
edx
||
{};
(
function
(
Backbone
)
{
edx
.
instructor_dashboard
=
edx
.
instructor_dashboard
||
{};
edx
.
instructor_dashboard
.
proctoring
=
edx
.
instructor_dashboard
.
proctoring
||
{};
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptCollection
=
Backbone
.
Collection
.
extend
({
/* model for a collection of ProctoredExamAllowance */
model
:
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptModel
,
url
:
'/api/edx_proctoring/v1/proctored_exam/attempt/course_id/'
});
this
.
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptCollection
=
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptCollection
;
}).
call
(
this
,
Backbone
);
\ No newline at end of file
edx_proctoring/static/proctoring/js/models/proctored_exam_attempt_model.js
0 → 100644
View file @
3f2712e6
var
edx
=
edx
||
{};
(
function
(
Backbone
)
{
'use strict'
;
edx
.
instructor_dashboard
=
edx
.
instructor_dashboard
||
{};
edx
.
instructor_dashboard
.
proctoring
=
edx
.
instructor_dashboard
.
proctoring
||
{};
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptModel
=
Backbone
.
Model
.
extend
({
url
:
'/api/edx_proctoring/v1/proctored_exam/allowance'
});
this
.
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptModel
=
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptModel
;
}).
call
(
this
,
Backbone
);
edx_proctoring/static/proctoring/js/proctored_app.js
View file @
3f2712e6
...
...
@@ -5,4 +5,9 @@ $(function() {
model
:
new
ProctoredExamModel
()
});
proctored_exam_view
.
render
();
var
proctored_exam_attempt_view
=
new
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptView
({
el
:
$
(
'.student-proctored-exam-container'
),
template_url
:
'/static/proctoring/templates/student-proctored-exam-attempts.underscore'
,
collection
:
new
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptCollection
()
});
});
edx_proctoring/static/proctoring/js/views/proctored_exam_attempt_view.js
0 → 100644
View file @
3f2712e6
var
edx
=
edx
||
{};
(
function
(
Backbone
,
$
,
_
)
{
'use strict'
;
edx
.
instructor_dashboard
=
edx
.
instructor_dashboard
||
{};
edx
.
instructor_dashboard
.
proctoring
=
edx
.
instructor_dashboard
.
proctoring
||
{};
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptView
=
Backbone
.
View
.
extend
({
initialize
:
function
(
options
)
{
this
.
$el
=
options
.
el
;
this
.
collection
=
options
.
collection
;
this
.
tempate_url
=
options
.
template_url
;
this
.
course_id
=
this
.
$el
.
data
(
'course-id'
);
this
.
template
=
null
;
this
.
initial_url
=
this
.
collection
.
url
;
this
.
collection
.
url
=
this
.
initial_url
+
this
.
course_id
;
/* re-render if the model changes */
this
.
listenTo
(
this
.
collection
,
'change'
,
this
.
collectionChanged
);
/* Load the static template for rendering. */
this
.
loadTemplateData
();
},
events
:
{
},
getCSRFToken
:
function
()
{
var
cookieValue
=
null
;
var
name
=
'csrftoken'
;
if
(
document
.
cookie
&&
document
.
cookie
!=
''
)
{
var
cookies
=
document
.
cookie
.
split
(
';'
);
for
(
var
i
=
0
;
i
<
cookies
.
length
;
i
++
)
{
var
cookie
=
jQuery
.
trim
(
cookies
[
i
]);
// Does this cookie string begin with the name we want?
if
(
cookie
.
substring
(
0
,
name
.
length
+
1
)
==
(
name
+
'='
))
{
cookieValue
=
decodeURIComponent
(
cookie
.
substring
(
name
.
length
+
1
));
break
;
}
}
}
return
cookieValue
;
},
loadTemplateData
:
function
()
{
var
self
=
this
;
$
.
ajax
({
url
:
self
.
tempate_url
,
dataType
:
"html"
})
.
error
(
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
})
.
done
(
function
(
template_data
)
{
self
.
template
=
_
.
template
(
template_data
);
self
.
hydrate
();
});
},
hydrate
:
function
()
{
/* This function will load the bound collection */
/* add and remove a class when we do the initial loading */
/* we might - at some point - add a visual element to the */
/* loading, like a spinner */
var
self
=
this
;
self
.
collection
.
fetch
({
success
:
function
()
{
self
.
render
();
}
});
},
collectionChanged
:
function
()
{
this
.
hydrate
();
},
render
:
function
()
{
if
(
this
.
template
!==
null
)
{
var
html
=
this
.
template
(
this
.
collection
.
toJSON
());
this
.
$el
.
html
(
html
);
this
.
$el
.
show
();
}
}
});
this
.
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptView
=
edx
.
instructor_dashboard
.
proctoring
.
ProctoredExamAttemptView
;
}).
call
(
this
,
Backbone
,
$
,
_
);
edx_proctoring/static/proctoring/templates/student-proctored-exam-attempts.underscore
0 → 100644
View file @
3f2712e6
<div class="wrapper-content wrapper">
<section class="content">
<table class="allowance-table">
<thead>
<tr class="allowance-headings">
<th class="exam-name"><%- gettext("Exam Name") %></th>
<th class="username"><%- gettext("Username") %></th>
<th class="email"><%- gettext("Email") %></th>
<th class="allowance-name"><%- gettext("Is Exam Completed") %> </th>
<th class="allowance-value"><%- gettext("Is Exam Completed in Time") %></th>
<th class="c_action"><%- gettext("Verification Status") %> </th>
</tr>
</thead>
<tbody>
<% _.each(proctored_exam_attempts, function(proctored_exam_attempt){ %>
<tr class="allowance-items">
<td>
<%- interpolate(gettext(' %(exam_display_name)s '), { exam_display_name: proctored_exam_attempt.proctored_exam.exam_name }, true) %>
</td>
<td>
<%- interpolate(gettext(' %(username)s '), { username: proctored_exam_attempt.user.username }, true) %>
</td>
<td>
<%- interpolate(gettext(' %(email)s '), { email: proctored_exam_attempt.user.email }, true) %>
</td>
<td>
True
</td>
<td>False</td>
<td>
True
</td>
</tr>
<% }); %>
</tbody>
</table>
</section>
</div>
\ No newline at end of file
edx_proctoring/tests/test_api.py
View file @
3f2712e6
...
...
@@ -288,8 +288,8 @@ class ProctoredExamApiTests(LoggedInTestCase):
self
.
_create_unstarted_exam_attempt
()
exam_attempt
=
get_exam_attempt
(
self
.
proctored_exam_id
,
self
.
user_id
)
self
.
assertEqual
(
exam_attempt
[
'proctored_exam
_
id'
],
self
.
proctored_exam_id
)
self
.
assertEqual
(
exam_attempt
[
'user
_
id'
],
self
.
user_id
)
self
.
assertEqual
(
exam_attempt
[
'proctored_exam
'
][
'
id'
],
self
.
proctored_exam_id
)
self
.
assertEqual
(
exam_attempt
[
'user
'
][
'
id'
],
self
.
user_id
)
def
test_start_uncreated_attempt
(
self
):
"""
...
...
edx_proctoring/views.py
View file @
3f2712e6
...
...
@@ -12,6 +12,7 @@ from django.core.urlresolvers import reverse, NoReverseMatch
from
rest_framework
import
status
from
rest_framework.response
import
Response
from
django.core.paginator
import
Paginator
,
EmptyPage
,
PageNotAnInteger
from
edx_proctoring.api
import
(
create_exam
,
update_exam
,
...
...
@@ -26,6 +27,7 @@ from edx_proctoring.api import (
get_allowances_for_course
,
get_all_exams_for_course
,
get_exam_attempt_by_id
,
get_all_exam_attempts
)
from
edx_proctoring.exceptions
import
(
ProctoredBaseException
,
...
...
@@ -362,6 +364,33 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView):
"""
HTTP GET Handler. Returns the status of the exam attempt.
"""
if
course_id
is
not
None
:
exam_attempts
=
get_all_exam_attempts
(
course_id
)
paginator
=
Paginator
(
exam_attempts
,
1
)
# Show 1 attempts per page
page
=
request
.
GET
.
get
(
'page'
)
try
:
exam_attempts_page
=
paginator
.
page
(
page
)
except
PageNotAnInteger
:
# If page is not an integer, deliver first page.
exam_attempts_page
=
paginator
.
page
(
1
)
except
EmptyPage
:
# If page is out of range (e.g. 9999), deliver last page of results.
exam_attempts_page
=
paginator
.
page
(
paginator
.
num_pages
)
data
=
{
'proctored_exam_attempts'
:
exam_attempts_page
.
object_list
,
'pagination_info'
:
{
'has_previous'
:
exam_attempts_page
.
has_previous
(),
'has_next'
:
exam_attempts_page
.
has_next
(),
'current_page'
:
exam_attempts_page
.
number
,
'total_pages'
:
exam_attempts_page
.
paginator
.
num_pages
,
}
}
return
Response
(
data
=
data
,
status
=
status
.
HTTP_200_OK
)
exams
=
get_active_exams_for_user
(
request
.
user
.
id
)
if
exams
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment