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):
# # of sql queries to default,
# # of mongo queries,
# )
(
'no_overrides'
,
1
,
True
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
5
,
1
),
(
'ccx'
,
1
,
True
,
False
):
(
2
5
,
1
),
(
'ccx'
,
2
,
True
,
False
):
(
2
5
,
1
),
(
'ccx'
,
3
,
True
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
5
,
1
),
(
'ccx'
,
1
,
False
,
False
):
(
2
5
,
1
),
(
'ccx'
,
2
,
False
,
False
):
(
2
5
,
1
),
(
'ccx'
,
3
,
False
,
False
):
(
2
5
,
1
),
(
'no_overrides'
,
1
,
True
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
7
,
1
),
(
'ccx'
,
1
,
True
,
False
):
(
2
7
,
1
),
(
'ccx'
,
2
,
True
,
False
):
(
2
7
,
1
),
(
'ccx'
,
3
,
True
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
7
,
1
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
7
,
1
),
(
'ccx'
,
1
,
False
,
False
):
(
2
7
,
1
),
(
'ccx'
,
2
,
False
,
False
):
(
2
7
,
1
),
(
'ccx'
,
3
,
False
,
False
):
(
2
7
,
1
),
}
...
...
@@ -254,19 +254,19 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
__test__
=
True
TEST_DATA
=
{
(
'no_overrides'
,
1
,
True
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
5
,
3
),
(
'ccx'
,
1
,
True
,
False
):
(
2
5
,
3
),
(
'ccx'
,
2
,
True
,
False
):
(
2
5
,
3
),
(
'ccx'
,
3
,
True
,
False
):
(
2
5
,
3
),
(
'ccx'
,
1
,
True
,
True
):
(
2
6
,
3
),
(
'ccx'
,
2
,
True
,
True
):
(
2
6
,
3
),
(
'ccx'
,
3
,
True
,
True
):
(
2
6
,
3
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
5
,
3
),
(
'ccx'
,
1
,
False
,
False
):
(
2
5
,
3
),
(
'ccx'
,
2
,
False
,
False
):
(
2
5
,
3
),
(
'ccx'
,
3
,
False
,
False
):
(
2
5
,
3
),
(
'no_overrides'
,
1
,
True
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
2
,
True
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
3
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
1
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
2
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
3
,
True
,
False
):
(
2
7
,
3
),
(
'ccx'
,
1
,
True
,
True
):
(
2
8
,
3
),
(
'ccx'
,
2
,
True
,
True
):
(
2
8
,
3
),
(
'ccx'
,
3
,
True
,
True
):
(
2
8
,
3
),
(
'no_overrides'
,
1
,
False
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
2
,
False
,
False
):
(
2
7
,
3
),
(
'no_overrides'
,
3
,
False
,
False
):
(
2
7
,
3
),
(
'ccx'
,
1
,
False
,
False
):
(
2
7
,
3
),
(
'ccx'
,
2
,
False
,
False
):
(
2
7
,
3
),
(
'ccx'
,
3
,
False
,
False
):
(
2
7
,
3
),
}
lms/djangoapps/courseware/date_summary.py
View file @
fdafd53a
...
...
@@ -72,9 +72,10 @@ class DateSummary(object):
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
.
user
=
user
self
.
course_id
=
course_id
or
self
.
course
.
id
@property
def
relative_datestring
(
self
):
...
...
@@ -174,7 +175,7 @@ class CourseEndDate(DateSummary):
@property
def
description
(
self
):
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
):
return
_
(
'To earn a certificate, you must complete all requirements before this date.'
)
else
:
...
...
@@ -204,10 +205,10 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
ecommerce_service
=
EcommerceService
()
if
ecommerce_service
.
is_enabled
(
self
.
user
):
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
reverse
(
'verify_student_upgrade_and_verify'
,
args
=
(
self
.
course
.
id
,))
return
reverse
(
'verify_student_upgrade_and_verify'
,
args
=
(
self
.
course
_
id
,))
@property
def
is_enabled
(
self
):
...
...
@@ -221,7 +222,7 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
if
not
is_enabled
:
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
if
enrollment_mode
is
None
and
is_active
is
None
:
...
...
@@ -234,7 +235,7 @@ class VerifiedUpgradeDeadlineDate(DateSummary):
def
date
(
self
):
try
:
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
except
CourseMode
.
DoesNotExist
:
...
...
@@ -273,7 +274,7 @@ class VerificationDeadlineDate(DateSummary):
'verification-deadline-retry'
:
(
_
(
'Retry Verification'
),
reverse
(
'verify_student_reverify'
)),
'verification-deadline-upcoming'
:
(
_
(
'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):
@lazy
def
date
(
self
):
return
VerificationDeadline
.
deadline_for_course
(
self
.
course
.
id
)
return
VerificationDeadline
.
deadline_for_course
(
self
.
course
_
id
)
@lazy
def
is_enabled
(
self
):
if
self
.
date
is
None
:
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'
:
return
self
.
verification_status
in
(
'expired'
,
'none'
,
'must_reverify'
)
return
False
...
...
lms/djangoapps/courseware/tests/test_course_info.py
View file @
fdafd53a
...
...
@@ -367,7 +367,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
self
.
assertEqual
(
resp
.
status_code
,
200
)
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
):
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):
)
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
):
"""Verify the block link redirects to ecommerce checkout if it's enabled."""
sku
=
'TESTSKU'
...
...
lms/djangoapps/courseware/tests/test_views.py
View file @
fdafd53a
...
...
@@ -210,8 +210,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
NUM_PROBLEMS
=
20
@ddt.data
(
(
ModuleStoreEnum
.
Type
.
mongo
,
10
,
14
5
),
(
ModuleStoreEnum
.
Type
.
split
,
4
,
14
5
),
(
ModuleStoreEnum
.
Type
.
mongo
,
10
,
14
7
),
(
ModuleStoreEnum
.
Type
.
split
,
4
,
14
7
),
)
@ddt.unpack
def
test_index_query_counts
(
self
,
store_type
,
expected_mongo_query_count
,
expected_mysql_query_count
):
...
...
@@ -572,16 +572,18 @@ class ViewsTestCase(ModuleStoreTestCase):
"""
registration_price
=
99
self
.
course
.
cosmetic_display_price
=
10
# Since registration_price is set, it overrides the cosmetic_display_price and should be returned
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
,
registration_price
),
"$99"
)
with
patch
(
'course_modes.models.CourseMode.min_course_price_for_currency'
,
return_value
=
registration_price
):
# 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
# Since registration_price is not set, cosmetic_display_price should be returned
self
.
assertEqual
(
views
.
get_cosmetic_display_price
(
self
.
course
,
registration_price
),
"$10"
)
with
patch
(
'course_modes.models.CourseMode.min_course_price_for_currency'
,
return_value
=
registration_price
):
# 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
# 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
):
# TODO add a test for invalid location
...
...
@@ -1420,12 +1422,12 @@ class ProgressPageTests(ProgressPageBaseTests):
"""Test that query counts remain the same for self-paced and instructor-paced courses."""
SelfPacedConfiguration
(
enabled
=
self_paced_enabled
)
.
save
()
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
()
@ddt.data
(
(
False
,
4
1
,
27
),
(
True
,
3
4
,
23
)
(
False
,
4
3
,
29
),
(
True
,
3
6
,
25
)
)
@ddt.unpack
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 (
from
..masquerade
import
setup_masquerade
from
..model_data
import
FieldDataCache
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
}
...
...
@@ -149,7 +152,7 @@ class CoursewareIndex(View):
self
.
_save_positions
()
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
):
"""
...
...
@@ -319,12 +322,11 @@ class CoursewareIndex(View):
save_child_position
(
self
.
course
,
self
.
chapter_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.
Also returns the table of contents for the courseware.
"""
request
=
RequestCache
.
get_current_request
()
course_url_name
=
default_course_url_name
(
request
)
course_url
=
reverse
(
course_url_name
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
courseware_context
=
{
...
...
@@ -346,6 +348,8 @@ class CoursewareIndex(View):
'section_title'
:
None
,
'sequence_title'
:
None
,
'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
(
self
.
effective_user
,
...
...
lms/djangoapps/courseware/views/views.py
View file @
fdafd53a
...
...
@@ -320,30 +320,12 @@ def course_info(request, course_id):
if
settings
.
FEATURES
.
get
(
'ENABLE_MKTG_SITE'
):
url_to_enroll
=
marketing_link
(
'COURSES'
)
store_upgrade_cookie
=
False
upgrade_cookie_name
=
'show_upgrade_notification'
upgrade_link
=
None
# Construct the dates fragment
dates_fragment
=
None
if
request
.
user
.
is_authenticated
():
if
SelfPacedConfiguration
.
current
()
.
enable_course_home_improvements
:
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
=
{
'request'
:
request
,
...
...
@@ -358,7 +340,8 @@ def course_info(request, course_id):
'show_enroll_banner'
:
show_enroll_banner
,
'dates_fragment'
:
dates_fragment
,
'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
...
...
@@ -375,25 +358,22 @@ def course_info(request, course_id):
if
CourseEnrollment
.
is_enrolled
(
request
.
user
,
course
.
id
):
inject_coursetalk_keys_into_context
(
context
,
course_key
)
response
=
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
])
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
:
cookie_value
=
course_id
if
cookie_value
is
not
None
:
response
.
set_cookie
(
upgrade_cookie_name
,
cookie_value
,
max_age
=
10
*
24
*
60
*
60
,
# set for 10 days
domain
=
settings
.
SESSION_COOKIE_DOMAIN
,
httponly
=
True
# no use case for accessing from JavaScript
)
return
render_to_response
(
'courseware/info.html'
,
context
)
UPGRADE_COOKIE_NAME
=
'show_upgrade_notification'
def
check_and_get_upgrade_link
(
request
,
user
,
course_id
):
upgrade_link
=
None
if
request
.
user
.
is_authenticated
():
upgrade_data
=
VerifiedUpgradeDeadlineDate
(
None
,
user
,
course_id
=
course_id
)
if
upgrade_data
.
is_enabled
:
upgrade_link
=
upgrade_data
.
link
request
.
need_to_set_upgrade_cookie
=
True
return
response
return
upgrade_link
class
StaticCourseTabView
(
EdxFragmentView
):
...
...
@@ -518,6 +498,8 @@ class CourseTabView(EdxFragmentView):
'supports_preview_menu'
:
supports_preview_menu
,
'uses_pattern_library'
:
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
):
...
...
@@ -569,23 +551,57 @@ def registered_for_course(course, user):
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
]
price
=
course
.
cosmetic_display_price
if
registration_price
>
0
:
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
:
# 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.
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
:
# 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
):
...
...
@@ -720,12 +736,7 @@ def course_about(request, course_id):
if
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
=
CourseMode
.
min_course_price_for_currency
(
course_key
,
settings
.
PAID_COURSE_REGISTRATION_CURRENCY
[
0
]
)
course_price
=
get_cosmetic_display_price
(
course
,
registration_price
)
registration_price
,
course_price
=
get_course_prices
(
course
)
# 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
...
...
@@ -889,6 +900,8 @@ def _progress(request, course_key, student_id):
'passed'
:
is_course_passed
(
course
,
grade_summary
),
'credit_course_requirements'
:
_credit_course_requirements
(
course_key
,
student
),
'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
():
...
...
lms/djangoapps/discussion/views.py
View file @
fdafd53a
...
...
@@ -39,6 +39,8 @@ from django_comment_client.utils import (
strip_none
)
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
openedx.core.djangoapps.plugin_api.views
import
EdxFragmentView
from
rest_framework
import
status
...
...
@@ -440,7 +442,9 @@ def _create_discussion_board_context(request, course_key, discussion_id=None, th
'sort_preference'
:
cc_user
.
default_sort_key
,
'category_map'
:
course_settings
[
"category_map"
],
'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
...
...
lms/templates/courseware/info.html
View file @
fdafd53a
...
...
@@ -82,26 +82,6 @@ from openedx.core.djangolib.markup import HTML, Text
</div>
% 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>
${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
<
%
block
name=
"headextra"
/>
<
%
block
name=
"head_extra"
/>
<
%
include
file=
"/courseware/upgrade.html"
/>
<
%
static:optional_include_mako
file=
"head-extra.html"
is_theming_enabled=
"True"
/>
<
%
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):
course_home_url
(
self
.
course
)
# Fetch the view and verify the query counts
with
self
.
assertNumQueries
(
4
2
):
with
self
.
assertNumQueries
(
4
5
):
with
check_mongo_calls
(
5
):
url
=
course_home_url
(
self
.
course
)
self
.
client
.
get
(
url
)
openedx/features/course_experience/tests/views/test_course_updates.py
View file @
fdafd53a
...
...
@@ -124,7 +124,7 @@ class TestCourseUpdatesPage(SharedModuleStoreTestCase):
course_updates_url
(
self
.
course
)
# 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
):
url
=
course_updates_url
(
self
.
course
)
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
from
web_fragments.fragment
import
Fragment
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
..utils
import
get_course_outline_block_tree
...
...
@@ -30,7 +31,9 @@ class CourseOutlineFragmentView(EdxFragmentView):
context
=
{
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'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
)
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