Commit 9cd7c932 by Renzo Lucioni

Link program listing cards to detail pages

When program detail pages are enabled, cards on the listing page will link to their respective detail pages. Includes extensive cleanup of program listing tests. ECOM-4227.
parent 142eb42e
...@@ -891,7 +891,7 @@ class AnonymousLookupTable(ModuleStoreTestCase): ...@@ -891,7 +891,7 @@ class AnonymousLookupTable(ModuleStoreTestCase):
self.assertEqual(anonymous_id, anonymous_id_for_user(self.user, course2.id, save=False)) self.assertEqual(anonymous_id, anonymous_id_for_user(self.user, course2.id, save=False))
# TODO: Clean up these tests so that they use the ProgramsDataMixin. # TODO: Clean up these tests so that they use program factories.
@attr('shard_3') @attr('shard_3')
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@ddt.ddt @ddt.ddt
......
...@@ -21,28 +21,26 @@ from lms.djangoapps.learner_dashboard.utils import ( ...@@ -21,28 +21,26 @@ from lms.djangoapps.learner_dashboard.utils import (
@require_GET @require_GET
def view_programs(request): def view_programs(request):
"""View programs in which the user is engaged.""" """View programs in which the user is engaged."""
show_program_listing = ProgramsApiConfig.current().show_program_listing programs_config = ProgramsApiConfig.current()
if not show_program_listing: if not programs_config.show_program_listing:
raise Http404 raise Http404
meter = utils.ProgramProgressMeter(request.user) meter = utils.ProgramProgressMeter(request.user)
programs = meter.engaged_programs programs = meter.engaged_programs
# TODO: Pull 'xseries' string from configuration model. # TODO: Pull 'xseries' string from configuration model.
marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/') marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').rstrip('/')
for program in programs: for program in programs:
program['detail_url'] = utils.get_program_detail_url(program, marketing_root)
program['display_category'] = utils.get_display_category(program) program['display_category'] = utils.get_display_category(program)
program['marketing_url'] = '{root}/{slug}'.format(
root=marketing_root,
slug=program['marketing_slug']
)
context = { context = {
'programs': programs, 'programs': programs,
'progress': meter.progress, 'progress': meter.progress,
'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None, 'xseries_url': marketing_root if programs_config.show_xseries_ad else None,
'nav_hidden': True, 'nav_hidden': True,
'show_program_listing': show_program_listing, 'show_program_listing': programs_config.show_program_listing,
'credentials': get_programs_credentials(request.user, category='xseries'), 'credentials': get_programs_credentials(request.user, category='xseries'),
'disable_courseware_js': True, 'disable_courseware_js': True,
'uses_pattern_library': True 'uses_pattern_library': True
...@@ -55,8 +53,8 @@ def view_programs(request): ...@@ -55,8 +53,8 @@ def view_programs(request):
@require_GET @require_GET
def program_details(request, program_id): def program_details(request, program_id):
"""View details about a specific program.""" """View details about a specific program."""
show_program_details = ProgramsApiConfig.current().show_program_details programs_config = ProgramsApiConfig.current()
if not show_program_details: if not programs_config.show_program_details:
raise Http404 raise Http404
program_data = utils.get_programs(request.user, program_id=program_id) program_data = utils.get_programs(request.user, program_id=program_id)
...@@ -65,7 +63,6 @@ def program_details(request, program_id): ...@@ -65,7 +63,6 @@ def program_details(request, program_id):
raise Http404 raise Http404
program_data = utils.supplement_program_data(program_data, request.user) program_data = utils.supplement_program_data(program_data, request.user)
show_program_listing = ProgramsApiConfig.current().show_program_listing
urls = { urls = {
'program_listing_url': reverse('program_listing_view'), 'program_listing_url': reverse('program_listing_view'),
...@@ -77,7 +74,7 @@ def program_details(request, program_id): ...@@ -77,7 +74,7 @@ def program_details(request, program_id):
context = { context = {
'program_data': program_data, 'program_data': program_data,
'urls': urls, 'urls': urls,
'show_program_listing': show_program_listing, 'show_program_listing': programs_config.show_program_listing,
'nav_hidden': True, 'nav_hidden': True,
'disable_courseware_js': True, 'disable_courseware_js': True,
'uses_pattern_library': True 'uses_pattern_library': True
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
type: data.display_category + ' Program', type: data.display_category + ' Program',
subtitle: data.subtitle, subtitle: data.subtitle,
organizations: data.organizations, organizations: data.organizations,
marketingUrl: data.marketing_url, detailUrl: data.detail_url,
smallBannerUrl: data.banner_image_urls.w348h116, smallBannerUrl: data.banner_image_urls.w348h116,
mediumBannerUrl: data.banner_image_urls.w435h145, mediumBannerUrl: data.banner_image_urls.w435h145,
largeBannerUrl: data.banner_image_urls.w726h242, largeBannerUrl: data.banner_image_urls.w726h242,
......
...@@ -28,7 +28,7 @@ define([ ...@@ -28,7 +28,7 @@ define([
modified: '2016-03-25T13:45:21.220732Z', modified: '2016-03-25T13:45:21.220732Z',
marketing_slug: 'p_2?param=haha&test=b', marketing_slug: 'p_2?param=haha&test=b',
id: 146, id: 146,
marketing_url: 'http://www.edx.org/xseries/p_2?param=haha&test=b', detail_url: 'http://courses.edx.org/dashboard/programs/1/foo',
banner_image_urls: { banner_image_urls: {
w348h116: 'http://www.edx.org/images/test1', w348h116: 'http://www.edx.org/images/test1',
w435h145: 'http://www.edx.org/images/test2', w435h145: 'http://www.edx.org/images/test2',
...@@ -55,7 +55,7 @@ define([ ...@@ -55,7 +55,7 @@ define([
expect($card.find('.title').html().trim()).toEqual(program.name); expect($card.find('.title').html().trim()).toEqual(program.name);
expect($card.find('.category span').html().trim()).toEqual('XSeries Program'); expect($card.find('.category span').html().trim()).toEqual('XSeries Program');
expect($card.find('.organization').html().trim()).toEqual(program.organizations[0].key); expect($card.find('.organization').html().trim()).toEqual(program.organizations[0].key);
expect($card.find('.card-link').attr('href')).toEqual(program.marketing_url); expect($card.find('.card-link').attr('href')).toEqual(program.detail_url);
}; };
beforeEach(function() { beforeEach(function() {
......
...@@ -5,4 +5,3 @@ ...@@ -5,4 +5,3 @@
<span><%- gettext('Explore XSeries Programs') %></span> <span><%- gettext('Explore XSeries Programs') %></span>
</a> </a>
</section> </section>
<div class="text-section"> <div class="text-section">
<h3 id="program-<%- id %>" class="title hd-3"><%- gettext(name) %></h3> <h3 id="program-<%- id %>" class="title hd-3"><%- gettext(name) %></h3>
<div class="meta-info grid-container"> <div class="meta-info grid-container">
...@@ -10,7 +9,7 @@ ...@@ -10,7 +9,7 @@
</div> </div>
<% if (progress) { %> <% if (progress) { %>
<p class="certificate-status"> <p class="certificate-status">
<a href="<%- marketingUrl %>" class="status-text secondary" aria-describedby="program-<%- id %>"><%= interpolate( <a href="<%- detailUrl %>" class="status-text secondary" aria-describedby="program-<%- id %>"><%= interpolate(
ngettext( ngettext(
'%(count)s course is in progress.', '%(count)s course is in progress.',
'%(count)s courses are in progress.', '%(count)s courses are in progress.',
...@@ -19,7 +18,7 @@ ...@@ -19,7 +18,7 @@
{count: progress.total.in_progress}, true {count: progress.total.in_progress}, true
) %></a> ) %></a>
<a href="<%- marketingUrl %>" class="status-text secondary" aria-describedby="program-<%- id %>"><%= interpolate( <a href="<%- detailUrl %>" class="status-text secondary" aria-describedby="program-<%- id %>"><%= interpolate(
ngettext( ngettext(
'%(count)s course has not been started.', '%(count)s course has not been started.',
'%(count)s courses have not been started.', '%(count)s courses have not been started.',
...@@ -42,7 +41,7 @@ ...@@ -42,7 +41,7 @@
<div class="bar not-started"></div> <div class="bar not-started"></div>
</div> </div>
<% } %> <% } %>
<a href="<%- marketingUrl %>" class="card-link"> <a href="<%- detailUrl %>" class="card-link">
<div class="banner-image-container"> <div class="banner-image-container">
<picture> <picture>
<source srcset="<%- smallBannerUrl %>" media="(max-width: <%- breakpoints.max.tiny %>)"> <source srcset="<%- smallBannerUrl %>" media="(max-width: <%- breakpoints.max.tiny %>)">
......
...@@ -14,7 +14,7 @@ class UserCredential(factory.Factory): ...@@ -14,7 +14,7 @@ class UserCredential(factory.Factory):
username = FuzzyText(prefix='user_') username = FuzzyText(prefix='user_')
status = 'awarded' status = 'awarded'
uuid = FuzzyText(prefix='uuid_') uuid = FuzzyText(prefix='uuid_')
certificate_url = 'http=//credentials.edx.org/credentials/dummy-uuid' certificate_url = FuzzyText(prefix='https://www.example.com/credentials/')
credential = {} credential = {}
......
...@@ -49,12 +49,14 @@ class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin ...@@ -49,12 +49,14 @@ class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin
factories.UserCredential( factories.UserCredential(
id=1, id=1,
username='test', username='test',
credential=factories.ProgramCredential() credential=factories.ProgramCredential(),
certificate_url=self.CREDENTIALS_API_RESPONSE['results'][0]['certificate_url'],
), ),
factories.UserCredential( factories.UserCredential(
id=2, id=2,
username='test', username='test',
credential=factories.ProgramCredential() credential=factories.ProgramCredential(),
certificate_url=self.CREDENTIALS_API_RESPONSE['results'][1]['certificate_url'],
) )
] ]
......
...@@ -6,6 +6,7 @@ import logging ...@@ -6,6 +6,7 @@ import logging
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.text import slugify
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
import pytz import pytz
...@@ -128,6 +129,26 @@ def get_programs_for_credentials(user, programs_credentials): ...@@ -128,6 +129,26 @@ def get_programs_for_credentials(user, programs_credentials):
return certificate_programs return certificate_programs
def get_program_detail_url(program, marketing_root):
"""Construct the URL to be used when linking to program details.
Arguments:
program (dict): Representation of a program.
marketing_root (str): Root URL used to build links to XSeries marketing pages.
Returns:
str, a link to program details
"""
if ProgramsApiConfig.current().show_program_details:
base = reverse('program_details_view', kwargs={'program_id': program['id']}).rstrip('/')
slug = slugify(program['name'])
else:
base = marketing_root.rstrip('/')
slug = program['marketing_slug']
return '{base}/{slug}'.format(base=base, slug=slug)
def get_display_category(program): def get_display_category(program):
""" Given the program, return the category of the program for display """ Given the program, return the category of the program for display
Arguments: Arguments:
......
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