Merge pull request #33186 from thezaeemaanwar/remove_badges_app

[DEPR]: lms/djangoapps/badges
This commit is contained in:
Feanil Patel
2023-10-20 10:29:43 -04:00
committed by GitHub
72 changed files with 17 additions and 3860 deletions

View File

@@ -11,7 +11,7 @@ COURSE_GRADE_CHANGED = Signal()
# Signal that fires when a user is awarded a certificate in a course (in the certificates django app)
# TODO: runtime coupling between apps will be reduced if this event is changed to carry a username
# rather than a User object; however, this will require changes to the milestones and badges APIs
# rather than a User object; however, this will require changes to the milestones
# Same providing_args=["user", "course_key", "mode", "status"] for next 3 signals.
COURSE_CERT_CHANGED = Signal()
COURSE_CERT_AWARDED = Signal()

View File

@@ -21,7 +21,6 @@ from common.djangoapps.student.models import (
UserPasswordToggleHistory,
UserProfile
)
from lms.djangoapps.badges.utils import badges_enabled
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.user_api import errors
from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled
@@ -136,7 +135,6 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
except ObjectDoesNotExist:
activation_key = None
accomplishments_shared = badges_enabled()
data = {
"username": user.username,
"url": self.context.get('request').build_absolute_uri(
@@ -164,7 +162,6 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
"level_of_education": None,
"mailing_address": None,
"requires_parental_consent": None,
"accomplishments_shared": accomplishments_shared,
"account_privacy": self.configuration.get('default_visibility'),
"social_links": None,
"extended_profile_fields": None,

View File

@@ -625,7 +625,6 @@ class AccountSettingsOnCreationTest(CreateAccountMixin, TestCase):
'requires_parental_consent': True,
'language_proficiencies': [],
'account_privacy': PRIVATE_VISIBILITY,
'accomplishments_shared': False,
'extended_profile': [],
'secondary_email': None,
'secondary_email_enabled': None,

View File

@@ -359,7 +359,7 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
ENABLED_CACHES = ['default']
TOTAL_QUERY_COUNT = 24
FULL_RESPONSE_FIELD_COUNT = 30
FULL_RESPONSE_FIELD_COUNT = 29
def setUp(self):
super().setUp()
@@ -379,12 +379,12 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
legacy_profile.save()
return year_of_birth
def _verify_full_shareable_account_response(self, response, account_privacy=None, badges_enabled=False):
def _verify_full_shareable_account_response(self, response, account_privacy=None):
"""
Verify that the shareable fields from the account are returned
"""
data = response.data
assert 12 == len(data)
assert 11 == len(data)
# public fields (3)
assert account_privacy == data['account_privacy']
@@ -399,7 +399,6 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
assert 'm' == data['level_of_education']
assert data['social_links'] is not None
assert data['time_zone'] is None
assert badges_enabled == data['accomplishments_shared']
def _verify_private_account_response(self, response, requires_parental_consent=False):
"""
@@ -436,7 +435,6 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
assert 'm' == data['level_of_education']
assert data['social_links'] is not None
assert UserPreference.get_value(self.user, 'time_zone') == data['time_zone']
assert data['accomplishments_shared'] is not None
assert ((self.user.first_name + ' ') + self.user.last_name) == data['name']
# additional admin fields (13)
@@ -669,7 +667,6 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
response = self.send_get(self.different_client)
self._verify_private_account_response(response)
@mock.patch.dict(settings.FEATURES, {'ENABLE_OPENBADGES': True})
@ddt.data(
("client", "user", PRIVATE_VISIBILITY),
("different_client", "different_user", PRIVATE_VISIBILITY),
@@ -691,7 +688,7 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
if preference_visibility == PRIVATE_VISIBILITY:
self._verify_private_account_response(response)
else:
self._verify_full_shareable_account_response(response, ALL_USERS_VISIBILITY, badges_enabled=True)
self._verify_full_shareable_account_response(response, ALL_USERS_VISIBILITY)
client = self.login_client(api_client, requesting_username)
@@ -812,8 +809,6 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
assert [] == data['language_proficiencies']
assert PRIVATE_VISIBILITY == data['account_privacy']
assert data['time_zone'] is None
# Badges aren't on by default, so should not be present.
assert data['accomplishments_shared'] is False
self.client.login(username=self.user.username, password=TEST_PASSWORD)
verify_get_own_information(self._get_num_queries(22))

View File

@@ -244,9 +244,6 @@ class AccountViewSet(ViewSet):
If "custom", the user has selectively chosen a subset of shareable
fields to make visible to others via the User Preferences API.
* accomplishments_shared: Signals whether badges are enabled on the
platform and should be fetched.
* phone_number: The phone number for the user. String of numbers with
an optional `+` sign at the start.

View File

@@ -14,14 +14,12 @@
'js/views/fields',
'learner_profile/js/views/learner_profile_fields',
'learner_profile/js/views/learner_profile_view',
'learner_profile/js/models/badges_model',
'learner_profile/js/views/badge_list_container',
'js/student_account/views/account_settings_fields',
'js/views/message_banner',
'string_utils'
], function(gettext, $, _, Backbone, Logger, StringUtils, PagingCollection, AccountSettingsModel,
AccountPreferencesModel, FieldsView, LearnerProfileFieldsView, LearnerProfileView, BadgeModel,
BadgeListContainer, AccountSettingsFieldViews, MessageBannerView) {
AccountPreferencesModel, FieldsView, LearnerProfileFieldsView, LearnerProfileView,
AccountSettingsFieldViews, MessageBannerView) {
return function(options) {
var $learnerProfileElement = $('.wrapper-profile');
@@ -55,9 +53,6 @@
nameFieldView,
sectionOneFieldViews,
sectionTwoFieldViews,
BadgeCollection,
badgeCollection,
badgeListContainer,
learnerProfileView,
getProfileVisibility,
showLearnerProfileView;
@@ -172,26 +167,6 @@
})
];
BadgeCollection = PagingCollection.extend({
queryParams: {
currentPage: 'current_page'
}
});
badgeCollection = new BadgeCollection();
badgeCollection.url = options.badges_api_url;
badgeListContainer = new BadgeListContainer({
attributes: {class: 'badge-set-display'},
collection: badgeCollection,
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
}
});
learnerProfileView = new LearnerProfileView({
el: $learnerProfileElement,
ownProfile: options.own_profile,
@@ -204,7 +179,6 @@
nameFieldView: nameFieldView,
sectionOneFieldViews: sectionOneFieldViews,
sectionTwoFieldViews: sectionTwoFieldViews,
badgeListContainer: badgeListContainer,
platformName: options.platform_name
});
@@ -239,7 +213,6 @@
accountSettingsModel: accountSettingsModel,
accountPreferencesModel: accountPreferencesModel,
learnerProfileView: learnerProfileView,
badgeListContainer: badgeListContainer
};
};
});

View File

@@ -1,8 +0,0 @@
(function(define) {
'use strict';
define(['backbone'], function(Backbone) {
var BadgesModel = Backbone.Model.extend({});
return BadgesModel;
});
}).call(this, define || RequireJS.define);

View File

@@ -31,7 +31,6 @@ define(
return new LearnerProfilePage({
accounts_api_url: Helpers.USER_ACCOUNTS_API_URL,
preferences_api_url: Helpers.USER_PREFERENCES_API_URL,
badges_api_url: Helpers.BADGES_API_URL,
own_profile: ownProfile,
account_settings_page_url: Helpers.USER_ACCOUNTS_API_URL,
country_options: Helpers.FIELD_OPTIONS,
@@ -68,148 +67,6 @@ define(
LearnerProfileHelpers.expectLimitedProfileSectionsAndFieldsToBeRendered(learnerProfileView);
});
it("doesn't show the mode toggle if badges are disabled", function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: false}),
tabbedView = context.learnerProfileView.tabbedView,
learnerProfileView = context.learnerProfileView;
LearnerProfileHelpers.expectTabbedViewToBeUndefined(requests, tabbedView);
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
});
it("doesn't show the mode toggle if badges fail to fetch", function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: false}),
tabbedView = context.learnerProfileView.tabbedView,
learnerProfileView = context.learnerProfileView;
LearnerProfileHelpers.expectTabbedViewToBeUndefined(requests, tabbedView);
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
});
it('renders the mode toggle if there are badges', function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: true}),
tabbedView = context.learnerProfileView.tabbedView;
AjaxHelpers.expectRequest(requests, 'POST', '/event');
AjaxHelpers.respondWithError(requests, 404);
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
LearnerProfileHelpers.expectTabbedViewToBeShown(tabbedView);
});
it('renders the mode toggle if badges enabled but none exist', function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: true}),
tabbedView = context.learnerProfileView.tabbedView;
AjaxHelpers.expectRequest(requests, 'POST', '/event');
AjaxHelpers.respondWithError(requests, 404);
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.emptyBadges);
LearnerProfileHelpers.expectTabbedViewToBeShown(tabbedView);
});
it('displays the badges when the accomplishments toggle is selected', function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: true}),
learnerProfileView = context.learnerProfileView,
tabbedView = learnerProfileView.tabbedView;
AjaxHelpers.expectRequest(requests, 'POST', '/event');
AjaxHelpers.respondWithError(requests, 404);
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.secondPageBadges);
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
tabbedView.$el.find('[data-url="accomplishments"]').click();
LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, false);
tabbedView.$el.find('[data-url="about_me"]').click();
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
});
it('displays a placeholder on the last page of badges', function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: true}),
learnerProfileView = context.learnerProfileView,
tabbedView = learnerProfileView.tabbedView;
AjaxHelpers.expectRequest(requests, 'POST', '/event');
AjaxHelpers.respondWithError(requests, 404);
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.thirdPageBadges);
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
tabbedView.$el.find('[data-url="accomplishments"]').click();
LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, true);
tabbedView.$el.find('[data-url="about_me"]').click();
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
});
it('displays a placeholder when the accomplishments toggle is selected and no badges exist', function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: true}),
learnerProfileView = context.learnerProfileView,
tabbedView = learnerProfileView.tabbedView;
AjaxHelpers.expectRequest(requests, 'POST', '/event');
AjaxHelpers.respondWithError(requests, 404);
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.emptyBadges);
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
tabbedView.$el.find('[data-url="accomplishments"]').click();
LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 0, true);
tabbedView.$el.find('[data-url="about_me"]').click();
LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
});
it('shows a paginated list of badges', function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: true}),
learnerProfileView = context.learnerProfileView,
tabbedView = learnerProfileView.tabbedView;
AjaxHelpers.expectRequest(requests, 'POST', '/event');
AjaxHelpers.respondWithError(requests, 404);
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
tabbedView.$el.find('[data-url="accomplishments"]').click();
LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, false);
LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.firstPageBadges);
});
it('allows forward and backward navigation of badges', function() {
var requests = AjaxHelpers.requests(this),
context = createProfilePage(true, {accomplishments_shared: true}),
learnerProfileView = context.learnerProfileView,
tabbedView = learnerProfileView.tabbedView,
badgeListContainer = context.badgeListContainer;
AjaxHelpers.expectRequest(requests, 'POST', '/event');
AjaxHelpers.respondWithError(requests, 404);
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
tabbedView.$el.find('[data-url="accomplishments"]').click();
badgeListContainer.$el.find('.next-page-link').click();
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.secondPageBadges);
LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.secondPageBadges);
badgeListContainer.$el.find('.next-page-link').click();
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.thirdPageBadges);
LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, true);
LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.thirdPageBadges);
badgeListContainer.$el.find('.previous-page-link').click();
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.secondPageBadges);
LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.secondPageBadges);
LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, false);
badgeListContainer.$el.find('.previous-page-link').click();
AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.firstPageBadges);
});
it('renders the limited profile for under 13 users', function() {
var context = createProfilePage(
true,

View File

@@ -1,99 +0,0 @@
define([
'backbone',
'jquery',
'underscore',
'URI',
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
'edx-ui-toolkit/js/pagination/paging-collection',
'learner_profile/js/spec_helpers/helpers',
'learner_profile/js/views/badge_list_container'
],
function(Backbone, $, _, URI, AjaxHelpers, PagingCollection, LearnerProfileHelpers, BadgeListContainer) {
'use strict';
describe('edx.user.BadgeListContainer', function() {
var view;
var createView = function(requests, pageNum, badgeListObject) {
var BadgeCollection = PagingCollection.extend({
queryParams: {
currentPage: 'current_page'
}
});
var badgeCollection = new BadgeCollection();
var models = [];
var badgeListContainer;
var request;
var path;
badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
_.each(_.range(badgeListObject.count), function(idx) {
models.push(LearnerProfileHelpers.makeBadge(idx));
});
badgeListObject.results = models; // eslint-disable-line no-param-reassign
badgeCollection.setPage(pageNum);
request = AjaxHelpers.currentRequest(requests);
path = new URI(request.url).path();
expect(path).toBe('/api/badges/v1/assertions/user/staff/');
AjaxHelpers.respondWithJson(requests, badgeListObject);
badgeListContainer = new BadgeListContainer({
collection: badgeCollection
});
badgeListContainer.render();
return badgeListContainer;
};
afterEach(function() {
view.$el.remove();
});
it('displays all badges', function() {
var requests = AjaxHelpers.requests(this),
badges;
view = createView(requests, 1, {
count: 30,
previous: '/arbitrary/url',
num_pages: 3,
next: null,
start: 20,
current_page: 1,
results: []
});
badges = view.$el.find('div.badge-display');
expect(badges.length).toBe(30);
});
it('displays placeholder on last page', function() {
var requests = AjaxHelpers.requests(this),
placeholder;
view = createView(requests, 3, {
count: 30,
previous: '/arbitrary/url',
num_pages: 3,
next: null,
start: 20,
current_page: 3,
results: []
});
placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(1);
});
it('does not display placeholder on first page', function() {
var requests = AjaxHelpers.requests(this),
placeholder;
view = createView(requests, 1, {
count: 30,
previous: '/arbitrary/url',
num_pages: 3,
next: null,
start: 0,
current_page: 1,
results: []
});
placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(0);
});
});
}
);

View File

@@ -1,81 +0,0 @@
define([
'backbone',
'jquery',
'underscore',
'edx-ui-toolkit/js/pagination/paging-collection',
'learner_profile/js/spec_helpers/helpers',
'learner_profile/js/views/badge_list_view'
],
function(Backbone, $, _, PagingCollection, LearnerProfileHelpers, BadgeListView) {
'use strict';
describe('edx.user.BadgeListView', function() {
var view;
var createView = function(badges, pages, page, hasNextPage) {
var badgeCollection = new PagingCollection();
var models = [];
var badgeList;
badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
_.each(badges, function(element) {
models.push(new Backbone.Model(element));
});
badgeCollection.models = models;
badgeCollection.length = badges.length;
badgeCollection.currentPage = page;
badgeCollection.totalPages = pages;
badgeCollection.hasNextPage = function() {
return hasNextPage;
};
badgeList = new BadgeListView({
collection: badgeCollection
});
return badgeList;
};
afterEach(function() {
view.$el.remove();
});
it('there is a single row if there is only one badge', function() {
var rows;
view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 1, false);
view.render();
rows = view.$el.find('div.row');
expect(rows.length).toBe(1);
});
it('accomplishments placeholder is visible on a last page', function() {
var placeholder;
view = createView([LearnerProfileHelpers.makeBadge(1)], 2, 2, false);
view.render();
placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(1);
});
it('accomplishments placeholder to be not visible on a first page', function() {
var placeholder;
view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 2, true);
view.render();
placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(0);
});
it('badges are in two columns (checked by counting rows for a known number of badges)', function() {
var badges = [];
var placeholder;
var rows;
_.each(_.range(4), function(item) {
badges.push(LearnerProfileHelpers.makeBadge(item));
});
view = createView(badges, 1, 2, true);
view.render();
placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(0);
rows = view.$el.find('div.row');
expect(rows.length).toBe(2);
});
});
}
);

View File

@@ -1,114 +0,0 @@
define([
'backbone', 'jquery', 'underscore',
'learner_profile/js/spec_helpers/helpers',
'learner_profile/js/views/badge_view'
],
function(Backbone, $, _, LearnerProfileHelpers, BadgeView) {
'use strict';
describe('edx.user.BadgeView', function() {
var view,
badge,
testBadgeNameIsDisplayed,
testBadgeIconIsDisplayed;
var createView = function(ownProfile) {
var options,
testView;
badge = LearnerProfileHelpers.makeBadge(1);
options = {
model: new Backbone.Model(badge),
ownProfile: ownProfile,
badgeMeta: {}
};
testView = new BadgeView(options);
testView.render();
$('body').append(testView.$el);
testView.$el.show();
expect(testView.$el.is(':visible')).toBe(true);
return testView;
};
afterEach(function() {
view.$el.remove();
$('.badges-modal').remove();
});
it('profile of other has no share button', function() {
view = createView(false);
expect(view.context.ownProfile).toBeFalsy();
expect(view.$el.find('button.share-button').length).toBe(0);
});
it('own profile has share button', function() {
view = createView(true);
expect(view.context.ownProfile).toBeTruthy();
expect(view.$el.find('button.share-button').length).toBe(1);
});
it('click on share button calls createModal function', function() {
var shareButton;
view = createView(true);
spyOn(view, 'createModal');
view.delegateEvents();
expect(view.context.ownProfile).toBeTruthy();
shareButton = view.$el.find('button.share-button');
expect(shareButton.length).toBe(1);
expect(view.createModal).not.toHaveBeenCalled();
shareButton.click();
expect(view.createModal).toHaveBeenCalled();
});
it('click on share button calls shows the dialog', function(done) {
var shareButton,
$modalElement;
view = createView(true);
expect(view.context.ownProfile).toBeTruthy();
shareButton = view.$el.find('button.share-button');
expect(shareButton.length).toBe(1);
$modalElement = $('.badges-modal');
expect($modalElement.length).toBe(0);
expect($modalElement.is(':visible')).toBeFalsy();
shareButton.click();
// Note: this element should have appeared in the dom during: shareButton.click();
$modalElement = $('.badges-modal');
jasmine.waitUntil(function() {
return $modalElement.is(':visible');
}).always(done);
});
testBadgeNameIsDisplayed = function(ownProfile) {
var badgeDiv;
view = createView(ownProfile);
badgeDiv = view.$el.find('.badge-name');
expect(badgeDiv.length).toBeTruthy();
expect(badgeDiv.is(':visible')).toBe(true);
expect(_.count(badgeDiv.html(), badge.badge_class.display_name)).toBeTruthy();
};
it('test badge name is displayed for own profile', function() {
testBadgeNameIsDisplayed(true);
});
it('test badge name is displayed for other profile', function() {
testBadgeNameIsDisplayed(false);
});
testBadgeIconIsDisplayed = function(ownProfile) {
var badgeImg;
view = createView(ownProfile);
badgeImg = view.$el.find('img.badge');
expect(badgeImg.length).toBe(1);
expect(badgeImg.attr('src')).toEqual(badge.image_url);
};
it('test badge icon is displayed for own profile', function() {
testBadgeIconIsDisplayed(true);
});
it('test badge icon is displayed for other profile', function() {
testBadgeIconIsDisplayed(false);
});
});
}
);

View File

@@ -15,13 +15,12 @@ define(
'js/student_account/models/user_preferences_model',
'learner_profile/js/views/learner_profile_fields',
'learner_profile/js/views/learner_profile_view',
'learner_profile/js/views/badge_list_container',
'js/student_account/views/account_settings_fields',
'js/views/message_banner'
],
function(gettext, Backbone, $, _, PagingCollection, AjaxHelpers, TemplateHelpers, Helpers, LearnerProfileHelpers,
FieldViews, UserAccountModel, AccountPreferencesModel, LearnerProfileFields, LearnerProfileView,
BadgeListContainer, AccountSettingsFieldViews, MessageBannerView) {
AccountSettingsFieldViews, MessageBannerView) {
'use strict';
describe('edx.user.LearnerProfileView', function() {
@@ -132,15 +131,6 @@ define(
})
];
var badgeCollection = new PagingCollection();
badgeCollection.url = Helpers.BADGES_API_URL;
var badgeListContainer = new BadgeListContainer({
attributes: {class: 'badge-set-display'},
collection: badgeCollection,
find_courses_url: Helpers.FIND_COURSES_URL
});
return new LearnerProfileView(
{
el: $('.wrapper-profile'),
@@ -154,7 +144,6 @@ define(
profileImageFieldView: profileImageFieldView,
sectionOneFieldViews: sectionOneFieldViews,
sectionTwoFieldViews: sectionTwoFieldViews,
badgeListContainer: badgeListContainer
});
};
@@ -225,16 +214,5 @@ define(
Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
LearnerProfileHelpers.expectLimitedProfileSectionsAndFieldsToBeRendered(learnerProfileView, true);
});
it("renders an error if the badges can't be fetched", function() {
var learnerProfileView = createLearnerProfileView(false, 'all_users', true);
learnerProfileView.options.accountSettingsModel.set({accomplishments_shared: true});
var requests = AjaxHelpers.requests(this);
learnerProfileView.render();
LearnerProfileHelpers.breakBadgeLoading(learnerProfileView, requests);
LearnerProfileHelpers.expectBadgeLoadingErrorIsRendered(learnerProfileView);
});
});
});

View File

@@ -1,63 +0,0 @@
define(
[
'backbone', 'jquery', 'underscore', 'moment',
'js/spec/student_account/helpers',
'learner_profile/js/spec_helpers/helpers',
'learner_profile/js/views/share_modal_view',
'jquery.simulate'
],
function(Backbone, $, _, Moment, Helpers, LearnerProfileHelpers, ShareModalView) {
'use strict';
describe('edx.user.ShareModalView', function() {
var keys = $.simulate.keyCode;
var view;
var createModalView = function() {
var badge = LearnerProfileHelpers.makeBadge(1);
var context = _.extend(badge, {
created: new Moment(badge.created),
ownProfile: true,
badgeMeta: {}
});
return new ShareModalView({
model: new Backbone.Model(context),
shareButton: $('<button/>')
});
};
beforeEach(function() {
view = createModalView();
// Attach view to document, otherwise click won't work
view.render();
$('body').append(view.$el);
view.$el.show();
expect(view.$el.is(':visible')).toBe(true);
});
afterEach(function() {
view.$el.remove();
});
it('modal view closes on escape', function() {
spyOn(view, 'close');
view.delegateEvents();
expect(view.close).not.toHaveBeenCalled();
$(view.$el).simulate('keydown', {keyCode: keys.ESCAPE});
expect(view.close).toHaveBeenCalled();
});
it('modal view closes click on close', function() {
var $closeButton;
spyOn(view, 'close');
view.delegateEvents();
$closeButton = view.$el.find('button.close');
expect($closeButton.length).toBe(1);
expect(view.close).not.toHaveBeenCalled();
$closeButton.trigger('click');
expect(view.close).toHaveBeenCalled();
});
});
}
);

View File

@@ -123,137 +123,11 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
expect(tabbedViewView.$el.find('.page-content-nav').is(':visible')).toBe(true);
};
var expectBadgesDisplayed = function(learnerProfileView, length, lastPage) {
var $badgeListingView = $('#tabpanel-accomplishments'),
updatedLength = length,
placeholder;
expect($('#tabpanel-about_me').hasClass('is-hidden')).toBe(true);
expect($badgeListingView.hasClass('is-hidden')).toBe(false);
if (lastPage) {
updatedLength += 1;
placeholder = $badgeListingView.find('.find-course');
expect(placeholder.length).toBe(1);
expect(placeholder.attr('href')).toBe('/courses/');
}
expect($badgeListingView.find('.badge-display').length).toBe(updatedLength);
};
var expectBadgesHidden = function() {
var $accomplishmentsTab = $('#tabpanel-accomplishments');
if ($accomplishmentsTab.length) {
// Nonexistence counts as hidden.
expect($('#tabpanel-accomplishments').hasClass('is-hidden')).toBe(true);
}
expect($('#tabpanel-about_me').hasClass('is-hidden')).toBe(false);
};
var expectPage = function(learnerProfileView, pageData) {
var $badgeListContainer = $('#tabpanel-accomplishments');
var index = $badgeListContainer.find('span.search-count').text().trim();
expect(index).toBe('Showing ' + (pageData.start + 1) + '-' + (pageData.start + pageData.results.length)
+ ' out of ' + pageData.count + ' total');
expect($badgeListContainer.find('.current-page').text()).toBe('' + pageData.current_page);
_.each(pageData.results, function(badge) {
expect($('.badge-display:contains(' + badge.badge_class.display_name + ')').length).toBe(1);
});
};
var expectBadgeLoadingErrorIsRendered = function() {
var errorMessage = $('.badge-set-display').text();
expect(errorMessage).toBe(
'Your request could not be completed. Reload the page and try again. If the issue persists, click the '
+ 'Help tab to report the problem.'
);
};
var breakBadgeLoading = function(learnerProfileView, requests) {
var request = AjaxHelpers.currentRequest(requests);
var path = new URI(request.url).path();
expect(path).toBe('/api/badges/v1/assertions/user/student/');
AjaxHelpers.respondWithError(requests, 500);
};
var firstPageBadges = {
count: 30,
previous: null,
next: '/arbitrary/url',
num_pages: 3,
start: 0,
current_page: 1,
results: []
};
var secondPageBadges = {
count: 30,
previous: '/arbitrary/url',
next: '/arbitrary/url',
num_pages: 3,
start: 10,
current_page: 2,
results: []
};
var thirdPageBadges = {
count: 30,
previous: '/arbitrary/url',
num_pages: 3,
next: null,
start: 20,
current_page: 3,
results: []
};
var emptyBadges = {
count: 0,
previous: null,
num_pages: 1,
results: []
};
function makeBadge(num) {
return {
badge_class: {
slug: 'test_slug_' + num,
issuing_component: 'test_component',
display_name: 'Test Badge ' + num,
course_id: null,
description: "Yay! It's a test badge.",
criteria: 'https://example.com/syllabus',
image_url: 'http://localhost:8000/media/badge_classes/test_lMB9bRw.png'
},
image_url: 'http://example.com/image.png',
assertion_url: 'http://example.com/example.json',
created_at: '2015-12-03T16:25:57.676113Z'
};
}
_.each(_.range(0, 10), function(i) {
firstPageBadges.results.push(makeBadge(i));
});
_.each(_.range(10, 20), function(i) {
secondPageBadges.results.push(makeBadge(i));
});
_.each(_.range(20, 30), function(i) {
thirdPageBadges.results.push(makeBadge(i));
});
return {
expectLimitedProfileSectionsAndFieldsToBeRendered: expectLimitedProfileSectionsAndFieldsToBeRendered,
expectProfileSectionsAndFieldsToBeRendered: expectProfileSectionsAndFieldsToBeRendered,
expectProfileSectionsNotToBeRendered: expectProfileSectionsNotToBeRendered,
expectTabbedViewToBeUndefined: expectTabbedViewToBeUndefined,
expectTabbedViewToBeShown: expectTabbedViewToBeShown,
expectBadgesDisplayed: expectBadgesDisplayed,
expectBadgesHidden: expectBadgesHidden,
expectBadgeLoadingErrorIsRendered: expectBadgeLoadingErrorIsRendered,
breakBadgeLoading: breakBadgeLoading,
firstPageBadges: firstPageBadges,
secondPageBadges: secondPageBadges,
thirdPageBadges: thirdPageBadges,
emptyBadges: emptyBadges,
expectPage: expectPage,
makeBadge: makeBadge
expectTabbedViewToBeShown: expectTabbedViewToBeShown
};
});

View File

@@ -1,35 +0,0 @@
/* eslint-disable no-underscore-dangle */
(function(define) {
'use strict';
define(
[
'gettext', 'jquery', 'underscore', 'common/js/components/views/paginated_view',
'learner_profile/js/views/badge_view', 'learner_profile/js/views/badge_list_view',
'text!learner_profile/templates/badge_list.underscore'
],
function(gettext, $, _, PaginatedView, BadgeView, BadgeListView, BadgeListTemplate) {
var BadgeListContainer = PaginatedView.extend({
type: 'badge',
itemViewClass: BadgeView,
listViewClass: BadgeListView,
viewTemplate: BadgeListTemplate,
isZeroIndexed: true,
paginationLabel: gettext('Accomplishments Pagination'),
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;
}
});
return BadgeListContainer;
});
}).call(this, define || RequireJS.define);

View File

@@ -1,65 +0,0 @@
(function(define) {
'use strict';
define([
'gettext',
'jquery',
'underscore',
'edx-ui-toolkit/js/utils/html-utils',
'common/js/components/views/list',
'learner_profile/js/views/badge_view',
'text!learner_profile/templates/badge_placeholder.underscore'
],
function(gettext, $, _, HtmlUtils, ListView, BadgeView, badgePlaceholder) {
var BadgeListView = ListView.extend({
tagName: 'div',
template: HtmlUtils.template(badgePlaceholder),
renderCollection: function() {
var self = this,
$row;
this.$el.empty();
// Split into two columns.
this.collection.each(function(badge, index) {
var $item;
if (index % 2 === 0) {
$row = $('<div class="row">');
this.$el.append($row);
}
$item = new BadgeView({
model: badge,
badgeMeta: this.badgeMeta,
ownProfile: this.ownProfile
}).render().el;
if ($row) {
$row.append($item);
}
this.itemViews.push($item);
}, this);
// Placeholder must always be at the end, and may need a new row.
if (!this.collection.hasNextPage()) {
// find_courses_url set by BadgeListContainer during initialization.
if (this.collection.length % 2 === 0) {
$row = $('<div class="row">');
this.$el.append($row);
}
if ($row) {
HtmlUtils.append(
$row,
this.template({find_courses_url: self.find_courses_url})
);
}
}
return this;
}
});
return BadgeListView;
});
}).call(this, define || RequireJS.define);

View File

@@ -1,47 +0,0 @@
(function(define) {
'use strict';
define(
[
'gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!learner_profile/templates/badge.underscore',
'learner_profile/js/views/share_modal_view',
'edx-ui-toolkit/js/utils/html-utils'
],
function(gettext, $, _, Backbone, Moment, badgeTemplate, ShareModalView, HtmlUtils) {
var BadgeView = Backbone.View.extend({
initialize: function(options) {
this.options = _.extend({}, 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'
},
template: _.template(badgeTemplate),
events: {
'click .share-button': 'createModal'
},
createModal: function() {
var modal = new ShareModalView({
model: new Backbone.Model(this.context),
shareButton: this.shareButton
});
modal.$el.hide();
modal.render();
$('body').append(modal.$el);
modal.$el.fadeIn('short', 'swing', _.bind(modal.ready, modal));
},
render: function() {
this.$el.html(HtmlUtils.HTML(this.template(this.context)).toString());
this.shareButton = this.$el.find('.share-button');
return this;
}
});
return BadgeView;
});
}).call(this, define || RequireJS.define);

View File

@@ -59,30 +59,12 @@
$('.wrapper-profile-section-container-one').removeClass('is-hidden');
$('.wrapper-profile-section-container-two').removeClass('is-hidden');
// Only show accomplishments if this is a full profile
if (this.showFullProfile()) {
$('.learner-achievements').removeClass('is-hidden');
} else {
$('.learner-achievements').addClass('is-hidden');
}
if (this.showFullProfile() && (this.options.accountSettingsModel.get('accomplishments_shared'))) {
tabs = [
{view: this.sectionTwoView, title: gettext('About Me'), url: 'about_me'},
{
view: this.options.badgeListContainer,
title: gettext('Accomplishments'),
url: 'accomplishments'
}
{view: this.sectionTwoView, title: gettext('About Me'), url: 'about_me'}
];
// Build the accomplishments Tab and fill with data
this.options.badgeListContainer.collection.fetch().done(function() {
self.options.badgeListContainer.render();
}).error(function() {
self.options.badgeListContainer.renderError();
});
this.tabbedView = new TabbedView({
tabs: tabs,
router: this.router,

View File

@@ -1,56 +0,0 @@
(function(define) {
'use strict';
define(
[
'gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!learner_profile/templates/share_modal.underscore',
'edx-ui-toolkit/js/utils/html-utils'
],
function(gettext, $, _, Backbone, Moment, badgeModalTemplate, HtmlUtils) {
var ShareModalView = Backbone.View.extend({
attributes: {
class: 'badges-overlay'
},
template: _.template(badgeModalTemplate),
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'
},
initialize: function(options) {
this.options = _.extend({}, options);
},
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(HtmlUtils.HTML(this.template(this.model.toJSON())).toString());
return this;
}
});
return ShareModalView;
});
}).call(this, define || RequireJS.define);

View File

@@ -1,30 +0,0 @@
<div class="badge-image-container">
<img class="badge" src="<%- image_url %>" alt=""/>
</div>
<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(
// Translators: Date stamp for earned badges. Example: Earned December 3, 2015.
gettext('Earned %(created)s.'),
{created: created.format('LL')},
true
)
%></div>
</div>

View File

@@ -1,4 +0,0 @@
<div class="sr-is-focusable sr-<%- type %>-view" tabindex="-1"></div>
<div class="<%- type %>-paging-header"></div>
<div class="<%- type %>-list cards-list"></div>
<div class="<%- type %>-paging-footer"></div>

View File

@@ -1,10 +0,0 @@
<div class="badge-display badge-placeholder">
<div class="badge-image-container">
<span class="accomplishment-placeholder" aria-hidden="true">
</div>
<div class="badge-details">
<div class="badge-name"><%- gettext("What's Your Next Accomplishment?") %></div>
<p class="badge-description"><%- gettext('Start working toward your next learning goal.') %></p>
<a class="find-course" href="<%- find_courses_url %>"><span class="find-button-container"><%- gettext('Find a course') %></span></a>
</div>
</div>

View File

@@ -1,41 +0,0 @@
<div class="focusguard focusguard-start" tabindex="0"></div>
<div class="badges-modal" tabindex="0">
<button class="close"><span class="fa fa-close" aria-hidden="true"></span><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">
<%= edx.HtmlUtils.interpolateHtml(
gettext("Create a {link_start}Mozilla Backpack{link_end} account, or log in to your existing account"),
{
link_start: edx.HtmlUtils.HTML('<a href="https://backpack.openbadges.org/" rel="noopener" target="_blank">'),
link_end: edx.HtmlUtils.HTML('</a>')
}
)
%>
</li>
<li class="step">
<%= edx.HtmlUtils.interpolateHtml(
gettext("{download_link_start}Download this image (right-click or option-click, save as){link_end} and then {upload_link_start}upload{link_end} it to your backpack."),
{
download_link_start: edx.HtmlUtils.joinHtml(
edx.HtmlUtils.HTML('<a class="badge-link" href="'),
image_url,
edx.HtmlUtils.HTML('" rel="noopener" target="_blank">'),
),
link_end: edx.HtmlUtils.HTML('</a>'),
upload_link_start: edx.HtmlUtils.HTML('<a href="https://backpack.openbadges.org/backpack/add" rel="noopener" target="_blank">')
}
)
%>
</li>
</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>

View File

@@ -11,7 +11,6 @@ from django.urls import reverse
from django.views.decorators.http import require_http_methods
from django_countries import countries
from lms.djangoapps.badges.utils import badges_enabled
from common.djangoapps.edxmako.shortcuts import marketing_link
from openedx.core.djangoapps.credentials.utils import get_credentials_records_url
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
@@ -105,8 +104,6 @@ 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': configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME),
'social_platforms': settings.SOCIAL_PLATFORMS,
@@ -128,7 +125,4 @@ def learner_profile_context(request, profile_username, user_is_staff):
)
context['achievements_fragment'] = achievements_fragment
if badges_enabled():
context['data']['badges_api_url'] = reverse("badges_api:user_assertions", kwargs={'username': profile_username})
return context