Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lms/djangoapps/badges/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Serializers for badging
Serializers for Badges
"""
from rest_framework import serializers

Expand Down
4 changes: 4 additions & 0 deletions lms/djangoapps/student_profile/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.http import Http404
from django.views.decorators.http import require_http_methods
from django_countries import countries
from django.contrib.staticfiles.storage import staticfiles_storage

from edxmako.shortcuts import render_to_response, marketing_link
from microsite_configuration import microsite
Expand Down Expand Up @@ -87,6 +88,9 @@ def learner_profile_context(request, profile_username, user_is_staff):
'country_options': list(countries),
'find_courses_url': marketing_link('COURSES'),
'language_options': settings.ALL_LANGUAGES,
'badges_logo': staticfiles_storage.url('certificates/images/backpack-logo.png'),
'badges_icon': staticfiles_storage.url('certificates/images/ico-mozillaopenbadges.png'),
'backpack_ui_img': staticfiles_storage.url('certificates/images/backpack-ui.png'),
'platform_name': microsite.get_value('platform_name', settings.PLATFORM_NAME),
},
'disable_courseware_js': True,
Expand Down
2 changes: 2 additions & 0 deletions lms/static/js/student_profile/views/badge_list_container.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
initialize: function (options) {
BadgeListContainer.__super__.initialize.call(this, options);
this.listView.find_courses_url = options.find_courses_url;
this.listView.badgeMeta = options.badgeMeta;
this.listView.ownProfile = options.ownProfile;
},
type: 'badge',
itemViewClass: BadgeView,
Expand Down
6 changes: 5 additions & 1 deletion lms/static/js/student_profile/views/badge_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
row = $('<div class="row">');
this.$el.append(row);
}
var item = new BadgeView({model: badge}).render().el;
var item = new BadgeView({
model: badge,
badgeMeta: this.badgeMeta,
ownProfile: this.ownProfile
}).render().el;
row.append(item);
this.itemViews.push(item);
}, this);
Expand Down
33 changes: 26 additions & 7 deletions lms/static/js/student_profile/views/badge_view.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
;(function (define, undefined) {
'use strict';
define([
'gettext', 'jquery', 'underscore', 'backbone', 'moment', 'text!templates/student_profile/badge.underscore'],
function (gettext, $, _, Backbone, Moment, badgeTemplate) {
define(['gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!templates/student_profile/badge.underscore',
'js/student_profile/views/share_modal_view'],
function (gettext, $, _, Backbone, Moment, badgeTemplate, ShareModalView) {

var BadgeView = Backbone.View.extend({
initialize: function(options) {
this.context = _.extend(this.options.model.toJSON(), {
'created': new Moment(this.options.model.toJSON().created),
'ownProfile': options.ownProfile,
'badgeMeta': options.badgeMeta
});
},
attributes: {
'class': 'badge-display'
},
render: function () {
var context = _.extend(this.options.model.toJSON(), {
'created': new Moment(this.options.model.toJSON().created)
events: {
'click .share-button': 'createModal'
},
createModal: function() {
var modal = new ShareModalView({
model: new Backbone.Model(this.context),
shareButton: this.shareButton
});
this.$el.html(_.template(badgeTemplate, context));
modal.$el.hide();
modal.render();
$('body').append(modal.$el);
modal.$el.fadeIn('short', 'swing', _.bind(modal.ready, modal));
},
render: function () {
this.$el.html(_.template(badgeTemplate, this.context));
this.shareButton = this.$el.find('.share-button');
return this;
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,13 @@
var badgeListContainer = new BadgeListContainer({
'attributes': {'class': 'badge-set-display'},
'collection': badgeCollection,
'find_courses_url': options.find_courses_url
'find_courses_url': options.find_courses_url,
'ownProfile': options.own_profile,
'badgeMeta': {
'badges_logo': options.badges_logo,
'backpack_ui_img': options.backpack_ui_img,
'badges_icon': options.badges_icon
}
});

var learnerProfileView = new LearnerProfileView({
Expand Down
48 changes: 48 additions & 0 deletions lms/static/js/student_profile/views/share_modal_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
;(function (define, undefined) {
'use strict';
define(['gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!templates/student_profile/share_modal.underscore'],
function (gettext, $, _, Backbone, Moment, badgeModalTemplate) {

var ShareModalView = Backbone.View.extend({
attributes: {
'class': 'badges-overlay'
},
events: {
'click .badges-modal': function (event) {event.stopPropagation();},
'click .badges-modal .close': 'close',
'click .badges-overlay': 'close',
'keydown': 'keyAction',
'focus .focusguard-start': 'focusGuardStart',
'focus .focusguard-end': 'focusGuardEnd'
},
focusGuardStart: function () {
// Should only be selected directly if shift-tabbing from the start, so grab last item.
this.$el.find("a").last().focus();
},
focusGuardEnd: function() {
this.$el.find(".badges-modal").focus();
},
close: function () {
this.$el.fadeOut('short', 'swing', _.bind(this.remove, this));
this.options.shareButton.focus();
},
keyAction: function (event) {
if (event.keyCode === $.ui.keyCode.ESCAPE) {
this.close();
}
},
ready: function() {
// Focusing on the modal background directly doesn't work, probably due
// to its positioning.
this.$el.find('.badges-modal').focus();
},
render: function () {
this.$el.html(_.template(badgeModalTemplate, this.model.toJSON()));
return this;
}
});

return ShareModalView;
});
}).call(this, define || RequireJS.define);
117 changes: 117 additions & 0 deletions lms/static/sass/views/_learner-profile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,128 @@
font-weight: bold;
color: $blue-s3;
}
.share-button {
@extend %t-action3;
@extend %button-reset;
background: $gray-l6;
color: $gray-d1;
padding: ($baseline / 4) ($baseline / 2);
margin-bottom: ($baseline / 2);
display: inline-block;
border-radius: 5px;
border: 2px solid $gray-d1;
cursor: pointer;
transition: background .5s;
.share-prefix {
display: inline-block;
vertical-align: middle;
}
.share-icon-container {
display: inline-block;
img.icon-mozillaopenbadges {
max-width: 1.5em;
margin-right: .25em;
}
}
&:hover {
background: $gray-l4;
}
&:active {
box-shadow: inset 0 4px 15px 0 $black-t2;
transition: none;
}
}
}
}
.badge-placeholder {
background-color: $gray-l7;
box-shadow: inset 0 0 4px 0 $gray-l4;
}
}

// ------------------------------
// #BADGES MODAL
// ------------------------------
.badges-overlay {
@extend %ui-depth1;
position: fixed;
top: 0;
left: 0;
background-color: $dark-trans-bg; /* dim the background */
width: 100%;
height: 100%;
vertical-align: middle;

.badges-modal {
@extend %t-copy-lead1;
@extend %ui-depth2;
color: $lighter-base-font-color;
box-sizing: content-box;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
max-width: 700px;
max-height: calc(100% - 100px);
margin-right: auto;
margin-left: auto;
border-top: rem(10) solid $blue-l2;
background: $light-gray3;
padding-right: ($baseline * 2);
padding-left: ($baseline * 2);
padding-bottom: ($baseline);
overflow-x: hidden;

.modal-header {
margin-top: ($baseline / 2);
margin-bottom: ($baseline / 2);
}

.close {
@extend %button-reset;
@extend %t-strong;
color: $lighter-base-font-color;
position: absolute;
right: ($baseline);
top: $baseline;
cursor: pointer;
padding: ($baseline / 4) ($baseline / 2);
@include transition(all $tmg-f2 ease-in-out 0s);
&:focus, &:hover {
background-color: $blue-d2;
border-radius: 3px;
color: $white;
}
}

.badges-steps {
display: table;
}

.image-container{
// Lines the image up with the content of the above list.
@include ltr {
@include padding-left(2em);
}
@include rtl {
@include padding-right(1em);
float: right;
}
}

.backpack-logo {
@include float(right);
@include margin-left($baseline);
}
}
}

.modal-hr {
display: block;
border: none;
background-color: $light-gray;
height: rem(2);
width: 100%;
}
}
14 changes: 14 additions & 0 deletions lms/templates/student_profile/badge.underscore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@
<div class="badge-details">
<div class="badge-name"><%- badge_class.display_name %></div>
<p class="badge-description"><%- badge_class.description %></p>
<% if (ownProfile) { %>
<button class="share-button">
<div class="share-icon-container">
<img class="icon icon-mozillaopenbadges" src="<%- badgeMeta.badges_icon %>" alt="<%-
interpolate(
// Translators: display_name is the name of an OpenBadges award.
gettext('Share your "%(display_name)s" award'),
{'display_name': badge_class.display_name},
true
)%>">
</div>
<div class="share-prefix" aria-hidden="true"><%- gettext("Share") %></div>
</div>
<% } %>
<div class="badge-date-stamp">
<%-
interpolate(
Expand Down
30 changes: 30 additions & 0 deletions lms/templates/student_profile/share_modal.underscore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div class="focusguard focusguard-start" tabindex="0"></div>
<div class="badges-modal" tabindex="0">
<button class="close"><i class="fa fa-close" aria-hidden="true"></i><span class="sr"><%- gettext("Close") %></span></button>
<h1 class="modal-header"><%- gettext("Share on Mozilla Backpack") %></h1>
<p class="explanation"><%- gettext("To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.") %>
</p>
<hr class="modal-hr"/>
<img class="backpack-logo" src="<%- badgeMeta.badges_logo %>" alt="">
<ol class="badges-steps">
<li class="step"><%=
interpolate(
gettext("Create a %(link_start)sMozilla Backpack%(link_end)s account, or log in to your existing account"),
{link_start: '<a href="https://backpack.openbadges.org/" target="_blank">', link_end: '</a>'},
true
)%>
</li>
<li class="step"><%=
interpolate(
gettext("%(download_link_start)sDownload this image (right-click or option-click, save as)%(link_end)s and then %(upload_link_start)supload%(link_end)s it to your backpack.</li>"), {
download_link_start: '<a class="badge-link" href="' + image_url + '" target="_blank">',
link_end: '</a>', upload_link_start: '<a href="https://backpack.openbadges.org/backpack/add" target="_blank">'
},
true
)%>
</ol>
<div class="image-container">
<img class="badges-backpack-example" src="<%- badgeMeta.backpack_ui_img %>" alt="">
</div>
</div>
<div class="focusguard focusguard-end" tabindex="0"></div>