diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 9d8d8efc63..ca60f6fe7e 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -122,15 +122,14 @@ import newrelic_custom_metrics # Note that this lives in LMS, so this dependency should be refactored. from notification_prefs.views import enable_notifications +from openedx.core.djangoapps.catalog.utils import get_programs_with_type_logo from openedx.core.djangoapps.credit.email_utils import get_credit_provider_display_names, make_providers_strings from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY -from openedx.core.djangoapps.catalog.utils import munge_catalog_program from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.utils import ProgramProgressMeter 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.user_api.preferences import api as preferences_api -from openedx.core.djangoapps.catalog.utils import get_programs_with_type_logo log = logging.getLogger("edx.student") @@ -670,9 +669,6 @@ def dashboard(request): meter = ProgramProgressMeter(user, enrollments=course_enrollments) inverted_programs = meter.invert_programs() - for program_list in inverted_programs.itervalues(): - program_list[:] = [munge_catalog_program(program) for program in program_list] - # Construct a dictionary of course mode information # used to render the course list. We re-use the course modes dict # we loaded earlier to avoid hitting the database. @@ -795,7 +791,7 @@ def dashboard(request): 'order_history_list': order_history_list, 'courses_requirements_not_met': courses_requirements_not_met, 'nav_hidden': True, - 'programs_by_run': inverted_programs, + 'inverted_programs': inverted_programs, 'show_program_listing': ProgramsApiConfig.current().show_program_listing, 'disable_courseware_js': True, 'display_course_modes_on_dashboard': enable_verified_certificates and display_course_modes_on_dashboard, diff --git a/lms/djangoapps/learner_dashboard/tests/test_programs.py b/lms/djangoapps/learner_dashboard/tests/test_programs.py index da4547fc48..a390864a82 100644 --- a/lms/djangoapps/learner_dashboard/tests/test_programs.py +++ b/lms/djangoapps/learner_dashboard/tests/test_programs.py @@ -16,7 +16,6 @@ import mock from openedx.core.djangoapps.catalog.tests.factories import ProgramFactory, CourseFactory, CourseRunFactory from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin -from openedx.core.djangoapps.catalog.utils import munge_catalog_program from openedx.core.djangoapps.credentials.tests.factories import UserCredential, ProgramCredential from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin @@ -64,13 +63,7 @@ class TestProgramListing(ProgramsApiConfigMixin, CredentialsApiConfigMixin, Shar """ Helper function used to sort dictionaries representing programs. """ - try: - return program['title'] - except: # pylint: disable=bare-except - # This is here temporarily because programs are still being munged - # to look like they came from the programs service before going out - # to the front end. - return program['name'] + return program['title'] def credential_sort_key(self, credential): """ @@ -157,7 +150,7 @@ class TestProgramListing(ProgramsApiConfigMixin, CredentialsApiConfigMixin, Shar actual = sorted(actual, key=self.program_sort_key) for index, actual_program in enumerate(actual): - expected_program = munge_catalog_program(self.data[index]) + expected_program = self.data[index] self.assert_dict_contains_subset(actual_program, expected_program) def test_program_discovery(self, mock_get_programs): diff --git a/lms/djangoapps/learner_dashboard/views.py b/lms/djangoapps/learner_dashboard/views.py index 89bcf60827..3336a91313 100644 --- a/lms/djangoapps/learner_dashboard/views.py +++ b/lms/djangoapps/learner_dashboard/views.py @@ -6,12 +6,11 @@ from django.views.decorators.http import require_GET from edxmako.shortcuts import render_to_response from lms.djangoapps.learner_dashboard.utils import strip_course_id, FAKE_COURSE_KEY -from openedx.core.djangoapps.catalog.utils import get_programs, munge_catalog_program +from openedx.core.djangoapps.catalog.utils import get_programs from openedx.core.djangoapps.credentials.utils import get_programs_credentials from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.utils import ( get_program_marketing_url, - munge_progress_map, ProgramProgressMeter, ProgramDataExtender, ) @@ -27,16 +26,14 @@ def program_listing(request): raise Http404 meter = ProgramProgressMeter(request.user) - engaged_programs = [munge_catalog_program(program) for program in meter.engaged_programs] - progress = [munge_progress_map(progress_map) for progress_map in meter.progress] context = { 'credentials': get_programs_credentials(request.user), 'disable_courseware_js': True, 'marketing_url': get_program_marketing_url(programs_config), 'nav_hidden': True, - 'programs': engaged_programs, - 'progress': progress, + 'programs': meter.engaged_programs, + 'progress': meter.progress, 'show_program_listing': programs_config.show_program_listing, 'uses_pattern_library': True, } @@ -56,7 +53,6 @@ def program_details(request, program_uuid): if not program_data: raise Http404 - program_data = munge_catalog_program(program_data) program_data = ProgramDataExtender(program_data, request.user).extend() urls = { diff --git a/lms/static/js/learner_dashboard/models/course_card_model.js b/lms/static/js/learner_dashboard/models/course_card_model.js index 2652d600c4..cc04551f5b 100644 --- a/lms/static/js/learner_dashboard/models/course_card_model.js +++ b/lms/static/js/learner_dashboard/models/course_card_model.js @@ -5,60 +5,93 @@ 'use strict'; define([ 'backbone', + 'underscore', + 'jquery', 'edx-ui-toolkit/js/utils/date-utils' ], - function(Backbone, DateUtils) { + function(Backbone, _, $, DateUtils) { return Backbone.Model.extend({ initialize: function(data) { if (data) { this.context = data; - this.setActiveRunMode(this.getRunMode(data.run_modes), data.user_preferences); + this.setActiveCourseRun(this.getCourseRun(data.course_runs), data.user_preferences); } }, - getUnselectedRunMode: function(runModes) { - if (runModes && runModes.length > 0) { - return { - course_image_url: runModes[0].course_image_url, - marketing_url: runModes[0].marketing_url, - is_enrollment_open: runModes[0].is_enrollment_open - }; - } + getCourseRun: function(courseRuns) { + var enrolledCourseRun = _.findWhere(courseRuns, {is_enrolled: true}), + openEnrollmentCourseRuns = this.getEnrollableCourseRuns(), + desiredCourseRun; - return {}; - }, - - getRunMode: function(runModes) { - var enrolled_mode = _.findWhere(runModes, {is_enrolled: true}), - openEnrollmentRunModes = this.getEnrollableRunModes(), - desiredRunMode; - // We populate our model by looking at the run modes. - if (enrolled_mode) { - // If the learner is already enrolled in a run mode, return that one. - desiredRunMode = enrolled_mode; - } else if (openEnrollmentRunModes.length > 0) { - if (openEnrollmentRunModes.length === 1) { - desiredRunMode = openEnrollmentRunModes[0]; + // We populate our model by looking at the course runs. + if (enrolledCourseRun) { + // If the learner is already enrolled in a course run, return that one. + desiredCourseRun = enrolledCourseRun; + } else if (openEnrollmentCourseRuns.length > 0) { + if (openEnrollmentCourseRuns.length === 1) { + desiredCourseRun = openEnrollmentCourseRuns[0]; } else { - desiredRunMode = this.getUnselectedRunMode(openEnrollmentRunModes); + desiredCourseRun = this.getUnselectedCourseRun(openEnrollmentCourseRuns); } } else { - desiredRunMode = this.getUnselectedRunMode(runModes); + desiredCourseRun = this.getUnselectedCourseRun(courseRuns); } - return desiredRunMode; + return desiredCourseRun; }, - getEnrollableRunModes: function() { - return _.where(this.context.run_modes, { + getUnselectedCourseRun: function(courseRuns) { + var unselectedRun = {}, + courseRun, + courseImageUrl; + + if (courseRuns && courseRuns.length > 0) { + courseRun = courseRuns[0]; + + if (courseRun.hasOwnProperty('image')) { + courseImageUrl = courseRun.image.src; + } else { + // The course_image_url property is attached by setActiveCourseRun. + // If that hasn't been called, it won't be present yet. + courseImageUrl = courseRun.course_image_url; + } + + $.extend(unselectedRun, { + course_image_url: courseImageUrl, + marketing_url: courseRun.marketing_url, + is_enrollment_open: courseRun.is_enrollment_open + }); + } + + return unselectedRun; + }, + + getEnrollableCourseRuns: function() { + var rawCourseRuns, + enrollableCourseRuns; + + rawCourseRuns = _.where(this.context.course_runs, { is_enrollment_open: true, is_enrolled: false, is_course_ended: false }); + + // Deep copy to avoid mutating this.context. + enrollableCourseRuns = $.extend(true, [], rawCourseRuns); + + // These are raw course runs from the server. The start + // dates are ISO-8601 formatted strings that need to be + // prepped for display. + _.each(enrollableCourseRuns, (function(courseRun) { + // eslint-disable-next-line no-param-reassign + courseRun.start_date = this.formatDate(courseRun.start); + }).bind(this)); + + return enrollableCourseRuns; }, - getUpcomingRunModes: function() { - return _.where(this.context.run_modes, { + getUpcomingCourseRuns: function() { + return _.where(this.context.course_runs, { is_enrollment_open: false, is_enrolled: false, is_course_ended: false @@ -82,51 +115,54 @@ return DateUtils.localize(context); }, - setActiveRunMode: function(runMode, userPreferences) { - var startDateString; - if (runMode) { - if (runMode.advertised_start !== undefined && runMode.advertised_start !== 'None') { - startDateString = runMode.advertised_start; + setActiveCourseRun: function(courseRun, userPreferences) { + var startDateString, + courseImageUrl; + + if (courseRun) { + if (courseRun.advertised_start !== undefined && courseRun.advertised_start !== 'None') { + startDateString = courseRun.advertised_start; } else { - startDateString = this.formatDate( - runMode.start_date, - userPreferences - ); + startDateString = this.formatDate(courseRun.start, userPreferences); } + + if (courseRun.hasOwnProperty('image')) { + courseImageUrl = courseRun.image.src; + } else { + courseImageUrl = courseRun.course_image_url; + } + this.set({ - certificate_url: runMode.certificate_url, - course_image_url: runMode.course_image_url || '', - course_key: runMode.course_key, - course_url: runMode.course_url || '', - display_name: this.context.display_name, - end_date: this.formatDate( - runMode.end_date, - userPreferences - ), - enrollable_run_modes: this.getEnrollableRunModes(), - is_course_ended: runMode.is_course_ended, - is_enrolled: runMode.is_enrolled, - is_enrollment_open: runMode.is_enrollment_open, - key: this.context.key, - marketing_url: runMode.marketing_url, - mode_slug: runMode.mode_slug, - run_key: runMode.run_key, + certificate_url: courseRun.certificate_url, + course_image_url: courseImageUrl || '', + course_run_key: courseRun.key, + course_url: courseRun.course_url || '', + title: this.context.title, + end_date: this.formatDate(courseRun.end, userPreferences), + enrollable_course_runs: this.getEnrollableCourseRuns(), + is_course_ended: courseRun.is_course_ended, + is_enrolled: courseRun.is_enrolled, + is_enrollment_open: courseRun.is_enrollment_open, + course_key: this.context.key, + marketing_url: courseRun.marketing_url, + mode_slug: courseRun.type, start_date: startDateString, - upcoming_run_modes: this.getUpcomingRunModes(), - upgrade_url: runMode.upgrade_url + upcoming_course_runs: this.getUpcomingCourseRuns(), + upgrade_url: courseRun.upgrade_url }); } }, + setUnselected: function() { - // Called to reset the model back to the unselected state. - var unselectedMode = this.getUnselectedRunMode(this.get('enrollable_run_modes')); - this.setActiveRunMode(unselectedMode); + // Called to reset the model back to the unselected state. + var unselectedCourseRun = this.getUnselectedCourseRun(this.get('enrollable_course_runs')); + this.setActiveCourseRun(unselectedCourseRun); }, - updateRun: function(runKey) { - var selectedRun = _.findWhere(this.get('run_modes'), {run_key: runKey}); - if (selectedRun) { - this.setActiveRunMode(selectedRun); + updateCourseRun: function(courseRunKey) { + var selectedCourseRun = _.findWhere(this.get('course_runs'), {key: courseRunKey}); + if (selectedCourseRun) { + this.setActiveCourseRun(selectedCourseRun); } } }); diff --git a/lms/static/js/learner_dashboard/models/program_model.js b/lms/static/js/learner_dashboard/models/program_model.js index d5921daa6d..66f937edea 100644 --- a/lms/static/js/learner_dashboard/models/program_model.js +++ b/lms/static/js/learner_dashboard/models/program_model.js @@ -11,17 +11,17 @@ initialize: function(data) { if (data) { this.set({ - name: data.name, - category: data.category, + title: data.title, + type: data.type, subtitle: data.subtitle, - organizations: data.organizations, + authoring_organizations: data.authoring_organizations, detailUrl: data.detail_url, - smallBannerUrl: data.banner_image_urls.w348h116, - mediumBannerUrl: data.banner_image_urls.w435h145, - largeBannerUrl: data.banner_image_urls.w726h242, + xsmallBannerUrl: data.banner_image['x-small'].url, + smallBannerUrl: data.banner_image.small.url, + mediumBannerUrl: data.banner_image.medium.url, breakpoints: { max: { - tiny: '320px', + xsmall: '320px', small: '540px', medium: '768px', large: '979px' diff --git a/lms/static/js/learner_dashboard/views/course_enroll_view.js b/lms/static/js/learner_dashboard/views/course_enroll_view.js index f8d45bbee2..c66211fb37 100644 --- a/lms/static/js/learner_dashboard/views/course_enroll_view.js +++ b/lms/static/js/learner_dashboard/views/course_enroll_view.js @@ -21,7 +21,7 @@ events: { 'click .enroll-button': 'handleEnroll', - 'change .run-select': 'handleRunSelect' + 'change .run-select': 'handleCourseRunSelect' }, initialize: function(options) { @@ -45,12 +45,12 @@ handleEnroll: function() { // Enrollment click event handled here - if (!this.model.get('course_key')) { + if (!this.model.get('course_run_key')) { this.$('.select-error').css('visibility', 'visible'); } else if (!this.model.get('is_enrolled')) { - // actually enroll + // Create the enrollment. this.enrollModel.save({ - course_id: this.model.get('course_key') + course_id: this.model.get('course_run_key') }, { success: _.bind(this.enrollSuccess, this), error: _.bind(this.enrollError, this) @@ -58,24 +58,22 @@ } }, - handleRunSelect: function(event) { - var runKey; - if (event.target) { - runKey = $(event.target).val(); - if (runKey) { - this.model.updateRun(runKey); - } else { - // Set back the unselected states - this.model.setUnselected(); - } + handleCourseRunSelect: function(event) { + var courseRunKey = $(event.target).val(); + + if (courseRunKey) { + this.model.updateCourseRun(courseRunKey); + } else { + // Set back the unselected states + this.model.setUnselected(); } }, enrollSuccess: function() { - var courseKey = this.model.get('course_key'); + var courseRunKey = this.model.get('course_run_key'); if (this.trackSelectionUrl) { - // Go to track selection page - this.redirect(this.trackSelectionUrl + courseKey); + // Go to track selection page + this.redirect(this.trackSelectionUrl + courseRunKey); } else { this.model.set({ is_enrolled: true @@ -98,7 +96,7 @@ * This can occur, for example, when a course does not * have a free enrollment mode, so we can't auto-enroll. */ - this.redirect(this.trackSelectionUrl + this.model.get('course_key')); + this.redirect(this.trackSelectionUrl + this.model.get('course_run_key')); } }, diff --git a/lms/static/js/learner_dashboard/views/program_card_view.js b/lms/static/js/learner_dashboard/views/program_card_view.js index bbbf9209e0..05cb63d389 100644 --- a/lms/static/js/learner_dashboard/views/program_card_view.js +++ b/lms/static/js/learner_dashboard/views/program_card_view.js @@ -22,7 +22,7 @@ attributes: function() { return { - 'aria-labelledby': 'program-' + this.model.get('id'), + 'aria-labelledby': 'program-' + this.model.get('uuid'), 'role': 'group' }; }, @@ -33,14 +33,14 @@ this.progressCollection = data.context.progressCollection; if (this.progressCollection) { this.progressModel = this.progressCollection.findWhere({ - id: this.model.get('id') + uuid: this.model.get('uuid') }); } this.render(); }, render: function() { - var orgList = _.map(this.model.get('organizations'), function(org) { + var orgList = _.map(this.model.get('authoring_organizations'), function(org) { return gettext(org.key); }), data = $.extend( @@ -56,7 +56,7 @@ postRender: function() { // Add describedby to parent only if progess is present if (this.progressModel) { - this.$el.attr('aria-describedby', 'status-' + this.model.get('id')); + this.$el.attr('aria-describedby', 'status-' + this.model.get('uuid')); } if (navigator.userAgent.indexOf('MSIE') !== -1 || @@ -73,19 +73,14 @@ var progress = this.progressModel ? this.progressModel.toJSON() : false; if (progress) { - progress.total = { - completed: progress.completed.length, - in_progress: progress.in_progress.length, - not_started: progress.not_started.length - }; - progress.total.courses = progress.total.completed + - progress.total.in_progress + - progress.total.not_started; + progress.total = progress.completed + + progress.in_progress + + progress.not_started; progress.percentage = { - completed: this.getWidth(progress.total.completed, progress.total.courses), - in_progress: this.getWidth(progress.total.in_progress, progress.total.courses) + completed: this.getWidth(progress.completed, progress.total), + in_progress: this.getWidth(progress.in_progress, progress.total) }; } 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 6536375c7e..afb267669a 100644 --- a/lms/static/js/learner_dashboard/views/program_details_view.js +++ b/lms/static/js/learner_dashboard/views/program_details_view.js @@ -33,7 +33,7 @@ this.options = options; this.programModel = new Backbone.Model(this.options.programData); this.courseCardCollection = new CourseCardCollection( - this.programModel.get('course_codes'), + this.programModel.get('courses'), this.options.userPreferences ); this.render(); diff --git a/lms/static/js/spec/learner_dashboard/collection_list_view_spec.js b/lms/static/js/spec/learner_dashboard/collection_list_view_spec.js index ee3e0c0cc3..c3f7a9b0c0 100644 --- a/lms/static/js/spec/learner_dashboard/collection_list_view_spec.js +++ b/lms/static/js/spec/learner_dashboard/collection_list_view_spec.js @@ -5,10 +5,9 @@ define([ 'js/learner_dashboard/collections/program_collection', 'js/learner_dashboard/views/collection_list_view', 'js/learner_dashboard/collections/program_progress_collection' -], function(Backbone, $, ProgramCardView, ProgramCollection, CollectionListView, - ProgressCollection) { +], function(Backbone, $, ProgramCardView, ProgramCollection, CollectionListView, ProgressCollection) { 'use strict'; - /* jslint maxlen: 500 */ + /* jslint maxlen: 500 */ describe('Collection List View', function() { var view = null, @@ -17,62 +16,90 @@ define([ context = { programsData: [ { - category: 'xseries', - status: 'active', - subtitle: 'program 1', - name: 'test program 1', - organizations: [ - { - display_name: 'edX', - key: 'edx' + uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8', + title: 'Food Security and Sustainability', + subtitle: 'Learn how to feed all people in the world in a sustainable way.', + type: 'XSeries', + detail_url: 'https://www.edx.org/foo/bar', + banner_image: { + medium: { + height: 242, + width: 726, + url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.medium.jpg' + }, + 'x-small': { + height: 116, + width: 348, + url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.x-small.jpg' + }, + small: { + height: 145, + width: 435, + url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.small.jpg' + }, + large: { + height: 480, + width: 1440, + url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.large.jpg' } - ], - created: '2016-03-03T19:18:50.061136Z', - modified: '2016-03-25T13:45:21.220732Z', - marketing_slug: 'p_2?param=haha&test=b', - id: 146, - marketing_url: 'http://www.edx.org/xseries/p_2?param=haha&test=b', - banner_image_urls: { - w348h116: 'http://www.edx.org/images/org1/test1', - w435h145: 'http://www.edx.org/images/org1/test2', - w726h242: 'http://www.edx.org/images/org1/test3' - } + }, + authoring_organizations: [ + { + uuid: '0c6e5fa2-96e8-40b2-9ebe-c8b0df2a3b22', + key: 'WageningenX', + name: 'Wageningen University & Research' + } + ] }, { - category: 'xseries', - status: 'active', - subtitle: 'fda', - name: 'fda', - organizations: [ - { - display_name: 'edX', - key: 'edx' + uuid: '91d144d2-1bb1-4afe-90df-d5cff63fa6e2', + title: 'edX Course Creator', + subtitle: 'Become an expert in creating courses for the edX platform.', + type: 'XSeries', + detail_url: 'https://www.edx.org/foo/bar', + banner_image: { + medium: { + height: 242, + width: 726, + url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.medium.jpg' + }, + 'x-small': { + height: 116, + width: 348, + url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.x-small.jpg' + }, + small: { + height: 145, + width: 435, + url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.small.jpg' + }, + large: { + height: 480, + width: 1440, + url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.large.jpg' } - ], - created: '2016-03-09T14:30:41.484848Z', - modified: '2016-03-09T14:30:52.840898Z', - marketing_slug: 'gdaf', - id: 147, - marketing_url: 'http://www.edx.org/xseries/gdaf', - banner_image_urls: { - w348h116: 'http://www.edx.org/images/org2/test1', - w435h145: 'http://www.edx.org/images/org2/test2', - w726h242: 'http://www.edx.org/images/org2/test3' - } + }, + authoring_organizations: [ + { + uuid: '4f8cb2c9-589b-4d1e-88c1-b01a02db3a9c', + key: 'edX', + name: 'edX' + } + ] } ], userProgress: [ { - id: 146, - completed: ['courses', 'the', 'user', 'completed'], - in_progress: ['in', 'progress'], - not_started: ['courses', 'not', 'yet', 'started'] + uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8', + completed: 4, + in_progress: 2, + not_started: 4 }, { - id: 147, - completed: ['Course 1'], - in_progress: [], - not_started: ['Course 2', 'Course 3', 'Course 4'] + uuid: '91d144d2-1bb1-4afe-90df-d5cff63fa6e2', + completed: 1, + in_progress: 0, + not_started: 3 } ] }; @@ -105,7 +132,8 @@ define([ var $cards = view.$el.find('.program-card'); expect($cards.length).toBe(2); $cards.each(function(index, el) { - expect($(el).find('.title').html().trim()).toEqual(context.programsData[index].name); + // eslint-disable-next-line newline-per-chained-call + expect($(el).find('.title').html().trim()).toEqual(context.programsData[index].title); }); }); @@ -116,13 +144,14 @@ define([ view = new CollectionListView({ el: '.program-cards-container', childView: ProgramCardView, - context: {'xseriesUrl': '/programs'}, + context: {}, collection: programCollection }); view.render(); $cards = view.$el.find('.program-card'); expect($cards.length).toBe(0); }); + it('should have no title when title not provided', function() { var $title; setFixtures('
${Text(_("You can no longer access this course because payment has not yet been received. "
diff --git a/lms/templates/learner_dashboard/course_card.underscore b/lms/templates/learner_dashboard/course_card.underscore
index fe035c459c..e93ff8eec1 100644
--- a/lms/templates/learner_dashboard/course_card.underscore
+++ b/lms/templates/learner_dashboard/course_card.underscore
@@ -7,7 +7,7 @@
class="header-img"
src="<%- course_image_url %>"
<% // safe-lint: disable=underscore-not-escaped %>
- alt="<%= interpolate(gettext('%(courseName)s Home Page.'), {courseName: display_name}, true) %>"/>
+ alt="<%= interpolate(gettext('%(courseName)s Home Page.'), {courseName: title}, true) %>"/>
<% } else { %>
@@ -18,10 +18,10 @@
- <%= interpolate( + <%= interpolate( ngettext( '%(count)s course is in progress.', '%(count)s courses are in progress.', - progress.total.in_progress + progress.in_progress ), - {count: progress.total.in_progress}, true + {count: progress.in_progress}, true ) %> - <%= interpolate( + <%= interpolate( ngettext( '%(count)s course has not been started.', '%(count)s courses have not been started.', - progress.total.not_started + progress.not_started ), - {count: progress.total.not_started}, true + {count: progress.not_started}, true ) %> - <%= interpolate( + <%= interpolate( gettext('You have earned certificates in %(completed_courses)s of the %(total_courses)s courses so far.'), - {completed_courses: progress.total.completed, total_courses: progress.total.courses}, true + {completed_courses: progress.completed, total_courses: progress.total}, true ) %>
<% } %> @@ -44,11 +44,11 @@ diff --git a/lms/templates/learner_dashboard/program_header_view.underscore b/lms/templates/learner_dashboard/program_header_view.underscore index 7fe8c90703..edcd3171a9 100644 --- a/lms/templates/learner_dashboard/program_header_view.underscore +++ b/lms/templates/learner_dashboard/program_header_view.underscore @@ -1,19 +1,19 @@