Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx
edx-platform
Commits
ffd72c10
Commit
ffd72c10
authored
Aug 16, 2017
by
Sofiya Semenova
Committed by
GitHub
Aug 16, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #15705 from edx/ssemenova/ed-526
EDUCATOR-526 Update view certificate button
parents
b8e48146
76f1df6b
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
99 additions
and
23 deletions
+99
-23
common/djangoapps/student/tests/tests.py
+1
-0
common/lib/xmodule/xmodule/course_metadata_utils.py
+19
-2
common/lib/xmodule/xmodule/course_module.py
+2
-1
common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py
+8
-5
lms/djangoapps/certificates/tests/test_api.py
+3
-1
lms/djangoapps/courseware/tests/test_views.py
+3
-0
lms/djangoapps/courseware/views/views.py
+33
-12
lms/djangoapps/mobile_api/testutils.py
+5
-1
lms/templates/courseware/progress.html
+2
-0
openedx/core/djangoapps/content/course_overviews/migrations/0014_courseoverview_certificate_available_date.py
+19
-0
openedx/core/djangoapps/content/course_overviews/models.py
+4
-1
No files found.
common/djangoapps/student/tests/tests.py
View file @
ffd72c10
...
...
@@ -514,6 +514,7 @@ class DashboardTest(ModuleStoreTestCase):
expiration_datetime
=
datetime
.
now
(
pytz
.
UTC
)
-
timedelta
(
days
=
1
)
)
self
.
course
.
certificate_available_date
=
datetime
.
now
(
pytz
.
UTC
)
-
timedelta
(
days
=
1
)
CourseEnrollment
.
enroll
(
self
.
user
,
self
.
course
.
id
,
mode
=
'honor'
)
self
.
course
.
start
=
datetime
.
now
(
pytz
.
UTC
)
-
timedelta
(
days
=
2
)
...
...
common/lib/xmodule/xmodule/course_metadata_utils.py
View file @
ffd72c10
...
...
@@ -93,7 +93,12 @@ def course_start_date_is_default(start, advertised_start):
return
advertised_start
is
None
and
start
==
DEFAULT_START_DATE
def
may_certify_for_course
(
certificates_display_behavior
,
certificates_show_before_end
,
has_ended
):
def
may_certify_for_course
(
certificates_display_behavior
,
certificates_show_before_end
,
has_ended
,
certificate_available_date
):
"""
Returns whether it is acceptable to show the student a certificate download
link for a course.
...
...
@@ -105,12 +110,24 @@ def may_certify_for_course(certificates_display_behavior, certificates_show_befo
certificates_show_before_end (bool): whether user can download the
course's certificates before the course has ended.
has_ended (bool): Whether the course has ended.
certificate_available_date (datetime): the date the certificate is available on for the course.
"""
show_early
=
(
certificates_display_behavior
in
(
'early_with_info'
,
'early_no_info'
)
or
certificates_show_before_end
)
return
show_early
or
has_ended
past_availability_date
=
(
certificate_available_date
and
certificate_available_date
<
datetime
.
now
(
utc
)
)
if
show_early
:
return
True
if
past_availability_date
:
return
True
if
(
certificate_available_date
is
None
)
and
has_ended
:
return
True
return
False
def
sorting_score
(
start
,
advertised_start
,
announcement
):
...
...
common/lib/xmodule/xmodule/course_module.py
View file @
ffd72c10
...
...
@@ -1065,7 +1065,8 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin):
return
course_metadata_utils
.
may_certify_for_course
(
self
.
certificates_display_behavior
,
self
.
certificates_show_before_end
,
self
.
has_ended
()
self
.
has_ended
(),
self
.
certificate_available_date
)
def
has_started
(
self
):
...
...
common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py
View file @
ffd72c10
...
...
@@ -161,11 +161,14 @@ class CourseMetadataUtilsTestCase(TestCase):
TestScenario
((
DEFAULT_START_DATE
,
None
),
True
),
]),
FunctionTest
(
may_certify_for_course
,
[
TestScenario
((
'early_with_info'
,
True
,
True
),
True
),
TestScenario
((
'early_no_info'
,
False
,
False
),
True
),
TestScenario
((
'end'
,
True
,
False
),
True
),
TestScenario
((
'end'
,
False
,
True
),
True
),
TestScenario
((
'end'
,
False
,
False
),
False
),
TestScenario
((
'early_with_info'
,
True
,
True
,
test_datetime
),
True
),
TestScenario
((
'early_no_info'
,
False
,
False
,
test_datetime
),
True
),
TestScenario
((
'end'
,
True
,
False
,
test_datetime
),
True
),
TestScenario
((
'end'
,
False
,
True
,
test_datetime
),
True
),
TestScenario
((
'end'
,
False
,
False
,
_NEXT_WEEK
),
False
),
TestScenario
((
'end'
,
False
,
False
,
_LAST_WEEK
),
True
),
TestScenario
((
'end'
,
False
,
False
,
None
),
False
),
TestScenario
((
'early_with_info'
,
False
,
False
,
None
),
True
),
]),
]
...
...
lms/djangoapps/certificates/tests/test_api.py
View file @
ffd72c10
...
...
@@ -4,6 +4,7 @@ from contextlib import contextmanager
from
functools
import
wraps
import
ddt
from
datetime
import
datetime
from
config_models.models
import
cache
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
...
...
@@ -92,7 +93,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
self
.
course
=
CourseFactory
.
create
(
org
=
'edx'
,
number
=
'verified'
,
display_name
=
'Verified Course'
display_name
=
'Verified Course'
,
end
=
datetime
.
now
()
)
self
.
request_factory
=
RequestFactory
()
...
...
lms/djangoapps/courseware/tests/test_views.py
View file @
ffd72c10
...
...
@@ -1216,6 +1216,8 @@ class ProgressPageBaseTests(ModuleStoreTestCase):
self
.
course
=
CourseFactory
.
create
(
start
=
datetime
(
2013
,
9
,
16
,
7
,
17
,
28
),
grade_cutoffs
=
{
u'çü†øƒƒ'
:
0.75
,
'Pass'
:
0.5
},
end
=
datetime
.
now
(),
certificate_available_date
=
datetime
.
now
(),
**
options
)
...
...
@@ -2052,6 +2054,7 @@ class GenerateUserCertTests(ModuleStoreTestCase):
self
.
course
=
CourseFactory
.
create
(
org
=
'edx'
,
number
=
'verified'
,
end
=
datetime
.
now
(),
display_name
=
'Verified Course'
,
grade_cutoffs
=
{
'cutoff'
:
0.75
,
'Pass'
:
0.5
}
)
...
...
lms/djangoapps/courseware/views/views.py
View file @
ffd72c10
...
...
@@ -112,7 +112,9 @@ log = logging.getLogger("edx.courseware")
# credit and verified modes.
REQUIREMENTS_DISPLAY_MODES
=
CourseMode
.
CREDIT_MODES
+
[
CourseMode
.
VERIFIED
]
CertData
=
namedtuple
(
"CertData"
,
[
"cert_status"
,
"title"
,
"msg"
,
"download_url"
,
"cert_web_view_url"
])
CertData
=
namedtuple
(
"CertData"
,
[
"cert_status"
,
"title"
,
"msg"
,
"download_url"
,
"cert_web_view_url"
,
"may_view_certificate"
]
)
def
user_groups
(
user
):
...
...
@@ -919,6 +921,7 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
Returns:
returns dict if course certificate is available else None.
"""
from
lms.djangoapps.courseware.courses
import
get_course_by_id
if
enrollment_mode
==
CourseMode
.
AUDIT
:
return
CertData
(
...
...
@@ -926,24 +929,28 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
_
(
'Your enrollment: Audit track'
),
_
(
'You are enrolled in the audit track for this course. The audit track does not include a certificate.'
),
download_url
=
None
,
cert_web_view_url
=
None
cert_web_view_url
=
None
,
may_view_certificate
=
None
)
show_
generate_cert_btn
=
(
show_
message
=
(
is_active
and
CourseMode
.
is_eligible_for_certificate
(
enrollment_mode
)
and
certs_api
.
cert_generation_enabled
(
course_key
)
)
if
not
show_
generate_cert_btn
:
if
not
show_
message
:
return
None
may_view_certificate
=
course_key
and
get_course_by_id
(
course_key
)
.
may_certify
()
if
certs_api
.
is_certificate_invalid
(
student
,
course_key
):
return
CertData
(
CertificateStatuses
.
invalidated
,
_
(
'Your certificate has been invalidated'
),
_
(
'Please contact your course team if you have any questions.'
),
download_url
=
None
,
cert_web_view_url
=
None
cert_web_view_url
=
None
,
may_view_certificate
=
None
)
cert_downloadable_status
=
certs_api
.
certificate_downloadable_status
(
student
,
course_key
)
...
...
@@ -957,7 +964,12 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
cert_web_view_url
=
certs_api
.
get_certificate_url
(
course_id
=
course_key
,
uuid
=
cert_downloadable_status
[
'uuid'
]
)
return
CertData
(
cert_status
,
title
,
msg
,
download_url
=
None
,
cert_web_view_url
=
cert_web_view_url
)
return
CertData
(
cert_status
,
title
,
msg
,
download_url
=
None
,
cert_web_view_url
=
cert_web_view_url
,
may_view_certificate
=
may_view_certificate
)
else
:
return
CertData
(
CertificateStatuses
.
generating
,
...
...
@@ -967,11 +979,17 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
"to it will appear here and on your Dashboard when it is ready."
),
download_url
=
None
,
cert_web_view_url
=
None
cert_web_view_url
=
None
,
may_view_certificate
=
None
)
return
CertData
(
cert_status
,
title
,
msg
,
download_url
=
cert_downloadable_status
[
'download_url'
],
cert_web_view_url
=
None
cert_status
,
title
,
msg
,
download_url
=
cert_downloadable_status
[
'download_url'
],
cert_web_view_url
=
None
,
may_view_certificate
=
may_view_certificate
)
if
cert_downloadable_status
[
'is_generating'
]:
...
...
@@ -983,7 +1001,8 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
"it will appear here and on your Dashboard when it is ready."
),
download_url
=
None
,
cert_web_view_url
=
None
cert_web_view_url
=
None
,
may_view_certificate
=
None
)
# If the learner is in verified modes and the student did not have
...
...
@@ -1001,7 +1020,8 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
'verified identity.'
)
.
format
(
platform_name
=
platform_name
),
download_url
=
None
,
cert_web_view_url
=
None
cert_web_view_url
=
None
,
may_view_certificate
=
None
)
return
CertData
(
...
...
@@ -1009,7 +1029,8 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
_
(
'Congratulations, you qualified for a certificate!'
),
_
(
'You can keep working for a higher grade, or request your certificate now.'
),
download_url
=
None
,
cert_web_view_url
=
None
cert_web_view_url
=
None
,
may_view_certificate
=
may_view_certificate
)
...
...
@@ -1355,7 +1376,7 @@ def _track_successful_certificate_generation(user_id, course_id): # pylint: dis
Track a successful certificate generation event.
Arguments:
user_id (str): The ID of the user generting the certificate.
user_id (str): The ID of the user gener
a
ting the certificate.
course_id (CourseKey): Identifier for the course.
Returns:
None
...
...
lms/djangoapps/mobile_api/testutils.py
View file @
ffd72c10
...
...
@@ -13,6 +13,7 @@ Test utilities for mobile API tests:
from
datetime
import
timedelta
import
ddt
import
datetime
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.utils
import
timezone
...
...
@@ -39,7 +40,10 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
"""
def
setUp
(
self
):
super
(
MobileAPITestCase
,
self
)
.
setUp
()
self
.
course
=
CourseFactory
.
create
(
mobile_available
=
True
,
static_asset_path
=
"needed_for_split"
)
self
.
course
=
CourseFactory
.
create
(
mobile_available
=
True
,
static_asset_path
=
"needed_for_split"
,
end
=
datetime
.
datetime
.
now
())
self
.
user
=
UserFactory
.
create
()
self
.
password
=
'test'
self
.
username
=
self
.
user
.
username
...
...
lms/templates/courseware/progress.html
View file @
ffd72c10
...
...
@@ -67,6 +67,7 @@ from django.utils.http import urlquote_plus
<h4
class=
"hd hd-4 title"
>
${certificate_data.title}
</h4>
<p
class=
"copy"
>
${certificate_data.msg}
</p>
</div>
%if certificate_data.may_view_certificate:
<div
class=
"msg-actions"
>
%if certificate_data.cert_web_view_url:
<a
class=
"btn"
href=
"${certificate_data.cert_web_view_url}"
target=
"_blank"
>
${_("View Certificate")}
<span
class=
"sr"
>
${_("Opens in a new browser window")}
</span></a>
...
...
@@ -76,6 +77,7 @@ from django.utils.http import urlquote_plus
<button
class=
"btn generate_certs"
data-endpoint=
"${post_url}"
id=
"btn_generate_cert"
>
${_('Request Certificate')}
</button>
%endif
</div>
%endif
</div>
</div>
%endif
...
...
openedx/core/djangoapps/content/course_overviews/migrations/0014_courseoverview_certificate_available_date.py
0 → 100644
View file @
ffd72c10
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'course_overviews'
,
'0013_courseoverview_language'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'courseoverview'
,
name
=
'certificate_available_date'
,
field
=
models
.
DateTimeField
(
default
=
None
,
null
=
True
),
),
]
openedx/core/djangoapps/content/course_overviews/models.py
View file @
ffd72c10
...
...
@@ -75,6 +75,7 @@ class CourseOverview(TimeStampedModel):
has_any_active_web_certificate
=
BooleanField
(
default
=
False
)
cert_name_short
=
TextField
()
cert_name_long
=
TextField
()
certificate_available_date
=
DateTimeField
(
default
=
None
,
null
=
True
)
# Grading
lowest_passing_grade
=
DecimalField
(
max_digits
=
5
,
decimal_places
=
2
,
null
=
True
)
...
...
@@ -172,6 +173,7 @@ class CourseOverview(TimeStampedModel):
course_overview
.
has_any_active_web_certificate
=
(
get_active_web_certificate
(
course
)
is
not
None
)
course_overview
.
cert_name_short
=
course
.
cert_name_short
course_overview
.
cert_name_long
=
course
.
cert_name_long
course_overview
.
certificate_available_date
=
course
.
certificate_available_date
course_overview
.
lowest_passing_grade
=
lowest_passing_grade
course_overview
.
end_of_course_survey_url
=
course
.
end_of_course_survey_url
...
...
@@ -476,7 +478,8 @@ class CourseOverview(TimeStampedModel):
return
course_metadata_utils
.
may_certify_for_course
(
self
.
certificates_display_behavior
,
self
.
certificates_show_before_end
,
self
.
has_ended
()
self
.
has_ended
(),
self
.
certificate_available_date
)
@property
...
...
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