Commit c60cf391 by Simon Chen

ECOM-4218 Draft 1 for Course Cards on program details page

parent 0bcb378a
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
], ],
function(ProgramDetailsView) { function(ProgramDetailsView) {
return function (options) { return function (options) {
var ProgramDetails = new ProgramDetailsView(options); var ProgramDetails = new ProgramDetailsView(options.programData);
return ProgramDetails; return ProgramDetails;
}; };
}); });
......
...@@ -21,7 +21,11 @@ ...@@ -21,7 +21,11 @@
el: '.program-cards-container', el: '.program-cards-container',
childView: ProgramCardView, childView: ProgramCardView,
collection: new ProgramCollection(options.programsData), collection: new ProgramCollection(options.programsData),
context: options context: options,
titleContext: {
el: 'h2',
title: 'Your Programs'
}
}).render(); }).render();
new SidebarView({ new SidebarView({
......
...@@ -5,31 +5,35 @@ ...@@ -5,31 +5,35 @@
'jquery', 'jquery',
'underscore', 'underscore',
'gettext', 'gettext',
'edx-ui-toolkit/js/utils/string-utils',
'edx-ui-toolkit/js/utils/html-utils',
'text!../../../templates/learner_dashboard/empty_programs_list.underscore' 'text!../../../templates/learner_dashboard/empty_programs_list.underscore'
], ],
function (Backbone, function (Backbone,
$, $,
_, _,
gettext, gettext,
StringUtils,
HtmlUtils,
emptyProgramsListTpl) { emptyProgramsListTpl) {
return Backbone.View.extend({ return Backbone.View.extend({
initialize: function(data) { initialize: function(data) {
this.childView = data.childView; this.childView = data.childView;
this.context = data.context; this.context = data.context;
this.titleContext = data.titleContext;
}, },
render: function() { render: function() {
var childList, tpl; var childList;
if (!this.collection.length) { if (!this.collection.length) {
if (this.context.xseriesUrl) { if (this.context.xseriesUrl) {
//Only show the xseries advertising panel if the link is passed in //Only show the xseries advertising panel if the link is passed in
tpl = _.template(emptyProgramsListTpl); HtmlUtils.setHtml(this.$el, HtmlUtils.template(emptyProgramsListTpl)(this.context));
this.$el.html(tpl(this.context));
} }
} else { } else {
childList = []; childList = [];
this.collection.each(function(model) { this.collection.each(function(model) {
var child = new this.childView({ var child = new this.childView({
...@@ -39,8 +43,23 @@ ...@@ -39,8 +43,23 @@
childList.push(child.el); childList.push(child.el);
}, this); }, this);
if (this.titleContext){
this.$el.before(HtmlUtils.ensureHtml(this.getTitleHtml()).toString());
}
this.$el.html(childList); this.$el.html(childList);
} }
},
getTitleHtml: function(){
var titleHtml = HtmlUtils.joinHtml(
HtmlUtils.HTML('<'),
this.titleContext.el,
HtmlUtils.HTML(' class="sr-only collection-title">'),
StringUtils.interpolate(this.titleContext.title),
HtmlUtils.HTML('</'),
this.titleContext.el,
HtmlUtils.HTML('>'));
return titleHtml;
} }
}); });
} }
......
;(function (define) {
'use strict';
define(['backbone',
'jquery',
'underscore',
'gettext',
'edx-ui-toolkit/js/utils/html-utils',
'text!../../../templates/learner_dashboard/course_card.underscore'
],
function(
Backbone,
$,
_,
gettext,
HtmlUtils,
pageTpl
) {
return Backbone.View.extend({
className: 'course-card card',
tpl: HtmlUtils.template(pageTpl),
initialize: function() {
this.render();
},
render: function() {
var filledTemplate = this.tpl(this.model.toJSON());
HtmlUtils.setHtml(this.$el, filledTemplate);
}
});
}
);
}).call(this, define || RequireJS.define);
...@@ -7,9 +7,21 @@ ...@@ -7,9 +7,21 @@
'gettext', 'gettext',
'edx-ui-toolkit/js/utils/html-utils', 'edx-ui-toolkit/js/utils/html-utils',
'js/learner_dashboard/views/program_header_view', 'js/learner_dashboard/views/program_header_view',
'js/learner_dashboard/views/collection_list_view',
'js/learner_dashboard/views/course_card_view',
'text!../../../templates/learner_dashboard/program_details_view.underscore' 'text!../../../templates/learner_dashboard/program_details_view.underscore'
], ],
function(Backbone, $, _, gettext, HtmlUtils, HeaderView, pageTpl) { function(
Backbone,
$,
_,
gettext,
HtmlUtils,
HeaderView,
CollectionListView,
CourseCardView,
pageTpl
) {
return Backbone.View.extend({ return Backbone.View.extend({
el: '.js-program-details-wrapper', el: '.js-program-details-wrapper',
...@@ -17,6 +29,9 @@ ...@@ -17,6 +29,9 @@
initialize: function(options) { initialize: function(options) {
this.programModel = new Backbone.Model(options); this.programModel = new Backbone.Model(options);
this.courseCardsCollection = new Backbone.Collection(
this.programModel.get('course_codes')
);
this.render(); this.render();
}, },
...@@ -29,6 +44,16 @@ ...@@ -29,6 +44,16 @@
this.headerView = new HeaderView({ this.headerView = new HeaderView({
model: this.programModel model: this.programModel
}); });
new CollectionListView({
el: '.js-course-list',
childView: CourseCardView,
collection: this.courseCardsCollection,
context: this.programModel.toJSON(),
titleContext: {
el: 'h2',
title: 'Course List'
}
}).render();
} }
}); });
} }
......
...@@ -124,6 +124,31 @@ define([ ...@@ -124,6 +124,31 @@ define([
$cards = view.$el.find('.program-card'); $cards = view.$el.find('.program-card');
expect($cards.length).toBe(0); expect($cards.length).toBe(0);
}); });
it('should have no title when title not provided', function(){
var $title;
setFixtures('<div class="test-container"><div class="program-cards-container"></div></div>');
view.remove();
view.render();
expect(view).toBeDefined();
$title = view.$el.parent().find('.collection-title');
expect($title.html()).not.toBeDefined();
});
it('should display screen reader header when provided', function(){
var $title, titleContext = {el:'h2', title:'list start'};
view.remove();
setFixtures('<div class="test-container"><div class="program-cards-container"></div></div>');
programCollection = new ProgramCollection(context.programsData);
view = new CollectionListView({
el: '.program-cards-container',
childView: ProgramCardView,
context: {'xseriesUrl': '/programs'},
collection: programCollection,
titleContext: titleContext
});
view.render();
$title = view.$el.parent().find('.collection-title');
expect($title.html()).toBe(titleContext.title);
});
}); });
} }
); );
define([
'backbone',
'jquery',
'js/learner_dashboard/views/course_card_view'
], function (Backbone, $, CourseCardView) {
'use strict';
describe('Course Card View', function () {
var view = null,
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',
mode_slug: 'verified',
run_key: '2T2016',
start_date: ''
}]
};
setupView = function(enrollment_status){
context.enrollment_status = enrollment_status;
setFixtures('<div class="course-card card"></div>');
courseCardModel = new Backbone.Model(context);
view = new CourseCardView({
model: courseCardModel
});
};
beforeEach(function() {
setupView(null);
});
afterEach(function() {
view.remove();
});
it('should exist', function() {
expect(view).toBeDefined();
});
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);
});
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);
});
});
}
);
...@@ -729,6 +729,7 @@ ...@@ -729,6 +729,7 @@
'js/spec/learner_dashboard/program_card_view_spec.js', 'js/spec/learner_dashboard/program_card_view_spec.js',
'js/spec/learner_dashboard/sidebar_view_spec.js', 'js/spec/learner_dashboard/sidebar_view_spec.js',
'js/spec/learner_dashboard/program_details_header_spec.js', 'js/spec/learner_dashboard/program_details_header_spec.js',
'js/spec/learner_dashboard/course_card_view_spec.js',
'js/spec/markdown_editor_spec.js', 'js/spec/markdown_editor_spec.js',
'js/spec/navigation_spec.js', 'js/spec/navigation_spec.js',
'js/spec/search/search_spec.js', 'js/spec/search/search_spec.js',
......
...@@ -5,3 +5,4 @@ ...@@ -5,3 +5,4 @@
@import 'views/program-list'; @import 'views/program-list';
@import 'views/program-details'; @import 'views/program-details';
@import 'elements/program-card'; @import 'elements/program-card';
@import 'elements/course-card';
.header-img{
@include float(left);
margin-right:20px;
}
.course-card{
height: 250px;
margin-top:20px;
}
<img class="header-img" src="<%- image_url %>" alt="<%- display_name %>"/>
<div class="course-details">
<h3 class="course-title"><%- display_name %></h3>
<p class="course-key"><%- key %></p>
<% if(enrollment_status){ %>
<span class="enrollment-info"><%- course_start %> - <%-course_end %></span>
<a href="<%- courseware_url %>" class="course-link cta"><%- gettext('View Course') %></a>
<% }else{ %>
<span class="enrollment-info"><%- gettext('Not Yet Enrolled') %></span>
<a href="<%- marketing_url %>" class="course-link cta"><%- gettext('Learn More') %></a>
<% } %>
</div>
<div class="action-msg-view"></div>
...@@ -18,7 +18,7 @@ ProgramListFactory({ ...@@ -18,7 +18,7 @@ ProgramListFactory({
certificatesData: ${credentials | n, dump_js_escaped_json}, certificatesData: ${credentials | n, dump_js_escaped_json},
userProgress: ${progress | n, dump_js_escaped_json}, userProgress: ${progress | n, dump_js_escaped_json},
xseriesUrl: '${xseries_url | n, js_escaped_string}', xseriesUrl: '${xseries_url | n, js_escaped_string}',
xseriesImage: '${static.url('images/xseries-certificate-visual.png')}' xseriesImage: '${static.url('images/xseries-certificate-visual.png') | n, js_escaped_string}'
}); });
</%static:require_module> </%static:require_module>
</%block> </%block>
...@@ -27,7 +27,6 @@ ProgramListFactory({ ...@@ -27,7 +27,6 @@ ProgramListFactory({
<main id="main" aria-label="Content" tabindex="-1"> <main id="main" aria-label="Content" tabindex="-1">
<div class="program-list-wrapper grid-container"> <div class="program-list-wrapper grid-container">
<h2 class="sr-only">${_("Your Programs")}</h2>
<div class="program-cards-container col"></div> <div class="program-cards-container col"></div>
<div class="sidebar col col-last"></div> <div class="sidebar col col-last"></div>
</div> </div>
......
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