Skip to content

Commit

Permalink
Merge pull request #558 from raccoongang/calypso-ginkgo-stage
Browse files Browse the repository at this point in the history
Calypso ginkgo stage
  • Loading branch information
oksana-slu authored Sep 6, 2018
2 parents 8eaec3b + 955aebc commit 566ae0b
Show file tree
Hide file tree
Showing 18 changed files with 219 additions and 45 deletions.
1 change: 1 addition & 0 deletions lms/djangoapps/commerce/api/v0/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def post(self, request, *args, **kwargs):
"""
Attempt to create the basket and enroll the user.
"""
return DetailResponse('Method not allowed', status=HTTP_406_NOT_ACCEPTABLE)
user = request.user
valid, course_key, error = self._is_data_valid(request)
if not valid:
Expand Down
17 changes: 16 additions & 1 deletion lms/djangoapps/courseware/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
from xmodule.modulestore.exceptions import ItemNotFoundError, NoPathToItem
from xmodule.tabs import CourseTabList
from xmodule.x_module import STUDENT_VIEW
from learner_dashboard.views import get_course_ids

from ..entrance_exams import user_can_skip_entrance_exam
from ..module_render import get_module, get_module_by_usage_id, get_module_for_descriptor
Expand Down Expand Up @@ -836,12 +837,26 @@ def program_marketing(request, program_uuid):
if not program_data:
raise Http404

course_ids = get_course_ids(program_data['courses'])
total_courses_count = len(course_ids)

started_courses_count = CourseEnrollment.enrollments_for_user(request.user).filter(course_id__in=course_ids).count()

program = ProgramMarketingDataExtender(program_data, request.user).extend()
program['type_slug'] = slugify(program['type'])
skus = program.get('skus')
ecommerce_service = EcommerceService()

context = {'program': program}
price = program.get('price', '0.00')
if price != '0.00' and started_courses_count:
program['full_program_price'] = (float(price) / total_courses_count) * (total_courses_count - started_courses_count)
elif price != '0.00':
program['full_program_price'] = float(price)

context = {
'program': program,
'add_to_cart_url': reverse('add_programm_to_cart', kwargs={'uuid': program_data['uuid']})
}

if program.get('is_learner_eligible_for_one_click_purchase') and skus:
context['buy_button_href'] = ecommerce_service.get_checkout_page_url(*skus)
Expand Down
35 changes: 17 additions & 18 deletions lms/djangoapps/learner_dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,22 @@
get_certificates,
get_program_marketing_url
)
from openedx.core.djangoapps.programs.views import program_listing as base_program_listing
from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences
from opaque_keys.edx.keys import CourseKey
from student.models import CourseEnrollment


@login_required
@require_GET
def program_listing(request):
"""View a list of programs in which the user is engaged."""
programs_config = ProgramsApiConfig.current()
if not programs_config.enabled:
raise Http404
return base_program_listing(request, request.user)

meter = ProgramProgressMeter(request.user)

context = {
'disable_courseware_js': True,
'marketing_url': get_program_marketing_url(programs_config),
'nav_hidden': True,
'programs': meter.engaged_programs,
'progress': meter.progress(),
'show_program_listing': programs_config.enabled,
'uses_pattern_library': True,
}

return render_to_response('learner_dashboard/programs.html', context)
def get_course_ids(courses):
course_ids = []
for course in courses:
course_ids.extend([CourseKey.from_string(c['key']) for c in course['course_runs']])
return course_ids


@login_required
Expand All @@ -58,7 +50,13 @@ def program_details(request, program_uuid):
course_data = meter.progress(programs=[program_data], count_only=False)[0]
certificate_data = get_certificates(request.user, program_data)

program_data.pop('courses')
course_ids = get_course_ids(program_data.pop('courses'))
total_courses_count = len(course_ids)

started_courses_count = CourseEnrollment.enrollments_for_user(request.user).filter(course_id__in=course_ids).count()

if started_courses_count:
program_data['price'] = '%.2f' % ((float(program_data['price']) / total_courses_count) * (total_courses_count - started_courses_count))

urls = {
'program_listing_url': reverse('program_listing_view'),
Expand All @@ -78,6 +76,7 @@ def program_details(request, program_uuid):
'program_data': program_data,
'course_data': course_data,
'certificate_data': certificate_data,
'add_to_cart_url': reverse('add_programm_to_cart', kwargs={'uuid': program_data['uuid']}),
}

return render_to_response('learner_dashboard/program_details.html', context)
3 changes: 2 additions & 1 deletion lms/djangoapps/shoppingcart/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
url(r'^donation/$', 'donate', name='donation'),
url(r'^csv_report/$', 'csv_report', name='payment_csv_report'),
# These following URLs are only valid if the ENABLE_SHOPPING_CART feature flag is set
url(r'^$', 'show_cart'),
url(r'^$', 'show_cart', name='show_cart'),
url(r'^clear/$', 'clear_cart'),
url(r'^remove_item/$', 'remove_item'),
url(r'^add/course/{}/$'.format(settings.COURSE_ID_PATTERN), 'add_course_to_cart', name='add_course_to_cart'),
Expand All @@ -19,6 +19,7 @@
url(r'^reset_code_redemption/$', 'reset_code_redemption'),
url(r'^billing_details/$', 'billing_details', name='billing_details'),
url(r'^verify_cart/$', 'verify_cart'),
url(r'^add/program/(?P<uuid>[0-9a-f-]+)/', 'add_program_to_cart', name='add_programm_to_cart'),
)

if settings.FEATURES.get('ENABLE_PAYMENT_FAKE'):
Expand Down
46 changes: 46 additions & 0 deletions lms/djangoapps/shoppingcart/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
render_purchase_form_html
)

from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.utils import ProgramProgressMeter

log = logging.getLogger("shoppingcart")
AUDIT_LOG = logging.getLogger("audit")

Expand Down Expand Up @@ -135,6 +138,49 @@ def add_course_to_cart(request, course_id):
return HttpResponse(_("Course added to cart."))


@require_POST
def add_program_to_cart(request, uuid):
if not request.user.is_authenticated():
return JsonResponse({'success': False, 'msg': _('You must be logged-in to add to a shopping cart')})

cart = Order.get_cart_for_user(request.user)

programs_config = ProgramsApiConfig.current()
if not programs_config.enabled:
raise JsonResponse({'success': False, 'msg': _('The program config you requested does not exist.')})

meter = ProgramProgressMeter(request.user, uuid=uuid)
program_data = meter.programs[0]

if not program_data:
return JsonResponse({'success': False, 'msg': _('The program you requested does not exist.')})

course_keys = []
for course in program_data['courses']:
for c in course['course_runs']:
course_key = SlashSeparatedCourseKey.from_deprecated_string(c['key'])
if course_key and course_key not in course_keys:
course_keys.append(course_key)

course_price = float(program_data['price']) / len(course_keys)

for course_key in course_keys:
try:
paid_course_item = PaidCourseRegistration.add_to_order(cart, course_key)
except CourseDoesNotExistException:
log.warning(u'A non-existent course "%s" is skipped.', course_key.to_deprecated_string())
except AlreadyEnrolledInCourseException:
log.info(u'Already enrolled course "%s" is skipped.', course_key.to_deprecated_string())
except ItemAlreadyInCartException:
paid_course_item = cart.orderitem_set.get(paidcourseregistration__course_id=course_key)

paid_course_item.unit_cost = course_price
paid_course_item.currency = program_data['currency']
paid_course_item.save()

return JsonResponse({'success': True, 'msg': 'Program added to cart.', 'redirect_url': reverse('show_cart')})


@login_required
@enforce_shopping_cart_enabled
def update_user_cart(request):
Expand Down
1 change: 1 addition & 0 deletions lms/static/js/learner_dashboard/models/program_model.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
subtitle: data.subtitle,
authoring_organizations: data.authoring_organizations,
detailUrl: data.detail_url,
marketingUrl: data.marketing_page_url,
xsmallBannerUrl: data.banner_image['x-small'].url,
smallBannerUrl: data.banner_image.small.url,
mediumBannerUrl: data.banner_image.medium.url,
Expand Down
2 changes: 2 additions & 0 deletions lms/static/js/learner_dashboard/views/program_card_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
uuid: this.model.get('uuid')
});
}
this.isMarketing = data.context.isMarketing;
this.render();
},

Expand All @@ -44,6 +45,7 @@
return gettext(org.key);
}),
data = $.extend(
{isMarketing: this.isMarketing},
this.model.toJSON(),
this.getProgramProgress(),
{orgList: orgList.join(' ')}
Expand Down
22 changes: 21 additions & 1 deletion lms/static/js/learner_dashboard/views/program_details_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
'js/learner_dashboard/views/collection_list_view',
'js/learner_dashboard/views/course_card_view',
'js/learner_dashboard/views/program_details_sidebar_view',
'text!../../../templates/learner_dashboard/program_details_view.underscore'
'text!../../../templates/learner_dashboard/program_details_view.underscore',
'jquery.ui'
],
function(
Backbone,
Expand All @@ -30,6 +31,10 @@

tpl: HtmlUtils.template(pageTpl),

events: {
'click button.buy-program': 'addProgramToCart'
},

initialize: function(options) {
this.options = options;
this.programModel = new Backbone.Model(this.options.programData);
Expand Down Expand Up @@ -106,6 +111,21 @@
courseModel: this.courseData,
certificateCollection: this.certificateCollection
});
},
addProgramToCart: function() {
var addToCartUrl = this.options.addToCartUrl;
$.ajax({
url: addToCartUrl,
method: 'POST',
success: function(data) {
if (data.success) {
window.location = data.redirect_url;
} else {
$("#shoppingcart-popup #msg").html(data.msg);
$("#shoppingcart-popup").dialog({width: 400});
}
}
});
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion lms/static/sass/elements/_program-card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
.program-card {
@include span(12);
border: 1px solid $border-color-l3;
border-bottom: none;
/* border-bottom: none; */
margin-bottom: $baseline;
position: relative;

Expand Down
58 changes: 46 additions & 12 deletions lms/templates/courseware/program_marketing.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@
description_max_length = 250
%>

<%static:css group='style-main-v2'/>
<%static:css group='style-main-v1'/>
<%static:css group='style-learner-dashboard'/>

<%block name="headextra">
<%static:css group='style-course-vendor'/>
<%static:css group='style-course'/>
</%block>

<%block name="js_extra">
<script src="${static.url('js/slick.min.js')}"></script>
<script src="${static.url('js/leanModal.js')}"></script>
Expand Down Expand Up @@ -75,18 +80,20 @@ <h1 class="banner-title">${title}</h1>
</a>
% endif
</div>
<div class="col col-12 md-col-4 lg-col-3" id="course-trailer">
<a href="#video-modal" class="media trailer-link visible-sm" rel="leanModal">
<i class="fa fa-play-circle-o" aria-hidden="true"></i>
<span>${_('View Program Trailer')}</span>
</a>
<div class="hidden-sm">
<button href="#video-modal" class="media btn-play" rel="leanModal">
<span class="sr">Play the ${title} program video</span>
<i class="icon fa fa-2x fa-play" alt="${_('Play')}"></i>
</button>
% if video_url:
<div class="col col-12 md-col-4 lg-col-3" id="course-trailer">
<a href="#video-modal" class="media trailer-link visible-sm" rel="leanModal">
<i class="fa fa-play-circle-o" aria-hidden="true"></i>
<span>${_('View Program Trailer')}</span>
</a>
<div class="hidden-sm">
<button href="#video-modal" class="media btn-play" rel="leanModal">
<span class="sr">Play the ${title} program video</span>
<i class="icon fa fa-2x fa-play" alt="${_('Play')}"></i>
</button>
</div>
</div>
</div>
% endif
</div>
</div>
</div>
Expand Down Expand Up @@ -391,6 +398,11 @@ <h3 class="hd">
program_type=program_type
)}
</h3>
% if (program['full_program_price'] and program['full_program_price'] != '0.00'):
<button class="btn buy-program" data-url="${add_to_cart_url}">
${Text(_('Buy all courses for ${full_program_price}')).format(full_program_price=full_program_price)}
</button>
% endif
<div class="course-cards">
% for course in courses:
% if course.get('course_runs'):
Expand Down Expand Up @@ -444,3 +456,25 @@ <h4 class="hd title">
</div>
</section>
</div>
<div id="shoppingcart-popup">
<p id='msg'></p>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('button.buy-program').click(function(e) {
var addToCartUrl = $(e.target).data('url');
$.ajax({
url: addToCartUrl,
method: 'POST',
success: function(data) {
if (data.success) {
window.location = data.redirect_url;
} else {
$("#shoppingcart-popup #msg").html(data.msg);
$("#shoppingcart-popup").dialog({width: 400});
}
}
});
});
});
</script>
5 changes: 0 additions & 5 deletions lms/templates/learner_dashboard/course_enroll.underscore
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@
</select>
</div>
<% } %>
<div class="enroll-button">
<button type="button" class="btn-brand btn cta-primary">
<%- gettext('Enroll Now') %>
</button>
</div>
<% } else if (upcoming_course_runs.length > 0) {%>
<div class="no-action-message">
<%- gettext('Coming Soon') %>
Expand Down
2 changes: 1 addition & 1 deletion lms/templates/learner_dashboard/program_card.underscore
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
</div>
</div>
<% } %>
<a href="<%- detailUrl %>" class="card-link">
<a href="<% if (isMarketing) { %><%- marketingUrl %><% } else { %><%- detailUrl %><% } %>" class="card-link">
<div class="banner-image-container">
<picture>
<source srcset="<%- xsmallBannerUrl %>" media="(max-width: <%- breakpoints.max.xsmall %>)">
Expand Down
8 changes: 7 additions & 1 deletion lms/templates/learner_dashboard/program_details.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
## Override the default styles_version to the Pattern Library version (version 2)
<%! main_css = "style-learner-dashboard" %>

<%page expression_filter="h"/>
<%inherit file="../main.html" />
Expand All @@ -11,6 +10,9 @@
)
%>

<%static:css group='style-main-v1'/>
<%static:css group='style-learner-dashboard'/>

<%block name="js_extra">
<%static:require_module module_name="js/learner_dashboard/program_details_factory" class_name="ProgramDetailsFactory">
ProgramDetailsFactory({
Expand All @@ -19,6 +21,7 @@
certificateData: ${certificate_data | n, dump_js_escaped_json},
urls: ${urls | n, dump_js_escaped_json},
userPreferences: ${user_preferences | n, dump_js_escaped_json},
addToCartUrl: "${add_to_cart_url | n}",
});
</%static:require_module>
</%block>
Expand All @@ -29,3 +32,6 @@
<main id="main" aria-label="Content" tabindex="-1">
<div class="js-program-details-wrapper program-details-wrapper"></div>
</main>
<div id="shoppingcart-popup">
<p id='msg'></p>
</div>
Loading

0 comments on commit 566ae0b

Please sign in to comment.