Commit 33bee3f7 by Andy Armstrong

Refactor learner profile into openedx/features directory

LEARNER-1855
parent 583719cc
...@@ -1782,7 +1782,6 @@ REQUIRE_JS_PATH_OVERRIDES = { ...@@ -1782,7 +1782,6 @@ REQUIRE_JS_PATH_OVERRIDES = {
'js/courseware/link_clicked_events': 'js/courseware/link_clicked_events.js', 'js/courseware/link_clicked_events': 'js/courseware/link_clicked_events.js',
'js/courseware/toggle_element_visibility': 'js/courseware/toggle_element_visibility.js', 'js/courseware/toggle_element_visibility': 'js/courseware/toggle_element_visibility.js',
'js/student_account/logistration_factory': 'js/student_account/logistration_factory.js', 'js/student_account/logistration_factory': 'js/student_account/logistration_factory.js',
'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory.js',
'js/courseware/courseware_factory': 'js/courseware/courseware_factory.js', 'js/courseware/courseware_factory': 'js/courseware/courseware_factory.js',
'js/groups/views/cohorts_dashboard_factory': 'js/groups/views/cohorts_dashboard_factory.js', 'js/groups/views/cohorts_dashboard_factory': 'js/groups/views/cohorts_dashboard_factory.js',
'js/groups/discussions_management/discussions_dashboard_factory': 'js/discussions_management/views/discussions_dashboard_factory.js', 'js/groups/discussions_management/discussions_dashboard_factory': 'js/discussions_management/views/discussions_dashboard_factory.js',
...@@ -2252,7 +2251,9 @@ INSTALLED_APPS = ( ...@@ -2252,7 +2251,9 @@ INSTALLED_APPS = (
'openedx.features.course_experience', 'openedx.features.course_experience',
'openedx.features.course_search', 'openedx.features.course_search',
'openedx.features.enterprise_support', 'openedx.features.enterprise_support',
'openedx.features.learner_profile',
# Experiments
'experiments', 'experiments',
# DRF filters # DRF filters
......
...@@ -31,14 +31,18 @@ var options = { ...@@ -31,14 +31,18 @@ var options = {
{pattern: 'course_search/**/!(*spec).js'}, {pattern: 'course_search/**/!(*spec).js'},
{pattern: 'discussion/js/**/!(*spec).js'}, {pattern: 'discussion/js/**/!(*spec).js'},
{pattern: 'js/**/!(*spec|djangojs).js'}, {pattern: 'js/**/!(*spec|djangojs).js'},
{pattern: 'learner_profile/**/!(*spec).js'},
{pattern: 'lms/js/**/!(*spec).js'}, {pattern: 'lms/js/**/!(*spec).js'},
{pattern: 'support/js/**/!(*spec).js'}, {pattern: 'support/js/**/!(*spec).js'},
{pattern: 'teams/js/**/!(*spec).js'} {pattern: 'teams/js/**/!(*spec).js'}
], ],
specFiles: [ specFiles: [
{pattern: '../**/*spec.js'}, // Define the Webpack-built spec files first
{pattern: 'course_experience/js/**/*_spec.js', webpack: true} {pattern: 'course_experience/js/**/*_spec.js', webpack: true},
// Add all remaining spec files to be used without Webpack
{pattern: '../**/*spec.js'}
], ],
fixtureFiles: [ fixtureFiles: [
......
../../openedx/features/learner_profile/static/learner_profile
\ No newline at end of file
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
'js/student_account/logistration_factory', 'js/student_account/logistration_factory',
'js/student_account/views/account_settings_factory', 'js/student_account/views/account_settings_factory',
'js/student_account/views/finish_auth_factory', 'js/student_account/views/finish_auth_factory',
'js/student_profile/views/learner_profile_factory',
'js/views/message_banner', 'js/views/message_banner',
'learner_profile/js/learner_profile_factory',
'lms/js/preview/preview_factory', 'lms/js/preview/preview_factory',
'support/js/certificates_factory', 'support/js/certificates_factory',
'support/js/enrollment_factory', 'support/js/enrollment_factory',
......
...@@ -88,9 +88,6 @@ ...@@ -88,9 +88,6 @@
'js/views/file_uploader': 'js/views/file_uploader', 'js/views/file_uploader': 'js/views/file_uploader',
'js/views/notification': 'js/views/notification', 'js/views/notification': 'js/views/notification',
'js/student_account/account': 'js/student_account/account', 'js/student_account/account': 'js/student_account/account',
'js/student_profile/views/learner_profile_fields': 'js/student_profile/views/learner_profile_fields',
'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory',
'js/student_profile/views/learner_profile_view': 'js/student_profile/views/learner_profile_view',
'js/ccx/schedule': 'js/ccx/schedule', 'js/ccx/schedule': 'js/ccx/schedule',
'js/views/message_banner': 'js/views/message_banner', 'js/views/message_banner': 'js/views/message_banner',
...@@ -784,14 +781,6 @@ ...@@ -784,14 +781,6 @@
'js/spec/student_account/password_reset_spec.js', 'js/spec/student_account/password_reset_spec.js',
'js/spec/student_account/register_spec.js', 'js/spec/student_account/register_spec.js',
'js/spec/student_account/shoppingcart_spec.js', 'js/spec/student_account/shoppingcart_spec.js',
'js/spec/student_profile/badge_list_container_spec.js',
'js/spec/student_profile/badge_list_view_spec.js',
'js/spec/student_profile/badge_view_spec.js',
'js/spec/student_profile/learner_profile_factory_spec.js',
'js/spec/student_profile/learner_profile_fields_spec.js',
'js/spec/student_profile/learner_profile_view_spec.js',
'js/spec/student_profile/section_two_tab_spec.js',
'js/spec/student_profile/share_modal_view_spec.js',
'js/spec/verify_student/image_input_spec.js', 'js/spec/verify_student/image_input_spec.js',
'js/spec/verify_student/make_payment_step_view_ab_testing_spec.js', 'js/spec/verify_student/make_payment_step_view_ab_testing_spec.js',
'js/spec/verify_student/make_payment_step_view_spec.js', 'js/spec/verify_student/make_payment_step_view_spec.js',
...@@ -803,6 +792,14 @@ ...@@ -803,6 +792,14 @@
'js/spec/views/file_uploader_spec.js', 'js/spec/views/file_uploader_spec.js',
'js/spec/views/message_banner_spec.js', 'js/spec/views/message_banner_spec.js',
'js/spec/views/notification_spec.js', 'js/spec/views/notification_spec.js',
'learner_profile/js/spec/learner_profile_factory_spec.js',
'learner_profile/js/spec/views/badge_list_container_spec.js',
'learner_profile/js/spec/views/badge_list_view_spec.js',
'learner_profile/js/spec/views/badge_view_spec.js',
'learner_profile/js/spec/views/learner_profile_fields_spec.js',
'learner_profile/js/spec/views/learner_profile_view_spec.js',
'learner_profile/js/spec/views/section_two_tab_spec.js',
'learner_profile/js/spec/views/share_modal_view_spec.js',
'support/js/spec/collections/enrollment_spec.js', 'support/js/spec/collections/enrollment_spec.js',
'support/js/spec/models/enrollment_spec.js', 'support/js/spec/models/enrollment_spec.js',
'support/js/spec/views/certificates_spec.js', 'support/js/spec/views/certificates_spec.js',
......
...@@ -604,15 +604,6 @@ urlpatterns += ( ...@@ -604,15 +604,6 @@ urlpatterns += (
include('student_account.urls') include('student_account.urls')
), ),
# Student profile
url(
r'^u/{username_pattern}$'.format(
username_pattern=settings.USERNAME_PATTERN,
),
'student_profile.views.learner_profile',
name='learner_profile',
),
# Student Notes # Student Notes
url( url(
r'^courses/{}/edxnotes'.format( r'^courses/{}/edxnotes'.format(
...@@ -651,6 +642,12 @@ urlpatterns += ( ...@@ -651,6 +642,12 @@ urlpatterns += (
), ),
include('openedx.features.course_search.urls'), include('openedx.features.course_search.urls'),
), ),
# Learner profile
url(
r'^u/',
include('openedx.features.learner_profile.urls'),
),
) )
if settings.FEATURES["ENABLE_TEAMS"]: if settings.FEATURES["ENABLE_TEAMS"]:
......
(function(define, undefined) { (function(define) {
'use strict'; 'use strict';
define([ define([
'gettext', 'gettext',
'jquery', 'jquery',
'underscore', 'underscore',
'backbone', 'backbone',
'logger', 'logger',
'edx-ui-toolkit/js/utils/string-utils',
'edx-ui-toolkit/js/pagination/paging-collection', 'edx-ui-toolkit/js/pagination/paging-collection',
'js/student_account/models/user_account_model', 'js/student_account/models/user_account_model',
'js/student_account/models/user_preferences_model', 'js/student_account/models/user_preferences_model',
'js/views/fields', 'js/views/fields',
'js/student_profile/views/learner_profile_fields', 'learner_profile/js/views/learner_profile_fields',
'js/student_profile/views/learner_profile_view', 'learner_profile/js/views/learner_profile_view',
'js/student_profile/models/badges_model', 'learner_profile/js/models/badges_model',
'js/student_profile/views/badge_list_container', 'learner_profile/js/views/badge_list_container',
'js/student_account/views/account_settings_fields', 'js/student_account/views/account_settings_fields',
'js/views/message_banner', 'js/views/message_banner',
'string_utils' 'string_utils'
], function(gettext, $, _, Backbone, Logger, PagingCollection, AccountSettingsModel, AccountPreferencesModel, ], function(gettext, $, _, Backbone, Logger, StringUtils, PagingCollection, AccountSettingsModel,
FieldsView, LearnerProfileFieldsView, LearnerProfileView, BadgeModel, BadgeListContainer, AccountPreferencesModel, FieldsView, LearnerProfileFieldsView, LearnerProfileView, BadgeModel,
AccountSettingsFieldViews, MessageBannerView) { BadgeListContainer, AccountSettingsFieldViews, MessageBannerView) {
return function(options) { return function(options) {
var learnerProfileElement = $('.wrapper-profile'); var $learnerProfileElement = $('.wrapper-profile');
var accountSettingsModel = new AccountSettingsModel( var accountSettingsModel = new AccountSettingsModel(
_.extend( _.extend(
options.account_settings_data, options.account_settings_data,
{'default_public_account_fields': options.default_public_account_fields} {default_public_account_fields: options.default_public_account_fields}
), ),
{parse: true} {parse: true}
); );
...@@ -37,22 +39,35 @@ ...@@ -37,22 +39,35 @@
}); });
var accountPreferencesModel = new AccountPreferencesModelWithDefaults(options.preferences_data); var accountPreferencesModel = new AccountPreferencesModelWithDefaults(options.preferences_data);
accountSettingsModel.url = options.accounts_api_url;
accountPreferencesModel.url = options.preferences_api_url;
var editable = options.own_profile ? 'toggle' : 'never'; var editable = options.own_profile ? 'toggle' : 'never';
var messageView = new MessageBannerView({ var messageView = new MessageBannerView({
el: $('.message-banner') el: $('.message-banner')
}); });
var accountPrivacyFieldView = new LearnerProfileFieldsView.AccountPrivacyFieldView({ var accountPrivacyFieldView,
profileImageFieldView,
usernameFieldView,
sectionOneFieldViews,
sectionTwoFieldViews,
BadgeCollection,
badgeCollection,
badgeListContainer,
learnerProfileView,
getProfileVisibility,
showLearnerProfileView;
accountSettingsModel.url = options.accounts_api_url;
accountPreferencesModel.url = options.preferences_api_url;
accountPrivacyFieldView = new LearnerProfileFieldsView.AccountPrivacyFieldView({
model: accountPreferencesModel, model: accountPreferencesModel,
required: true, required: true,
editable: 'always', editable: 'always',
showMessages: false, showMessages: false,
title: interpolate_text( title: StringUtils.interpolate(
gettext('{platform_name} learners can see my:'), {platform_name: options.platform_name} gettext('{platform_name} learners can see my:'),
{platform_name: options.platform_name}
), ),
valueAttribute: 'account_privacy', valueAttribute: 'account_privacy',
options: [ options: [
...@@ -64,25 +79,25 @@ ...@@ -64,25 +79,25 @@
persistChanges: true persistChanges: true
}); });
var profileImageFieldView = new LearnerProfileFieldsView.ProfileImageFieldView({ profileImageFieldView = new LearnerProfileFieldsView.ProfileImageFieldView({
model: accountSettingsModel, model: accountSettingsModel,
valueAttribute: 'profile_image', valueAttribute: 'profile_image',
editable: editable === 'toggle', editable: editable === 'toggle',
messageView: messageView, messageView: messageView,
imageMaxBytes: options['profile_image_max_bytes'], imageMaxBytes: options.profile_image_max_bytes,
imageMinBytes: options['profile_image_min_bytes'], imageMinBytes: options.profile_image_min_bytes,
imageUploadUrl: options['profile_image_upload_url'], imageUploadUrl: options.profile_image_upload_url,
imageRemoveUrl: options['profile_image_remove_url'] imageRemoveUrl: options.profile_image_remove_url
}); });
var usernameFieldView = new FieldsView.ReadonlyFieldView({ usernameFieldView = new FieldsView.ReadonlyFieldView({
model: accountSettingsModel, model: accountSettingsModel,
screenReaderTitle: gettext('Username'), screenReaderTitle: gettext('Username'),
valueAttribute: 'username', valueAttribute: 'username',
helpMessage: '' helpMessage: ''
}); });
var sectionOneFieldViews = [ sectionOneFieldViews = [
new FieldsView.DropdownFieldView({ new FieldsView.DropdownFieldView({
model: accountSettingsModel, model: accountSettingsModel,
screenReaderTitle: gettext('Country'), screenReaderTitle: gettext('Country'),
...@@ -113,12 +128,13 @@ ...@@ -113,12 +128,13 @@
}) })
]; ];
var sectionTwoFieldViews = [ sectionTwoFieldViews = [
new FieldsView.TextareaFieldView({ new FieldsView.TextareaFieldView({
model: accountSettingsModel, model: accountSettingsModel,
editable: editable, editable: editable,
showMessages: false, showMessages: false,
title: gettext('About me'), title: gettext('About me'),
// eslint-disable-next-line max-len
placeholderValue: gettext("Tell other learners a little about yourself: where you live, what your interests are, why you're taking courses, or what you hope to learn."), placeholderValue: gettext("Tell other learners a little about yourself: where you live, what your interests are, why you're taking courses, or what you hope to learn."),
valueAttribute: 'bio', valueAttribute: 'bio',
helpMessage: '', helpMessage: '',
...@@ -127,28 +143,28 @@ ...@@ -127,28 +143,28 @@
}) })
]; ];
var BadgeCollection = PagingCollection.extend({ BadgeCollection = PagingCollection.extend({
queryParams: { queryParams: {
currentPage: 'current_page' currentPage: 'current_page'
} }
}); });
var badgeCollection = new BadgeCollection(); badgeCollection = new BadgeCollection();
badgeCollection.url = options.badges_api_url; badgeCollection.url = options.badges_api_url;
var badgeListContainer = new BadgeListContainer({ badgeListContainer = new BadgeListContainer({
'attributes': {'class': 'badge-set-display'}, attributes: {class: 'badge-set-display'},
'collection': badgeCollection, collection: badgeCollection,
'find_courses_url': options.find_courses_url, find_courses_url: options.find_courses_url,
'ownProfile': options.own_profile, ownProfile: options.own_profile,
'badgeMeta': { badgeMeta: {
'badges_logo': options.badges_logo, badges_logo: options.badges_logo,
'backpack_ui_img': options.backpack_ui_img, backpack_ui_img: options.backpack_ui_img,
'badges_icon': options.badges_icon badges_icon: options.badges_icon
} }
}); });
var learnerProfileView = new LearnerProfileView({ learnerProfileView = new LearnerProfileView({
el: learnerProfileElement, el: $learnerProfileElement,
ownProfile: options.own_profile, ownProfile: options.own_profile,
has_preferences_access: options.has_preferences_access, has_preferences_access: options.has_preferences_access,
accountSettingsModel: accountSettingsModel, accountSettingsModel: accountSettingsModel,
...@@ -161,7 +177,7 @@ ...@@ -161,7 +177,7 @@
badgeListContainer: badgeListContainer badgeListContainer: badgeListContainer
}); });
var getProfileVisibility = function() { getProfileVisibility = function() {
if (options.has_preferences_access) { if (options.has_preferences_access) {
return accountPreferencesModel.get('account_privacy'); return accountPreferencesModel.get('account_privacy');
} else { } else {
...@@ -169,7 +185,7 @@ ...@@ -169,7 +185,7 @@
} }
}; };
var showLearnerProfileView = function() { showLearnerProfileView = function() {
// Record that the profile page was viewed // Record that the profile page was viewed
Logger.log('edx.user.settings.viewed', { Logger.log('edx.user.settings.viewed', {
page: 'profile', page: 'profile',
......
(function(define) { (function(define) {
'use strict'; 'use strict';
define(['backbone'], function(Backbone) { define(['backbone'], function(Backbone) {
var BadgesModel = Backbone.Model.extend({}); var BadgesModel = Backbone.Model.extend({});
return BadgesModel; return BadgesModel;
......
...@@ -5,13 +5,14 @@ define([ ...@@ -5,13 +5,14 @@ define([
'URI', 'URI',
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
'edx-ui-toolkit/js/pagination/paging-collection', 'edx-ui-toolkit/js/pagination/paging-collection',
'js/spec/student_profile/helpers', 'learner_profile/js/spec_helpers/helpers',
'js/student_profile/views/badge_list_container' 'learner_profile/js/views/badge_list_container'
], ],
function(Backbone, $, _, URI, AjaxHelpers, PagingCollection, LearnerProfileHelpers, BadgeListContainer) { function(Backbone, $, _, URI, AjaxHelpers, PagingCollection, LearnerProfileHelpers, BadgeListContainer) {
'use strict'; 'use strict';
describe('edx.user.BadgeListContainer', function() { describe('edx.user.BadgeListContainer', function() {
var view, requests; var view;
var createView = function(requests, pageNum, badgeListObject) { var createView = function(requests, pageNum, badgeListObject) {
var BadgeCollection = PagingCollection.extend({ var BadgeCollection = PagingCollection.extend({
...@@ -20,19 +21,22 @@ define([ ...@@ -20,19 +21,22 @@ define([
} }
}); });
var badgeCollection = new BadgeCollection(); var badgeCollection = new BadgeCollection();
badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
var models = []; var models = [];
var badgeListContainer;
var request;
var path;
badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
_.each(_.range(badgeListObject.count), function(idx) { _.each(_.range(badgeListObject.count), function(idx) {
models.push(LearnerProfileHelpers.makeBadge(idx)); models.push(LearnerProfileHelpers.makeBadge(idx));
}); });
badgeListObject.results = models; badgeListObject.results = models; // eslint-disable-line no-param-reassign
badgeCollection.setPage(pageNum); badgeCollection.setPage(pageNum);
var request = AjaxHelpers.currentRequest(requests); request = AjaxHelpers.currentRequest(requests);
var path = new URI(request.url).path(); path = new URI(request.url).path();
expect(path).toBe('/api/badges/v1/assertions/user/staff/'); expect(path).toBe('/api/badges/v1/assertions/user/staff/');
AjaxHelpers.respondWithJson(requests, badgeListObject); AjaxHelpers.respondWithJson(requests, badgeListObject);
var badgeListContainer = new BadgeListContainer({ badgeListContainer = new BadgeListContainer({
'collection': badgeCollection collection: badgeCollection
}); });
badgeListContainer.render(); badgeListContainer.render();
...@@ -44,7 +48,8 @@ define([ ...@@ -44,7 +48,8 @@ define([
}); });
it('displays all badges', function() { it('displays all badges', function() {
requests = AjaxHelpers.requests(this); var requests = AjaxHelpers.requests(this),
badges;
view = createView(requests, 1, { view = createView(requests, 1, {
count: 30, count: 30,
previous: '/arbitrary/url', previous: '/arbitrary/url',
...@@ -54,12 +59,13 @@ define([ ...@@ -54,12 +59,13 @@ define([
current_page: 1, current_page: 1,
results: [] results: []
}); });
var badges = view.$el.find('div.badge-display'); badges = view.$el.find('div.badge-display');
expect(badges.length).toBe(30); expect(badges.length).toBe(30);
}); });
it('displays placeholder on last page', function() { it('displays placeholder on last page', function() {
requests = AjaxHelpers.requests(this); var requests = AjaxHelpers.requests(this),
placeholder;
view = createView(requests, 3, { view = createView(requests, 3, {
count: 30, count: 30,
previous: '/arbitrary/url', previous: '/arbitrary/url',
...@@ -69,12 +75,13 @@ define([ ...@@ -69,12 +75,13 @@ define([
current_page: 3, current_page: 3,
results: [] results: []
}); });
var placeholder = view.$el.find('span.accomplishment-placeholder'); placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(1); expect(placeholder.length).toBe(1);
}); });
it('does not display placeholder on first page', function() { it('does not display placeholder on first page', function() {
requests = AjaxHelpers.requests(this); var requests = AjaxHelpers.requests(this),
placeholder;
view = createView(requests, 1, { view = createView(requests, 1, {
count: 30, count: 30,
previous: '/arbitrary/url', previous: '/arbitrary/url',
...@@ -84,7 +91,7 @@ define([ ...@@ -84,7 +91,7 @@ define([
current_page: 1, current_page: 1,
results: [] results: []
}); });
var placeholder = view.$el.find('span.accomplishment-placeholder'); placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(0); expect(placeholder.length).toBe(0);
}); });
}); });
......
...@@ -3,18 +3,20 @@ define([ ...@@ -3,18 +3,20 @@ define([
'jquery', 'jquery',
'underscore', 'underscore',
'edx-ui-toolkit/js/pagination/paging-collection', 'edx-ui-toolkit/js/pagination/paging-collection',
'js/spec/student_profile/helpers', 'learner_profile/js/spec_helpers/helpers',
'js/student_profile/views/badge_list_view' 'learner_profile/js/views/badge_list_view'
], ],
function(Backbone, $, _, PagingCollection, LearnerProfileHelpers, BadgeListView) { function(Backbone, $, _, PagingCollection, LearnerProfileHelpers, BadgeListView) {
'use strict'; 'use strict';
describe('edx.user.BadgeListView', function() { describe('edx.user.BadgeListView', function() {
var view; var view;
var createView = function(badges, pages, page, hasNextPage) { var createView = function(badges, pages, page, hasNextPage) {
var badgeCollection = new PagingCollection(); var badgeCollection = new PagingCollection();
badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
var models = []; var models = [];
var badgeList;
badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
_.each(badges, function(element) { _.each(badges, function(element) {
models.push(new Backbone.Model(element)); models.push(new Backbone.Model(element));
}); });
...@@ -25,11 +27,11 @@ define([ ...@@ -25,11 +27,11 @@ define([
badgeCollection.hasNextPage = function() { badgeCollection.hasNextPage = function() {
return hasNextPage; return hasNextPage;
}; };
var badge_list = new BadgeListView({ badgeList = new BadgeListView({
'collection': badgeCollection collection: badgeCollection
}); });
return badge_list; return badgeList;
}; };
afterEach(function() { afterEach(function() {
...@@ -37,36 +39,41 @@ define([ ...@@ -37,36 +39,41 @@ define([
}); });
it('there is a single row if there is only one badge', function() { it('there is a single row if there is only one badge', function() {
var rows;
view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 1, false); view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 1, false);
view.render(); view.render();
var rows = view.$el.find('div.row'); rows = view.$el.find('div.row');
expect(rows.length).toBe(1); expect(rows.length).toBe(1);
}); });
it('accomplishments placeholder is visible on a last page', function() { it('accomplishments placeholder is visible on a last page', function() {
var placeholder;
view = createView([LearnerProfileHelpers.makeBadge(1)], 2, 2, false); view = createView([LearnerProfileHelpers.makeBadge(1)], 2, 2, false);
view.render(); view.render();
var placeholder = view.$el.find('span.accomplishment-placeholder'); placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(1); expect(placeholder.length).toBe(1);
}); });
it('accomplishments placeholder to be not visible on a first page', function() { it('accomplishments placeholder to be not visible on a first page', function() {
var placeholder;
view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 2, true); view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 2, true);
view.render(); view.render();
var placeholder = view.$el.find('span.accomplishment-placeholder'); placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(0); expect(placeholder.length).toBe(0);
}); });
it('badges are in two columns (checked by counting rows for a known number of badges)', function() { it('badges are in two columns (checked by counting rows for a known number of badges)', function() {
var badges = []; var badges = [];
var placeholder;
var rows;
_.each(_.range(4), function(item) { _.each(_.range(4), function(item) {
badges.push(LearnerProfileHelpers.makeBadge(item)); badges.push(LearnerProfileHelpers.makeBadge(item));
}); });
view = createView(badges, 1, 2, true); view = createView(badges, 1, 2, true);
view.render(); view.render();
var placeholder = view.$el.find('span.accomplishment-placeholder'); placeholder = view.$el.find('span.accomplishment-placeholder');
expect(placeholder.length).toBe(0); expect(placeholder.length).toBe(0);
var rows = view.$el.find('div.row'); rows = view.$el.find('div.row');
expect(rows.length).toBe(2); expect(rows.length).toBe(2);
}); });
}); });
......
define(['backbone', 'jquery', 'underscore', define([
'js/spec/student_profile/helpers', 'backbone', 'jquery', 'underscore',
'js/student_profile/views/badge_view' 'learner_profile/js/spec_helpers/helpers',
], 'learner_profile/js/views/badge_view'
],
function(Backbone, $, _, LearnerProfileHelpers, BadgeView) { function(Backbone, $, _, LearnerProfileHelpers, BadgeView) {
'use strict'; 'use strict';
describe('edx.user.BadgeView', function() { describe('edx.user.BadgeView', function() {
var view, badge; var view,
badge,
testBadgeNameIsDisplayed,
testBadgeIconIsDisplayed;
var createView = function(ownProfile) { var createView = function(ownProfile) {
var options,
testView;
badge = LearnerProfileHelpers.makeBadge(1); badge = LearnerProfileHelpers.makeBadge(1);
var options = { options = {
'model': new Backbone.Model(badge), model: new Backbone.Model(badge),
'ownProfile': ownProfile, ownProfile: ownProfile,
'badgeMeta': {} badgeMeta: {}
}; };
var view = new BadgeView(options); testView = new BadgeView(options);
view.render(); testView.render();
$('body').append(view.$el); $('body').append(testView.$el);
view.$el.show(); testView.$el.show();
expect(view.$el.is(':visible')).toBe(true); expect(testView.$el.is(':visible')).toBe(true);
return view; return testView;
}; };
afterEach(function() { afterEach(function() {
...@@ -40,11 +47,12 @@ define(['backbone', 'jquery', 'underscore', ...@@ -40,11 +47,12 @@ define(['backbone', 'jquery', 'underscore',
}); });
it('click on share button calls createModal function', function() { it('click on share button calls createModal function', function() {
var shareButton;
view = createView(true); view = createView(true);
spyOn(view, 'createModal'); spyOn(view, 'createModal');
view.delegateEvents(); view.delegateEvents();
expect(view.context.ownProfile).toBeTruthy(); expect(view.context.ownProfile).toBeTruthy();
var shareButton = view.$el.find('button.share-button'); shareButton = view.$el.find('button.share-button');
expect(shareButton.length).toBe(1); expect(shareButton.length).toBe(1);
expect(view.createModal).not.toHaveBeenCalled(); expect(view.createModal).not.toHaveBeenCalled();
shareButton.click(); shareButton.click();
...@@ -52,24 +60,27 @@ define(['backbone', 'jquery', 'underscore', ...@@ -52,24 +60,27 @@ define(['backbone', 'jquery', 'underscore',
}); });
it('click on share button calls shows the dialog', function(done) { it('click on share button calls shows the dialog', function(done) {
var shareButton,
$modalElement;
view = createView(true); view = createView(true);
expect(view.context.ownProfile).toBeTruthy(); expect(view.context.ownProfile).toBeTruthy();
var shareButton = view.$el.find('button.share-button'); shareButton = view.$el.find('button.share-button');
expect(shareButton.length).toBe(1); expect(shareButton.length).toBe(1);
var modalElement = $('.badges-modal'); $modalElement = $('.badges-modal');
expect(modalElement.length).toBe(0); expect($modalElement.length).toBe(0);
expect(modalElement.is(':visible')).toBeFalsy(); expect($modalElement.is(':visible')).toBeFalsy();
shareButton.click(); shareButton.click();
// Note: this element should have appeared in the dom during: shareButton.click(); // Note: this element should have appeared in the dom during: shareButton.click();
modalElement = $('.badges-modal'); $modalElement = $('.badges-modal');
jasmine.waitUntil(function() { jasmine.waitUntil(function() {
return modalElement.is(':visible'); return $modalElement.is(':visible');
}).always(done); }).always(done);
}); });
var testBadgeNameIsDisplayed = function(ownProfile) { testBadgeNameIsDisplayed = function(ownProfile) {
var badgeDiv;
view = createView(ownProfile); view = createView(ownProfile);
var badgeDiv = view.$el.find('.badge-name'); badgeDiv = view.$el.find('.badge-name');
expect(badgeDiv.length).toBeTruthy(); expect(badgeDiv.length).toBeTruthy();
expect(badgeDiv.is(':visible')).toBe(true); expect(badgeDiv.is(':visible')).toBe(true);
expect(_.count(badgeDiv.html(), badge.badge_class.display_name)).toBeTruthy(); expect(_.count(badgeDiv.html(), badge.badge_class.display_name)).toBeTruthy();
...@@ -83,9 +94,10 @@ define(['backbone', 'jquery', 'underscore', ...@@ -83,9 +94,10 @@ define(['backbone', 'jquery', 'underscore',
testBadgeNameIsDisplayed(false); testBadgeNameIsDisplayed(false);
}); });
var testBadgeIconIsDisplayed = function(ownProfile) { testBadgeIconIsDisplayed = function(ownProfile) {
var badgeImg;
view = createView(ownProfile); view = createView(ownProfile);
var badgeImg = view.$el.find('img.badge'); badgeImg = view.$el.find('img.badge');
expect(badgeImg.length).toBe(1); expect(badgeImg.length).toBe(1);
expect(badgeImg.attr('src')).toEqual(badge.image_url); expect(badgeImg.attr('src')).toEqual(badge.image_url);
}; };
......
define(['backbone', define(
[
'backbone',
'jquery', 'jquery',
'underscore', 'underscore',
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
'common/js/spec_helpers/template_helpers', 'common/js/spec_helpers/template_helpers',
'js/spec/student_account/helpers', 'js/spec/student_account/helpers',
'js/student_account/models/user_account_model', 'js/student_account/models/user_account_model',
'js/student_profile/views/learner_profile_fields', 'learner_profile/js/views/learner_profile_fields',
'js/views/message_banner' 'js/views/message_banner'
], ],
function(Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, UserAccountModel, LearnerProfileFields, function(Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, UserAccountModel, LearnerProfileFields,
MessageBannerView) { MessageBannerView) {
'use strict'; 'use strict';
describe('edx.user.LearnerProfileFields', function() { describe('edx.user.LearnerProfileFields', function() {
...@@ -21,20 +23,21 @@ define(['backbone', ...@@ -21,20 +23,21 @@ define(['backbone',
var yearOfBirth = _.isUndefined(options.yearOfBirth) ? MOCK_YEAR_OF_BIRTH : options.yearOfBirth; var yearOfBirth = _.isUndefined(options.yearOfBirth) ? MOCK_YEAR_OF_BIRTH : options.yearOfBirth;
var imageMaxBytes = _.isUndefined(options.imageMaxBytes) ? MOCK_IMAGE_MAX_BYTES : options.imageMaxBytes; var imageMaxBytes = _.isUndefined(options.imageMaxBytes) ? MOCK_IMAGE_MAX_BYTES : options.imageMaxBytes;
var imageMinBytes = _.isUndefined(options.imageMinBytes) ? MOCK_IMAGE_MIN_BYTES : options.imageMinBytes; var imageMinBytes = _.isUndefined(options.imageMinBytes) ? MOCK_IMAGE_MIN_BYTES : options.imageMinBytes;
var messageView;
var imageData = { var imageData = {
image_url_large: '/media/profile-images/default.jpg', image_url_large: '/media/profile-images/default.jpg',
has_image: options.hasImage ? true : false has_image: !!options.hasImage
}; };
var accountSettingsModel = new UserAccountModel(); var accountSettingsModel = new UserAccountModel();
accountSettingsModel.set({'profile_image': imageData}); accountSettingsModel.set({profile_image: imageData});
accountSettingsModel.set({'year_of_birth': yearOfBirth}); accountSettingsModel.set({year_of_birth: yearOfBirth});
accountSettingsModel.set({'requires_parental_consent': _.isEmpty(yearOfBirth) ? true : false}); accountSettingsModel.set({requires_parental_consent: !!_.isEmpty(yearOfBirth)});
accountSettingsModel.url = Helpers.USER_ACCOUNTS_API_URL; accountSettingsModel.url = Helpers.USER_ACCOUNTS_API_URL;
var messageView = new MessageBannerView({ messageView = new MessageBannerView({
el: $('.message-banner') el: $('.message-banner')
}); });
...@@ -50,18 +53,6 @@ define(['backbone', ...@@ -50,18 +53,6 @@ define(['backbone',
}); });
}; };
beforeEach(function() {
loadFixtures('js/fixtures/student_profile/student_profile.html');
TemplateHelpers.installTemplate('templates/student_profile/learner_profile');
TemplateHelpers.installTemplate('templates/fields/field_image');
TemplateHelpers.installTemplate('templates/fields/message_banner');
});
afterEach(function() {
// image_field.js's window.onBeforeUnload breaks Karma in Chrome, clean it up after each test
$(window).off('beforeunload');
});
var createFakeImageFile = function(size) { var createFakeImageFile = function(size) {
var fileFakeData = 'i63ljc6giwoskyb9x5sw0169bdcmcxr3cdz8boqv0lik971972cmd6yknvcxr5sw0nvc169bdcmcxsdf'; var fileFakeData = 'i63ljc6giwoskyb9x5sw0169bdcmcxr3cdz8boqv0lik971972cmd6yknvcxr5sw0nvc169bdcmcxsdf';
return new Blob( return new Blob(
...@@ -80,6 +71,17 @@ define(['backbone', ...@@ -80,6 +71,17 @@ define(['backbone',
}); });
}; };
beforeEach(function() {
loadFixtures('learner_profile/fixtures/learner_profile.html');
TemplateHelpers.installTemplate('templates/fields/field_image');
TemplateHelpers.installTemplate('templates/fields/message_banner');
});
afterEach(function() {
// image_field.js's window.onBeforeUnload breaks Karma in Chrome, clean it up after each test
$(window).off('beforeunload');
});
describe('ProfileImageFieldView', function() { describe('ProfileImageFieldView', function() {
var verifyImageUploadButtonMessage = function(view, inProgress) { var verifyImageUploadButtonMessage = function(view, inProgress) {
var iconName = inProgress ? 'fa-spinner' : 'fa-camera'; var iconName = inProgress ? 'fa-spinner' : 'fa-camera';
...@@ -96,11 +98,11 @@ define(['backbone', ...@@ -96,11 +98,11 @@ define(['backbone',
}; };
it('can upload profile image', function() { it('can upload profile image', function() {
var imageView = createImageView({ownProfile: true, hasImage: false});
imageView.render();
var requests = AjaxHelpers.requests(this); var requests = AjaxHelpers.requests(this);
var imageName = 'profile_image.jpg'; var imageName = 'profile_image.jpg';
var imageView = createImageView({ownProfile: true, hasImage: false});
var data;
imageView.render();
initializeUploader(imageView); initializeUploader(imageView);
...@@ -124,7 +126,7 @@ define(['backbone', ...@@ -124,7 +126,7 @@ define(['backbone',
// Upon successful image upload, account settings model will be fetched to // Upon successful image upload, account settings model will be fetched to
// get the url for newly uploaded image, So we need to send the response for that GET // get the url for newly uploaded image, So we need to send the response for that GET
var data = {profile_image: { data = {profile_image: {
image_url_large: '/media/profile-images/' + imageName, image_url_large: '/media/profile-images/' + imageName,
has_image: true has_image: true
}}; }};
...@@ -141,10 +143,11 @@ define(['backbone', ...@@ -141,10 +143,11 @@ define(['backbone',
}); });
it('can remove profile image', function() { it('can remove profile image', function() {
var requests = AjaxHelpers.requests(this);
var imageView = createImageView({ownProfile: true, hasImage: false}); var imageView = createImageView({ownProfile: true, hasImage: false});
var data;
imageView.render(); imageView.render();
var requests = AjaxHelpers.requests(this);
// Verify image remove title // Verify image remove title
verifyImageRemoveButtonMessage(imageView, false); verifyImageRemoveButtonMessage(imageView, false);
...@@ -162,7 +165,7 @@ define(['backbone', ...@@ -162,7 +165,7 @@ define(['backbone',
// Upon successful image removal, account settings model will be fetched to get default image url // Upon successful image removal, account settings model will be fetched to get default image url
// So we need to send the response for that GET // So we need to send the response for that GET
var data = {profile_image: { data = {profile_image: {
image_url_large: '/media/profile-images/default.jpg', image_url_large: '/media/profile-images/default.jpg',
has_image: false has_image: false
}}; }};
...@@ -267,11 +270,10 @@ define(['backbone', ...@@ -267,11 +270,10 @@ define(['backbone',
}); });
it('shows error message for HTTP 500', function() { it('shows error message for HTTP 500', function() {
var requests = AjaxHelpers.requests(this);
var imageView = createImageView({ownProfile: true, hasImage: false}); var imageView = createImageView({ownProfile: true, hasImage: false});
imageView.render(); imageView.render();
var requests = AjaxHelpers.requests(this);
initializeUploader(imageView); initializeUploader(imageView);
// Add image to upload queue. Validate the image size and send POST request to upload image // Add image to upload queue. Validate the image size and send POST request to upload image
......
define(['backbone', /* eslint-disable vars-on-top */
define(
[
'backbone',
'jquery', 'jquery',
'underscore', 'underscore',
'edx-ui-toolkit/js/pagination/paging-collection', 'edx-ui-toolkit/js/pagination/paging-collection',
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
'common/js/spec_helpers/template_helpers', 'common/js/spec_helpers/template_helpers',
'js/spec/student_account/helpers', 'js/spec/student_account/helpers',
'js/spec/student_profile/helpers', 'learner_profile/js/spec_helpers/helpers',
'js/views/fields', 'js/views/fields',
'js/student_account/models/user_account_model', 'js/student_account/models/user_account_model',
'js/student_account/models/user_preferences_model', 'js/student_account/models/user_preferences_model',
'js/student_profile/views/learner_profile_fields', 'learner_profile/js/views/learner_profile_fields',
'js/student_profile/views/learner_profile_view', 'learner_profile/js/views/learner_profile_view',
'js/student_profile/views/badge_list_container', 'learner_profile/js/views/badge_list_container',
'js/student_account/views/account_settings_fields', 'js/student_account/views/account_settings_fields',
'js/views/message_banner' 'js/views/message_banner'
], ],
...@@ -24,8 +27,8 @@ define(['backbone', ...@@ -24,8 +27,8 @@ define(['backbone',
var createLearnerProfileView = function(ownProfile, accountPrivacy, profileIsPublic) { var createLearnerProfileView = function(ownProfile, accountPrivacy, profileIsPublic) {
var accountSettingsModel = new UserAccountModel(); var accountSettingsModel = new UserAccountModel();
accountSettingsModel.set(Helpers.createAccountSettingsData()); accountSettingsModel.set(Helpers.createAccountSettingsData());
accountSettingsModel.set({'profile_is_public': profileIsPublic}); accountSettingsModel.set({profile_is_public: profileIsPublic});
accountSettingsModel.set({'profile_image': Helpers.PROFILE_IMAGE}); accountSettingsModel.set({profile_image: Helpers.PROFILE_IMAGE});
var accountPreferencesModel = new AccountPreferencesModel(); var accountPreferencesModel = new AccountPreferencesModel();
accountPreferencesModel.set({account_privacy: accountPrivacy}); accountPreferencesModel.set({account_privacy: accountPrivacy});
...@@ -114,9 +117,9 @@ define(['backbone', ...@@ -114,9 +117,9 @@ define(['backbone',
badgeCollection.url = Helpers.BADGES_API_URL; badgeCollection.url = Helpers.BADGES_API_URL;
var badgeListContainer = new BadgeListContainer({ var badgeListContainer = new BadgeListContainer({
'attributes': {'class': 'badge-set-display'}, attributes: {class: 'badge-set-display'},
'collection': badgeCollection, collection: badgeCollection,
'find_courses_url': Helpers.FIND_COURSES_URL find_courses_url: Helpers.FIND_COURSES_URL
}); });
return new LearnerProfileView( return new LearnerProfileView(
...@@ -136,7 +139,7 @@ define(['backbone', ...@@ -136,7 +139,7 @@ define(['backbone',
}; };
beforeEach(function() { beforeEach(function() {
loadFixtures('js/fixtures/student_profile/student_profile.html'); loadFixtures('learner_profile/fixtures/learner_profile.html');
}); });
afterEach(function() { afterEach(function() {
...@@ -205,7 +208,7 @@ define(['backbone', ...@@ -205,7 +208,7 @@ define(['backbone',
it("renders an error if the badges can't be fetched", function() { it("renders an error if the badges can't be fetched", function() {
var learnerProfileView = createLearnerProfileView(false, 'all_users', true); var learnerProfileView = createLearnerProfileView(false, 'all_users', true);
learnerProfileView.options.accountSettingsModel.set({'accomplishments_shared': true}); learnerProfileView.options.accountSettingsModel.set({accomplishments_shared: true});
var requests = AjaxHelpers.requests(this); var requests = AjaxHelpers.requests(this);
learnerProfileView.render(); learnerProfileView.render();
......
define(['backbone', 'jquery', 'underscore', /* eslint-disable vars-on-top */
define(
[
'backbone', 'jquery', 'underscore',
'js/spec/student_account/helpers', 'js/spec/student_account/helpers',
'js/student_profile/views/section_two_tab', 'learner_profile/js/views/section_two_tab',
'js/views/fields', 'js/views/fields',
'js/student_account/models/user_account_model' 'js/student_account/models/user_account_model'
], ],
function(Backbone, $, _, Helpers, SectionTwoTabView, FieldViews, UserAccountModel) { function(Backbone, $, _, Helpers, SectionTwoTabView, FieldViews, UserAccountModel) {
'use strict'; 'use strict';
describe('edx.user.SectionTwoTab', function() { describe('edx.user.SectionTwoTab', function() {
var createSectionTwoView = function(ownProfile, profileIsPublic) { var createSectionTwoView = function(ownProfile, profileIsPublic) {
var accountSettingsModel = new UserAccountModel(); var accountSettingsModel = new UserAccountModel();
accountSettingsModel.set(Helpers.createAccountSettingsData()); accountSettingsModel.set(Helpers.createAccountSettingsData());
accountSettingsModel.set({'profile_is_public': profileIsPublic}); accountSettingsModel.set({profile_is_public: profileIsPublic});
accountSettingsModel.set({'profile_image': Helpers.PROFILE_IMAGE}); accountSettingsModel.set({profile_image: Helpers.PROFILE_IMAGE});
var editable = ownProfile ? 'toggle' : 'never'; var editable = ownProfile ? 'toggle' : 'never';
...@@ -56,14 +60,14 @@ define(['backbone', 'jquery', 'underscore', ...@@ -56,14 +60,14 @@ define(['backbone', 'jquery', 'underscore',
}); });
}); });
var testPrivateProfile = function(ownProfile, msg_string) { var testPrivateProfile = function(ownProfile, messageString) {
var view = createSectionTwoView(ownProfile, false); var view = createSectionTwoView(ownProfile, false);
view.render(); view.render();
var bio = view.$el.find('.u-field-bio'); var bio = view.$el.find('.u-field-bio');
expect(bio.length).toBe(0); expect(bio.length).toBe(0);
var msg = view.$el.find('span.profile-private--message'); var msg = view.$el.find('span.profile-private--message');
expect(msg.length).toBe(1); expect(msg.length).toBe(1);
expect(_.count(msg.html(), msg_string)).toBeTruthy(); expect(_.count(msg.html(), messageString)).toBeTruthy();
}; };
it('no profile when profile is private for other people', function() { it('no profile when profile is private for other people', function() {
......
define(['backbone', 'jquery', 'underscore', 'moment', define(
[
'backbone', 'jquery', 'underscore', 'moment',
'js/spec/student_account/helpers', 'js/spec/student_account/helpers',
'js/spec/student_profile/helpers', 'learner_profile/js/spec_helpers/helpers',
'js/student_profile/views/share_modal_view', 'learner_profile/js/views/share_modal_view',
'jquery.simulate' 'jquery.simulate'
], ],
function(Backbone, $, _, Moment, Helpers, LearnerProfileHelpers, ShareModalView) { function(Backbone, $, _, Moment, Helpers, LearnerProfileHelpers, ShareModalView) {
'use strict'; 'use strict';
describe('edx.user.ShareModalView', function() { describe('edx.user.ShareModalView', function() {
var keys = $.simulate.keyCode; var keys = $.simulate.keyCode;
...@@ -14,9 +17,9 @@ define(['backbone', 'jquery', 'underscore', 'moment', ...@@ -14,9 +17,9 @@ define(['backbone', 'jquery', 'underscore', 'moment',
var createModalView = function() { var createModalView = function() {
var badge = LearnerProfileHelpers.makeBadge(1); var badge = LearnerProfileHelpers.makeBadge(1);
var context = _.extend(badge, { var context = _.extend(badge, {
'created': new Moment(badge.created), created: new Moment(badge.created),
'ownProfile': true, ownProfile: true,
'badgeMeta': {} badgeMeta: {}
}); });
return new ShareModalView({ return new ShareModalView({
model: new Backbone.Model(context), model: new Backbone.Model(context),
...@@ -46,9 +49,10 @@ define(['backbone', 'jquery', 'underscore', 'moment', ...@@ -46,9 +49,10 @@ define(['backbone', 'jquery', 'underscore', 'moment',
}); });
it('modal view closes click on close', function() { it('modal view closes click on close', function() {
var $closeButton;
spyOn(view, 'close'); spyOn(view, 'close');
view.delegateEvents(); view.delegateEvents();
var $closeButton = view.$el.find('button.close'); $closeButton = view.$el.find('button.close');
expect($closeButton.length).toBe(1); expect($closeButton.length).toBe(1);
expect(view.close).not.toHaveBeenCalled(); expect(view.close).not.toHaveBeenCalled();
$closeButton.trigger('click'); $closeButton.trigger('click');
......
...@@ -15,7 +15,9 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers' ...@@ -15,7 +15,9 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
} else if (view.fieldValue()) { } else if (view.fieldValue()) {
expect(view.fieldValue()).toBe(view.modelValue()); expect(view.fieldValue()).toBe(view.modelValue());
} else if ('optionForValue' in view) { } else if ('optionForValue' in view) {
expect($($element.find('.u-field-value .u-field-value-readonly')[0]).text()).toBe(view.displayValue(view.modelValue())); expect($($element.find('.u-field-value .u-field-value-readonly')[0]).text()).toBe(
view.displayValue(view.modelValue())
);
} else { } else {
expect($($element.find('.u-field-value .u-field-value-readonly')[0]).text()).toBe(view.modelValue()); expect($($element.find('.u-field-value .u-field-value-readonly')[0]).text()).toBe(view.modelValue());
} }
...@@ -72,10 +74,10 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers' ...@@ -72,10 +74,10 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
}; };
var expectLimitedProfileSectionsAndFieldsToBeRendered = function(learnerProfileView, othersProfile) { var expectLimitedProfileSectionsAndFieldsToBeRendered = function(learnerProfileView, othersProfile) {
expectProfilePrivacyFieldTobeRendered(learnerProfileView, othersProfile);
var sectionOneFieldElements = $(learnerProfileView.$('.wrapper-profile-section-one')).find('.u-field'); var sectionOneFieldElements = $(learnerProfileView.$('.wrapper-profile-section-one')).find('.u-field');
expectProfilePrivacyFieldTobeRendered(learnerProfileView, othersProfile);
expect(sectionOneFieldElements.length).toBe(2); expect(sectionOneFieldElements.length).toBe(2);
expectProfileElementContainsField( expectProfileElementContainsField(
sectionOneFieldElements[0], sectionOneFieldElements[0],
...@@ -111,16 +113,18 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers' ...@@ -111,16 +113,18 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
}; };
var expectBadgesDisplayed = function(learnerProfileView, length, lastPage) { var expectBadgesDisplayed = function(learnerProfileView, length, lastPage) {
var badgeListingView = learnerProfileView.$el.find('#tabpanel-accomplishments'); var badgeListingView = learnerProfileView.$el.find('#tabpanel-accomplishments'),
updatedLength = length,
placeholder;
expect(learnerProfileView.$el.find('#tabpanel-about_me').hasClass('is-hidden')).toBe(true); expect(learnerProfileView.$el.find('#tabpanel-about_me').hasClass('is-hidden')).toBe(true);
expect(badgeListingView.hasClass('is-hidden')).toBe(false); expect(badgeListingView.hasClass('is-hidden')).toBe(false);
if (lastPage) { if (lastPage) {
length += 1; updatedLength += 1;
var placeholder = badgeListingView.find('.find-course'); placeholder = badgeListingView.find('.find-course');
expect(placeholder.length).toBe(1); expect(placeholder.length).toBe(1);
expect(placeholder.attr('href')).toBe('/courses/'); expect(placeholder.attr('href')).toBe('/courses/');
} }
expect(badgeListingView.find('.badge-display').length).toBe(length); expect(badgeListingView.find('.badge-display').length).toBe(updatedLength);
}; };
var expectBadgesHidden = function(learnerProfileView) { var expectBadgesHidden = function(learnerProfileView) {
...@@ -188,20 +192,27 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers' ...@@ -188,20 +192,27 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
results: [] results: []
}; };
var emptyBadges = {
count: 0,
previous: null,
num_pages: 1,
results: []
};
function makeBadge(num) { function makeBadge(num) {
return { return {
'badge_class': { badge_class: {
'slug': 'test_slug_' + num, slug: 'test_slug_' + num,
'issuing_component': 'test_component', issuing_component: 'test_component',
'display_name': 'Test Badge ' + num, display_name: 'Test Badge ' + num,
'course_id': null, course_id: null,
'description': "Yay! It's a test badge.", description: "Yay! It's a test badge.",
'criteria': 'https://example.com/syllabus', criteria: 'https://example.com/syllabus',
'image_url': 'http://localhost:8000/media/badge_classes/test_lMB9bRw.png' image_url: 'http://localhost:8000/media/badge_classes/test_lMB9bRw.png'
}, },
'image_url': 'http://example.com/image.png', image_url: 'http://example.com/image.png',
'assertion_url': 'http://example.com/example.json', assertion_url: 'http://example.com/example.json',
'created_at': '2015-12-03T16:25:57.676113Z' created_at: '2015-12-03T16:25:57.676113Z'
}; };
} }
...@@ -217,13 +228,6 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers' ...@@ -217,13 +228,6 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
thirdPageBadges.results.push(makeBadge(i)); thirdPageBadges.results.push(makeBadge(i));
}); });
var emptyBadges = {
'count': 0,
'previous': null,
'num_pages': 1,
'results': []
};
return { return {
expectLimitedProfileSectionsAndFieldsToBeRendered: expectLimitedProfileSectionsAndFieldsToBeRendered, expectLimitedProfileSectionsAndFieldsToBeRendered: expectLimitedProfileSectionsAndFieldsToBeRendered,
expectProfileSectionsAndFieldsToBeRendered: expectProfileSectionsAndFieldsToBeRendered, expectProfileSectionsAndFieldsToBeRendered: expectProfileSectionsAndFieldsToBeRendered,
......
(function(define, undefined) { /* eslint-disable no-underscore-dangle */
(function(define) {
'use strict'; 'use strict';
define([
'gettext', 'jquery', 'underscore', 'common/js/components/views/paginated_view', define(
'js/student_profile/views/badge_view', 'js/student_profile/views/badge_list_view', [
'text!templates/student_profile/badge_list.underscore'], '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) { function(gettext, $, _, PaginatedView, BadgeView, BadgeListView, BadgeListTemplate) {
var BadgeListContainer = PaginatedView.extend({ var BadgeListContainer = PaginatedView.extend({
type: 'badge', type: 'badge',
......
(function(define, undefined) { (function(define) {
'use strict'; 'use strict';
define([ define([
'gettext', 'gettext',
'jquery', 'jquery',
'underscore', 'underscore',
'edx-ui-toolkit/js/utils/html-utils', 'edx-ui-toolkit/js/utils/html-utils',
'common/js/components/views/list', 'common/js/components/views/list',
'js/student_profile/views/badge_view', 'learner_profile/js/views/badge_view',
'text!templates/student_profile/badge_placeholder.underscore' 'text!learner_profile/templates/badge_placeholder.underscore'
], ],
function(gettext, $, _, HtmlUtils, ListView, BadgeView, badgePlaceholder) { function(gettext, $, _, HtmlUtils, ListView, BadgeView, badgePlaceholder) {
var BadgeListView = ListView.extend({ var BadgeListView = ListView.extend({
...@@ -23,11 +24,12 @@ ...@@ -23,11 +24,12 @@
// Split into two columns. // Split into two columns.
this.collection.each(function(badge, index) { this.collection.each(function(badge, index) {
var $item;
if (index % 2 === 0) { if (index % 2 === 0) {
$row = $('<div class="row">'); $row = $('<div class="row">');
this.$el.append($row); this.$el.append($row);
} }
var $item = new BadgeView({ $item = new BadgeView({
model: badge, model: badge,
badgeMeta: this.badgeMeta, badgeMeta: this.badgeMeta,
ownProfile: this.ownProfile ownProfile: this.ownProfile
......
(function(define, undefined) { (function(define) {
'use strict'; 'use strict';
define(['gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!templates/student_profile/badge.underscore', define(
'js/student_profile/views/share_modal_view'], [
'gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!learner_profile/templates/badge.underscore',
'learner_profile/js/views/share_modal_view'
],
function(gettext, $, _, Backbone, Moment, badgeTemplate, ShareModalView) { function(gettext, $, _, Backbone, Moment, badgeTemplate, ShareModalView) {
var BadgeView = Backbone.View.extend({ var BadgeView = Backbone.View.extend({
initialize: function(options) { initialize: function(options) {
this.options = _.extend({}, options); this.options = _.extend({}, options);
this.context = _.extend(this.options.model.toJSON(), { this.context = _.extend(this.options.model.toJSON(), {
'created': new Moment(this.options.model.toJSON().created), created: new Moment(this.options.model.toJSON().created),
'ownProfile': options.ownProfile, ownProfile: options.ownProfile,
'badgeMeta': options.badgeMeta badgeMeta: options.badgeMeta
}); });
}, },
attributes: { attributes: {
'class': 'badge-display' class: 'badge-display'
}, },
template: _.template(badgeTemplate), template: _.template(badgeTemplate),
events: { events: {
......
(function(define, undefined) { /* eslint-disable no-underscore-dangle */
(function(define) {
'use strict'; 'use strict';
define([ define([
'gettext', 'jquery', 'underscore', 'backbone', 'edx-ui-toolkit/js/utils/string-utils', 'gettext', 'jquery', 'underscore', 'backbone', 'edx-ui-toolkit/js/utils/string-utils',
'edx-ui-toolkit/js/utils/html-utils', 'js/views/fields', 'js/views/image_field', 'backbone-super' 'edx-ui-toolkit/js/utils/html-utils', 'js/views/fields', 'js/views/image_field', 'backbone-super'
...@@ -27,18 +29,17 @@ ...@@ -27,18 +29,17 @@
this._super( this._super(
HtmlUtils.interpolateHtml( HtmlUtils.interpolateHtml(
gettext('You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}'), // eslint-disable-line max-len gettext('You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}'), // eslint-disable-line max-len
{'account_settings_page_link': accountSettingsLink} {account_settings_page_link: accountSettingsLink}
) )
); );
} else if (this.requiresParentalConsent) { } else if (this.requiresParentalConsent) {
this._super( this._super(
HtmlUtils.interpolateHtml( HtmlUtils.interpolateHtml(
gettext('You must be over 13 to share a full profile. If you are over 13, make sure that you have specified a birth year on the {account_settings_page_link}'), // eslint-disable-line max-len gettext('You must be over 13 to share a full profile. If you are over 13, make sure that you have specified a birth year on the {account_settings_page_link}'), // eslint-disable-line max-len
{'account_settings_page_link': accountSettingsLink} {account_settings_page_link: accountSettingsLink}
) )
); );
} } else {
else {
this._super(''); this._super('');
} }
}, },
...@@ -60,12 +61,13 @@ ...@@ -60,12 +61,13 @@
}, },
imageAltText: function() { imageAltText: function() {
return interpolate_text( return StringUtils.interpolate(
gettext('Profile image for {username}'), {username: this.model.get('username')} gettext('Profile image for {username}'),
{username: this.model.get('username')}
); );
}, },
imageChangeSucceeded: function(e, data) { imageChangeSucceeded: function() {
var view = this; var view = this;
// Update model to get the latest urls of profile image. // Update model to get the latest urls of profile image.
this.model.fetch().done(function() { this.model.fetch().done(function() {
...@@ -84,9 +86,10 @@ ...@@ -84,9 +86,10 @@
}, },
showImageChangeFailedMessage: function(status, responseText) { showImageChangeFailedMessage: function(status, responseText) {
var errors;
if (_.contains([400, 404], status)) { if (_.contains([400, 404], status)) {
try { try {
var errors = JSON.parse(responseText); errors = JSON.parse(responseText);
this.showErrorMessage(errors.user_message); this.showErrorMessage(errors.user_message);
} catch (error) { } catch (error) {
this.showErrorMessage(this.errorMessage); this.showErrorMessage(this.errorMessage);
......
(function(define, undefined) { (function(define) {
'use strict'; 'use strict';
define([
'gettext', 'jquery', 'underscore', 'backbone', 'edx-ui-toolkit/js/utils/html-utils', define(
'common/js/components/views/tabbed_view', [
'js/student_profile/views/section_two_tab', 'gettext', 'jquery', 'underscore', 'backbone', 'edx-ui-toolkit/js/utils/html-utils',
'text!templates/student_profile/learner_profile.underscore'], 'common/js/components/views/tabbed_view',
'learner_profile/js/views/section_two_tab',
'text!learner_profile/templates/learner_profile.underscore'
],
function(gettext, $, _, Backbone, HtmlUtils, TabbedView, SectionTwoTab, learnerProfileTemplate) { function(gettext, $, _, Backbone, HtmlUtils, TabbedView, SectionTwoTab, learnerProfileTemplate) {
var LearnerProfileView = Backbone.View.extend({ var LearnerProfileView = Backbone.View.extend({
initialize: function(options) { initialize: function(options) {
var Router;
this.options = _.extend({}, options); this.options = _.extend({}, options);
_.bindAll(this, 'showFullProfile', 'render', 'renderFields', 'showLoadingError'); _.bindAll(this, 'showFullProfile', 'render', 'renderFields', 'showLoadingError');
this.listenTo(this.options.preferencesModel, 'change:' + 'account_privacy', this.render); this.listenTo(this.options.preferencesModel, 'change:account_privacy', this.render);
var Router = Backbone.Router.extend({ Router = Backbone.Router.extend({
routes: {':about_me': 'loadTab', ':accomplishments': 'loadTab'} routes: {':about_me': 'loadTab', ':accomplishments': 'loadTab'}
}); });
...@@ -25,14 +29,15 @@ ...@@ -25,14 +29,15 @@
showFullProfile: function() { showFullProfile: function() {
var isAboveMinimumAge = this.options.accountSettingsModel.isAboveMinimumAge(); var isAboveMinimumAge = this.options.accountSettingsModel.isAboveMinimumAge();
if (this.options.ownProfile) { if (this.options.ownProfile) {
return isAboveMinimumAge && this.options.preferencesModel.get('account_privacy') === 'all_users'; return isAboveMinimumAge
&& this.options.preferencesModel.get('account_privacy') === 'all_users';
} else { } else {
return this.options.accountSettingsModel.get('profile_is_public'); return this.options.accountSettingsModel.get('profile_is_public');
} }
}, },
setActiveTab: function(tab) { setActiveTab: function(tab) {
// This tab may not actually exist. // This tab may not actually exist.
if (this.tabbedView.getTabMeta(tab).tab) { if (this.tabbedView.getTabMeta(tab).tab) {
this.tabbedView.setActiveTab(tab); this.tabbedView.setActiveTab(tab);
} }
...@@ -99,11 +104,14 @@ ...@@ -99,11 +104,14 @@
}, },
renderFields: function() { renderFields: function() {
var view = this; var view = this,
fieldView,
imageView,
settings;
if (this.options.ownProfile) { if (this.options.ownProfile) {
var fieldView = this.options.accountPrivacyFieldView, fieldView = this.options.accountPrivacyFieldView;
settings = this.options.accountSettingsModel; settings = this.options.accountSettingsModel;
fieldView.profileIsPrivate = !settings.get('year_of_birth'); fieldView.profileIsPrivate = !settings.get('year_of_birth');
fieldView.requiresParentalConsent = settings.get('requires_parental_consent'); fieldView.requiresParentalConsent = settings.get('requires_parental_consent');
fieldView.isAboveMinimumAge = settings.isAboveMinimumAge(); fieldView.isAboveMinimumAge = settings.isAboveMinimumAge();
...@@ -114,12 +122,12 @@ ...@@ -114,12 +122,12 @@
this.$('.profile-section-one-fields').append(this.options.usernameFieldView.render().el); this.$('.profile-section-one-fields').append(this.options.usernameFieldView.render().el);
var imageView = this.options.profileImageFieldView; imageView = this.options.profileImageFieldView;
this.$('.profile-image-field').append(imageView.render().el); this.$('.profile-image-field').append(imageView.render().el);
if (this.showFullProfile()) { if (this.showFullProfile()) {
_.each(this.options.sectionOneFieldViews, function(fieldView) { _.each(this.options.sectionOneFieldViews, function(childFieldView) {
view.$('.profile-section-one-fields').append(fieldView.render().el); view.$('.profile-section-one-fields').append(childFieldView.render().el);
}); });
} }
}, },
......
(function(define, undefined) { (function(define) {
'use strict'; 'use strict';
define([
'gettext', 'jquery', 'underscore', 'backbone', 'text!templates/student_profile/section_two.underscore'], define(
[
'gettext', 'jquery', 'underscore', 'backbone', 'text!learner_profile/templates/section_two.underscore'
],
function(gettext, $, _, Backbone, sectionTwoTemplate) { function(gettext, $, _, Backbone, sectionTwoTemplate) {
var SectionTwoTab = Backbone.View.extend({ var SectionTwoTab = Backbone.View.extend({
attributes: { attributes: {
'class': 'wrapper-profile-section-two' class: 'wrapper-profile-section-two'
}, },
template: _.template(sectionTwoTemplate), template: _.template(sectionTwoTemplate),
initialize: function(options) { initialize: function(options) {
......
(function(define, undefined) { (function(define) {
'use strict'; 'use strict';
define(['gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!templates/student_profile/share_modal.underscore'], define(
[
'gettext', 'jquery', 'underscore', 'backbone', 'moment',
'text!learner_profile/templates/share_modal.underscore'
],
function(gettext, $, _, Backbone, Moment, badgeModalTemplate) { function(gettext, $, _, Backbone, Moment, badgeModalTemplate) {
var ShareModalView = Backbone.View.extend({ var ShareModalView = Backbone.View.extend({
attributes: { attributes: {
'class': 'badges-overlay' class: 'badges-overlay'
}, },
template: _.template(badgeModalTemplate), template: _.template(badgeModalTemplate),
events: { events: {
'click .badges-modal': function(event) { event.stopPropagation(); }, 'click .badges-modal': function(event) { event.stopPropagation(); },
'click .badges-modal .close': 'close', 'click .badges-modal .close': 'close',
'click .badges-overlay': 'close', 'click .badges-overlay': 'close',
'keydown': 'keyAction', keydown: 'keyAction',
'focus .focusguard-start': 'focusGuardStart', 'focus .focusguard-start': 'focusGuardStart',
'focus .focusguard-end': 'focusGuardEnd' 'focus .focusguard-end': 'focusGuardEnd'
}, },
......
## mako
<%page expression_filter="h"/> <%page expression_filter="h"/>
<%inherit file="/main.html" /> <%inherit file="/main.html" />
<%def name="online_help_token()"><% return "profile" %></%def> <%def name="online_help_token()"><% return "profile" %></%def>
...@@ -26,7 +28,7 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json ...@@ -26,7 +28,7 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json
</%block> </%block>
<%block name="js_extra"> <%block name="js_extra">
<%static:require_module module_name="js/student_profile/views/learner_profile_factory" class_name="LearnerProfileFactory"> <%static:require_module module_name="learner_profile/js/learner_profile_factory" class_name="LearnerProfileFactory">
var options = ${data | n, dump_js_escaped_json}; var options = ${data | n, dump_js_escaped_json};
LearnerProfileFactory(options); LearnerProfileFactory(options);
</%static:require_module> </%static:require_module>
......
...@@ -5,11 +5,11 @@ from django.conf import settings ...@@ -5,11 +5,11 @@ from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
from django.test.client import RequestFactory from django.test.client import RequestFactory
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from student_profile.views import learner_profile_context
from util.testing import UrlResetMixin from util.testing import UrlResetMixin
from ..views import learner_profile_context
class LearnerProfileViewTest(UrlResetMixin, TestCase): class LearnerProfileViewTest(UrlResetMixin, TestCase):
""" Tests for the student profile view. """ """ Tests for the student profile view. """
......
"""
Defines URLs for the learner profile.
"""
from django.conf import settings
from django.conf.urls import url
urlpatterns = [
url(
r'^{username_pattern}$'.format(
username_pattern=settings.USERNAME_PATTERN,
),
'openedx.features.learner_profile.views.learner_profile',
name='learner_profile',
),
]
""" Views for a student's profile information. """ """ Views for a student's profile information. """
from badges.utils import badges_enabled
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.staticfiles.storage import staticfiles_storage from django.contrib.staticfiles.storage import staticfiles_storage
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import Http404 from django.http import Http404
from django.shortcuts import render_to_response
from django.views.decorators.http import require_http_methods from django.views.decorators.http import require_http_methods
from django_countries import countries from django_countries import countries
from edxmako.shortcuts import marketing_link
from badges.utils import badges_enabled
from edxmako.shortcuts import marketing_link, render_to_response
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.user_api.accounts.api import get_account_settings from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
from openedx.core.djangoapps.user_api.errors import UserNotAuthorized, UserNotFound from openedx.core.djangoapps.user_api.errors import UserNotAuthorized, UserNotFound
...@@ -39,7 +39,7 @@ def learner_profile(request, username): ...@@ -39,7 +39,7 @@ def learner_profile(request, username):
""" """
try: try:
return render_to_response( return render_to_response(
'student_profile/learner_profile.html', 'learner_profile/learner_profile.html',
learner_profile_context(request, username, request.user.is_staff) learner_profile_context(request, username, request.user.is_staff)
) )
except (UserNotAuthorized, UserNotFound, ObjectDoesNotExist): except (UserNotAuthorized, UserNotFound, ObjectDoesNotExist):
......
...@@ -12,7 +12,7 @@ set -e ...@@ -12,7 +12,7 @@ set -e
# Violations thresholds for failing the build # Violations thresholds for failing the build
export PYLINT_THRESHOLD=3600 export PYLINT_THRESHOLD=3600
export ESLINT_THRESHOLD=10122 export ESLINT_THRESHOLD=9190
XSSLINT_THRESHOLDS=`cat scripts/xsslint_thresholds.json` XSSLINT_THRESHOLDS=`cat scripts/xsslint_thresholds.json`
export XSSLINT_THRESHOLDS=${XSSLINT_THRESHOLDS//[[:space:]]/} export XSSLINT_THRESHOLDS=${XSSLINT_THRESHOLDS//[[:space:]]/}
......
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