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
fdafd53a
Commit
fdafd53a
authored
Jun 07, 2017
by
Nimisha Asthagiri
Committed by
Calen Pennington
Jun 08, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upsell Courses in Courseware, CourseOutline, Discussions, Progress
parent
4e9d41f2
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
139 additions
and
207 deletions
+139
-207
lms/djangoapps/ccx/tests/test_field_override_performance.py
+27
-27
lms/djangoapps/courseware/date_summary.py
+10
-9
lms/djangoapps/courseware/tests/test_course_info.py
+2
-2
lms/djangoapps/courseware/tests/test_date_summary.py
+0
-83
lms/djangoapps/courseware/tests/test_views.py
+12
-10
lms/djangoapps/courseware/views/index.py
+8
-4
lms/djangoapps/courseware/views/views.py
+61
-48
lms/djangoapps/discussion/views.py
+5
-1
lms/templates/courseware/info.html
+0
-20
lms/templates/courseware/upgrade.html
+7
-0
lms/templates/main.html
+1
-0
openedx/features/course_experience/tests/views/test_course_home.py
+1
-1
openedx/features/course_experience/tests/views/test_course_updates.py
+1
-1
openedx/features/course_experience/views/course_outline.py
+4
-1
No files found.
lms/djangoapps/ccx/tests/test_field_override_performance.py
View file @
fdafd53a
...
@@ -231,18 +231,18 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
...
@@ -231,18 +231,18 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
# # of sql queries to default,
# # of sql queries to default,
# # of mongo queries,
# # of mongo queries,
# )
# )
(
'no_overrides'
,
1
,
True
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
1
,
True
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
7
,
1
),
(
'ccx'
,
1
,
True
,
False
):
(
2
5
,
1
),
(
'ccx'
,
1
,
True
,
False
):
(
2
7
,
1
),
(
'ccx'
,
2
,
True
,
False
):
(
2
5
,
1
),
(
'ccx'
,
2
,
True
,
False
):
(
2
7
,
1
),
(
'ccx'
,
3
,
True
,
False
):
(
2
5
,
1
),
(
'ccx'
,
3
,
True
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
7
,
1
),
(
'ccx'
,
1
,
False
,
False
):
(
2
5
,
1
),
(
'ccx'
,
1
,
False
,
False
):
(
2
7
,
1
),
(
'ccx'
,
2
,
False
,
False
):
(
2
5
,
1
),
(
'ccx'
,
2
,
False
,
False
):
(
2
7
,
1
),
(
'ccx'
,
3
,
False
,
False
):
(
2
5
,
1
),
(
'ccx'
,
3
,
False
,
False
):
(
2
7
,
1
),
}
}
...
@@ -254,19 +254,19 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
...
@@ -254,19 +254,19 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
__test__
=
True
__test__
=
True
TEST_DATA
=
{
TEST_DATA
=
{
(
'no_overrides'
,
1
,
True
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
1
,
True
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
1
,
True
,
False
):
(
2
5
,
3
),
(
'ccx'
,
1
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
2
,
True
,
False
):
(
2
5
,
3
),
(
'ccx'
,
2
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
3
,
True
,
False
):
(
2
5
,
3
),
(
'ccx'
,
3
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
1
,
True
,
True
):
(
2
6
,
3
),
(
'ccx'
,
1
,
True
,
True
):
(
2
8
,
3
),
(
'ccx'
,
2
,
True
,
True
):
(
2
6
,
3
),
(
'ccx'
,
2
,
True
,
True
):
(
2
8
,
3
),
(
'ccx'
,
3
,
True
,
True
):
(
2
6
,
3
),
(
'ccx'
,
3
,
True
,
True
):
(
2
8
,
3
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
7
,
3
),
(
'ccx'
,
1
,
False
,
False
):
(
2
5
,
3
),
(
'ccx'
,
1
,
False
,
False
):
(
2
7
,
3
),
(
'ccx'
,
2
,
False
,
False
):
(
2
5
,
3
),
(
'ccx'
,
2
,
False
,
False
):
(
2
7
,
3
),
(
'ccx'
,
3
,
False
,
False
):
(
2
5
,
3
),
(
'ccx'
,
3
,
False
,
False
):
(
2
7
,
3
),
}
}
lms/djangoapps/courseware/date_summary.py
View file @
fdafd53a
...
@@ -72,9 +72,10 @@ class DateSummary(object):
...
@@ -72,9 +72,10 @@ class DateSummary(object):
self
.
user
.
preferences
.
model
.
get_value
(
self
.
user
,
"time_zone"
,
"UTC"
)
self
.
user
.
preferences
.
model
.
get_value
(
self
.
user
,
"time_zone"
,
"UTC"
)
)
)
def
__init__
(
self
,
course
,
user
):
def
__init__
(
self
,
course
,
user
,
course_id
=
None
):
self
.
course
=
course
self
.
course
=
course
self
.
user
=
user
self
.
user
=
user
self
.
course_id
=
course_id
or
self
.
course
.
id
@property
@property
def
relative_datestring
(
self
):
def
relative_datestring
(
self
):
...
@@ -174,7 +175,7 @@ class CourseEndDate(DateSummary):
...
@@ -174,7 +175,7 @@ class CourseEndDate(DateSummary):
@property
@property
def
description
(
self
):
def
description
(
self
):
if
datetime
.
now
(
utc
)
<=
self
.
date
:
if
datetime
.
now
(
utc
)
<=
self
.
date
:
mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
.
id
)
mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
_
id
)
if
is_active
and
CourseMode
.
is_eligible_for_certificate
(
mode
):
if
is_active
and
CourseMode
.
is_eligible_for_certificate
(
mode
):
return
_
(
'To earn a certificate, you must complete all requirements before this date.'
)
return
_
(
'To earn a certificate, you must complete all requirements before this date.'
)
else
:
else
:
...
@@ -204,10 +205,10 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
...
@@ -204,10 +205,10 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
ecommerce_service
=
EcommerceService
()
ecommerce_service
=
EcommerceService
()
if
ecommerce_service
.
is_enabled
(
self
.
user
):
if
ecommerce_service
.
is_enabled
(
self
.
user
):
course_mode
=
CourseMode
.
objects
.
get
(
course_mode
=
CourseMode
.
objects
.
get
(
course_id
=
self
.
course
.
id
,
mode_slug
=
CourseMode
.
VERIFIED
course_id
=
self
.
course
_
id
,
mode_slug
=
CourseMode
.
VERIFIED
)
)
return
ecommerce_service
.
checkout_page_url
(
course_mode
.
sku
)
return
ecommerce_service
.
checkout_page_url
(
course_mode
.
sku
)
return
reverse
(
'verify_student_upgrade_and_verify'
,
args
=
(
self
.
course
.
id
,))
return
reverse
(
'verify_student_upgrade_and_verify'
,
args
=
(
self
.
course
_
id
,))
@property
@property
def
is_enabled
(
self
):
def
is_enabled
(
self
):
...
@@ -221,7 +222,7 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
...
@@ -221,7 +222,7 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
if
not
is_enabled
:
if
not
is_enabled
:
return
False
return
False
enrollment_mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
.
id
)
enrollment_mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
_
id
)
# Return `true` if user is not enrolled in course
# Return `true` if user is not enrolled in course
if
enrollment_mode
is
None
and
is_active
is
None
:
if
enrollment_mode
is
None
and
is_active
is
None
:
...
@@ -234,7 +235,7 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
...
@@ -234,7 +235,7 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
def
date
(
self
):
def
date
(
self
):
try
:
try
:
verified_mode
=
CourseMode
.
objects
.
get
(
verified_mode
=
CourseMode
.
objects
.
get
(
course_id
=
self
.
course
.
id
,
mode_slug
=
CourseMode
.
VERIFIED
course_id
=
self
.
course
_
id
,
mode_slug
=
CourseMode
.
VERIFIED
)
)
return
verified_mode
.
expiration_datetime
return
verified_mode
.
expiration_datetime
except
CourseMode
.
DoesNotExist
:
except
CourseMode
.
DoesNotExist
:
...
@@ -273,7 +274,7 @@ class VerificationDeadlineDate(DateSummary):
...
@@ -273,7 +274,7 @@ class VerificationDeadlineDate(DateSummary):
'verification-deadline-retry'
:
(
_
(
'Retry Verification'
),
reverse
(
'verify_student_reverify'
)),
'verification-deadline-retry'
:
(
_
(
'Retry Verification'
),
reverse
(
'verify_student_reverify'
)),
'verification-deadline-upcoming'
:
(
'verification-deadline-upcoming'
:
(
_
(
'Verify My Identity'
),
_
(
'Verify My Identity'
),
reverse
(
'verify_student_verify_now'
,
args
=
(
self
.
course
.
id
,))
reverse
(
'verify_student_verify_now'
,
args
=
(
self
.
course
_
id
,))
)
)
}
}
...
@@ -297,13 +298,13 @@ class VerificationDeadlineDate(DateSummary):
...
@@ -297,13 +298,13 @@ class VerificationDeadlineDate(DateSummary):
@lazy
@lazy
def
date
(
self
):
def
date
(
self
):
return
VerificationDeadline
.
deadline_for_course
(
self
.
course
.
id
)
return
VerificationDeadline
.
deadline_for_course
(
self
.
course
_
id
)
@lazy
@lazy
def
is_enabled
(
self
):
def
is_enabled
(
self
):
if
self
.
date
is
None
:
if
self
.
date
is
None
:
return
False
return
False
(
mode
,
is_active
)
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
.
id
)
(
mode
,
is_active
)
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
_
id
)
if
is_active
and
mode
==
'verified'
:
if
is_active
and
mode
==
'verified'
:
return
self
.
verification_status
in
(
'expired'
,
'none'
,
'must_reverify'
)
return
self
.
verification_status
in
(
'expired'
,
'none'
,
'must_reverify'
)
return
False
return
False
...
...
lms/djangoapps/courseware/tests/test_course_info.py
View file @
fdafd53a
...
@@ -367,7 +367,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
...
@@ -367,7 +367,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
def
test_num_queries_instructor_paced
(
self
):
def
test_num_queries_instructor_paced
(
self
):
self
.
fetch_course_info_with_queries
(
self
.
instructor_paced_course
,
2
1
,
4
)
self
.
fetch_course_info_with_queries
(
self
.
instructor_paced_course
,
2
3
,
4
)
def
test_num_queries_self_paced
(
self
):
def
test_num_queries_self_paced
(
self
):
self
.
fetch_course_info_with_queries
(
self
.
self_paced_course
,
2
1
,
4
)
self
.
fetch_course_info_with_queries
(
self
.
self_paced_course
,
2
3
,
4
)
lms/djangoapps/courseware/tests/test_date_summary.py
View file @
fdafd53a
...
@@ -310,89 +310,6 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
...
@@ -310,89 +310,6 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
)
)
self
.
assertEqual
(
block
.
title
,
'Course End'
)
self
.
assertEqual
(
block
.
title
,
'Course End'
)
# Tests Verified Upgrade Deadline Date Block
def
check_upgrade_banner
(
self
,
banner_expected
=
True
,
include_url_parameter
=
True
,
expected_cookie_value
=
None
):
"""
Helper method to check for the presence of the Upgrade Banner
"""
url
=
reverse
(
'info'
,
args
=
[
self
.
course
.
id
.
to_deprecated_string
()])
if
include_url_parameter
:
url
+=
'?upgrade=true'
resp
=
self
.
client
.
get
(
url
)
upgrade_cookie_name
=
'show_upgrade_notification'
expected_banner_text
=
"Give yourself an additional incentive to complete"
if
banner_expected
:
self
.
assertIn
(
expected_banner_text
,
resp
.
content
)
self
.
assertIn
(
str
(
self
.
course
.
id
),
self
.
client
.
cookies
[
upgrade_cookie_name
]
.
value
)
else
:
self
.
assertNotIn
(
expected_banner_text
,
resp
.
content
)
if
upgrade_cookie_name
in
self
.
client
.
cookies
:
self
.
assertNotIn
(
str
(
self
.
course
.
id
),
self
.
client
.
cookies
[
upgrade_cookie_name
]
.
value
)
if
expected_cookie_value
is
not
None
:
self
.
assertIn
(
str
(
expected_cookie_value
),
self
.
client
.
cookies
[
upgrade_cookie_name
]
.
value
)
def
test_verified_upgrade_deadline_date
(
self
):
with
freeze_time
(
'2015-01-02'
):
self
.
setup_course_and_user
(
days_till_upgrade_deadline
=
1
,
user_enrollment_mode
=
CourseMode
.
AUDIT
)
self
.
client
.
login
(
username
=
'mrrobot'
,
password
=
'test'
)
block
=
VerifiedUpgradeDeadlineDate
(
self
.
course
,
self
.
user
)
self
.
assertEqual
(
block
.
date
,
datetime
.
now
(
utc
)
+
timedelta
(
days
=
1
))
self
.
assertTrue
(
block
.
is_enabled
)
self
.
assertEqual
(
block
.
link
,
reverse
(
'verify_student_upgrade_and_verify'
,
args
=
(
self
.
course
.
id
,)))
self
.
check_upgrade_banner
()
def
test_without_upgrade_deadline
(
self
):
self
.
setup_course_and_user
(
enrollment_mode
=
None
)
self
.
client
.
login
(
username
=
'mrrobot'
,
password
=
'test'
)
block
=
VerifiedUpgradeDeadlineDate
(
self
.
course
,
self
.
user
)
self
.
assertFalse
(
block
.
is_enabled
)
self
.
assertIsNone
(
block
.
date
)
self
.
check_upgrade_banner
(
banner_expected
=
False
)
def
test_verified_upgrade_banner_not_present_past_deadline
(
self
):
with
freeze_time
(
'2015-01-02'
):
self
.
setup_course_and_user
(
days_till_upgrade_deadline
=-
1
,
user_enrollment_mode
=
CourseMode
.
AUDIT
)
self
.
client
.
login
(
username
=
'mrrobot'
,
password
=
'test'
)
block
=
VerifiedUpgradeDeadlineDate
(
self
.
course
,
self
.
user
)
self
.
assertFalse
(
block
.
is_enabled
)
self
.
check_upgrade_banner
(
banner_expected
=
False
)
def
test_verified_upgrade_banner_cookie
(
self
):
with
freeze_time
(
'2015-01-02'
):
self
.
setup_course_and_user
(
days_till_upgrade_deadline
=
1
,
user_enrollment_mode
=
CourseMode
.
AUDIT
)
self
.
client
.
login
(
username
=
'mrrobot'
,
password
=
'test'
)
# No URL parameter or cookie present, notification should not be shown.
self
.
check_upgrade_banner
(
include_url_parameter
=
False
,
banner_expected
=
False
)
# Now pass URL parameter-- notification should be shown.
self
.
check_upgrade_banner
(
include_url_parameter
=
True
)
# A cookie should be set in the previous call, so it is no longer necessary to pass
# the URL parameter in order to see the notification.
self
.
check_upgrade_banner
(
include_url_parameter
=
False
)
# Store the current course_id for testing
old_course_id
=
self
.
course
.
id
# Change to another course
self
.
setup_course_and_user
(
days_till_upgrade_deadline
=
1
,
user_enrollment_mode
=
CourseMode
.
AUDIT
,
create_user
=
False
)
# Banner should not be present in the newly created course
self
.
check_upgrade_banner
(
include_url_parameter
=
False
,
banner_expected
=
False
,
expected_cookie_value
=
old_course_id
)
# Unfortunately (according to django doc), it is not possible to test expiration of the cookie.
def
test_ecommerce_checkout_redirect
(
self
):
def
test_ecommerce_checkout_redirect
(
self
):
"""Verify the block link redirects to ecommerce checkout if it's enabled."""
"""Verify the block link redirects to ecommerce checkout if it's enabled."""
sku
=
'TESTSKU'
sku
=
'TESTSKU'
...
...
lms/djangoapps/courseware/tests/test_views.py
View file @
fdafd53a
...
@@ -210,8 +210,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
...
@@ -210,8 +210,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
NUM_PROBLEMS
=
20
NUM_PROBLEMS
=
20
@ddt.data
(
@ddt.data
(
(
ModuleStoreEnum
.
Type
.
mongo
,
10
,
14
5
),
(
ModuleStoreEnum
.
Type
.
mongo
,
10
,
14
7
),
(
ModuleStoreEnum
.
Type
.
split
,
4
,
14
5
),
(
ModuleStoreEnum
.
Type
.
split
,
4
,
14
7
),
)
)
@ddt.unpack
@ddt.unpack
def
test_index_query_counts
(
self
,
store_type
,
expected_mongo_query_count
,
expected_mysql_query_count
):
def
test_index_query_counts
(
self
,
store_type
,
expected_mongo_query_count
,
expected_mysql_query_count
):
...
@@ -572,16 +572,18 @@ class ViewsTestCase(ModuleStoreTestCase):
...
@@ -572,16 +572,18 @@ class ViewsTestCase(ModuleStoreTestCase):
"""
"""
registration_price
=
99
registration_price
=
99
self
.
course
.
cosmetic_display_price
=
10
self
.
course
.
cosmetic_display_price
=
10
# Since registration_price is set, it overrides the cosmetic_display_price and should be returned
with
patch
(
'course_modes.models.CourseMode.min_course_price_for_currency'
,
return_value
=
registration_price
):
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
,
registration_price
),
"$99"
)
# Since registration_price is set, it overrides the cosmetic_display_price and should be returned
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
),
"$99"
)
registration_price
=
0
registration_price
=
0
# Since registration_price is not set, cosmetic_display_price should be returned
with
patch
(
'course_modes.models.CourseMode.min_course_price_for_currency'
,
return_value
=
registration_price
):
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
,
registration_price
),
"$10"
)
# Since registration_price is not set, cosmetic_display_price should be returned
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
),
"$10"
)
self
.
course
.
cosmetic_display_price
=
0
self
.
course
.
cosmetic_display_price
=
0
# Since both prices are not set, there is no price, thus "Free"
# Since both prices are not set, there is no price, thus "Free"
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
,
registration_price
),
"Free"
)
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
),
"Free"
)
def
test_jump_to_invalid
(
self
):
def
test_jump_to_invalid
(
self
):
# TODO add a test for invalid location
# TODO add a test for invalid location
...
@@ -1420,12 +1422,12 @@ class ProgressPageTests(ProgressPageBaseTests):
...
@@ -1420,12 +1422,12 @@ class ProgressPageTests(ProgressPageBaseTests):
"""Test that query counts remain the same for self-paced and instructor-paced courses."""
"""Test that query counts remain the same for self-paced and instructor-paced courses."""
SelfPacedConfiguration
(
enabled
=
self_paced_enabled
)
.
save
()
SelfPacedConfiguration
(
enabled
=
self_paced_enabled
)
.
save
()
self
.
setup_course
(
self_paced
=
self_paced
)
self
.
setup_course
(
self_paced
=
self_paced
)
with
self
.
assertNumQueries
(
4
1
),
check_mongo_calls
(
1
):
with
self
.
assertNumQueries
(
4
3
),
check_mongo_calls
(
1
):
self
.
_get_progress_page
()
self
.
_get_progress_page
()
@ddt.data
(
@ddt.data
(
(
False
,
4
1
,
27
),
(
False
,
4
3
,
29
),
(
True
,
3
4
,
23
)
(
True
,
3
6
,
25
)
)
)
@ddt.unpack
@ddt.unpack
def
test_progress_queries
(
self
,
enable_waffle
,
initial
,
subsequent
):
def
test_progress_queries
(
self
,
enable_waffle
,
initial
,
subsequent
):
...
...
lms/djangoapps/courseware/views/index.py
View file @
fdafd53a
...
@@ -55,7 +55,10 @@ from ..entrance_exams import (
...
@@ -55,7 +55,10 @@ from ..entrance_exams import (
from
..masquerade
import
setup_masquerade
from
..masquerade
import
setup_masquerade
from
..model_data
import
FieldDataCache
from
..model_data
import
FieldDataCache
from
..module_render
import
toc_for_course
,
get_module_for_descriptor
from
..module_render
import
toc_for_course
,
get_module_for_descriptor
from
.views
import
CourseTabView
,
check_access_to_course
from
.views
import
(
CourseTabView
,
check_access_to_course
,
check_and_get_upgrade_link
,
get_cosmetic_verified_display_price
)
TEMPLATE_IMPORTS
=
{
'urllib'
:
urllib
}
TEMPLATE_IMPORTS
=
{
'urllib'
:
urllib
}
...
@@ -149,7 +152,7 @@ class CoursewareIndex(View):
...
@@ -149,7 +152,7 @@ class CoursewareIndex(View):
self
.
_save_positions
()
self
.
_save_positions
()
self
.
_prefetch_and_bind_section
()
self
.
_prefetch_and_bind_section
()
return
render_to_response
(
'courseware/courseware.html'
,
self
.
_create_courseware_context
())
return
render_to_response
(
'courseware/courseware.html'
,
self
.
_create_courseware_context
(
request
))
def
_redirect_if_not_requested_section
(
self
):
def
_redirect_if_not_requested_section
(
self
):
"""
"""
...
@@ -319,12 +322,11 @@ class CoursewareIndex(View):
...
@@ -319,12 +322,11 @@ class CoursewareIndex(View):
save_child_position
(
self
.
course
,
self
.
chapter_url_name
)
save_child_position
(
self
.
course
,
self
.
chapter_url_name
)
save_child_position
(
self
.
chapter
,
self
.
section_url_name
)
save_child_position
(
self
.
chapter
,
self
.
section_url_name
)
def
_create_courseware_context
(
self
):
def
_create_courseware_context
(
self
,
request
):
"""
"""
Returns and creates the rendering context for the courseware.
Returns and creates the rendering context for the courseware.
Also returns the table of contents for the courseware.
Also returns the table of contents for the courseware.
"""
"""
request
=
RequestCache
.
get_current_request
()
course_url_name
=
default_course_url_name
(
request
)
course_url_name
=
default_course_url_name
(
request
)
course_url
=
reverse
(
course_url_name
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
course_url
=
reverse
(
course_url_name
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
courseware_context
=
{
courseware_context
=
{
...
@@ -346,6 +348,8 @@ class CoursewareIndex(View):
...
@@ -346,6 +348,8 @@ class CoursewareIndex(View):
'section_title'
:
None
,
'section_title'
:
None
,
'sequence_title'
:
None
,
'sequence_title'
:
None
,
'disable_accordion'
:
waffle
.
flag_is_active
(
request
,
UNIFIED_COURSE_VIEW_FLAG
),
'disable_accordion'
:
waffle
.
flag_is_active
(
request
,
UNIFIED_COURSE_VIEW_FLAG
),
'upgrade_link'
:
check_and_get_upgrade_link
(
request
,
self
.
effective_user
,
self
.
course
.
id
),
'upgrade_price'
:
get_cosmetic_verified_display_price
(
self
.
course
),
}
}
table_of_contents
=
toc_for_course
(
table_of_contents
=
toc_for_course
(
self
.
effective_user
,
self
.
effective_user
,
...
...
lms/djangoapps/courseware/views/views.py
View file @
fdafd53a
...
@@ -320,30 +320,12 @@ def course_info(request, course_id):
...
@@ -320,30 +320,12 @@ def course_info(request, course_id):
if
settings
.
FEATURES
.
get
(
'ENABLE_MKTG_SITE'
):
if
settings
.
FEATURES
.
get
(
'ENABLE_MKTG_SITE'
):
url_to_enroll
=
marketing_link
(
'COURSES'
)
url_to_enroll
=
marketing_link
(
'COURSES'
)
store_upgrade_cookie
=
False
upgrade_cookie_name
=
'show_upgrade_notification'
upgrade_link
=
None
# Construct the dates fragment
# Construct the dates fragment
dates_fragment
=
None
dates_fragment
=
None
if
request
.
user
.
is_authenticated
():
if
request
.
user
.
is_authenticated
():
if
SelfPacedConfiguration
.
current
()
.
enable_course_home_improvements
:
if
SelfPacedConfiguration
.
current
()
.
enable_course_home_improvements
:
dates_fragment
=
CourseDatesFragmentView
()
.
render_to_fragment
(
request
,
course_id
=
course_id
)
dates_fragment
=
CourseDatesFragmentView
()
.
render_to_fragment
(
request
,
course_id
=
course_id
)
show_upgrade_notification
=
False
if
request
.
GET
.
get
(
'upgrade'
,
'false'
)
==
'true'
:
store_upgrade_cookie
=
True
show_upgrade_notification
=
True
elif
upgrade_cookie_name
in
request
.
COOKIES
and
course_id
in
request
.
COOKIES
[
upgrade_cookie_name
]:
show_upgrade_notification
=
True
if
show_upgrade_notification
:
upgrade_data
=
VerifiedUpgradeDeadlineDate
(
course
,
user
)
if
upgrade_data
.
is_enabled
:
upgrade_link
=
upgrade_data
.
link
else
:
# The upgrade is not enabled so the cookie does not need to be stored
store_upgrade_cookie
=
False
context
=
{
context
=
{
'request'
:
request
,
'request'
:
request
,
...
@@ -358,7 +340,8 @@ def course_info(request, course_id):
...
@@ -358,7 +340,8 @@ def course_info(request, course_id):
'show_enroll_banner'
:
show_enroll_banner
,
'show_enroll_banner'
:
show_enroll_banner
,
'dates_fragment'
:
dates_fragment
,
'dates_fragment'
:
dates_fragment
,
'url_to_enroll'
:
url_to_enroll
,
'url_to_enroll'
:
url_to_enroll
,
'upgrade_link'
:
upgrade_link
,
'upgrade_link'
:
check_and_get_upgrade_link
(
request
,
user
,
course
.
id
),
'upgrade_price'
:
get_cosmetic_verified_display_price
(
course
),
}
}
# Get the URL of the user's last position in order to display the 'where you were last' message
# Get the URL of the user's last position in order to display the 'where you were last' message
...
@@ -375,25 +358,22 @@ def course_info(request, course_id):
...
@@ -375,25 +358,22 @@ def course_info(request, course_id):
if
CourseEnrollment
.
is_enrolled
(
request
.
user
,
course
.
id
):
if
CourseEnrollment
.
is_enrolled
(
request
.
user
,
course
.
id
):
inject_coursetalk_keys_into_context
(
context
,
course_key
)
inject_coursetalk_keys_into_context
(
context
,
course_key
)
response
=
render_to_response
(
'courseware/info.html'
,
context
)
return
render_to_response
(
'courseware/info.html'
,
context
)
if
store_upgrade_cookie
:
if
upgrade_cookie_name
in
request
.
COOKIES
and
str
(
course_id
)
not
in
request
.
COOKIES
[
upgrade_cookie_name
]:
cookie_value
=
'
%
s,
%
s'
%
(
course_id
,
request
.
COOKIES
[
upgrade_cookie_name
])
UPGRADE_COOKIE_NAME
=
'show_upgrade_notification'
elif
upgrade_cookie_name
in
request
.
COOKIES
and
str
(
course_id
)
in
request
.
COOKIES
[
upgrade_cookie_name
]:
cookie_value
=
request
.
COOKIES
[
upgrade_cookie_name
]
else
:
def
check_and_get_upgrade_link
(
request
,
user
,
course_id
):
cookie_value
=
course_id
upgrade_link
=
None
if
cookie_value
is
not
None
:
if
request
.
user
.
is_authenticated
():
response
.
set_cookie
(
upgrade_data
=
VerifiedUpgradeDeadlineDate
(
None
,
user
,
course_id
=
course_id
)
upgrade_cookie_name
,
if
upgrade_data
.
is_enabled
:
cookie_value
,
upgrade_link
=
upgrade_data
.
link
max_age
=
10
*
24
*
60
*
60
,
# set for 10 days
request
.
need_to_set_upgrade_cookie
=
True
domain
=
settings
.
SESSION_COOKIE_DOMAIN
,
httponly
=
True
# no use case for accessing from JavaScript
)
return
response
return
upgrade_link
class
StaticCourseTabView
(
EdxFragmentView
):
class
StaticCourseTabView
(
EdxFragmentView
):
...
@@ -518,6 +498,8 @@ class CourseTabView(EdxFragmentView):
...
@@ -518,6 +498,8 @@ class CourseTabView(EdxFragmentView):
'supports_preview_menu'
:
supports_preview_menu
,
'supports_preview_menu'
:
supports_preview_menu
,
'uses_pattern_library'
:
True
,
'uses_pattern_library'
:
True
,
'disable_courseware_js'
:
True
,
'disable_courseware_js'
:
True
,
'upgrade_link'
:
check_and_get_upgrade_link
(
request
,
request
.
user
,
course
.
id
),
'upgrade_price'
:
get_cosmetic_verified_display_price
(
course
),
}
}
def
render_to_fragment
(
self
,
request
,
course
=
None
,
page_context
=
None
,
**
kwargs
):
def
render_to_fragment
(
self
,
request
,
course
=
None
,
page_context
=
None
,
**
kwargs
):
...
@@ -569,23 +551,57 @@ def registered_for_course(course, user):
...
@@ -569,23 +551,57 @@ def registered_for_course(course, user):
return
False
return
False
def
get_cosmetic_
display_price
(
course
,
registration_pric
e
):
def
get_cosmetic_
verified_display_price
(
cours
e
):
"""
"""
Return Course Price as a string preceded by correct currency, or 'Free'
Returns the minimum verified cert course price as a string preceded by correct currency, or 'Free'.
"""
return
get_course_prices
(
course
,
verified_only
=
True
)[
1
]
def
get_cosmetic_display_price
(
course
):
"""
Returns the course price as a string preceded by correct currency, or 'Free'.
"""
return
get_course_prices
(
course
)[
1
]
def
get_course_prices
(
course
,
verified_only
=
False
):
"""
"""
Return registration_price and cosmetic_display_prices.
registration_price is the minimum price for the course across all course modes.
cosmetic_display_prices is the course price as a string preceded by correct currency, or 'Free'.
"""
# Find the
if
verified_only
:
registration_price
=
CourseMode
.
min_course_price_for_verified_for_currency
(
course
.
id
,
settings
.
PAID_COURSE_REGISTRATION_CURRENCY
[
0
]
)
else
:
registration_price
=
CourseMode
.
min_course_price_for_currency
(
course
.
id
,
settings
.
PAID_COURSE_REGISTRATION_CURRENCY
[
0
]
)
currency_symbol
=
settings
.
PAID_COURSE_REGISTRATION_CURRENCY
[
1
]
currency_symbol
=
settings
.
PAID_COURSE_REGISTRATION_CURRENCY
[
1
]
price
=
course
.
cosmetic_display_price
if
registration_price
>
0
:
if
registration_price
>
0
:
price
=
registration_price
price
=
registration_price
# Handle course overview objects which have no cosmetic_display_price
elif
hasattr
(
course
,
'cosmetic_display_price'
):
price
=
course
.
cosmetic_display_price
else
:
price
=
None
if
price
:
if
price
:
# Translators: This will look like '$50', where {currency_symbol} is a symbol such as '$' and {price} is a
# Translators: This will look like '$50', where {currency_symbol} is a symbol such as '$' and {price} is a
# numerical amount in that currency. Adjust this display as needed for your language.
# numerical amount in that currency. Adjust this display as needed for your language.
return
_
(
"{currency_symbol}{price}"
)
.
format
(
currency_symbol
=
currency_symbol
,
price
=
price
)
cosmetic_display_price
=
_
(
"{currency_symbol}{price}"
)
.
format
(
currency_symbol
=
currency_symbol
,
price
=
price
)
else
:
else
:
# Translators: This refers to the cost of the course. In this case, the course costs nothing so it is free.
# Translators: This refers to the cost of the course. In this case, the course costs nothing so it is free.
return
_
(
'Free'
)
cosmetic_display_price
=
_
(
'Free'
)
return
registration_price
,
cosmetic_display_price
class
EnrollStaffView
(
View
):
class
EnrollStaffView
(
View
):
...
@@ -720,12 +736,7 @@ def course_about(request, course_id):
...
@@ -720,12 +736,7 @@ def course_about(request, course_id):
if
professional_mode
.
bulk_sku
:
if
professional_mode
.
bulk_sku
:
ecommerce_bulk_checkout_link
=
ecomm_service
.
checkout_page_url
(
professional_mode
.
bulk_sku
)
ecommerce_bulk_checkout_link
=
ecomm_service
.
checkout_page_url
(
professional_mode
.
bulk_sku
)
# Find the minimum price for the course across all course modes
registration_price
,
course_price
=
get_course_prices
(
course
)
registration_price
=
CourseMode
.
min_course_price_for_currency
(
course_key
,
settings
.
PAID_COURSE_REGISTRATION_CURRENCY
[
0
]
)
course_price
=
get_cosmetic_display_price
(
course
,
registration_price
)
# Determine which checkout workflow to use -- LMS shoppingcart or Otto basket
# Determine which checkout workflow to use -- LMS shoppingcart or Otto basket
can_add_course_to_cart
=
_is_shopping_cart_enabled
and
registration_price
and
not
ecommerce_checkout_link
can_add_course_to_cart
=
_is_shopping_cart_enabled
and
registration_price
and
not
ecommerce_checkout_link
...
@@ -889,6 +900,8 @@ def _progress(request, course_key, student_id):
...
@@ -889,6 +900,8 @@ def _progress(request, course_key, student_id):
'passed'
:
is_course_passed
(
course
,
grade_summary
),
'passed'
:
is_course_passed
(
course
,
grade_summary
),
'credit_course_requirements'
:
_credit_course_requirements
(
course_key
,
student
),
'credit_course_requirements'
:
_credit_course_requirements
(
course_key
,
student
),
'certificate_data'
:
_get_cert_data
(
student
,
course
,
course_key
,
is_active
,
enrollment_mode
),
'certificate_data'
:
_get_cert_data
(
student
,
course
,
course_key
,
is_active
,
enrollment_mode
),
'upgrade_link'
:
check_and_get_upgrade_link
(
request
,
student
,
course
.
id
),
'upgrade_price'
:
get_cosmetic_verified_display_price
(
course
),
}
}
with
outer_atomic
():
with
outer_atomic
():
...
...
lms/djangoapps/discussion/views.py
View file @
fdafd53a
...
@@ -39,6 +39,8 @@ from django_comment_client.utils import (
...
@@ -39,6 +39,8 @@ from django_comment_client.utils import (
strip_none
strip_none
)
)
from
django_comment_common.utils
import
ThreadContext
,
get_course_discussion_settings
,
set_course_discussion_settings
from
django_comment_common.utils
import
ThreadContext
,
get_course_discussion_settings
,
set_course_discussion_settings
from
lms.djangoapps.courseware.views.views
import
check_and_get_upgrade_link
,
get_cosmetic_verified_display_price
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
from
openedx.core.djangoapps.plugin_api.views
import
EdxFragmentView
from
openedx.core.djangoapps.plugin_api.views
import
EdxFragmentView
from
rest_framework
import
status
from
rest_framework
import
status
...
@@ -440,7 +442,9 @@ def _create_discussion_board_context(request, course_key, discussion_id=None, th
...
@@ -440,7 +442,9 @@ def _create_discussion_board_context(request, course_key, discussion_id=None, th
'sort_preference'
:
cc_user
.
default_sort_key
,
'sort_preference'
:
cc_user
.
default_sort_key
,
'category_map'
:
course_settings
[
"category_map"
],
'category_map'
:
course_settings
[
"category_map"
],
'course_settings'
:
course_settings
,
'course_settings'
:
course_settings
,
'is_commentable_divided'
:
is_commentable_divided
(
course_key
,
discussion_id
,
course_discussion_settings
)
'is_commentable_divided'
:
is_commentable_divided
(
course_key
,
discussion_id
,
course_discussion_settings
),
'upgrade_link'
:
check_and_get_upgrade_link
(
request
,
user
,
course
.
id
),
'upgrade_price'
:
get_cosmetic_verified_display_price
(
course
),
})
})
return
context
return
context
...
...
lms/templates/courseware/info.html
View file @
fdafd53a
...
@@ -82,26 +82,6 @@ from openedx.core.djangolib.markup import HTML, Text
...
@@ -82,26 +82,6 @@ from openedx.core.djangolib.markup import HTML, Text
</div>
</div>
% endif
% endif
% if upgrade_link:
<div
class=
"upgrade-banner"
>
<div
class=
"notification-color-border"
></div>
<div
class=
"notification-content"
>
<div
class=
"upgrade-icon"
>
<img
src=
"${STATIC_URL}images/edx-verified-mini-cert.png"
>
</div>
<div
class=
"upgrade-msg"
>
<h3
class=
"msg-title"
>
${_("Give yourself an additional incentive to complete")}
</h3>
<p
class=
"view-verified-info"
>
${_("Earn a verified certificate.")}
<a
href=
"https://www.edx.org/verified-certificate"
target=
"_blank"
>
${_("Learn More")}
</a>
</p>
</div>
<div
class=
"upgrade-banner-button"
>
<a
href=
"${upgrade_link}"
class=
"btn-upgrade"
>
${_("Upgrade Now")}
</a>
</div>
</div>
</div>
% endif
<h3
class=
"hd hd-3"
>
${_("Course Updates and News")}
</h3>
<h3
class=
"hd hd-3"
>
${_("Course Updates and News")}
</h3>
${HTML(get_course_info_section(request, masquerade_user, course, 'updates'))}
${HTML(get_course_info_section(request, masquerade_user, course, 'updates'))}
...
...
lms/templates/courseware/upgrade.html
0 → 100644
View file @
fdafd53a
% if upgrade_link:
<script
type=
"text/plain"
id=
"upgrade_user"
data-link=
"${upgrade_link}"
data-price=
"${upgrade_price}"
>
</script>
% endif
lms/templates/main.html
View file @
fdafd53a
...
@@ -98,6 +98,7 @@ from pipeline_mako import render_require_js_path_overrides
...
@@ -98,6 +98,7 @@ from pipeline_mako import render_require_js_path_overrides
<
%
block
name=
"headextra"
/>
<
%
block
name=
"headextra"
/>
<
%
block
name=
"head_extra"
/>
<
%
block
name=
"head_extra"
/>
<
%
include
file=
"/courseware/upgrade.html"
/>
<
%
static:optional_include_mako
file=
"head-extra.html"
is_theming_enabled=
"True"
/>
<
%
static:optional_include_mako
file=
"head-extra.html"
is_theming_enabled=
"True"
/>
<
%
include
file=
"widgets/optimizely.html"
/>
<
%
include
file=
"widgets/optimizely.html"
/>
...
...
openedx/features/course_experience/tests/views/test_course_home.py
View file @
fdafd53a
...
@@ -89,7 +89,7 @@ class TestCourseHomePage(SharedModuleStoreTestCase):
...
@@ -89,7 +89,7 @@ class TestCourseHomePage(SharedModuleStoreTestCase):
course_home_url
(
self
.
course
)
course_home_url
(
self
.
course
)
# Fetch the view and verify the query counts
# Fetch the view and verify the query counts
with
self
.
assertNumQueries
(
4
2
):
with
self
.
assertNumQueries
(
4
5
):
with
check_mongo_calls
(
5
):
with
check_mongo_calls
(
5
):
url
=
course_home_url
(
self
.
course
)
url
=
course_home_url
(
self
.
course
)
self
.
client
.
get
(
url
)
self
.
client
.
get
(
url
)
openedx/features/course_experience/tests/views/test_course_updates.py
View file @
fdafd53a
...
@@ -124,7 +124,7 @@ class TestCourseUpdatesPage(SharedModuleStoreTestCase):
...
@@ -124,7 +124,7 @@ class TestCourseUpdatesPage(SharedModuleStoreTestCase):
course_updates_url
(
self
.
course
)
course_updates_url
(
self
.
course
)
# Fetch the view and verify that the query counts haven't changed
# Fetch the view and verify that the query counts haven't changed
with
self
.
assertNumQueries
(
3
2
):
with
self
.
assertNumQueries
(
3
4
):
with
check_mongo_calls
(
4
):
with
check_mongo_calls
(
4
):
url
=
course_updates_url
(
self
.
course
)
url
=
course_updates_url
(
self
.
course
)
self
.
client
.
get
(
url
)
self
.
client
.
get
(
url
)
openedx/features/course_experience/views/course_outline.py
View file @
fdafd53a
...
@@ -8,6 +8,7 @@ from opaque_keys.edx.keys import CourseKey
...
@@ -8,6 +8,7 @@ from opaque_keys.edx.keys import CourseKey
from
web_fragments.fragment
import
Fragment
from
web_fragments.fragment
import
Fragment
from
courseware.courses
import
get_course_overview_with_access
from
courseware.courses
import
get_course_overview_with_access
from
lms.djangoapps.courseware.views.views
import
check_and_get_upgrade_link
,
get_cosmetic_verified_display_price
from
openedx.core.djangoapps.plugin_api.views
import
EdxFragmentView
from
openedx.core.djangoapps.plugin_api.views
import
EdxFragmentView
from
..utils
import
get_course_outline_block_tree
from
..utils
import
get_course_outline_block_tree
...
@@ -30,7 +31,9 @@ class CourseOutlineFragmentView(EdxFragmentView):
...
@@ -30,7 +31,9 @@ class CourseOutlineFragmentView(EdxFragmentView):
context
=
{
context
=
{
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'course'
:
course_overview
,
'course'
:
course_overview
,
'blocks'
:
course_block_tree
'blocks'
:
course_block_tree
,
'upgrade_link'
:
check_and_get_upgrade_link
(
request
,
request
.
user
,
course_key
),
'upgrade_price'
:
get_cosmetic_verified_display_price
(
course_overview
),
}
}
html
=
render_to_string
(
'course_experience/course-outline-fragment.html'
,
context
)
html
=
render_to_string
(
'course_experience/course-outline-fragment.html'
,
context
)
return
Fragment
(
html
)
return
Fragment
(
html
)
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