From 619829d5b56047e669245534f3f215401e350f9f Mon Sep 17 00:00:00 2001 From: AlasdairSwan Date: Wed, 15 Jun 2016 15:10:06 -0400 Subject: [PATCH] Program details front end for certificates Part of ECOM-4224. --- .../models/course_card_model.js | 15 +-- .../views/certificate_status_view.js | 33 +++++++ .../views/course_card_view.js | 14 +++ .../course_card_view_spec.js | 25 +++-- lms/static/sass/_build-learner-dashboard.scss | 1 + lms/static/sass/elements/_course-card.scss | 97 +++++++++++++++---- lms/static/sass/elements/_icons.scss | 11 +++ .../certificate_status.underscore | 10 ++ .../learner_dashboard/course_card.underscore | 5 +- .../course_enroll.underscore | 2 +- 10 files changed, 176 insertions(+), 37 deletions(-) create mode 100644 lms/static/js/learner_dashboard/views/certificate_status_view.js create mode 100644 lms/static/sass/elements/_icons.scss create mode 100644 lms/templates/learner_dashboard/certificate_status.underscore 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 93f4cfc6f3..7407db7e20 100644 --- a/lms/static/js/learner_dashboard/models/course_card_model.js +++ b/lms/static/js/learner_dashboard/models/course_card_model.js @@ -33,18 +33,19 @@ setActiveRunMode: function(runMode){ if (runMode){ 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, - 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_key: runMode.course_key, - course_url: runMode.course_url || '', - course_image_url: runMode.course_image_url || '', + key: this.context.key, + marketing_url: runMode.marketing_url || '', mode_slug: runMode.mode_slug, - run_key: runMode.run_key + run_key: runMode.run_key, + start_date: runMode.start_date }); } }, diff --git a/lms/static/js/learner_dashboard/views/certificate_status_view.js b/lms/static/js/learner_dashboard/views/certificate_status_view.js new file mode 100644 index 0000000000..ec1b43cea8 --- /dev/null +++ b/lms/static/js/learner_dashboard/views/certificate_status_view.js @@ -0,0 +1,33 @@ +;(function (define) { + 'use strict'; + define(['backbone', + 'jquery', + 'underscore', + 'gettext', + 'edx-ui-toolkit/js/utils/html-utils', + 'text!../../../templates/learner_dashboard/certificate_status.underscore' + ], + function( + Backbone, + $, + _, + gettext, + HtmlUtils, + certificateStatusTpl + ) { + return Backbone.View.extend({ + tpl: HtmlUtils.template(certificateStatusTpl), + + initialize: function(options) { + this.$el = options.$el; + this.render(); + }, + + render: function() { + var data = this.model.toJSON(); + HtmlUtils.setHtml(this.$el, this.tpl(data)); + } + }); + } + ); +}).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 b77536bb32..4836e80bcc 100644 --- a/lms/static/js/learner_dashboard/views/course_card_view.js +++ b/lms/static/js/learner_dashboard/views/course_card_view.js @@ -7,6 +7,7 @@ 'gettext', 'edx-ui-toolkit/js/utils/html-utils', 'js/learner_dashboard/models/course_enroll_model', + 'js/learner_dashboard/views/certificate_status_view', 'js/learner_dashboard/views/course_enroll_view', 'text!../../../templates/learner_dashboard/course_card.underscore' ], @@ -17,6 +18,7 @@ gettext, HtmlUtils, EnrollModel, + CertificateStatusView, CourseEnrollView, pageTpl ) { @@ -42,12 +44,24 @@ }, postRender: function(){ + var $certStatus = this.$('.certificate-status'); + this.enrollView = new CourseEnrollView({ $parentEl: this.$('.course-actions'), model: this.model, urlModel: this.urlModel, enrollModel: this.enrollModel }); + + if ( this.model.get('certificate_url') ) { + this.certificateStatus = new CertificateStatusView({ + $el: $certStatus, + model: this.model + }); + } else { + // Styles are applied to the element that show if it's empty + $certStatus.remove(); + } } }); } 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 7f9db28149..6869bbe266 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 @@ -29,14 +29,14 @@ define([ run_key: '2T2016', course_started: true, is_enrolled: true, - certificate_url: '', + certificate_url: '' }] }, - setupView = function(isEnrolled){ + setupView = function(data, isEnrolled){ context.run_modes[0].is_enrolled = isEnrolled; setFixtures('
'); - courseCardModel = new CourseCardModel(context); + courseCardModel = new CourseCardModel(data); view = new CourseCardView({ model: courseCardModel }); @@ -54,7 +54,7 @@ define([ }; beforeEach(function() { - setupView(false); + setupView(context, false); }); afterEach(function() { @@ -67,7 +67,7 @@ define([ it('should render the course card based on the data enrolled', function() { view.remove(); - setupView(true); + setupView(context, true); validateCourseInfoDisplay(); }); @@ -75,12 +75,25 @@ define([ validateCourseInfoDisplay(); }); - it('should update render if the course card is_enrolled updated', function(){ + it('should update render if the course card is_enrolled updated', function() { courseCardModel.set({ is_enrolled: true }); validateCourseInfoDisplay(); }); + + it('should only show certificate status section if a certificate has been earned', function() { + var data = context, + certUrl = 'sample-certificate'; + + setupView(context, false); + expect(view.$('certificate-status').length).toEqual(0); + view.remove(); + data.run_modes[0].certificate_url = certUrl; + setupView(data, false); + expect(view.$('.certificate-status').length).toEqual(1); + expect(view.$('.certificate-status .cta-secondary').attr('href')).toEqual(certUrl); + }); }); } ); diff --git a/lms/static/sass/_build-learner-dashboard.scss b/lms/static/sass/_build-learner-dashboard.scss index e82ae2ea37..b7d41431ee 100644 --- a/lms/static/sass/_build-learner-dashboard.scss +++ b/lms/static/sass/_build-learner-dashboard.scss @@ -5,5 +5,6 @@ @import 'elements/banners'; @import 'elements/program-card'; @import 'elements/course-card'; +@import 'elements/icons'; @import 'views/program-list'; @import 'views/program-details'; diff --git a/lms/static/sass/elements/_course-card.scss b/lms/static/sass/elements/_course-card.scss index bfece9319b..c1f1ea249b 100644 --- a/lms/static/sass/elements/_course-card.scss +++ b/lms/static/sass/elements/_course-card.scss @@ -1,62 +1,117 @@ -.course-card{ +.course-card { @include span(10); margin-left: $baseline*2; margin-bottom: $baseline; - .course-image-link{ + padding: $baseline/2 0; + + .section { + @extend .grid-container; + @extend .grid-manual; + + padding: $baseline/2 $baseline; + } + + .course-image-link { @include float(left); - .header-img{ + + .header-img { max-width: 191px; } } - .course-details{ + + .course-details { @include float(right); width: 100%; @include susy-media($bp-screen-sm) { width: calc(100% - 191px); } padding-left: $baseline*1.5; - .course-title{ + + .course-title { font-size: font-size(x-large); font-weight: font-weight(normal); margin-bottom: $baseline/4; } - .course-text{ + + .course-text { color: palette(grayscale, dark); - .run-period{ + + .run-period { color: palette(grayscale, black); } } } - .course-actions{ - .enrollment-info{ + + .course-actions { + .enrollment-info { width: $baseline*10; text-align: center; margin-bottom: $baseline/2; text-transform: uppercase; } - .run-select-container{ + + .run-select-container { margin-bottom: $baseline; - .run-select{ + + .run-select { width: $baseline*10; } } - .enroll-button{ + + .enroll-button { width: $baseline*10; 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{ + .view-course-link { width: $baseline*10; text-align: center; } } - .action-msg-view{ + .cta-primary { + display: inline-block; + background-color: palette(success, dark); + border-color: palette(success, dark); + + &:active, + &:focus, + &:hover { + background-color: palette(success, base); + border-color: palette(success, base); + } + } + + .cta-secondary { + display: inline-block; + background-color: palette(primary, dark); + border-color: palette(primary, dark); + + &:active, + &:focus, + &:hover { + background-color: palette(primary, base); + border-color: palette(primary, base); + } + } + + .action-msg-view { clear: both; } + + .message { + margin-bottom: $baseline; + + @include susy-media($bp-screen-md) { + margin-bottom: 0; + } + } + + .certificate-status { + border-top: 1px solid palette(grayscale, x-trans); + padding-top: $baseline; + + @include susy-media($bp-screen-md) { + display: flex; + align-items: center; + } + } } diff --git a/lms/static/sass/elements/_icons.scss b/lms/static/sass/elements/_icons.scss new file mode 100644 index 0000000000..da6e511a14 --- /dev/null +++ b/lms/static/sass/elements/_icons.scss @@ -0,0 +1,11 @@ +.verified-cert-icon { + @include float(left); + @include margin-right($baseline*0.4); + + margin-top: ($baseline/4); + background: url('#{$static-path}/images/icon-sm-verified.png') no-repeat; + background-position: -4px -5px; + background-color: palette(grayscale, white-t); + width: 20px; + height: 18px; +} diff --git a/lms/templates/learner_dashboard/certificate_status.underscore b/lms/templates/learner_dashboard/certificate_status.underscore new file mode 100644 index 0000000000..efd86b5c36 --- /dev/null +++ b/lms/templates/learner_dashboard/certificate_status.underscore @@ -0,0 +1,10 @@ +
+ + <%- gettext('Congratulations! You have earned a certificate for this course.') %> +
+
+ + + <%- gettext('View/Share Certificate') %> + +
diff --git a/lms/templates/learner_dashboard/course_card.underscore b/lms/templates/learner_dashboard/course_card.underscore index d70a6e07ab..c6e6edb40e 100644 --- a/lms/templates/learner_dashboard/course_card.underscore +++ b/lms/templates/learner_dashboard/course_card.underscore @@ -1,4 +1,4 @@ -
+ -
+
+
diff --git a/lms/templates/learner_dashboard/course_enroll.underscore b/lms/templates/learner_dashboard/course_enroll.underscore index c2488ebb87..4b3b43ff60 100644 --- a/lms/templates/learner_dashboard/course_enroll.underscore +++ b/lms/templates/learner_dashboard/course_enroll.underscore @@ -26,7 +26,7 @@
<% } %> - <% } %>