Commit 000bbaf0 by Matthew Piatetsky

Add bundle purchase button to course dashboard

parent 7ba83dd5
...@@ -83,10 +83,14 @@ from openedx.core.djangoapps.external_auth.login_and_register import register as ...@@ -83,10 +83,14 @@ from openedx.core.djangoapps.external_auth.login_and_register import register as
from openedx.core.djangoapps.external_auth.models import ExternalAuthMap from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.utils import ProgramProgressMeter from openedx.core.djangoapps.programs.utils import (
ProgramDataExtender,
ProgramProgressMeter
)
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.theming import helpers as theming_helpers from openedx.core.djangoapps.theming import helpers as theming_helpers
from openedx.core.djangoapps.user_api.preferences import api as preferences_api from openedx.core.djangoapps.user_api.preferences import api as preferences_api
from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace, WaffleFlag
from openedx.core.djangolib.markup import HTML from openedx.core.djangolib.markup import HTML
from openedx.features.course_experience import course_home_url_name from openedx.features.course_experience import course_home_url_name
from openedx.features.enterprise_support.api import get_dashboard_consent_notification from openedx.features.enterprise_support.api import get_dashboard_consent_notification
...@@ -779,8 +783,28 @@ def dashboard(request): ...@@ -779,8 +783,28 @@ def dashboard(request):
# is passed in the template context to allow rendering of program-related # is passed in the template context to allow rendering of program-related
# information on the dashboard. # information on the dashboard.
meter = ProgramProgressMeter(request.site, user, enrollments=course_enrollments) meter = ProgramProgressMeter(request.site, user, enrollments=course_enrollments)
ecommerce_service = EcommerceService()
inverted_programs = meter.invert_programs() inverted_programs = meter.invert_programs()
urls, program_data = {}, {}
bundles_on_dashboard_flag = WaffleFlag(WaffleFlagNamespace(name=u'student.experiments'), u'bundles_on_dashboard')
if (bundles_on_dashboard_flag.is_enabled()):
programs_data = meter.programs
if programs_data:
program_data = meter.programs[0]
program_data = ProgramDataExtender(program_data, request.user).extend()
course_data = meter.progress(programs=[program_data], count_only=False)[0]
program_data.pop('courses')
skus = program_data.get('skus')
urls = {
'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
'buy_button_url': ecommerce_service.get_checkout_page_url(*skus)
}
urls['completeProgramURL'] = urls['buy_button_url'] + '&bundle=' + program_data.get('uuid')
# Construct a dictionary of course mode information # Construct a dictionary of course mode information
# used to render the course list. We re-use the course modes dict # used to render the course list. We re-use the course modes dict
# we loaded earlier to avoid hitting the database. # we loaded earlier to avoid hitting the database.
...@@ -878,6 +902,8 @@ def dashboard(request): ...@@ -878,6 +902,8 @@ def dashboard(request):
course_enrollments = [enr for enr in course_enrollments if entitlement.enrollment_course_run.course_id != enr.course_id] # pylint: disable=line-too-long course_enrollments = [enr for enr in course_enrollments if entitlement.enrollment_course_run.course_id != enr.course_id] # pylint: disable=line-too-long
context = { context = {
'urls': urls,
'program_data': program_data,
'enterprise_message': enterprise_message, 'enterprise_message': enterprise_message,
'consent_required_courses': consent_required_courses, 'consent_required_courses': consent_required_courses,
'enterprise_customer_name': enterprise_customer_name, 'enterprise_customer_name': enterprise_customer_name,
...@@ -920,7 +946,6 @@ def dashboard(request): ...@@ -920,7 +946,6 @@ def dashboard(request):
'display_sidebar_on_dashboard': display_sidebar_on_dashboard, 'display_sidebar_on_dashboard': display_sidebar_on_dashboard,
} }
ecommerce_service = EcommerceService()
if ecommerce_service.is_enabled(request.user): if ecommerce_service.is_enabled(request.user):
context.update({ context.update({
'use_ecommerce_payment_flow': True, 'use_ecommerce_payment_flow': True,
......
...@@ -4,396 +4,38 @@ ...@@ -4,396 +4,38 @@
// Please list the ticket number of the experiment // Please list the ticket number of the experiment
// -------------------- // --------------------
// LEARNER-1726 Track Selection V3 // LEARNER-3072 Program Purchase on dashboard
/* This css was added as part of the LEARNER-1726 experiment */ /* This css was added as part of the LEARNER-3072 experiment */
.v2.register-choice {
margin: 0 2% 20px 0 !important
}
.v2.register-choice-certificate .list-actions {
text-align: left !important;
}
.v2.register-choice-continue .list-actions {
margin-bottom: 0 !important;
}
.v2.register-choice-continue .action-select {
display: inline-block !important;
list-style-type: none !important;
width: 100% !important;
}
.v2.register-choice-continue .continue-link {
display: inline-block !important;
padding: 10px 15px !important;
border-radius: 3px !important;
border: 1px solid #d7548e !important;
box-shadow: 0 2px 1px 0 #982c62 !important;
background: white !important;
text-align: center !important;
color: #d7548e !important;
float: left !important;
font-size: 15px;
font-weight: 500 !important;
}
.v2.register-choice-v2-donate {
height: 300px;
background: none !important;
border-top-color: grey !important;
border-top-width: 1px !important;
}
@media screen and (min-width: 375px) {
.v2.register-choice-v2-donate {
height: 250px;
}
}
.v2.register-choice-v2-donate .list-actions {
margin-bottom: 0 !important;
}
.v2.register-choice-v2-donate .list-actions a {
background: transparent !important;
color: #0075b4 !important;
box-shadow: none !important;
text-decoration: underline !important;
border: none !important;
white-space: normal;
}
.v2.register-choice-v2-donate .wrapper-copy-inline {
height: 70px !important;
width: 100% !important;
display: flex !important;
}
.v2.register-choice-v2-donate .wrapper-copy {
width: 70% !important;
height: auto !important;
}
.v2.page-header {
padding: 0;
}
.v2 img {
margin-top: 20px;
margin-left: 5px;
}
.v2 .continue-link {
font-weight: bold !important;
}
.v2.register-choice-certificate,
.v2.register-choice-continue,
.v2.register-choice-view {
width: 100%;
}
.v2.register-choice-continue {
border-color: #d7548e !important;
}
.v2 .wrapper-copy-inline {
max-height: 115px;
}
.v2.register-choice-v2-donate .wrapper-copy-inline {
display: block !important;
}
.v2.register-choice-v2-donate .copy-inline {
width: 100% !important;
}
.v2.register-choice-v2-donate .list-actions { .complete-program-dashboard-button {
width: 100% !important; float: right;
margin-top: 20px !important; display: block;
text-align: center !important; box-sizing: border-box;
} color: rgb(242, 248, 251) !important;
.v2 .wrapper-copy-inline .wrapper-copy {
width: 100% !important;
}
.v2 input, .v2 a {
font-size: 15px !important;
}
.v2 button {
background-color: rgb(0, 103, 0);
border-color: rgb(0, 103, 0);
border-radius: 2px;
box-shadow: rgb(0, 77, 0) 0 2px 1px 0;
cursor: pointer; cursor: pointer;
font-family: $font-family-sans-serif; background: rgb(0, 129, 0) none repeat scroll 0% 0% / auto padding-box border-box !important;
height: auto; font: normal normal 600 normal 15px / normal "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
margin-right: 4px; padding: 7px;
margin-top: 0; transition: color 0.25s ease-in-out 0s, background 0.25s ease-in-out 0s, box-shadow 0.25s ease-in-out 0s;
padding: 10px 15px; text-decoration: none !important;
width: initial; border: none !important;
background-image: none !important; margin-top: 5px;
font-size: 14px !important;
font-weight: 500 !important;
&:hover,
&:focus {
background-color: #009b00 !important;
border-color: #009b00;
box-shadow: #004d00 0 2px 1px 0;
}
}
.savings-message {
margin-top: 10px;
font-size: 11px;
}
@media screen and (min-width: 375px) {
.savings-message {
font-size: 13px;
margin-left: 16px;
}
} }
.v2 .continue-link, .v2 input, .v2 button, .v2 a { .complete-program-dashboard-button:hover {
width: 100%; background: #009b00 !important;
} }
.v2 img { .complete-program-dashboard-span {
display: none; display: block;
float: right;
} }
.v2 .deco-divider { .complete-program-dashboard-div {
display: none; display: none;
} float: right;
width: auto;
.v2 .visual-reference { max-width: 420px;
width: 38%; margin: 0 0 10px 0;
}
@media (min-width: 420px) {
.v2 button {
height: 45px;
font-size: 16px !important;
}
}
@media (min-width: 768px) {
.v2.register-choice-certificate,
.v2.register-choice-continue,
.v2.deco-divider {
width: 46.5% !important;
display: inline-block;
min-height: 270px;
}
.v2.register-choice-v2-donate .wrapper-copy-inline {
display: flex !important;
}
.v2.register-choice-v2-donate .copy-inline {
width: 40% !important;
}
.v2.register-choice-v2-donate .list-actions {
margin-top: 0 !important;
text-align: right !important;
}
.v2 .wrapper-copy-inline .wrapper-copy {
width: 100% !important;
}
.v2 input, .v2 a {
font-size: 15px !important;
}
.v2 .continue-link, .v2.register-choice-certificate button, .v2.register-choice-certificate input {
margin-top: 20px;
width: initial;
}
.v2.register-choice-v2-donate a {
width: 100% !important;
}
.v2.register-choice-view {
height: 250px;
}
.v2 img {
display: initial;
}
.v2.register-choice {
margin: 0 2% 20px 0;
}
.v2.register-choice-continue .wrapper-copy-inline .wrapper-copy, .v2.register-choice-certificate .wrapper-copy-inline .wrapper-copy {
width: 60%;
}
.v2.register-choice-view .wrapper-copy-inline .wrapper-copy {
width: 100%;
}
.v2.register-choice {
padding: 15px !important;
}
.v2.register-choice-continue .wrapper-copy-inline .wrapper-copy, .v2.register-choice-certificate .wrapper-copy-inline .wrapper-copy {
width: 60%;
}
.v2.register-choice {
padding: 20px !important;
}
.v2.register-choice.register-choice-view {
margin-right: 0;
}
.v2.register-choice .list-actions:last-child {
float: left;
width: 100%;
margin-top: 0;
}
.v2.register-choice .action-select {
width: 100% !important;
}
.v2 .continue-link:hover,
.v2 .continue-link:focus {
background-color: #d7548e !important;
color: white !important;
text-decoration: none;
}
.v2 .continue-link:hover {
cursor: pointer;
}
.v2 .copy li {
margin-bottom: 5px;
}
.v2.register-choice .copy-inline {
width: 100%;
}
.v2 .register-choice-view {
border-color: #2991c3 !important;
}
.v2 .visual-reference {
vertical-align: top;
}
.v2 .wrapper-copy-inline .wrapper-copy ul {
margin-top: 0;
padding-left: 30px;
}
.v2 .img-certificate {
border: 2px solid #009b00 !important;
float: right;
height: 120px;
width: auto;
margin-top: 0 !important;
display: none;
}
.v2 .img-donate {
margin-top: 0;
float: right;
border: 2px solid #d7548e !important;
display: none;
}
.v2 .img-view {
border: 2px solid #2991c3 !important;
}
.v2.register-choice .title {
width: 100%;
margin-bottom: 20px;
}
.v2.register-choice.register-choice-view .action-select {
border: 1px solid transparent !important;
border-radius: 3px;
}
.v2.register-choice.register-choice-view .action-select button {
border: 1px solid transparent !important;
}
.v2.register-choice.register-choice-view .action-select:hover {
border: 1px solid #0075b4 !important;
}
.v2.deco-divider {
width: 3% !important;
box-sizing: border-box;
float: left;
display: inline-block;
height: 250px;
margin: 0 0 40px 0 !important;
border-left: 4px solid #f5f5f5 !important; border-top:none !important;
.copy {
position: absolute;
top: 110px !important;
left: calc(50% - 40px) !important;
margin-left: 20px;
background: white;
text-align: center;
color: #474747;
width: 10px;
padding: 0 !important;
}
}
}
@media (min-width: 835px) {
.v2.register-choice-certificate,
.v2.register-choice-continue,
.v2.deco-divider {
min-height: 250px;
}
}
@media (min-width: 1024px) {
.v2 .continue-link {
width: 55%;
}
.v2.deco-divider .copy {
margin-left: 15px;
}
}
@media (min-width: 1096px) {
.v2.register-choice-certificate,
.v2.register-choice-continue,
.v2.deco-divider {
min-height: 260px;
}
.v2 .img-certificate, .v2 .img-donate {
margin-top: 10px;
display: initial;
}
.v2 .continue-link, .v2.register-choice-certificate button,
.v2.register-choice-certificate input {
margin-top: -22px !important;
}
} }
...@@ -299,17 +299,31 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ ...@@ -299,17 +299,31 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
%endif %endif
% if related_programs: % if related_programs:
<div class="message message-related-programs is-shown"> <div class="message message-related-programs is-shown">
<span class="related-programs-preface" tabindex="0">${_('Related Programs')}:</span> <span class="related-programs-preface" tabindex="0">${_('Related Programs')}:</span>
<ul> <ul>
% for program in related_programs: % for program in related_programs:
<li> <li>
<span class="category-icon ${program['type'].lower()}-icon" aria-hidden="true"></span> <span class="category-icon ${program['type'].lower()}-icon" aria-hidden="true"></span>
<span><a href="${program['detail_url']}">${u'{title} {type}'.format(title=program['title'], type=program['type'])}</a></span> <span><a href="${program['detail_url']}">${u'{title} {type}'.format(title=program['title'], type=program['type'])}</a></span>
</li> </li>
% endfor % endfor
</ul> </ul>
</div> % if program_data.get('is_learner_eligible_for_one_click_purchase'):
<div class="complete-program-dashboard-div"><span class="complete-program-dashboard-span">${_('Buy all remaining courses in this program and save 10%')}</span>
<a href="${urls.get('completeProgramURL')}" class="btn-brand btn cta-primary upgrade-button complete-program-dashboard-button">
${_('Upgrade All Remaining Courses (')}
% if program_data.get('discount_data', {}).get('is_discounted'):
<span class='list-price'>
${_('{"{0:.2f}".format(a)}'.format(program_data['discount_data']['total_incl_tax_excl_discounts'], 2))}
</span>
% endif
${_(' ${price:.2f} {currency} ) '.format(price=program_data.get('full_program_price'),
currency=program_data.get('discount_data', {}).get('currency')))}
</a>
</div>
% endif
</div>
% endif % endif
% if cert_status: % if cert_status:
......
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