Commit 638f80bb by Renzo Lucioni

Merge pull request #282 from edx/renzo/credit-detail

Update CAT detail view to support display of credit seats
parents 18f7315a e454e648
...@@ -18,7 +18,13 @@ define([ ...@@ -18,7 +18,13 @@ define([
return Backbone.RelationalModel.extend({ return Backbone.RelationalModel.extend({
urlRoot: '/api/v2/products/', urlRoot: '/api/v2/products/',
nestedAttributes: ['certificate_type', 'course_key', 'id_verification_required'], nestedAttributes: [
'certificate_type',
'course_key',
'id_verification_required',
'credit_provider',
'credit_hours'
],
parse: function (response) { parse: function (response) {
// Un-nest the attributes // Un-nest the attributes
......
...@@ -43,5 +43,33 @@ define([ ...@@ -43,5 +43,33 @@ define([
}); });
}); });
}); });
describe('filterSeats', function () {
it('should filter CourseSeats of the requested type', function () {
var honor = new HonorSeat(),
verified = new VerifiedSeat(),
professional = new ProfessionalSeat(),
expected = [
{
input: [honor, verified, professional],
output: {
filtered: [verified],
residual: [honor, professional]
}
},
{
input: [honor, verified, verified, professional],
output: {
filtered: [verified, verified],
residual: [honor, professional]
}
},
];
_.each(expected, function (expected) {
expect(CourseUtils.filterSeats(expected.input, 'verified')).toEqual(expected.output);
});
});
});
} }
); );
...@@ -85,6 +85,70 @@ define([ ...@@ -85,6 +85,70 @@ define([
} }
], ],
is_available_to_buy: false is_available_to_buy: false
},
{
id: 6,
url: 'http://ecommerce.local:8002/api/v2/products/6/',
structure: 'child',
product_class: 'Seat',
title: 'Seat in edX Demonstration Course with credit certificate (and ID verification)',
price: '150.00',
expires: null,
attribute_values: [
{
name: 'certificate_type',
value: 'credit'
},
{
name: 'course_key',
value: 'edX/DemoX/Demo_Course'
},
{
name: 'id_verification_required',
value: true
},
{
name: 'credit_provider',
value: 'Harvard'
},
{
name: 'credit_hours',
value: 1
}
],
is_available_to_buy: true
},
{
id: 5,
url: 'http://ecommerce.local:8002/api/v2/products/5/',
structure: 'child',
product_class: 'Seat',
title: 'Seat in edX Demonstration Course with credit certificate (and ID verification)',
price: '100.00',
expires: null,
attribute_values: [
{
name: 'certificate_type',
value: 'credit'
},
{
name: 'course_key',
value: 'edX/DemoX/Demo_Course'
},
{
name: 'id_verification_required',
value: true
},
{
name: 'credit_provider',
value: 'MIT'
},
{
name: 'credit_hours',
value: 2
}
],
is_available_to_buy: true
} }
] ]
}; };
...@@ -103,9 +167,16 @@ define([ ...@@ -103,9 +167,16 @@ define([
it('should list the course seats', function () { it('should list the course seats', function () {
var $seats = view.$el.find('.course-seat'), var $seats = view.$el.find('.course-seat'),
$creditSeats = view.$el.find('.credit-seats .course-seat'),
products = _.where(data.products, {structure: 'child'}); products = _.where(data.products, {structure: 'child'});
expect($seats.length).toEqual(products.length); expect($seats.length).toEqual(products.length);
expect($creditSeats.length).toEqual(
_.where(
products,
{title: 'Seat in edX Demonstration Course with credit certificate (and ID verification)'}
).length
);
// TODO Verify the rendered info matches the data // TODO Verify the rendered info matches the data
}); });
......
...@@ -55,7 +55,26 @@ define([ ...@@ -55,7 +55,26 @@ define([
return _.sortBy(seatTypes, function (seatType) { return _.sortBy(seatTypes, function (seatType) {
return this.seatSortObj[seatType]; return this.seatSortObj[seatType];
}, this); }, this);
} },
/**
* Given an array of CourseSeats and seatType, returns an object
* containing two arrays of CourseSeats, one containing seats of
* type seatType and a second containing all seats of other types.
*
* @param {CourseSeat[]} seats
* @param {String} seatType
* @returns {Object}
*/
filterSeats: function (seats, seatType) {
return _.groupBy(seats, function (seat) {
if (seat.getSeatType() === seatType) {
return 'filtered';
}
return 'residual';
});
},
}; };
} }
); );
...@@ -6,6 +6,7 @@ define([ ...@@ -6,6 +6,7 @@ define([
'moment', 'moment',
'text!templates/course_detail.html', 'text!templates/course_detail.html',
'text!templates/_course_seat.html', 'text!templates/_course_seat.html',
'text!templates/_course_credit_seats.html',
'utils/course_utils' 'utils/course_utils'
], ],
function ($, function ($,
...@@ -15,6 +16,7 @@ define([ ...@@ -15,6 +16,7 @@ define([
moment, moment,
CourseDetailTemplate, CourseDetailTemplate,
CourseSeatTemplate, CourseSeatTemplate,
CourseCreditSeatsTemplate,
CourseUtils) { CourseUtils) {
'use strict'; 'use strict';
...@@ -49,10 +51,16 @@ define([ ...@@ -49,10 +51,16 @@ define([
seats = CourseUtils.orderSeatsForDisplay(this.model.seats()), seats = CourseUtils.orderSeatsForDisplay(this.model.seats()),
$seatHolder = $('.course-seats', this.$el); $seatHolder = $('.course-seats', this.$el);
_.each(seats, function (seat) { seats = CourseUtils.filterSeats(seats, 'credit');
_.each(seats.residual, function (seat) {
html += _.template(CourseSeatTemplate)({seat: seat, moment: moment}); html += _.template(CourseSeatTemplate)({seat: seat, moment: moment});
}); });
if (seats.filtered && seats.filtered.length > 0) {
html += _.template(CourseCreditSeatsTemplate)({creditSeats: seats.filtered, moment: moment});
}
$seatHolder.html(html); $seatHolder.html(html);
} }
}); });
......
...@@ -38,13 +38,13 @@ ...@@ -38,13 +38,13 @@
.course-seats { .course-seats {
.course-seat { .course-seat {
margin-bottom: spacing-vertical(mid-small); margin-bottom: spacing-vertical(mid-small);
}
.seat-type { .seat-type {
margin-bottom: 5px; margin-bottom: 5px;
border-bottom: 1px solid $page-header-border-color; border-bottom: 1px solid $page-header-border-color;
padding-bottom: 3px; padding-bottom: 3px;
font-weight: bold; font-weight: bold;
}
} }
} }
} }
......
<div class="row">
<div class="col-sm-12">
<div class="seat-type"><%= creditSeats[0].getSeatTypeDisplayName() %></div>
</div>
<div class="col-sm-4 col-sm-offset-4 seat-certificate-type">
<%= creditSeats[0].getCertificateDisplayName() %>
</div>
<div class="col-md-8">
<table class="table table-striped credit-seats">
<thead>
<tr>
<th><%= gettext('Credit Provider') %></th>
<th><%= gettext('Price (USD)') %></th>
<th><%= gettext('Credit Hours') %></th>
<th><%= gettext('Upgrade Deadline') %></th>
</tr>
</thead>
<tbody>
<% _.each(creditSeats, function (seat) { %>
<tr class="course-seat">
<td class="seat-credit-provider"><%= seat.get('credit_provider') %></td>
<td class="seat-price"><%= '$' + Number(seat.get('price')).toLocaleString() %></td>
<td class="seat-credit-hours"><%= seat.get('credit_hours') %></td>
<td class="seat-expires"><% var expires = seat.get('expires');
if (expires) {
print(moment.utc(expires).format('lll z'));
}
%></td>
</tr>
<% }); %>
</tbody>
</table>
</div>
<div class="col-sm-4 seat-additional-info"></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