diff --git a/lms/static/js/learner_dashboard/collections/course_card_collection.js b/lms/static/js/learner_dashboard/collections/course_card_collection.js new file mode 100644 index 0000000000..998e0d33e8 --- /dev/null +++ b/lms/static/js/learner_dashboard/collections/course_card_collection.js @@ -0,0 +1,12 @@ +(function (define) { + 'use strict'; + define([ + 'backbone', + 'js/learner_dashboard/models/course_card_model' + ], + function (Backbone, CourseCard) { + return Backbone.Collection.extend({ + model: CourseCard + }); + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/learner_dashboard/models/course_card_model.js b/lms/static/js/learner_dashboard/models/course_card_model.js new file mode 100644 index 0000000000..e3d4c744bc --- /dev/null +++ b/lms/static/js/learner_dashboard/models/course_card_model.js @@ -0,0 +1,38 @@ +/** + * Model for Course Programs. + */ +(function (define) { + 'use strict'; + define([ + 'backbone' + ], + function (Backbone) { + return Backbone.Model.extend({ + initialize: function(data) { + if (data){ + this.context = data; + //we should populate our model by looking at the run_modes + if (data.run_modes.length > 0){ + //We only have 1 run mode for this program + this.setActiveRunMode(data.run_modes[0]); + } + } + }, + + setActiveRunMode: function(runMode){ + this.set({ + display_name: this.context.display_name, + key: this.context.key, + marketing_url: runMode.marketing_url || '', + start_date: runMode.start_date, + end_date: runMode.end_date, + is_enrolled: runMode.is_enrolled, + is_enrollment_open: runMode.is_enrollment_open, + course_url: runMode.course_url || '', + course_image_url: runMode.course_image_url || '', + mode_slug: runMode.mode_slug + }); + } + }); + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/learner_dashboard/views/course_card_view.js b/lms/static/js/learner_dashboard/views/course_card_view.js index 33ea0b0297..69f17c1cee 100644 --- a/lms/static/js/learner_dashboard/views/course_card_view.js +++ b/lms/static/js/learner_dashboard/views/course_card_view.js @@ -6,6 +6,7 @@ 'underscore', 'gettext', 'edx-ui-toolkit/js/utils/html-utils', + 'js/learner_dashboard/views/course_enroll_view', 'text!../../../templates/learner_dashboard/course_card.underscore' ], function( @@ -14,6 +15,7 @@ _, gettext, HtmlUtils, + CourseEnrollView, pageTpl ) { return Backbone.View.extend({ @@ -28,6 +30,15 @@ render: function() { var filledTemplate = this.tpl(this.model.toJSON()); HtmlUtils.setHtml(this.$el, filledTemplate); + this.postRender(); + }, + + postRender: function(){ + this.enrollView = new CourseEnrollView({ + $el: this.$('.course-actions'), + model: this.model, + context: this.context + }); } }); } diff --git a/lms/static/js/learner_dashboard/views/course_enroll_view.js b/lms/static/js/learner_dashboard/views/course_enroll_view.js new file mode 100644 index 0000000000..3f45779b6e --- /dev/null +++ b/lms/static/js/learner_dashboard/views/course_enroll_view.js @@ -0,0 +1,44 @@ +;(function (define) { + 'use strict'; + + define(['backbone', + 'jquery', + 'underscore', + 'gettext', + 'edx-ui-toolkit/js/utils/html-utils', + 'text!../../../templates/learner_dashboard/course_enroll.underscore' + ], + function( + Backbone, + $, + _, + gettext, + HtmlUtils, + pageTpl + ) { + return Backbone.View.extend({ + tpl: HtmlUtils.template(pageTpl), + + events: { + 'click .enroll-button': 'handleEnroll' + }, + + initialize: function(options) { + if (options.$el){ + this.$el = options.$el; + this.render(); + } + }, + + render: function() { + var filledTemplate = this.tpl(this.model.toJSON()); + HtmlUtils.setHtml(this.$el, filledTemplate); + }, + + handleEnroll: function(){ + //Enrollment click event handled here + } + }); + } + ); +}).call(this, define || RequireJS.define); 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 98dd5cff81..37fb94c34b 100644 --- a/lms/static/js/learner_dashboard/views/program_details_view.js +++ b/lms/static/js/learner_dashboard/views/program_details_view.js @@ -6,6 +6,7 @@ 'underscore', 'gettext', 'edx-ui-toolkit/js/utils/html-utils', + 'js/learner_dashboard/collections/course_card_collection', 'js/learner_dashboard/views/program_header_view', 'js/learner_dashboard/views/collection_list_view', 'js/learner_dashboard/views/course_card_view', @@ -17,6 +18,7 @@ _, gettext, HtmlUtils, + CourseCardCollection, HeaderView, CollectionListView, CourseCardView, @@ -29,7 +31,7 @@ initialize: function(options) { this.programModel = new Backbone.Model(options); - this.courseCardsCollection = new Backbone.Collection( + this.courseCardCollection = new CourseCardCollection( this.programModel.get('course_codes') ); this.render(); @@ -47,7 +49,7 @@ new CollectionListView({ el: '.js-course-list', childView: CourseCardView, - collection: this.courseCardsCollection, + collection: this.courseCardCollection, context: this.programModel.toJSON(), titleContext: { el: 'h2', diff --git a/lms/static/js/spec/learner_dashboard/course_card_view_spec.js b/lms/static/js/spec/learner_dashboard/course_card_view_spec.js index db1fc69397..5fa267b361 100644 --- a/lms/static/js/spec/learner_dashboard/course_card_view_spec.js +++ b/lms/static/js/spec/learner_dashboard/course_card_view_spec.js @@ -1,8 +1,9 @@ define([ 'backbone', 'jquery', + 'js/learner_dashboard/models/course_card_model', 'js/learner_dashboard/views/course_card_view' - ], function (Backbone, $, CourseCardView) { + ], function (Backbone, $, CourseCardModel, CourseCardView) { 'use strict'; @@ -11,40 +12,39 @@ define([ courseCardModel, setupView, context = { - certificate_url: '', - course_end: 'Jun 13, 2016', course_modes: [], - course_key: 'course-v1:ANUx+ANU-ASTRO1x+3T2015', - courseware_url: 'http://localhost:8000/courses/course-v1:edX+DemoX+Demo_Course/info', - course_start: 'Apr 25, 2016', - course_started: true, display_name: 'Astrophysics: Exploring Exoplanets', - image_url: 'https://testimage.com/image', key: 'ANU-ASTRO1x', - marketing_url: 'https://www.edx.org/course/astrophysics-exploring-exoplanets-anux-anu-astro2x-1', organization: { display_name: 'Australian National University', key: 'ANUx' }, run_modes: [{ - course_key: '12313', + start_date: 'Apr 25, 2016', + end_date: 'Jun 13, 2016', + course_key: 'course-v1:ANUx+ANU-ASTRO1x+3T2015', + course_url: 'http://localhost:8000/courses/course-v1:edX+DemoX+Demo_Course/info', + marketing_url: 'https://www.edx.org/course/astrophysics-exploring', + course_image_url: 'http://test.com/image1', mode_slug: 'verified', run_key: '2T2016', - start_date: '' + course_started: true, + is_enrolled: true, + certificate_url: '', }] }; - setupView = function(enrollment_status){ - context.enrollment_status = enrollment_status; + setupView = function(isEnrolled){ + context.run_modes[0].is_enrolled = isEnrolled; setFixtures('
'); - courseCardModel = new Backbone.Model(context); + courseCardModel = new CourseCardModel(context); view = new CourseCardView({ model: courseCardModel }); }; beforeEach(function() { - setupView(null); + setupView(false); }); afterEach(function() { @@ -57,21 +57,23 @@ define([ it('should render the course card based on the data enrolled', function() { view.remove(); - setupView('enrolled'); - expect(view.$('.header-img').attr('src')).toEqual(context.image_url); - expect(view.$('.course-details .course-title').html()).toEqual(context.display_name); - expect(view.$('.course-details .course-key').html()).toEqual(context.key); - expect(view.$('.course-details .enrollment-info').html()) - .toEqual(context.course_start + ' - ' + context.course_end); - expect(view.$('.course-details .course-link').attr('href')).toEqual(context.courseware_url); + setupView(true); + expect(view.$('.header-img').attr('src')).toEqual(context.run_modes[0].course_image_url); + expect(view.$('.course-details .course-title-link').text().trim()).toEqual(context.display_name); + expect(view.$('.course-details .course-title-link').attr('href')).toEqual( + context.run_modes[0].marketing_url); + expect(view.$('.course-details .course-text .course-key').html()).toEqual(context.key); + expect(view.$('.course-details .course-text .run-period').html()) + .toEqual(context.run_modes[0].start_date + ' - ' + context.run_modes[0].end_date); }); it('should render the course card based on the data not enrolled', function() { - expect(view.$('.header-img').attr('src')).toEqual(context.image_url); - expect(view.$('.course-details .course-title').html()).toEqual(context.display_name); - expect(view.$('.course-details .course-key').html()).toEqual(context.key); - expect(view.$('.course-details .enrollment-info').html()).toEqual('Not Yet Enrolled'); - expect(view.$('.course-details .course-link').attr('href')).toEqual(context.marketing_url); + expect(view.$('.header-img').attr('src')).toEqual(context.run_modes[0].course_image_url); + expect(view.$('.course-details .course-title-link').text().trim()).toEqual(context.display_name); + expect(view.$('.course-details .course-title-link').attr('href')).toEqual( + context.run_modes[0].marketing_url); + expect(view.$('.course-details .course-text .course-key').html()).toEqual(context.key); + expect(view.$('.course-details .course-text .run-period').html()).not.toBeDefined(); }); }); } diff --git a/lms/static/js/spec/learner_dashboard/course_enroll_view_spec.js b/lms/static/js/spec/learner_dashboard/course_enroll_view_spec.js new file mode 100644 index 0000000000..9638312867 --- /dev/null +++ b/lms/static/js/spec/learner_dashboard/course_enroll_view_spec.js @@ -0,0 +1,72 @@ +define([ + 'backbone', + 'jquery', + 'js/learner_dashboard/models/course_card_model', + 'js/learner_dashboard/views/course_enroll_view' + ], function (Backbone, $, CourseCardModel, CourseEnrollView) { + + 'use strict'; + + describe('Course Enroll View', function () { + var view = null, + courseCardModel, + setupView, + context = { + display_name: 'Astrophysics: Exploring Exoplanets', + key: 'ANU-ASTRO1x', + organization: { + display_name: 'Australian National University', + key: 'ANUx' + }, + run_modes: [{ + start_date: 'Apr 25, 2016', + end_date: 'Jun 13, 2016', + course_key: 'course-v1:ANUx+ANU-ASTRO1x+3T2015', + course_url: 'http://localhost:8000/courses/course-v1:edX+DemoX+Demo_Course/info', + course_image_url: 'http://test.com/image1', + marketing_url: 'http://test.com/image2', + mode_slug: 'verified', + run_key: '2T2016', + is_enrolled: false, + certificate_url: '', + }] + }; + + setupView = function(isEnrolled){ + context.run_modes[0].is_enrolled = isEnrolled; + setFixtures(''); + courseCardModel = new CourseCardModel(context); + view = new CourseEnrollView({ + $el: $('.course-actions'), + model: courseCardModel + }); + }; + + beforeEach(function() { + setupView(false); + }); + + afterEach(function() { + view.remove(); + }); + + it('should exist', function() { + expect(view).toBeDefined(); + }); + + it('should render the course enroll view based on not enrolled data', function() { + expect(view.$('.enrollment-info').html().trim()).toEqual('not enrolled'); + expect(view.$('.enroll-button').text().trim()).toEqual('Enroll Now'); + }); + + it('should render the course enroll view based on enrolled data', function(){ + view.remove(); + setupView(true); + expect(view.$('.enrollment-info').html().trim()).toEqual('enrolled'); + expect(view.$('.view-course-link').attr('href')).toEqual( + context.run_modes[0].course_url); + expect(view.$('.view-course-link').text().trim()).toEqual('View Course'); + }); + }); + } +); diff --git a/lms/static/lms/js/spec/main.js b/lms/static/lms/js/spec/main.js index 62c17fc499..5d397d9295 100644 --- a/lms/static/lms/js/spec/main.js +++ b/lms/static/lms/js/spec/main.js @@ -745,6 +745,7 @@ 'js/spec/learner_dashboard/sidebar_view_spec.js', 'js/spec/learner_dashboard/program_details_header_spec.js', 'js/spec/learner_dashboard/course_card_view_spec.js', + 'js/spec/learner_dashboard/course_enroll_view_spec.js', 'js/spec/markdown_editor_spec.js', 'js/spec/navigation_spec.js', 'js/spec/search/search_spec.js', diff --git a/lms/static/sass/elements/_course-card.scss b/lms/static/sass/elements/_course-card.scss index b3746b4b52..4578317749 100644 --- a/lms/static/sass/elements/_course-card.scss +++ b/lms/static/sass/elements/_course-card.scss @@ -1,8 +1,53 @@ -.header-img{ - @include float(left); - margin-right:20px; -} .course-card{ - height: 250px; - margin-top:20px; + @include span(10); + margin-left: $baseline*2 + px; + margin-bottom: $baseline + px; + .course-image-link{ + @include float(left); + .header-img{ + max-width: 191px; + } + } + .course-details{ + @include float(right); + width: 100%; + @include susy-media($bp-screen-sm) { width: calc(100% - 191px); } + padding-left: $baseline*1.5 + px; + .course-title{ + font-size: font-size(x-large); + font-weight: font-weight(normal); + margin-bottom: $baseline/4 + px; + } + .course-text{ + color: palette(grayscale, dark); + } + } + .course-actions{ + .enrollment-info{ + width: $baseline*10 + px; + text-align: center; + margin-bottom: $baseline/2 + px; + text-transform: uppercase; + } + .enroll-button{ + width: $baseline*10 + px; + text-align: center; + background-color: palette(success, dark); + border-color: palette(success, dark); + &:hover, + &:focus{ + background-color: palette(success, base); + border-color: palette(success, base); + } + } + + .view-course-link{ + width: $baseline*10 + px; + text-align: center; + } + } + + .action-msg-view{ + clear: both; + } } diff --git a/lms/templates/learner_dashboard/course_card.underscore b/lms/templates/learner_dashboard/course_card.underscore index 2ea94e0602..1f4a923d15 100644 --- a/lms/templates/learner_dashboard/course_card.underscore +++ b/lms/templates/learner_dashboard/course_card.underscore @@ -1,13 +1,26 @@ -<%- key %>
- <% if(enrollment_status){ %> - <%- course_start %> - <%-course_end %> - <%- gettext('View Course') %> - <% }else{ %> - <%- gettext('Not Yet Enrolled') %> - <%- gettext('Learn More') %> - <% } %> +<%- subtitle %>
-<%- gettext('Programs') %> +<%- gettext('Programs') %> <%- StringUtils.interpolate( gettext('{category}\'s program'), {category: category}