UX improvements on learner profile.

LEARNER-1857

This story constitutes a large change to the UX of the learner profile.

Some specific changes include adding a flexible learner profile card, limiting the bio entry to only 300 characters and assuring that the page is responsive.
This commit is contained in:
Harry Rein
2017-07-25 15:30:42 -04:00
parent ed4a831f57
commit e8bae62f04
21 changed files with 292 additions and 142 deletions

View File

@@ -114,11 +114,8 @@ class CourseHomeMessageFragmentView(EdxFragmentView):
CourseHomeMessages.register_info_message(
request,
Text(_(
"{add_reminder_open_tag}Don't forget to add a calendar reminder!{add_reminder_close_tag}."
)).format(
add_reminder_open_tag='',
add_reminder_close_tag=''
),
"Don't forget to add a calendar reminder!"
)),
title=Text("Course starts in {days_until_start_string} on {course_start_date}.").format(
days_until_start_string=course_start_data['days_until_start_string'],
course_start_date=course_start_data['course_start_date']

View File

@@ -48,6 +48,7 @@
var accountPrivacyFieldView,
profileImageFieldView,
usernameFieldView,
nameFieldView,
sectionOneFieldViews,
sectionTwoFieldViews,
BadgeCollection,
@@ -65,10 +66,7 @@
required: true,
editable: 'always',
showMessages: false,
title: StringUtils.interpolate(
gettext('{platform_name} learners can see my:'),
{platform_name: options.platform_name}
),
title: gettext('Profile Visibility:'),
valueAttribute: 'account_privacy',
options: [
['private', gettext('Limited Profile')],
@@ -97,29 +95,37 @@
helpMessage: ''
});
nameFieldView = new FieldsView.ReadonlyFieldView({
model: accountSettingsModel,
screenReaderTitle: gettext('Full Name'),
valueAttribute: 'name',
helpMessage: ''
});
sectionOneFieldViews = [
new FieldsView.DropdownFieldView({
title: gettext('Location'),
titleVisible: true,
model: accountSettingsModel,
screenReaderTitle: gettext('Country'),
titleVisible: false,
required: true,
editable: editable,
showMessages: false,
iconName: 'fa-map-marker',
placeholderValue: gettext('Add Country'),
valueAttribute: 'country',
options: options.country_options,
helpMessage: '',
persistChanges: true
}),
new AccountSettingsFieldViews.LanguageProficienciesFieldView({
title: gettext('Language'),
titleVisible: true,
model: accountSettingsModel,
screenReaderTitle: gettext('Preferred Language'),
titleVisible: false,
required: false,
editable: editable,
showMessages: false,
iconName: 'fa-comment',
placeholderValue: gettext('Add language'),
valueAttribute: 'language_proficiencies',
options: options.language_options,
@@ -139,7 +145,8 @@
valueAttribute: 'bio',
helpMessage: '',
persistChanges: true,
messagePosition: 'header'
messagePosition: 'header',
maxCharacters: 300
})
];
@@ -172,9 +179,11 @@
accountPrivacyFieldView: accountPrivacyFieldView,
profileImageFieldView: profileImageFieldView,
usernameFieldView: usernameFieldView,
nameFieldView: nameFieldView,
sectionOneFieldViews: sectionOneFieldViews,
sectionTwoFieldViews: sectionTwoFieldViews,
badgeListContainer: badgeListContainer
badgeListContainer: badgeListContainer,
platformName: options.platform_name
});
getProfileVisibility = function() {

View File

@@ -1,6 +1,7 @@
/* eslint-disable vars-on-top */
define(
[
'gettext',
'backbone',
'jquery',
'underscore',
@@ -18,7 +19,7 @@ define(
'js/student_account/views/account_settings_fields',
'js/views/message_banner'
],
function(Backbone, $, _, PagingCollection, AjaxHelpers, TemplateHelpers, Helpers, LearnerProfileHelpers,
function(gettext, Backbone, $, _, PagingCollection, AjaxHelpers, TemplateHelpers, Helpers, LearnerProfileHelpers,
FieldViews, UserAccountModel, AccountPreferencesModel, LearnerProfileFields, LearnerProfileView,
BadgeListContainer, AccountSettingsFieldViews, MessageBannerView) {
'use strict';
@@ -73,13 +74,19 @@ define(
helpMessage: ''
});
var nameFieldView = new FieldViews.ReadonlyFieldView({
model: accountSettingsModel,
valueAttribute: 'name',
helpMessage: ''
});
var sectionOneFieldViews = [
new FieldViews.DropdownFieldView({
title: gettext('Location'),
model: accountSettingsModel,
required: false,
editable: editable,
showMessages: false,
iconName: 'fa-map-marker',
placeholderValue: '',
valueAttribute: 'country',
options: Helpers.FIELD_OPTIONS,
@@ -87,11 +94,11 @@ define(
}),
new AccountSettingsFieldViews.LanguageProficienciesFieldView({
title: gettext('Language'),
model: accountSettingsModel,
required: false,
editable: editable,
showMessages: false,
iconName: 'fa-comment',
placeholderValue: 'Add language',
valueAttribute: 'language_proficiencies',
options: Helpers.FIELD_OPTIONS,
@@ -131,6 +138,7 @@ define(
preferencesModel: accountPreferencesModel,
accountPrivacyFieldView: accountPrivacyFieldView,
usernameFieldView: usernameFieldView,
nameFieldView: nameFieldView,
profileImageFieldView: profileImageFieldView,
sectionOneFieldViews: sectionOneFieldViews,
sectionTwoFieldViews: sectionTwoFieldViews,

View File

@@ -65,7 +65,7 @@ define(
view.render();
var bio = view.$el.find('.u-field-bio');
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(_.count(msg.html(), messageString)).toBeTruthy();
};

View File

@@ -41,11 +41,12 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
var expectSectionOneTobeRendered = function(learnerProfileView) {
var sectionOneFieldElements = $(learnerProfileView.$('.wrapper-profile-section-one')).find('.u-field');
expect(sectionOneFieldElements.length).toBe(4);
expect(sectionOneFieldElements.length).toBe(5);
expectProfileElementContainsField(sectionOneFieldElements[0], learnerProfileView.options.profileImageFieldView);
expectProfileElementContainsField(sectionOneFieldElements[1], learnerProfileView.options.usernameFieldView);
expectProfileElementContainsField(sectionOneFieldElements[2], learnerProfileView.options.nameFieldView);
_.each(_.rest(sectionOneFieldElements, 2), function(sectionFieldElement, fieldIndex) {
_.each(_.rest(sectionOneFieldElements, 3), function(sectionFieldElement, fieldIndex) {
expectProfileElementContainsField(
sectionFieldElement,
learnerProfileView.options.sectionOneFieldViews[fieldIndex]
@@ -89,10 +90,10 @@ define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
);
if (othersProfile) {
expect($('.profile-private--message').text())
expect($('.profile-private-message').text())
.toBe('This learner is currently sharing a limited profile.');
} else {
expect($('.profile-private--message').text()).toBe('You are currently sharing a limited profile.');
expect($('.profile-private-message').text()).toBe('You are currently sharing a limited profile.');
}
};

View File

@@ -6,9 +6,10 @@
'gettext', 'jquery', 'underscore', 'backbone', 'edx-ui-toolkit/js/utils/html-utils',
'common/js/components/views/tabbed_view',
'learner_profile/js/views/section_two_tab',
'text!learner_profile/templates/learner_profile.underscore'
'text!learner_profile/templates/learner_profile.underscore',
'edx-ui-toolkit/js/utils/string-utils'
],
function(gettext, $, _, Backbone, HtmlUtils, TabbedView, SectionTwoTab, learnerProfileTemplate) {
function(gettext, $, _, Backbone, HtmlUtils, TabbedView, SectionTwoTab, learnerProfileTemplate, StringUtils) {
var LearnerProfileView = Backbone.View.extend({
initialize: function(options) {
@@ -53,10 +54,19 @@
ownProfile: this.options.ownProfile
});
HtmlUtils.setHtml(this.$el, HtmlUtils.template(learnerProfileTemplate)({
username: self.options.accountSettingsModel.get('username'),
name: self.options.accountSettingsModel.get('name'),
ownProfile: self.options.ownProfile,
showFullProfile: self.showFullProfile()
showFullProfile: self.showFullProfile(),
profile_header: gettext('My Profile'),
profile_subheader:
StringUtils.interpolate(
gettext('Build out your profile to personalize your identity on {platform_name}.'), {
platform_name: self.options.platformName
}
)
}));
this.renderFields();
@@ -98,7 +108,7 @@
Backbone.history.start();
}
} else {
this.$el.find('.account-settings-container').append(this.sectionTwoView.render().el);
this.$el.find('.wrapper-profile-section-container-two').append(this.sectionTwoView.render().el);
}
return this;
},
@@ -120,6 +130,10 @@
fieldView.delegateEvents();
}
// Do not show name when in limited mode or no name has been set
if (this.showFullProfile() && this.options.accountSettingsModel.get('name')) {
this.$('.profile-section-one-fields').append(this.options.nameFieldView.render().el);
}
this.$('.profile-section-one-fields').append(this.options.usernameFieldView.render().el);
imageView = this.options.profileImageFieldView;

View File

@@ -1,15 +1,25 @@
<div class="profile <%- ownProfile ? 'profile-self' : 'profile-other' %>">
<div class="wrapper-profile-field-account-privacy"></div>
<div class="wrapper-profile-sections account-settings-container">
<div class="wrapper-profile-section-one">
<div class="profile-image-field">
<% if (ownProfile) { %>
<div class="profile-header">
<div class="header"> <%- profile_header %></div>
<div class="subheader"> <%- profile_subheader %></div>
</div>
<div class="profile-section-one-fields">
<% } %>
<div class="wrapper-profile-section-container-one">
<div class="wrapper-profile-section-one">
<div class="profile-image-field">
</div>
<div class="profile-section-one-fields">
</div>
</div>
<div class="ui-loading-error is-hidden">
<span class="fa fa-exclamation-triangle message-error" aria-hidden="true"></span>
<span class="copy"><%- gettext("An error occurred. Try loading the page again.") %></span>
</div>
</div>
<div class="ui-loading-error is-hidden">
<span class="fa fa-exclamation-triangle message-error" aria-hidden="true"></span>
<span class="copy"><%- gettext("An error occurred. Try loading the page again.") %></span>
<div class="wrapper-profile-section-container-two">
</div>
</div>
</div>

View File

@@ -2,9 +2,9 @@
<div class="field-container"></div>
<% if (!showFullProfile) { %>
<% if(ownProfile) { %>
<span class="profile-private--message" tabindex="0"><%- gettext("You are currently sharing a limited profile.") %></span>
<span class="profile-private-message"><%- gettext("You are currently sharing a limited profile.") %></span>
<% } else { %>
<span class="profile-private--message" tabindex="0"><%- gettext("This learner is currently sharing a limited profile.") %></span>
<span class="profile-private-message"><%- gettext("This learner is currently sharing a limited profile.") %></span>
<% } %>
<% } %>
</div>