From 9f88427f9bd75a803c6a49fd7936128a67365d30 Mon Sep 17 00:00:00 2001 From: Harry Rein Date: Tue, 15 Aug 2017 16:23:06 -0400 Subject: [PATCH] Add social links to learner profile. LEARNER-1859 Added fields to add social links to the user account settings file. Added icons to the user profile when these links are set, only shown when users show their entire profile. Added jasmine tests for account settings and learner profile pages. Added python unit tests to test validation on the user account. --- .../student/migrations/0012_sociallink.py | 23 +++++ common/djangoapps/student/models.py | 15 ++++ .../tests/lms/test_account_settings.py | 21 +++++ lms/envs/common.py | 28 ++++++ .../account_settings_fields_spec.js | 36 ++++---- .../account_settings_view_spec.js | 18 ++-- lms/static/js/spec/student_account/helpers.js | 19 ++++ .../models/user_account_model.js | 1 + .../views/account_settings_factory.js | 41 +++++++-- .../views/account_settings_fields.js | 33 +++++++ lms/static/js/views/fields.js | 3 +- .../sass/features/_learner-profile.scss | 38 ++++++-- lms/static/sass/views/_account-settings.scss | 11 +-- .../fields/field_text_account.underscore | 2 +- .../student_account/account_settings.html | 6 +- .../account_settings_section.underscore | 2 +- .../core/djangoapps/user_api/accounts/api.py | 6 +- .../user_api/accounts/serializers.py | 85 +++++++++++++++--- .../user_api/accounts/tests/test_api.py | 1 + .../user_api/accounts/tests/test_utils.py | 52 +++++++++++ .../user_api/accounts/tests/test_views.py | 20 ++--- .../djangoapps/user_api/accounts/utils.py | 90 +++++++++++++++++++ .../djangoapps/user_api/accounts/views.py | 6 ++ .../js/learner_profile_factory.js | 6 ++ .../spec/views/learner_profile_fields_spec.js | 83 +++++++++++++++++ .../spec/views/learner_profile_view_spec.js | 6 ++ .../js/spec_helpers/helpers.js | 16 +++- .../js/views/learner_profile_fields.js | 39 +++++++- .../templates/social_icons.underscore | 9 ++ openedx/features/learner_profile/views.py | 1 + 30 files changed, 638 insertions(+), 79 deletions(-) create mode 100644 common/djangoapps/student/migrations/0012_sociallink.py create mode 100644 openedx/core/djangoapps/user_api/accounts/tests/test_utils.py create mode 100644 openedx/core/djangoapps/user_api/accounts/utils.py create mode 100644 openedx/features/learner_profile/static/learner_profile/templates/social_icons.underscore diff --git a/common/djangoapps/student/migrations/0012_sociallink.py b/common/djangoapps/student/migrations/0012_sociallink.py new file mode 100644 index 0000000000..9e98824b63 --- /dev/null +++ b/common/djangoapps/student/migrations/0012_sociallink.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('student', '0011_course_key_field_to_foreign_key'), + ] + + operations = [ + migrations.CreateModel( + name='SocialLink', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('platform', models.CharField(max_length=30)), + ('social_link', models.CharField(max_length=100, blank=True)), + ('user_profile', models.ForeignKey(related_name='social_links', to='student.UserProfile')), + ], + ), + ] diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 580b00bd70..74a9748260 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -2374,6 +2374,21 @@ class LanguageProficiency(models.Model): ) +class SocialLink(models.Model): # pylint: disable=model-missing-unicode + """ + Represents a URL connecting a particular social platform to a user's social profile. + + The platforms are listed in the lms/common.py file under SOCIAL_PLATFORMS. + Each entry has a display name, a url_stub that describes a required + component of the stored URL and an example of a valid URL. + + The stored social_link value must adhere to the form 'https://www.[url_stub][username]'. + """ + user_profile = models.ForeignKey(UserProfile, db_index=True, related_name='social_links') + platform = models.CharField(max_length=30) + social_link = models.CharField(max_length=100, blank=True) + + class CourseEnrollmentAttribute(models.Model): """ Provide additional information about the user's enrollment. diff --git a/common/test/acceptance/tests/lms/test_account_settings.py b/common/test/acceptance/tests/lms/test_account_settings.py index 9a0eeda4b6..3a79f57955 100644 --- a/common/test/acceptance/tests/lms/test_account_settings.py +++ b/common/test/acceptance/tests/lms/test_account_settings.py @@ -124,6 +124,7 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, AcceptanceTest): """ super(AccountSettingsPageTest, self).setUp() self.full_name = XSS_INJECTION + self.social_link = '' self.username, self.user_id = self.log_in_as_unique_user(full_name=self.full_name) self.visit_account_settings_page() @@ -177,6 +178,14 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, AcceptanceTest): 'Year of Birth', 'Preferred Language', ] + }, + { + 'title': 'Social Media Links', + 'fields': [ + 'Twitter Link', + 'Facebook Link', + 'LinkedIn Link', + ] } ] @@ -463,6 +472,18 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, AcceptanceTest): actual_events ) + def test_social_links_field(self): + """ + Test behaviour of one of the social media links field. + """ + self._test_text_field( + u'social_links', + u'Twitter Link', + self.social_link, + u'www.google.com/invalidlink', + [u'https://www.twitter.com/edX', self.social_link], + ) + def test_linked_accounts(self): """ Test that fields for third party auth providers exist. diff --git a/lms/envs/common.py b/lms/envs/common.py index 9a63804cb6..b20d06c969 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2931,6 +2931,7 @@ ACCOUNT_VISIBILITY_CONFIGURATION = { 'date_joined', 'language_proficiencies', 'bio', + 'social_links', 'account_privacy', # Not an actual field, but used to signal whether badges should be public. 'accomplishments_shared', @@ -2953,6 +2954,7 @@ ACCOUNT_VISIBILITY_CONFIGURATION = { "date_joined", "profile_image", "language_proficiencies", + "social_links", "name", "gender", "goals", @@ -2965,6 +2967,32 @@ ACCOUNT_VISIBILITY_CONFIGURATION = { ] } +# The current list of social platforms to be shown to the user. +# +# url_stub represents the host URL, it must end with a forward +# slash and represent the profile at https://www.[url_stub][username] +# +# The example will be used as a placeholder in the social link +# input field as well as in some messaging describing an example of a +# valid link. +SOCIAL_PLATFORMS = { + 'facebook': { + 'display_name': 'Facebook', + 'url_stub': 'facebook.com/', + 'example': 'https://www.facebook.com/username' + }, + 'twitter': { + 'display_name': 'Twitter', + 'url_stub': 'twitter.com/', + 'example': 'https://www.twitter.com/username' + }, + 'linkedin': { + 'display_name': 'LinkedIn', + 'url_stub': 'linkedin.com/in/', + 'example': 'www.linkedin.com/in/username' + } +} + # E-Commerce API Configuration ECOMMERCE_PUBLIC_URL_ROOT = None ECOMMERCE_API_URL = None diff --git a/lms/static/js/spec/student_account/account_settings_fields_spec.js b/lms/static/js/spec/student_account/account_settings_fields_spec.js index 165e80a66c..d9b1110b28 100644 --- a/lms/static/js/spec/student_account/account_settings_fields_spec.js +++ b/lms/static/js/spec/student_account/account_settings_fields_spec.js @@ -1,21 +1,23 @@ define(['backbone', - 'jquery', - 'underscore', - 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', - 'common/js/spec_helpers/template_helpers', - 'js/views/fields', - 'js/spec/views/fields_helpers', - 'js/spec/student_account/account_settings_fields_helpers', - 'js/student_account/views/account_settings_fields', - 'js/student_account/models/user_account_model', - 'string_utils'], - function(Backbone, $, _, AjaxHelpers, TemplateHelpers, FieldViews, FieldViewsSpecHelpers, + 'jquery', + 'underscore', + 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', + 'common/js/spec_helpers/template_helpers', + 'js/student_account/models/user_account_model', + 'js/views/fields', + 'js/spec/views/fields_helpers', + 'js/spec/student_account/account_settings_fields_helpers', + 'js/student_account/views/account_settings_fields', + 'js/student_account/models/user_account_model', + 'string_utils'], + function(Backbone, $, _, AjaxHelpers, TemplateHelpers, UserAccountModel, FieldViews, FieldViewsSpecHelpers, AccountSettingsFieldViewSpecHelpers, AccountSettingsFieldViews) { 'use strict'; describe('edx.AccountSettingsFieldViews', function() { var requests, - timerCallback; + timerCallback, // eslint-disable-line no-unused-vars + data; beforeEach(function() { timerCallback = jasmine.createSpy('timerCallback'); @@ -40,7 +42,7 @@ define(['backbone', view.$('.u-field-value > button').click(); expect(view.$('.u-field-value > button').is(':disabled')).toBe(true); AjaxHelpers.expectRequest(requests, 'POST', '/password_reset', 'email=legolas%40woodland.middlearth'); - AjaxHelpers.respondWithJson(requests, {'success': 'true'}); + AjaxHelpers.respondWithJson(requests, {success: 'true'}); FieldViewsSpecHelpers.expectMessageContains( view, "We've sent a message to legolas@woodland.middlearth. " + @@ -130,7 +132,7 @@ define(['backbone', var view = new AccountSettingsFieldViews.LanguagePreferenceFieldView(fieldData).render(); - var data = {'language': FieldViewsSpecHelpers.SELECT_OPTIONS[2][0]}; + data = {language: FieldViewsSpecHelpers.SELECT_OPTIONS[2][0]}; view.$(selector).val(data[fieldData.valueAttribute]).change(); view.$(selector).focusout(); FieldViewsSpecHelpers.expectAjaxRequestWithData(requests, data); @@ -145,7 +147,7 @@ define(['backbone', AjaxHelpers.respondWithNoContent(requests); FieldViewsSpecHelpers.expectMessageContains(view, 'Your changes have been saved.'); - data = {'language': FieldViewsSpecHelpers.SELECT_OPTIONS[1][0]}; + data = {language: FieldViewsSpecHelpers.SELECT_OPTIONS[1][0]}; view.$(selector).val(data[fieldData.valueAttribute]).change(); view.$(selector).focusout(); FieldViewsSpecHelpers.expectAjaxRequestWithData(requests, data); @@ -173,13 +175,13 @@ define(['backbone', options: FieldViewsSpecHelpers.SELECT_OPTIONS, persistChanges: true }); - fieldData.model.set({'language_proficiencies': [{'code': FieldViewsSpecHelpers.SELECT_OPTIONS[0][0]}]}); + fieldData.model.set({language_proficiencies: [{code: FieldViewsSpecHelpers.SELECT_OPTIONS[0][0]}]}); var view = new AccountSettingsFieldViews.LanguageProficienciesFieldView(fieldData).render(); expect(view.modelValue()).toBe(FieldViewsSpecHelpers.SELECT_OPTIONS[0][0]); - var data = {'language_proficiencies': [{'code': FieldViewsSpecHelpers.SELECT_OPTIONS[1][0]}]}; + data = {language_proficiencies: [{code: FieldViewsSpecHelpers.SELECT_OPTIONS[1][0]}]}; view.$(selector).val(FieldViewsSpecHelpers.SELECT_OPTIONS[1][0]).change(); view.$(selector).focusout(); FieldViewsSpecHelpers.expectAjaxRequestWithData(requests, data); diff --git a/lms/static/js/spec/student_account/account_settings_view_spec.js b/lms/static/js/spec/student_account/account_settings_view_spec.js index f171762b53..d97eebc341 100644 --- a/lms/static/js/spec/student_account/account_settings_view_spec.js +++ b/lms/static/js/spec/student_account/account_settings_view_spec.js @@ -1,13 +1,13 @@ define(['backbone', - 'jquery', - 'underscore', - 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', - 'common/js/spec_helpers/template_helpers', - 'js/spec/student_account/helpers', - 'js/views/fields', - 'js/student_account/models/user_account_model', - 'js/student_account/views/account_settings_view' - ], + 'jquery', + 'underscore', + 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', + 'common/js/spec_helpers/template_helpers', + 'js/spec/student_account/helpers', + 'js/views/fields', + 'js/student_account/models/user_account_model', + 'js/student_account/views/account_settings_view' +], function(Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, FieldViews, UserAccountModel, AccountSettingsView) { 'use strict'; diff --git a/lms/static/js/spec/student_account/helpers.js b/lms/static/js/spec/student_account/helpers.js index 23df61438f..a03ac6aaa9 100644 --- a/lms/static/js/spec/student_account/helpers.js +++ b/lms/static/js/spec/student_account/helpers.js @@ -65,6 +65,23 @@ define(['underscore'], function(_) { }; var IMAGE_MAX_BYTES = 1024 * 1024; var IMAGE_MIN_BYTES = 100; + var SOCIAL_PLATFORMS = { + facebook: { + display_name: 'Facebook', + url_stub: 'facebook.com/', + example: 'https://www.facebook.com/username' + }, + twitter: { + display_name: 'Twitter', + url_stub: 'twitter.com/', + example: 'https://www.twitter.com/username' + }, + linkedin: { + display_name: 'LinkedIn', + url_stub: 'linkedin.com/in/', + example: 'https://www.linkedin.com/in/username' + } + }; var DEFAULT_ACCOUNT_SETTINGS_DATA = { username: 'student', name: 'Student', @@ -77,6 +94,7 @@ define(['underscore'], function(_) { language: 'en-US', date_joined: 'December 17, 1995 03:24:00', bio: 'About the student', + social_links: [{platform: 'facebook', social_link: 'https://www.facebook.com/edX'}], language_proficiencies: [{code: '1'}], profile_image: PROFILE_IMAGE, accomplishments_shared: false @@ -170,6 +188,7 @@ define(['underscore'], function(_) { AUTH_DATA: AUTH_DATA, IMAGE_MAX_BYTES: IMAGE_MAX_BYTES, IMAGE_MIN_BYTES: IMAGE_MIN_BYTES, + SOCIAL_PLATFORMS: SOCIAL_PLATFORMS, createAccountSettingsData: createAccountSettingsData, createUserPreferencesData: createUserPreferencesData, expectLoadingIndicatorIsVisible: expectLoadingIndicatorIsVisible, diff --git a/lms/static/js/student_account/models/user_account_model.js b/lms/static/js/student_account/models/user_account_model.js index 4f9293b92f..da40216eda 100644 --- a/lms/static/js/student_account/models/user_account_model.js +++ b/lms/static/js/student_account/models/user_account_model.js @@ -19,6 +19,7 @@ mailing_address: '', year_of_birth: null, bio: null, + social_links: [], language_proficiencies: [], requires_parental_consent: true, profile_image: null, diff --git a/lms/static/js/student_account/views/account_settings_factory.js b/lms/static/js/student_account/views/account_settings_factory.js index b88a1223da..30e3440bc9 100644 --- a/lms/static/js/student_account/views/account_settings_factory.js +++ b/lms/static/js/student_account/views/account_settings_factory.js @@ -19,14 +19,15 @@ accountUserId, platformName, contactEmail, - allowEmailChange + allowEmailChange, + socialPlatforms ) { - var accountSettingsElement, userAccountModel, userPreferencesModel, aboutSectionsData, + var $accountSettingsElement, userAccountModel, userPreferencesModel, aboutSectionsData, accountsSectionData, ordersSectionData, accountSettingsView, showAccountSettingsPage, showLoadingError, orderNumber, getUserField, userFields, timeZoneDropdownField, countryDropdownField, - emailFieldView; + emailFieldView, socialFields, platformData; - accountSettingsElement = $('.wrapper-account-settings'); + $accountSettingsElement = $('.wrapper-account-settings'); userAccountModel = new UserAccountModel(); userAccountModel.url = userAccountsApiUrl; @@ -64,7 +65,7 @@ aboutSectionsData = [ { title: gettext('Basic Account Information'), - subtitle: gettext('These settings include basic information about your account. You can also specify additional information and see your linked social accounts on this page.'), // eslint-disable-line max-len + subtitle: gettext('These settings include basic information about your account.'), fields: [ { view: new AccountSettingsFieldViews.ReadonlyFieldView({ @@ -191,6 +192,34 @@ } ]; + // Add the social link fields + socialFields = { + title: gettext('Social Media Links'), + subtitle: gettext('Optionally, link your personal accounts to the social media icons on your edX profile.'), // eslint-disable-line max-len + fields: [] + }; + + for (var socialPlatform in socialPlatforms) { // eslint-disable-line guard-for-in, no-restricted-syntax, vars-on-top, max-len + platformData = socialPlatforms[socialPlatform]; + socialFields.fields.push( + { + view: new AccountSettingsFieldViews.SocialLinkTextFieldView({ + model: userAccountModel, + title: gettext(platformData.display_name + ' Link'), + valueAttribute: 'social_links', + helpMessage: gettext( + 'Enter your ' + platformData.display_name + ' username or the URL to your ' + + platformData.display_name + ' page. Delete the URL to remove the link.' + ), + platform: socialPlatform, + persistChanges: true, + placeholder: platformData.example + }) + } + ); + } + aboutSectionsData.push(socialFields); + // set TimeZoneField to listen to CountryField getUserField = function(list, search) { return _.find(list, function(field) { @@ -266,7 +295,7 @@ accountSettingsView = new AccountSettingsView({ model: userAccountModel, accountUserId: accountUserId, - el: accountSettingsElement, + el: $accountSettingsElement, tabSections: { aboutTabSections: aboutSectionsData, accountsTabSections: accountsSectionData, diff --git a/lms/static/js/student_account/views/account_settings_fields.js b/lms/static/js/student_account/views/account_settings_fields.js index 88d229a747..77123c66fd 100644 --- a/lms/static/js/student_account/views/account_settings_fields.js +++ b/lms/static/js/student_account/views/account_settings_fields.js @@ -224,6 +224,39 @@ } } }), + SocialLinkTextFieldView: FieldViews.TextFieldView.extend({ + render: function() { + HtmlUtils.setHtml(this.$el, HtmlUtils.template(field_text_account_template)({ + id: this.options.valueAttribute + '_' + this.options.platform, + title: this.options.title, + value: this.modelValue(), + message: this.options.helpMessage, + placeholder: this.options.placeholder || '' + })); + this.delegateEvents(); + return this; + }, + + modelValue: function() { + var socialLinks = this.model.get(this.options.valueAttribute); + for (var i = 0; i < socialLinks.length; i++) { // eslint-disable-line vars-on-top + if (socialLinks[i].platform === this.options.platform) { + return socialLinks[i].social_link; + } + } + return null; + }, + saveValue: function() { + var attributes, value; + if (this.persistChanges === true) { + attributes = {}; + value = this.fieldValue() != null ? [{platform: this.options.platform, + social_link: this.fieldValue()}] : []; + attributes[this.options.valueAttribute] = value; + this.saveAttributes(attributes); + } + } + }), AuthFieldView: FieldViews.LinkFieldView.extend({ fieldTemplate: field_social_link_template, className: function() { diff --git a/lms/static/js/views/fields.js b/lms/static/js/views/fields.js index 06215c8280..9376d887d2 100644 --- a/lms/static/js/views/fields.js +++ b/lms/static/js/views/fields.js @@ -367,7 +367,8 @@ id: this.options.valueAttribute, title: this.options.title, value: this.modelValue(), - message: this.helpMessage + message: this.helpMessage, + placeholder: this.options.placeholder || '' })); this.delegateEvents(); return this; diff --git a/lms/static/sass/features/_learner-profile.scss b/lms/static/sass/features/_learner-profile.scss index c5ab800d33..33a1305462 100644 --- a/lms/static/sass/features/_learner-profile.scss +++ b/lms/static/sass/features/_learner-profile.scss @@ -195,6 +195,10 @@ .profile-header { @include padding(0, $baseline*2, $baseline, $baseline*3); + @media (max-width: $learner-profile-container-flex) { // Switch to map-get($grid-breakpoints,md) for bootstrap + @include padding(0, $baseline*2, $baseline, $baseline*0.75); + } + .header { @extend %t-title4; @extend %t-ultrastrong; @@ -221,11 +225,34 @@ } .profile-section-one-fields { - margin: 0 $baseline/2; + @include margin(0, $baseline/2, 0, $baseline*0.75); + + .social-links { + font-size: 2rem; + padding-top: $baseline/4; + + & > span { + color: $gray-l4; + } + + a { + .fa-facebook-square { + color: $facebook-blue; + } + + .fa-twitter-square { + color: $twitter-blue; + } + + .fa-linkedin-square { + color: $linkedin-blue; + } + } + } .u-field { @extend %t-weight4; - @include padding(0, 0, 0, 3px); + padding: 0; color: $base-font-color; margin-top: $baseline/5; @@ -297,18 +324,19 @@ .wrapper-profile-section-container-two { @include float(left); - width: calc(100% - 360px); + @include padding-left($baseline); + width: calc(100% - 380px); max-width: $learner-profile-container-flex; // Switch to map-get($grid-breakpoints,md) for bootstrap - padding-left: $baseline; @media (max-width: $learner-profile-container-flex) { // Switch to map-get($grid-breakpoints,md) for bootstrap + @include padding-left(0); width: 100%; margin-top: $baseline; } .u-field-textarea { margin-bottom: ($baseline/2); - padding: 0 ($baseline*.75) ($baseline*.75) ($baseline/4); + @include padding(0, ($baseline*.75), ($baseline*.75), ($baseline/4)); .u-field-header { position: relative; diff --git a/lms/static/sass/views/_account-settings.scss b/lms/static/sass/views/_account-settings.scss index 67a5d4759b..8cbdd9df0c 100644 --- a/lms/static/sass/views/_account-settings.scss +++ b/lms/static/sass/views/_account-settings.scss @@ -94,7 +94,7 @@ .account-settings-sections { .section-header { - @extend %t-title6; + @extend %t-title5; @extend %t-strong; padding-top: ($baseline/2)*3; color: $dark-gray1; @@ -102,14 +102,13 @@ .section { background-color: $white; - margin-top: $baseline; + margin: $baseline 5% 0; border-bottom: 4px solid $m-gray-l4; .account-settings-header-subtitle { - font-size: em(18); + font-size: em(14); line-height: normal; color: $dark-gray; - padding-top: 20px; padding-bottom: 10px; } @@ -117,6 +116,7 @@ .u-field { border-bottom: 2px solid $m-gray-l4; + padding: $baseline*0.75 0; .field { width: 30%; @@ -301,7 +301,8 @@ .u-field-message { position: relative; - padding: 24px 0 0 ($baseline*5); + padding: $baseline*0.75 0 0 ($baseline*4); + width: 60%; .u-field-message-notification { position: absolute; diff --git a/lms/templates/fields/field_text_account.underscore b/lms/templates/fields/field_text_account.underscore index 18133ea2eb..0c4f8a1ae1 100644 --- a/lms/templates/fields/field_text_account.underscore +++ b/lms/templates/fields/field_text_account.underscore @@ -1,6 +1,6 @@
- +
diff --git a/lms/templates/student_account/account_settings.html b/lms/templates/student_account/account_settings.html index 5c92f0577c..de271d908c 100644 --- a/lms/templates/student_account/account_settings.html +++ b/lms/templates/student_account/account_settings.html @@ -37,7 +37,8 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str authData = ${ auth | n, dump_js_escaped_json }, platformName = '${ static.get_platform_name() | n, js_escaped_string }', contactEmail = '${ static.get_contact_email_address() | n, js_escaped_string }', - allowEmailChange = ${ bool(settings.FEATURES['ALLOW_EMAIL_ADDRESS_CHANGE']) | n, dump_js_escaped_json }; + allowEmailChange = ${ bool(settings.FEATURES['ALLOW_EMAIL_ADDRESS_CHANGE']) | n, dump_js_escaped_json }, + socialPlatforms = ${ settings.SOCIAL_PLATFORMS | n, dump_js_escaped_json }; AccountSettingsFactory( fieldsData, @@ -49,7 +50,8 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str ${ user.id | n, dump_js_escaped_json }, platformName, contactEmail, - allowEmailChange + allowEmailChange, + socialPlatforms ); diff --git a/lms/templates/student_account/account_settings_section.underscore b/lms/templates/student_account/account_settings_section.underscore index f99d41f278..11bbbfef82 100644 --- a/lms/templates/student_account/account_settings_section.underscore +++ b/lms/templates/student_account/account_settings_section.underscore @@ -3,10 +3,10 @@ <% _.each(sections, function(section) { %>
+

<%- gettext(section.title) %>

<% if (section.subtitle) { %> <% } %> -

<%- gettext(section.title) %>