Commit bed05040 by Chris Dodge

add the ready_to_start page

parent 5ad4465d
...@@ -718,25 +718,30 @@ def get_student_view(user_id, course_id, content_id, ...@@ -718,25 +718,30 @@ def get_student_view(user_id, course_id, content_id,
expires_at = attempt['started_at'] + timedelta(minutes=attempt['allowed_time_limit_mins']) expires_at = attempt['started_at'] + timedelta(minutes=attempt['allowed_time_limit_mins'])
does_time_remain = datetime.now(pytz.UTC) < expires_at does_time_remain = datetime.now(pytz.UTC) < expires_at
if not has_started_exam: if attempt:
print '*** status = {}'.format(attempt['status'])
if not attempt:
# determine whether to show a timed exam only entrance screen # determine whether to show a timed exam only entrance screen
# or a screen regarding proctoring # or a screen regarding proctoring
if is_proctored: if is_proctored:
if not attempt: if exam['is_practice_exam']:
if exam['is_practice_exam']: student_view_template = 'proctoring/seq_proctored_practice_exam_entrance.html'
student_view_template = 'proctoring/seq_proctored_practice_exam_entrance.html'
else:
student_view_template = 'proctoring/seq_proctored_exam_entrance.html'
else: else:
provider = get_backend_provider() student_view_template = 'proctoring/seq_proctored_exam_entrance.html'
student_view_template = 'proctoring/seq_proctored_exam_instructions.html'
context.update({
'exam_code': attempt['attempt_code'],
'software_download_url': provider.get_software_download_url(),
})
else: else:
student_view_template = 'proctoring/seq_timed_exam_entrance.html' student_view_template = 'proctoring/seq_timed_exam_entrance.html'
elif attempt['status'] == ProctoredExamStudentAttemptStatus.created:
provider = get_backend_provider()
student_view_template = 'proctoring/seq_proctored_exam_instructions.html'
context.update({
'exam_code': attempt['attempt_code'],
'software_download_url': provider.get_software_download_url(),
})
elif attempt['status'] == ProctoredExamStudentAttemptStatus.ready_to_start:
student_view_template = 'proctoring/seq_proctored_exam_ready_to_start.html'
elif attempt['status'] == ProctoredExamStudentAttemptStatus.error: elif attempt['status'] == ProctoredExamStudentAttemptStatus.error:
student_view_template = 'proctoring/seq_proctored_exam_error.html' student_view_template = 'proctoring/seq_proctored_exam_error.html'
elif attempt['status'] == ProctoredExamStudentAttemptStatus.timed_out: elif attempt['status'] == ProctoredExamStudentAttemptStatus.timed_out:
......
...@@ -192,11 +192,13 @@ ...@@ -192,11 +192,13 @@
{% endblocktrans %} {% endblocktrans %}
</p> </p>
</div> </div>
<!--
<div class="footer"> <div class="footer">
<button> <button>
{% blocktrans %} Go to my exam {% endblocktrans %} {% blocktrans %} Go to my exam {% endblocktrans %}
</button> </button>
</div> </div>
-->
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
......
...@@ -138,24 +138,9 @@ ...@@ -138,24 +138,9 @@
if (_waiting_for_proctored_interval != null) { if (_waiting_for_proctored_interval != null) {
clearInterval(_waiting_for_proctored_interval) clearInterval(_waiting_for_proctored_interval)
} }
// Let the student know exam is ready to start. // we've state transitioned, so refresh the page
// This alert may or may not bring the browser window back to the // to reflect the new state (which will expose the test)
// foreground (depending on browser as well as user settings) location.reload();
alert('{% trans "Your proctored exam has started, please click OK to enter into your exam." %}')
// after the user acknowledges the alert then we can start
// the exam and timer
$.ajax({
url: url,
type: 'PUT',
data: {
action: 'start'
},
success: function() {
// Reloading page will reflect the new state of the attempt
location.reload()
}
});
} }
}); });
} }
......
{% load i18n %}
<div class="sequence proctored-exam instructions" data-exam-id="{{exam_id}}" data-exam-started-poll-url="{{exam_started_poll_url}}">
<h3>
{% blocktrans %}
Your Proctoring Installation and Set Up is Complete
{% endblocktrans %}
</h3>
<p>
{% blocktrans %}
Placeholder content. <strong>Please keep the proctoring software open and running while you complete your exam</strong>.
{% endblocktrans %}
</p>
<div class="proctored-exam-message">
<h3>
{% blocktrans %}
You May Begin Your Exam Now
{% endblocktrans %}
</h3>
<p>
{% blocktrans %}
Your proctored and timed exam is now ready. Once you start, <strong>you will have {{total_time}} to
complete the exam and cannot stop the timer</strong>. If you did not active complete the exam, at the
end of that period your exam will close and proctoring session will be reviewed.
{% endblocktrans %}
</p>
<div>
<button type="button" class="proctored-enter-exam" data-action="start" data-exam-id="{{exam_id}}" data-change-state-url="{{change_state_url}}">
{% blocktrans %}
I'm ready! Start my timed proctored exam
{% endblocktrans %}
</button>
</div>
</div>
</div>
{% include 'proctoring/seq_proctored_exam_footer.html' %}
<script type="text/javascript">
$('.proctored-enter-exam').click(
function(e) {
e.preventDefault();
e.stopPropagation();
var action_url = $(this).data('change-state-url');
var exam_id = $(this).data('exam-id');
var action = $(this).data('action')
// Update the state of the attempt
$.ajax({
url: action_url,
type: 'PUT',
data: {
action: action
},
success: function() {
// Reloading page will reflect the new state of the attempt
location.reload()
}
});
}
);
</script>
...@@ -101,6 +101,7 @@ class ProctoredExamApiTests(LoggedInTestCase): ...@@ -101,6 +101,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.timed_exam_completed_msg = 'This is the end of your timed exam' self.timed_exam_completed_msg = 'This is the end of your timed exam'
self.start_a_practice_exam_msg = 'Would you like to take %s as a practice proctored exam?' self.start_a_practice_exam_msg = 'Would you like to take %s as a practice proctored exam?'
self.practice_exam_submitted_msg = 'You have submitted this practice proctored exam' self.practice_exam_submitted_msg = 'You have submitted this practice proctored exam'
self.ready_to_start_msg = 'Your Proctoring Installation and Set Up is Complete'
set_runtime_service('credit', MockCreditService()) set_runtime_service('credit', MockCreditService())
set_runtime_service('instructor', MockInstructorService()) set_runtime_service('instructor', MockInstructorService())
...@@ -161,7 +162,8 @@ class ProctoredExamApiTests(LoggedInTestCase): ...@@ -161,7 +162,8 @@ class ProctoredExamApiTests(LoggedInTestCase):
proctored_exam_id=self.proctored_exam_id if is_proctored else self.timed_exam, proctored_exam_id=self.proctored_exam_id if is_proctored else self.timed_exam,
user_id=self.user_id, user_id=self.user_id,
external_id=self.external_id, external_id=self.external_id,
allowed_time_limit_mins=10 allowed_time_limit_mins=10,
status='created'
) )
def _create_started_exam_attempt(self, started_at=None, is_proctored=True): def _create_started_exam_attempt(self, started_at=None, is_proctored=True):
...@@ -820,6 +822,27 @@ class ProctoredExamApiTests(LoggedInTestCase): ...@@ -820,6 +822,27 @@ class ProctoredExamApiTests(LoggedInTestCase):
) )
self.assertIsNone(rendered_response) self.assertIsNone(rendered_response)
def test_get_studentview_ready(self):
"""
Assert that we get the right content
when the exam is ready to be started
"""
exam_attempt = self._create_started_exam_attempt()
exam_attempt.status = ProctoredExamStudentAttemptStatus.ready_to_start
exam_attempt.save()
rendered_response = get_student_view(
user_id=self.user_id,
course_id=self.course_id,
content_id=self.content_id,
context={
'is_proctored': True,
'display_name': self.exam_name,
'default_time_limit_mins': 90
}
)
self.assertIn(self.ready_to_start_msg, rendered_response)
def test_get_studentview_started_exam(self): # pylint: disable=invalid-name def test_get_studentview_started_exam(self): # pylint: disable=invalid-name
""" """
Test for get_student_view proctored exam which has started. Test for get_student_view proctored exam which has started.
...@@ -869,7 +892,7 @@ class ProctoredExamApiTests(LoggedInTestCase): ...@@ -869,7 +892,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
Test for get_student_view proctored exam which has been submitted. Test for get_student_view proctored exam which has been submitted.
""" """
exam_attempt = self._create_started_exam_attempt() exam_attempt = self._create_started_exam_attempt()
exam_attempt.status = "submitted" exam_attempt.status = ProctoredExamStudentAttemptStatus.submitted
exam_attempt.save() exam_attempt.save()
rendered_response = get_student_view( rendered_response = get_student_view(
...@@ -905,7 +928,7 @@ class ProctoredExamApiTests(LoggedInTestCase): ...@@ -905,7 +928,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
Test for get_student_view proctored exam which has been rejected. Test for get_student_view proctored exam which has been rejected.
""" """
exam_attempt = self._create_started_exam_attempt() exam_attempt = self._create_started_exam_attempt()
exam_attempt.status = "rejected" exam_attempt.status = ProctoredExamStudentAttemptStatus.rejected
exam_attempt.save() exam_attempt.save()
rendered_response = get_student_view( rendered_response = get_student_view(
...@@ -925,7 +948,7 @@ class ProctoredExamApiTests(LoggedInTestCase): ...@@ -925,7 +948,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
Test for get_student_view proctored exam which has been verified. Test for get_student_view proctored exam which has been verified.
""" """
exam_attempt = self._create_started_exam_attempt() exam_attempt = self._create_started_exam_attempt()
exam_attempt.status = "verified" exam_attempt.status = ProctoredExamStudentAttemptStatus.verified
exam_attempt.save() exam_attempt.save()
rendered_response = get_student_view( rendered_response = get_student_view(
......
...@@ -14,34 +14,34 @@ class TestHumanizedTime(unittest.TestCase): ...@@ -14,34 +14,34 @@ class TestHumanizedTime(unittest.TestCase):
tests the humanized_time utility function against different values. tests the humanized_time utility function against different values.
""" """
human_time = humanized_time(0) human_time = humanized_time(0)
self.assertEqual(human_time, "0 Minutes") self.assertEqual(human_time, "0 minutes")
human_time = humanized_time(1) human_time = humanized_time(1)
self.assertEqual(human_time, "1 Minute") self.assertEqual(human_time, "1 minute")
human_time = humanized_time(10) human_time = humanized_time(10)
self.assertEqual(human_time, "10 Minutes") self.assertEqual(human_time, "10 minutes")
human_time = humanized_time(60) human_time = humanized_time(60)
self.assertEqual(human_time, "1 Hour") self.assertEqual(human_time, "1 hour")
human_time = humanized_time(61) human_time = humanized_time(61)
self.assertEqual(human_time, "1 Hour and 1 Minute") self.assertEqual(human_time, "1 hour and 1 minute")
human_time = humanized_time(62) human_time = humanized_time(62)
self.assertEqual(human_time, "1 Hour and 2 Minutes") self.assertEqual(human_time, "1 hour and 2 minutes")
human_time = humanized_time(120) human_time = humanized_time(120)
self.assertEqual(human_time, "2 Hours") self.assertEqual(human_time, "2 hours")
human_time = humanized_time(121) human_time = humanized_time(121)
self.assertEqual(human_time, "2 Hours and 1 Minute") self.assertEqual(human_time, "2 hours and 1 minute")
human_time = humanized_time(150) human_time = humanized_time(150)
self.assertEqual(human_time, "2 Hours and 30 Minutes") self.assertEqual(human_time, "2 hours and 30 minutes")
human_time = humanized_time(180) human_time = humanized_time(180)
self.assertEqual(human_time, "3 Hours") self.assertEqual(human_time, "3 hours")
human_time = humanized_time(-60) human_time = humanized_time(-60)
self.assertEqual(human_time, "error") self.assertEqual(human_time, "error")
...@@ -33,10 +33,10 @@ def humanized_time(time_in_minutes): ...@@ -33,10 +33,10 @@ def humanized_time(time_in_minutes):
hours_present = False hours_present = False
template = "" template = ""
elif hours == 1: elif hours == 1:
template = _("{num_of_hours} Hour") template = _("{num_of_hours} hour")
hours_present = True hours_present = True
elif hours >= 2: elif hours >= 2:
template = _("{num_of_hours} Hours") template = _("{num_of_hours} hours")
hours_present = True hours_present = True
else: else:
template = "error" template = "error"
...@@ -44,17 +44,17 @@ def humanized_time(time_in_minutes): ...@@ -44,17 +44,17 @@ def humanized_time(time_in_minutes):
if template != "error": if template != "error":
if minutes == 0: if minutes == 0:
if not hours_present: if not hours_present:
template = _("{num_of_minutes} Minutes") template = _("{num_of_minutes} minutes")
elif minutes == 1: elif minutes == 1:
if hours_present: if hours_present:
template += _(" and {num_of_minutes} Minute") template += _(" and {num_of_minutes} minute")
else: else:
template += _("{num_of_minutes} Minute") template += _("{num_of_minutes} minute")
else: else:
if hours_present: if hours_present:
template += _(" and {num_of_minutes} Minutes") template += _(" and {num_of_minutes} minutes")
else: else:
template += _("{num_of_minutes} Minutes") template += _("{num_of_minutes} minutes")
human_time = template.format(num_of_hours=hours, num_of_minutes=minutes) human_time = template.format(num_of_hours=hours, num_of_minutes=minutes)
return human_time return human_time
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