diff --git a/lms/djangoapps/learner_dashboard/views.py b/lms/djangoapps/learner_dashboard/views.py index e166ee1ea0..57202af5c4 100644 --- a/lms/djangoapps/learner_dashboard/views.py +++ b/lms/djangoapps/learner_dashboard/views.py @@ -5,11 +5,12 @@ from django.http import Http404 from django.views.decorators.http import require_GET from edxmako.shortcuts import render_to_response +from commerce.utils import EcommerceService + from lms.djangoapps.learner_dashboard.utils import FAKE_COURSE_KEY, strip_course_id -from openedx.core.djangoapps.catalog.utils import get_programs from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.utils import ( - ProgramDataExtender, + ProgramMarketingDataExtender, ProgramProgressMeter, get_certificates, get_program_marketing_url @@ -54,11 +55,13 @@ def program_details(request, program_uuid): if not program_data: raise Http404 - program_data = ProgramDataExtender(program_data, request.user).extend() + program_data = ProgramMarketingDataExtender(program_data, request.user).extend() course_data = meter.progress(programs=[program_data], count_only=False)[0] certificate_data = get_certificates(request.user, program_data) program_data.pop('courses') + skus = program_data.get('skus') + ecommerce_service = EcommerceService() urls = { 'program_listing_url': reverse('program_listing_view'), @@ -66,6 +69,7 @@ def program_details(request, program_uuid): reverse('course_modes_choose', kwargs={'course_id': FAKE_COURSE_KEY}) ), 'commerce_api_url': reverse('commerce_api:v0:baskets:create'), + 'buy_button_url': ecommerce_service.get_checkout_page_url(*skus) } context = { @@ -77,7 +81,7 @@ def program_details(request, program_uuid): 'user_preferences': get_user_preferences(request.user), 'program_data': program_data, 'course_data': course_data, - 'certificate_data': certificate_data, + 'certificate_data': certificate_data } return render_to_response('learner_dashboard/program_details.html', context) diff --git a/lms/static/js/learner_dashboard/views/program_details_view.js b/lms/static/js/learner_dashboard/views/program_details_view.js index 442a98a6b8..435e3966c3 100644 --- a/lms/static/js/learner_dashboard/views/program_details_view.js +++ b/lms/static/js/learner_dashboard/views/program_details_view.js @@ -32,6 +32,7 @@ initialize: function(options) { this.options = options; + this.programModel = new Backbone.Model(this.options.programData); this.courseData = new Backbone.Model(this.options.courseData); this.certificateCollection = new Backbone.Collection(this.options.certificateData); @@ -60,7 +61,8 @@ totalCount: totalCount, inProgressCount: inProgressCount, remainingCount: remainingCount, - completedCount: completedCount + completedCount: completedCount, + completeProgramURL: this.options.urls.buy_button_url }; data = $.extend(data, this.programModel.toJSON()); HtmlUtils.setHtml(this.$el, this.tpl(data)); diff --git a/lms/static/js/spec/learner_dashboard/program_details_view_spec.js b/lms/static/js/spec/learner_dashboard/program_details_view_spec.js index cde77f6144..ddb4d5ac1a 100644 --- a/lms/static/js/spec/learner_dashboard/program_details_view_spec.js +++ b/lms/static/js/spec/learner_dashboard/program_details_view_spec.js @@ -52,6 +52,14 @@ define([ marketing_url: 'someurl', status: 'active', credit_redemption_overview: '', + discount_data: { + currency: 'USD', + discount_value: 0, + is_discounted: false, + total_incl_tax: 300, + total_incl_tax_excl_discounts: 300 + }, + full_program_price: 300, card_image_url: 'some image', faq: [], price_ranges: [ @@ -117,7 +125,8 @@ define([ credit_backing_organizations: [], weeks_to_complete_min: 8, weeks_to_complete_max: 8, - min_hours_effort_per_week: null + min_hours_effort_per_week: null, + is_learner_eligible_for_one_click_purchase: false }, courseData: { completed: [ @@ -549,7 +558,42 @@ define([ view.render(); expect($(view.$('.upgrade-message .card-msg')).text().trim()).toEqual('Certificate Status:'); expect($(view.$('.upgrade-message .price')).text().trim()).toEqual('$10.00'); - expect($(view.$('.upgrade-button')[0]).text().trim()).toEqual('Buy Certificate'); + expect($(view.$('.upgrade-button.single-course-run')[0]).text().trim()).toEqual('Upgrade to Verified'); + }); + + it('should render full program purchase link', function() { + view = initView({ + programData: $.extend({}, options.programData, { + is_learner_eligible_for_one_click_purchase: true + }) + }); + view.render(); + expect($(view.$('.upgrade-button.complete-program')).text().trim(). + replace(/\s+/g, ' ')). + toEqual( + 'Upgrade All Remaining Courses ( $300 USD )' + ); + }); + + it('should render partial program purchase link', function() { + view = initView({ + programData: $.extend({}, options.programData, { + is_learner_eligible_for_one_click_purchase: true, + discount_data: { + currency: 'USD', + discount_value: 30, + is_discounted: true, + total_incl_tax: 300, + total_incl_tax_excl_discounts: 270 + } + }) + }); + view.render(); + expect($(view.$('.upgrade-button.complete-program')).text().trim(). + replace(/\s+/g, ' ')). + toEqual( + 'Upgrade All Remaining Courses ( $270 $300 USD )' + ); }); it('should render enrollment information', function() { diff --git a/lms/static/sass/views/_program-details.scss b/lms/static/sass/views/_program-details.scss index 8eb9b60fa7..725373212c 100644 --- a/lms/static/sass/views/_program-details.scss +++ b/lms/static/sass/views/_program-details.scss @@ -285,8 +285,10 @@ } .program-heading { - width: 100%; margin-bottom: 40px; + display: flex; + justify-content: flex-start; + flex-direction: column; .program-heading-title { font-family: "Open Sans"; @@ -300,6 +302,7 @@ .program-heading-message { font-weight: 300; } + } .course-enroll-view { @@ -387,7 +390,34 @@ padding: 0; } } - + + .upgrade-button { + background: palette(success, text); + border-color: palette(success, text); + border-radius: 0; + padding: 7px; + text-align: center; + font-size: 0.9375em; + + /* IE11 CSS styles */ + @media(min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { + @include float(right); + } + &.complete-program { + margin: 10px 15px 10px 5px; + align-self: flex-start; + + @media(min-width: $bp-screen-md) { + align-self: flex-end; + } + + .list-price { + text-decoration: line-through; + } + } + } + + .program-course-card { width: 100%; padding: 15px; @@ -462,22 +492,6 @@ .upgrade-message { flex-wrap: wrap; - .upgrade-button { - background: palette(success, text); - border-color: palette(success, text); - height: 37px; - width: 128px; - border-radius: 0; - padding: 7px 0 0 0; - text-align: center; - font-size: 0.9375em; - - /* IE11 CSS styles */ - @media(min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { - @include float(right); - } - } - .action { width: 100%; margin: 5px 0; diff --git a/lms/templates/learner_dashboard/program_details_view.underscore b/lms/templates/learner_dashboard/program_details_view.underscore index ba314359b7..a6c4f69eb1 100644 --- a/lms/templates/learner_dashboard/program_details_view.underscore +++ b/lms/templates/learner_dashboard/program_details_view.underscore @@ -20,6 +20,23 @@