Commit 7689fee0 by AlasdairSwan Committed by GitHub

Merge pull request #14778 from edx/alasdair/ECOM-7386-program-progress-circle

ECOM-7386 Added a program progress circle to program details page
parents c9f9b728 a466b437
(function(define) {
'use strict';
define(['backbone',
'jquery',
'underscore',
'gettext',
'text!../../../templates/components/progress_circle_view.underscore',
'text!../../../templates/components/progress_circle_segment.underscore'
],
function(
Backbone,
$,
_,
gettext,
progressViewTpl,
progressSegmentTpl
) {
return Backbone.View.extend({
x: 22,
y: 22,
radius: 16,
degrees: 180,
strokeWidth: 1.2,
viewTpl: _.template(progressViewTpl),
segmentTpl: _.template(progressSegmentTpl),
initialize: function() {
var progress = this.model.get('progress');
this.model.set({
totalCourses: progress.completed + progress.in_progress + progress.not_started
});
this.render();
},
render: function() {
var data = $.extend({}, this.model.toJSON(), {
circleSegments: this.getProgressSegments(),
x: this.x,
y: this.y,
radius: this.radius,
strokeWidth: this.strokeWidth
});
this.$el.html(this.viewTpl(data));
},
getDegreeIncrement: function(total) {
return 360 / total;
},
getOffset: function(total) {
return 100 - ((1 / total) * 100);
},
getProgressSegments: function() {
var progressHTML = [],
total = this.model.get('totalCourses'),
segmentDash = 2 * Math.PI * this.radius,
degreeInc = this.getDegreeIncrement(total),
data = {
// Remove strokeWidth to show a gap between the segments
dashArray: segmentDash - this.strokeWidth,
degrees: this.degrees,
offset: this.getOffset(total),
x: this.x,
y: this.y,
radius: this.radius,
strokeWidth: this.strokeWidth
},
i,
segmentData;
for (i = 0; i < total; i++) {
segmentData = $.extend({}, data, {
classList: (i >= this.model.get('progress').completed) ? 'incomplete' : 'complete',
degrees: data.degrees + (i * degreeInc)
});
// Want the incomplete segments to have no gaps
if (segmentData.classList === 'incomplete' && (i + 1) < total) {
segmentData.dashArray = segmentDash;
}
progressHTML.push(this.segmentTpl(segmentData));
}
return progressHTML.join('');
}
});
}
);
}).call(this, define || RequireJS.define);
define([
'backbone',
'jquery',
'edx-ui-toolkit/js/utils/spec-helpers/spec-helpers',
'common/js/components/views/progress_circle_view'
], function(Backbone, $, SpecHelpers, ProgressCircleView) {
'use strict';
describe('Progress Circle View', function() {
var view = null,
context = {
title: 'XSeries Progress',
label: 'Earned Certificates',
progress: {
completed: 2,
in_progress: 1,
not_started: 3
}
},
testCircle,
testText,
initView,
getProgress,
testProgress;
testCircle = function(progress) {
var $circle = view.$('.progress-circle');
expect($circle.find('.complete').length).toEqual(progress.completed);
expect($circle.find('.incomplete').length).toEqual(progress.in_progress + progress.not_started);
};
testText = function(progress) {
var $numbers = view.$('.numbers'),
total = progress.completed + progress.in_progress + progress.not_started;
expect(view.$('.progress-heading').html()).toEqual('XSeries Progress');
expect(parseInt($numbers.find('.complete').html(), 10)).toEqual(progress.completed);
expect(parseInt($numbers.find('.total').html(), 10)).toEqual(total);
};
getProgress = function(x, y, z) {
return {
completed: x,
in_progress: y,
not_started: z
};
};
testProgress = function(x, y, z) {
var progress = getProgress(x, y, z);
view = initView(progress);
view.render();
testCircle(progress);
testText(progress);
};
initView = function(progress) {
var data = $.extend({}, context, {
progress: progress
});
return new ProgressCircleView({
el: '.js-program-progress',
model: new Backbone.Model(data)
});
};
beforeEach(function() {
setFixtures('<div class="js-program-progress"></div>');
});
afterEach(function() {
view.remove();
});
it('should exist', function() {
var progress = getProgress(2, 1, 3);
view = initView(progress);
view.render();
expect(view).toBeDefined();
});
it('should render the progress circle based on the passed in model', function() {
var progress = getProgress(2, 1, 3);
view = initView(progress);
view.render();
testCircle(progress);
});
it('should render the progress text based on the passed in model', function() {
var progress = getProgress(2, 1, 3);
view = initView(progress);
view.render();
testText(progress);
});
SpecHelpers.withData({
'should render the progress text with only completed courses': [5, 0, 0],
'should render the progress text with only in progress courses': [0, 4, 0],
'should render the progress circle with only not started courses': [0, 0, 5],
'should render the progress text with no completed courses': [0, 2, 3],
'should render the progress text with no in progress courses': [2, 0, 7],
'should render the progress text with no not started courses': [2, 4, 0]
}, testProgress);
});
});
...@@ -165,6 +165,7 @@ ...@@ -165,6 +165,7 @@
'common/js/spec/components/paginated_view_spec.js', 'common/js/spec/components/paginated_view_spec.js',
'common/js/spec/components/paging_header_spec.js', 'common/js/spec/components/paging_header_spec.js',
'common/js/spec/components/paging_footer_spec.js', 'common/js/spec/components/paging_footer_spec.js',
'common/js/spec/components/progress_circle_view_spec.js',
'common/js/spec/components/search_field_spec.js', 'common/js/spec/components/search_field_spec.js',
'common/js/spec/components/view_utils_spec.js', 'common/js/spec/components/view_utils_spec.js',
'common/js/spec/utils/edx.utils.validate_spec.js' 'common/js/spec/utils/edx.utils.validate_spec.js'
......
<circle class="<%- classList %>"
r="<%- radius %>" cx="<%- x %>" cy="<%- y %>"
transform="rotate(<%- degrees %>, <%- x %>, <%- y %>)"
stroke-width="<%- strokeWidth %>"
fill="none"
stroke-dasharray="<%- dashArray %>"
stroke-dashoffset="<%- offset %>">
</circle>
<% if (title) { %>
<h2 class="progress-heading"><%- title %></h2>
<% } %>
<div class="progress-circle-wrapper">
<svg class="progress-circle" viewBox="0 0 44 44" aria-hidden="true">
<circle class="js-circle bg" r="<%- radius %>" cx="<%- x %>" cy="<%- y %>" stroke-width="<%- strokeWidth %>" fill="none"></circle>
<%= circleSegments %>
</svg>
<div class="progress-label">
<div class="numbers">
<span class="complete"><%- progress.completed %></span>/<span class="total"><%- totalCourses %></span>
</div>
<div class="label"><% if (label) { %><%- label %><% } %></div>
</div>
</div>
(function(define) {
'use strict';
define(['backbone',
'jquery',
'underscore',
'gettext',
'text!../../../templates/learner_dashboard/certificate_list.underscore'
],
function(
Backbone,
$,
_,
gettext,
certificateTpl
) {
return Backbone.View.extend({
tpl: _.template(certificateTpl),
initialize: function(options) {
this.title = options.title || false;
this.render();
},
render: function() {
var data = {
title: this.title,
certificateList: this.collection.toJSON()
};
this.$el.html(this.tpl(data));
}
});
}
);
}).call(this, define || RequireJS.define);
(function(define) { (function(define) {
'use strict'; 'use strict';
define(['backbone', define([
'jquery', 'backbone',
'underscore', 'jquery',
'gettext', 'underscore',
'js/learner_dashboard/views/explore_new_programs_view', 'gettext',
'js/learner_dashboard/views/certificate_view', 'edx-ui-toolkit/js/utils/html-utils',
'text!../../../templates/learner_dashboard/sidebar.underscore' 'edx-ui-toolkit/js/utils/string-utils',
], 'common/js/components/views/progress_circle_view',
function( 'js/learner_dashboard/views/certificate_list_view',
Backbone, 'text!../../../templates/learner_dashboard/program_details_sidebar.underscore'
$, ],
_, function(
gettext, Backbone,
NewProgramsView, $,
CertificateView, _,
sidebarTpl gettext,
) { HtmlUtils,
return Backbone.View.extend({ StringUtils,
el: '.sidebar', ProgramProgressView,
CertificateView,
tpl: _.template(sidebarTpl), sidebarTpl
) {
initialize: function(data) { return Backbone.View.extend({
this.context = data.context; tpl: HtmlUtils.template(sidebarTpl),
},
initialize: function(options) {
render: function() { this.courseModel = options.courseModel || {};
this.$el.html(this.tpl(this.context)); this.certificateCollection = options.certificateCollection || [];
this.postRender(); this.programCertificate = this.getProgramCertificate();
}, this.render();
},
postRender: function() {
this.newProgramsView = new NewProgramsView({ render: function() {
context: this.context var data = $.extend({}, this.model.toJSON(), {
}); programCertificate: this.programCertificate ?
this.programCertificate.toJSON() : {}
this.newCertificateView = new CertificateView({ });
context: this.context
}); HtmlUtils.setHtml(this.$el, this.tpl(data));
} this.postRender();
}); },
}
postRender: function() {
if (!this.programCertificate) {
this.progressModel = new Backbone.Model({
title: StringUtils.interpolate(
gettext('{type} Progress'),
{type: this.model.get('type')}
),
label: gettext('Earned Certificates'),
progress: {
completed: this.courseModel.get('completed').length,
in_progress: this.courseModel.get('in_progress').length,
not_started: this.courseModel.get('not_started').length
}
});
this.programProgressView = new ProgramProgressView({
el: '.js-program-progress',
model: this.progressModel
});
}
if (this.certificateCollection.length) {
this.certificateView = new CertificateView({
el: '.js-course-certificates',
collection: this.certificateCollection,
title: gettext('Earned Certificates')
});
}
},
getProgramCertificate: function() {
var certificate = this.certificateCollection.findWhere({type: 'program'}),
base = '/static/images/programs/program-certificate-';
if (certificate) {
certificate.set({
img: base + this.getType() + '.gif'
});
}
return certificate;
},
getType: function() {
var type = this.model.get('type').toLowerCase();
return type.replace(/\s+/g, '-');
}
});
}
); );
}).call(this, define || RequireJS.define); }).call(this, define || RequireJS.define);
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
this.options = options; this.options = options;
this.programModel = new Backbone.Model(this.options.programData); this.programModel = new Backbone.Model(this.options.programData);
this.courseData = new Backbone.Model(this.options.courseData); this.courseData = new Backbone.Model(this.options.courseData);
this.certificateCollection = new Backbone.Collection(this.options.certificateData);
this.completedCourseCollection = new CourseCardCollection( this.completedCourseCollection = new CourseCardCollection(
this.courseData.get('completed') || [], this.courseData.get('completed') || [],
this.options.userPreferences this.options.userPreferences
...@@ -61,7 +62,7 @@ ...@@ -61,7 +62,7 @@
remainingCount: remainingCount, remainingCount: remainingCount,
completedCount: completedCount completedCount: completedCount
}; };
data = $.extend(data, this.options.programData); data = $.extend(data, this.programModel.toJSON());
HtmlUtils.setHtml(this.$el, this.tpl(data)); HtmlUtils.setHtml(this.$el, this.tpl(data));
this.postRender(); this.postRender();
}, },
...@@ -99,10 +100,12 @@ ...@@ -99,10 +100,12 @@
}).render(); }).render();
} }
new SidebarView({ this.sidebarView = new SidebarView({
el: '.sidebar', el: '.js-program-sidebar',
context: this.options model: this.programModel,
}).render(); courseModel: this.courseData,
certificateCollection: this.certificateCollection
});
} }
}); });
} }
......
...@@ -743,6 +743,7 @@ ...@@ -743,6 +743,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/program_details_sidebar_view_spec.js',
'js/spec/learner_dashboard/course_card_view_spec.js', 'js/spec/learner_dashboard/course_card_view_spec.js',
'js/spec/learner_dashboard/course_enroll_view_spec.js', 'js/spec/learner_dashboard/course_enroll_view_spec.js',
'js/spec/learner_dashboard/course_enroll_view_spec_2017.js', 'js/spec/learner_dashboard/course_enroll_view_spec_2017.js',
......
...@@ -6,5 +6,6 @@ ...@@ -6,5 +6,6 @@
@import 'elements/course-card'; @import 'elements/course-card';
@import 'elements/program-card'; @import 'elements/program-card';
@import 'elements-v2/icons'; @import 'elements-v2/icons';
@import 'elements/progress-circle';
@import 'views/program-details'; @import 'views/program-details';
@import 'views/program-list'; @import 'views/program-list';
$progress-title-color: $blue-d1 !default;
$progress-complete-color: $blue-u1 !default;
$progress-incomplete-color: $gray-l3 !default;
$progress-complete-number-color: $blue-d1 !default;
$progress-incomplete-number-color: $gray !default;
$progress-number-label-color: palette(grayscale, base) !default;
.program-progress {
width: 300px;
margin: 0 auto 30px;
@media(min-width: $bp-screen-md) {
margin-left: 0;
}
}
.progress-heading {
color: $progress-title-color;
text-align: center;
margin-bottom: 0;
font: {
size: 1.1em;
weight: 700;
}
}
.progress-circle-wrapper {
position: relative;
margin-top: -20px;
width: 300px;
height: 300px;
.progress-label {
position: absolute;
width: 100%;
top: 92px;
text-align: center;
}
.numbers {
font-size: 3em;
color: $progress-incomplete-number-color;
.complete {
color: $progress-complete-number-color;
}
}
.label {
font: {
size: 1.1em;
weight: 600;
}
color: $progress-number-label-color;
}
}
.progress-circle {
.complete {
stroke: $progress-complete-color;
}
.incomplete {
stroke: $progress-incomplete-color;
}
}
...@@ -47,8 +47,8 @@ ...@@ -47,8 +47,8 @@
} }
.crumb { .crumb {
@include float(left);
position: relative; position: relative;
float: left;
font-size: font-size(x-small); font-size: font-size(x-small);
line-height: line-height(x-small); line-height: line-height(x-small);
color: palette(grayscale, dark); color: palette(grayscale, dark);
...@@ -78,14 +78,18 @@ ...@@ -78,14 +78,18 @@
} }
// CSS for April 2017 version of Program Details Page // CSS for April 2017 version of Program Details Page
.program-details { .program-details {
.window-wrap { .window-wrap {
background-color: $white; background-color: $white;
} }
.wrapper-footer {
@include clearfix();
clear: both;
}
} }
.program-details-wrapper {
.program-details-wrapper {
.program-details-header { .program-details-header {
background-color: $light-gray4; background-color: $light-gray4;
display: flex; display: flex;
...@@ -93,14 +97,20 @@ ...@@ -93,14 +97,20 @@
font-family: 'Open Sans'; font-family: 'Open Sans';
font-weight: normal; font-weight: normal;
flex-wrap: wrap; flex-wrap: wrap;
padding-top: 40px; padding: 40px 10px 35px;
padding-bottom: 35px;
margin-left: 10px;
margin-right: 10px;
@media(min-width: $bp-screen-md) { @media(min-width: $bp-screen-md) {
margin-left: 30px; padding: {
margin-right: 80px; left: 30px;
right: 30px;
}
}
@media(min-width: $lms-max-width) {
padding: {
left: calc(((100% - 1180px) / 2) + 30px);
right: calc(((100% - 1180px) / 2) + 30px);
}
} }
.hd-1 { .hd-1 {
...@@ -111,7 +121,7 @@ ...@@ -111,7 +121,7 @@
} }
.program-details-icon { .program-details-icon {
margin-left: 3px; @include margin-left(3px);
margin-top: 10px; margin-top: 10px;
height: auto; height: auto;
...@@ -182,7 +192,7 @@ ...@@ -182,7 +192,7 @@
margin-top: auto; margin-top: auto;
margin-bottom: auto; margin-bottom: auto;
@media(min-width: $bp-screen-md) { @media(min-width: $bp-screen-md) {
margin: 10px 0 0 0; @include margin-right(10px 0 0 0);
} }
} }
...@@ -192,8 +202,8 @@ ...@@ -192,8 +202,8 @@
width: 30%; width: 30%;
.orgs .org-logo { .orgs .org-logo {
@include margin-left(2.5%);
width: 46.5%; width: 46.5%;
margin-left: 2.5%;
height: auto; height: auto;
} }
} }
...@@ -202,26 +212,49 @@ ...@@ -202,26 +212,49 @@
width: 25%; width: 25%;
} }
} }
} }
.program-details-content { .program-details-content {
width: 100%;
margin-bottom: 30px;
padding: 30px 10px;
@media(min-width: $bp-screen-md) { @media(min-width: $bp-screen-md) {
margin-left: 30px; @include float(left);
padding: {
left: 30px;
right: 30px;
}
width: calc( 100% - 330px );
position: relative;
}
@media(min-width: $bp-screen-lg) {
width: calc( 100% - 510px );
max-width: 700px;
}
@media(min-width: $lms-max-width) {
@include margin-left(calc((100% - 1180px) / 2));
} }
margin-left: 10px;
} }
.course-list-heading { .course-list-heading {
font-family: "Open Sans"; font-family: "Open Sans";
font-weight: bold; font-weight: bold;
text-transform: uppercase;
color: palette(primary, dark); color: palette(primary, dark);
font-size: 0.9375em; font-size: 0.9375em;
line-height: normal; line-height: normal;
margin-top: 10px; padding-bottom: 5px;
margin-bottom: 0; border-bottom: 3px solid $divider-color;
margin: {
top: 10px;
bottom: 20px;
}
.status { .status {
margin-right: 7px; @include margin-right(7px);
} }
} }
...@@ -230,27 +263,9 @@ ...@@ -230,27 +263,9 @@
} }
.course-list-headings { .course-list-headings {
width: 700px;
.divider {
margin-left: 0;
margin-bottom: 20px;
background-color: $divider-color;
margin-top: 5px;
height: 3px;
width: 315px;
@media(min-width: $bp-screen-sm) {
width: 550px;
}
@media(min-width: $bp-screen-md) {
width: 700px;
}
border: none;
}
.motivating-section { .motivating-section {
@include margin-left(15px);
font-size: 0.9375em; font-size: 0.9375em;
margin-left: 15px;
width: 310px; width: 310px;
@media(min-width: $bp-screen-sm) { @media(min-width: $bp-screen-sm) {
width: auto; width: auto;
...@@ -269,11 +284,7 @@ ...@@ -269,11 +284,7 @@
} }
.program-heading { .program-heading {
@media(min-width: $bp-screen-md) { width: 100%;
width: 70%;
}
width: 90%;
margin-top: 40px;
margin-bottom: 40px; margin-bottom: 40px;
.program-heading-title { .program-heading-title {
...@@ -318,17 +329,17 @@ ...@@ -318,17 +329,17 @@
/* IE11 CSS styles */ /* IE11 CSS styles */
@media(min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { @media(min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) {
float: right; @include float(right);
} }
} }
} }
.select-choice { .select-choice {
@include margin-right(2px);
font-family: "Open Sans"; font-family: "Open Sans";
font-weight: bold; font-weight: bold;
font-size: 0.9375em; font-size: 0.9375em;
color: palette(grayscale, base); color: palette(grayscale, base);
margin-top: 6px; margin-top: 6px;
margin-right: 2px;
display: block; display: block;
@media(min-width: $bp-screen-md) { @media(min-width: $bp-screen-md) {
...@@ -344,21 +355,19 @@ ...@@ -344,21 +355,19 @@
} }
} }
.run-select { .run-select {
@include margin-right(10px);
width: 95%; width: 95%;
@media(min-width: $bp-screen-sm) { @media(min-width: $bp-screen-sm) {
width: 300px; width: 300px;
} }
height: 34px; height: 34px;
padding: 0; padding: 0;
margin-right: 10px;
} }
} }
.program-course-card { .program-course-card {
@media(min-width: $bp-screen-md) { width: 100%;
width: 100%; padding: 15px;
}
margin-bottom: 10px; margin-bottom: 10px;
@media(min-width: $bp-screen-md) { @media(min-width: $bp-screen-md) {
...@@ -368,12 +377,6 @@ ...@@ -368,12 +377,6 @@
.section { .section {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-right: 40px;
margin-left: 15px;
@media(min-width: $bp-screen-sm) {
margin-left: 20px;
}
@media(min-width: $bp-screen-md) { @media(min-width: $bp-screen-md) {
flex-wrap: wrap; flex-wrap: wrap;
...@@ -405,9 +408,12 @@ ...@@ -405,9 +408,12 @@
.course-meta-container { .course-meta-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-wrap: wrap;
@media(min-width: $bp-screen-md) { @media(min-width: $bp-screen-md) {
width: 100%; width: 100%;
flex-direction: row;
justify-content: space-between;
} }
} }
...@@ -422,6 +428,10 @@ ...@@ -422,6 +428,10 @@
} }
} }
.course-certificate {
width: 100%;
}
.upgrade-message { .upgrade-message {
flex-wrap: wrap; flex-wrap: wrap;
...@@ -437,7 +447,7 @@ ...@@ -437,7 +447,7 @@
/* IE11 CSS styles */ /* IE11 CSS styles */
@media(min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { @media(min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) {
float: right; @include float(right);
} }
} }
...@@ -500,6 +510,109 @@ ...@@ -500,6 +510,109 @@
font-size: 0.9375em; font-size: 0.9375em;
} }
} }
}
}
.program-sidebar {
padding: 30px 10px;
@media(min-width: $bp-screen-md) {
@include float(right);
width: 300px;
padding-right: 30px;
position: relative;
}
@media(min-width: $bp-screen-lg) {
width: 450px;
.program-progress {
@include margin-left(50px);
}
}
@media(min-width: $lms-max-width) {
@include margin-right(calc((100% - 1180px) / 2));
}
}
.certificate-heading {
margin-bottom: 10px;
@media(min-width: $bp-screen-md) {
@include margin-right(30px);
}
@media(min-width: $bp-screen-lg) {
@include margin-left(10px);
@include margin-right(0);
}
}
.program-cert-link {
display: inline-block;
&:active,
&:focus,
&:hover {
.program-cert {
border-color: $blue-d1;
}
}
}
.program-cert {
width: 100%;
border: 1px solid $divider-color;
@media(min-width: $bp-screen-md) {
width: calc(100% - 30px);
}
@media(min-width: $bp-screen-lg) {
width: 100%;
}
}
.certificate-list {
@include margin(0, 0, 0, 10px);
list-style: none;
.certificate {
display: flex;
flex-direction: row;
padding: 5px 0 10px;
}
.certificate-link {
@include margin-left(20px);
color: $black;
font: {
size: 1.1em;
weight: 600;
}
@media(min-width: $bp-screen-md) {
font-size: 0.9em;
}
@media(min-width: $bp-screen-lg) {
font-size: 1.1em;
}
&:active,
&:focus,
&:hover {
.sample-cert {
border-color: $blue-d1;
}
}
}
.sample-cert {
width: 120px;
border: 3px solid $gray-l3;
border-radius: 5px;
.expired-notification { .expired-notification {
display: inline-block; display: inline-block;
...@@ -516,7 +629,7 @@ ...@@ -516,7 +629,7 @@
} }
.expired-icon { .expired-icon {
float: left; @include float(left);
color: palette(primary, dark); color: palette(primary, dark);
} }
...@@ -525,5 +638,12 @@ ...@@ -525,5 +638,12 @@
padding-left: 10px; padding-left: 10px;
} }
@media(min-width: $bp-screen-md) {
width: 100px;
}
@media(min-width: $bp-screen-lg) {
width: 120px;
}
} }
} }
<div class="certificate-container">
<% if (title) { %>
<h2 class="course-list-heading"><%- title %></h2>
<% } %>
<ul class="certificate-list">
<% _.each(certificateList, function(certificate){ %>
<li class="certificate">
<a class="image-link" href="<%- certificate.url %>" aria-hidden="true" tabindex="-1"><img src="/static/images/programs/sample-cert.png" class="sample-cert" alt=""></a>
<a class="certificate-link" href="<%- certificate.url %>"><%- certificate.title %></a>
</li>
<% }); %>
</ul>
</div>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
</div> </div>
</div> </div>
<div class="course-actions col-12 md-col-4 sm-col-12"></div> <div class="course-actions col-12 md-col-4 sm-col-12"></div>
<div class="certificate-status"></div> <div class="course-certificate certificate-status"></div>
</div> </div>
</div> </div>
<div class="section action-msg-view"></div> <div class="section action-msg-view"></div>
......
<aside class="aside js-program-progress program-progress">
<% if (programCertificate) { %>
<h2 class="progress-heading certificate-heading"><%- StringUtils.interpolate(gettext('Your {program} Certificate'), {program: type}, true) %></h2>
<a href="<%- programCertificate.url %>" class="program-cert-link">
<img src="<%- programCertificate.img %>" class="program-cert" alt="<%- interpolate(gettext('Open the certificate you earned for the %(title)s program.'), {title: programCertificate.title}, true) %>" />
</a>
<% } %>
</aside>
<aside class="aside js-course-certificates"></aside>
<header class="js-program-header program-header full-width-banner"></header> <header class="js-program-header program-header full-width-banner"></header>
<div class="program-details-content"> <section class="program-details-content">
<div class="js-program-progress-view"></div>
<div class="program-heading"> <div class="program-heading">
<% if (inProgressCount === totalCount) { %> <% if (inProgressCount === totalCount) { %>
<h3 class="program-heading-title"><%- gettext('Congratulations!') %></h3> <h3 class="program-heading-title"><%- gettext('Congratulations!') %></h3>
...@@ -29,7 +28,6 @@ ...@@ -29,7 +28,6 @@
<span class="status"><%- gettext('COURSES IN PROGRESS') %></span> <span class="status"><%- gettext('COURSES IN PROGRESS') %></span>
<span class="count"><%- inProgressCount %></span> <span class="count"><%- inProgressCount %></span>
</h4> </h4>
<div class="divider"></div>
<div class="course-list js-course-list-in-progress row"></div> <div class="course-list js-course-list-in-progress row"></div>
</div> </div>
<% } %> <% } %>
...@@ -39,7 +37,6 @@ ...@@ -39,7 +37,6 @@
<span class="status"><%- gettext('REMAINING COURSES') %></span> <span class="status"><%- gettext('REMAINING COURSES') %></span>
<span class="count"><%- remainingCount %></span> <span class="count"><%- remainingCount %></span>
</h4> </h4>
<div class="divider"></div>
<div class="course-list js-course-list-remaining row"></div> <div class="course-list js-course-list-remaining row"></div>
</div> </div>
<% } %> <% } %>
...@@ -48,7 +45,6 @@ ...@@ -48,7 +45,6 @@
<span class="status"><%- gettext('COMPLETED COURSES') %></span> <span class="status"><%- gettext('COMPLETED COURSES') %></span>
<span class="count"><%- completedCount %></span> <span class="count"><%- completedCount %></span>
</h4> </h4>
<div class="divider"></div>
<% if (completedCount) { %> <% if (completedCount) { %>
<div class="course-list js-course-list-completed row"></div> <div class="course-list js-course-list-completed row"></div>
<% } else { %> <% } else { %>
...@@ -59,6 +55,5 @@ ...@@ -59,6 +55,5 @@
<% } %> <% } %>
</div> </div>
</div> </div>
</section>
<aside class="js-course-sidebar"></aside> <aside class="js-program-sidebar program-sidebar"></aside>
</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