diff --git a/lms/djangoapps/student_profile/test/test_views.py b/lms/djangoapps/student_profile/test/test_views.py
index 12d57026bb..aa78183108 100644
--- a/lms/djangoapps/student_profile/test/test_views.py
+++ b/lms/djangoapps/student_profile/test/test_views.py
@@ -53,6 +53,26 @@ class LearnerProfileViewTest(UrlResetMixin, TestCase):
reverse('preferences_api', kwargs={'username': self.user.username})
)
+ self.assertEqual(
+ context['data']['profile_image_upload_url'],
+ reverse("profile_image_upload", kwargs={'username': self.user.username})
+ )
+
+ self.assertEqual(
+ context['data']['profile_image_remove_url'],
+ reverse('profile_image_remove', kwargs={'username': self.user.username})
+ )
+
+ self.assertEqual(
+ context['data']['profile_image_max_bytes'],
+ settings.PROFILE_IMAGE_MAX_BYTES
+ )
+
+ self.assertEqual(
+ context['data']['profile_image_min_bytes'],
+ settings.PROFILE_IMAGE_MIN_BYTES
+ )
+
self.assertEqual(context['data']['account_settings_page_url'], reverse('account_settings'))
for attribute in self.CONTEXT_DATA:
diff --git a/lms/static/js/spec/main.js b/lms/static/js/spec/main.js
index 8bebcf05dd..05b9357134 100644
--- a/lms/static/js/spec/main.js
+++ b/lms/static/js/spec/main.js
@@ -598,6 +598,7 @@
'lms/include/js/spec/views/fields_spec.js',
'lms/include/js/spec/student_profile/learner_profile_factory_spec.js',
'lms/include/js/spec/student_profile/learner_profile_view_spec.js',
+ 'lms/include/js/spec/student_profile/learner_profile_fields_spec.js',
'lms/include/js/spec/verify_student/pay_and_verify_view_spec.js',
'lms/include/js/spec/verify_student/webcam_photo_view_spec.js',
'lms/include/js/spec/verify_student/image_input_spec.js',
diff --git a/lms/static/js/spec/student_account/helpers.js b/lms/static/js/spec/student_account/helpers.js
index c4dc04e48a..3ca13867e2 100644
--- a/lms/static/js/spec/student_account/helpers.js
+++ b/lms/static/js/spec/student_account/helpers.js
@@ -6,11 +6,15 @@ define(['underscore'], function(_) {
var IMAGE_UPLOAD_API_URL = '/api/profile_images/v0/staff/upload';
var IMAGE_REMOVE_API_URL = '/api/profile_images/v0/staff/remove';
+ var PROFILE_IMAGE = {
+ image_url_large: '/media/profile-images/image.jpg',
+ has_image: true
+ };
+
var USER_ACCOUNTS_DATA = {
username: 'student',
name: 'Student',
email: 'student@edx.org',
-
level_of_education: '0',
gender: '0',
year_of_birth: '0',
@@ -18,7 +22,8 @@ define(['underscore'], function(_) {
language: '0',
bio: "About the student",
language_proficiencies: [{code: '1'}],
- requires_parental_consent: true
+ requires_parental_consent: true,
+ profile_image: PROFILE_IMAGE
};
var USER_PREFERENCES_DATA = {
@@ -101,6 +106,7 @@ define(['underscore'], function(_) {
IMAGE_REMOVE_API_URL: IMAGE_REMOVE_API_URL,
IMAGE_MAX_BYTES: IMAGE_MAX_BYTES,
IMAGE_MIN_BYTES: IMAGE_MIN_BYTES,
+ PROFILE_IMAGE: PROFILE_IMAGE,
USER_ACCOUNTS_DATA: USER_ACCOUNTS_DATA,
USER_PREFERENCES_DATA: USER_PREFERENCES_DATA,
FIELD_OPTIONS: FIELD_OPTIONS,
diff --git a/lms/static/js/spec/student_profile/helpers.js b/lms/static/js/spec/student_profile/helpers.js
index 5ea7dd1877..dff6e9c26c 100644
--- a/lms/static/js/spec/student_profile/helpers.js
+++ b/lms/static/js/spec/student_profile/helpers.js
@@ -9,10 +9,12 @@ define(['underscore'], function(_) {
expect(fieldTitle).toBe(view.options.title);
}
- if ('fieldValue' in view) {
+ if ('fieldValue' in view || 'imageUrl' in view) {
expect(view.model.get(view.options.valueAttribute)).toBeTruthy();
- if (view.fieldValue()) {
+ if ('imageUrl' in view) {
+ expect($($element.find('.image-frame')[0]).attr('src')).toBe(view.imageUrl());
+ } else if (view.fieldValue()) {
expect(view.fieldValue()).toBe(view.modelValue());
} else if ('optionForValue' in view) {
@@ -43,9 +45,11 @@ define(['underscore'], function(_) {
var sectionOneFieldElements = $(learnerProfileView.$('.wrapper-profile-section-one')).find('.u-field');
- expect(sectionOneFieldElements.length).toBe(learnerProfileView.options.sectionOneFieldViews.length);
+ expect(sectionOneFieldElements.length).toBe(4);
+ expectProfileElementContainsField(sectionOneFieldElements[0], learnerProfileView.options.profileImageFieldView);
+ expectProfileElementContainsField(sectionOneFieldElements[1], learnerProfileView.options.usernameFieldView);
- _.each(sectionOneFieldElements, function (sectionFieldElement, fieldIndex) {
+ _.each(_.rest(sectionOneFieldElements, 2) , function (sectionFieldElement, fieldIndex) {
expectProfileElementContainsField(
sectionFieldElement,
learnerProfileView.options.sectionOneFieldViews[fieldIndex]
@@ -79,13 +83,15 @@ define(['underscore'], function(_) {
var sectionOneFieldElements = $(learnerProfileView.$('.wrapper-profile-section-one')).find('.u-field');
- expect(sectionOneFieldElements.length).toBe(1);
- _.each(sectionOneFieldElements, function (sectionFieldElement, fieldIndex) {
- expectProfileElementContainsField(
- sectionFieldElement,
- learnerProfileView.options.sectionOneFieldViews[fieldIndex]
- );
- });
+ expect(sectionOneFieldElements.length).toBe(2);
+ expectProfileElementContainsField(
+ sectionOneFieldElements[0],
+ learnerProfileView.options.profileImageFieldView
+ );
+ expectProfileElementContainsField(
+ sectionOneFieldElements[1],
+ learnerProfileView.options.usernameFieldView
+ );
if (othersProfile) {
expect($('.profile-private--message').text())
diff --git a/lms/static/js/spec/student_profile/learner_profile_factory_spec.js b/lms/static/js/spec/student_profile/learner_profile_factory_spec.js
index 3fba060b8e..a004c53aa2 100644
--- a/lms/static/js/spec/student_profile/learner_profile_factory_spec.js
+++ b/lms/static/js/spec/student_profile/learner_profile_factory_spec.js
@@ -6,7 +6,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
'js/student_account/models/user_preferences_model',
'js/student_profile/views/learner_profile_view',
'js/student_profile/views/learner_profile_fields',
- 'js/student_profile/views/learner_profile_factory'
+ 'js/student_profile/views/learner_profile_factory',
+ 'js/views/message_banner'
],
function (Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, LearnerProfileHelpers, FieldViews,
UserAccountModel, UserPreferencesModel, LearnerProfileView, LearnerProfileFields, LearnerProfilePage) {
@@ -17,10 +18,12 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
var requests;
beforeEach(function () {
- setFixtures('
An error occurred. Please reload the page.
');
+ setFixtures('An error occurred. Please reload the page.
');
TemplateHelpers.installTemplate('templates/fields/field_readonly');
TemplateHelpers.installTemplate('templates/fields/field_dropdown');
TemplateHelpers.installTemplate('templates/fields/field_textarea');
+ TemplateHelpers.installTemplate('templates/fields/field_image');
+ TemplateHelpers.installTemplate('templates/fields/message_banner');
TemplateHelpers.installTemplate('templates/student_profile/learner_profile');
});
@@ -32,7 +35,11 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
'account_settings_page_url': Helpers.USER_ACCOUNTS_API_URL,
'country_options': Helpers.FIELD_OPTIONS,
'language_options': Helpers.FIELD_OPTIONS,
- 'has_preferences_access': true
+ 'has_preferences_access': true,
+ 'profile_image_max_bytes': Helpers.IMAGE_MAX_BYTES,
+ 'profile_image_min_bytes': Helpers.IMAGE_MIN_BYTES,
+ 'profile_image_upload_url': Helpers.IMAGE_UPLOAD_API_URL,
+ 'profile_image_remove_url': Helpers.IMAGE_REMOVE_API_URL
});
};
diff --git a/lms/static/js/spec/student_profile/learner_profile_fields_spec.js b/lms/static/js/spec/student_profile/learner_profile_fields_spec.js
new file mode 100644
index 0000000000..cb39ae53d5
--- /dev/null
+++ b/lms/static/js/spec/student_profile/learner_profile_fields_spec.js
@@ -0,0 +1,276 @@
+define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'js/common_helpers/template_helpers',
+ 'js/spec/student_account/helpers',
+ 'js/student_account/models/user_account_model',
+ 'js/student_profile/views/learner_profile_fields',
+ 'js/views/message_banner'
+ ],
+ function (Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, UserAccountModel, LearnerProfileFields,
+ MessageBannerView) {
+ 'use strict';
+
+ describe("edx.user.LearnerProfileFields", function () {
+
+ var createImageView = function (ownProfile, hasImage, imageMaxBytes, imageMinBytes, yearOfBirth) {
+
+ var imageData = {
+ image_url_large: '/media/profile-images/default.jpg',
+ has_image: hasImage ? true : false
+ };
+
+ yearOfBirth = _.isUndefined(yearOfBirth) ? 1989 : yearOfBirth;
+
+ var accountSettingsModel = new UserAccountModel();
+ accountSettingsModel.set({'profile_image': imageData});
+ accountSettingsModel.set({'year_of_birth': yearOfBirth});
+ accountSettingsModel.set({'requires_parental_consent': _.isEmpty(yearOfBirth) ? true : false});
+
+ accountSettingsModel.url = Helpers.USER_ACCOUNTS_API_URL;
+
+ var messageView = new MessageBannerView({
+ el: $('.message-banner')
+ });
+
+ imageMaxBytes = imageMaxBytes || 64;
+ imageMinBytes = imageMinBytes || 16;
+
+ var editable = ownProfile ? 'toggle' : 'never';
+
+ return new LearnerProfileFields.ProfileImageFieldView({
+ model: accountSettingsModel,
+ valueAttribute: "profile_image",
+ editable: editable === 'toggle',
+ messageView: messageView,
+ imageMaxBytes: imageMaxBytes,
+ imageMinBytes: imageMinBytes,
+ imageUploadUrl: Helpers.IMAGE_UPLOAD_API_URL,
+ imageRemoveUrl: Helpers.IMAGE_REMOVE_API_URL
+ });
+ };
+
+ beforeEach(function () {
+ setFixtures('An error occurred. Please reload the page.
');
+ TemplateHelpers.installTemplate('templates/student_profile/learner_profile');
+ TemplateHelpers.installTemplate('templates/fields/field_image');
+ TemplateHelpers.installTemplate("templates/fields/message_banner");
+ });
+
+ var createFakeImageFile = function (size) {
+ var fileFakeData = 'i63ljc6giwoskyb9x5sw0169bdcmcxr3cdz8boqv0lik971972cmd6yknvcxr5sw0nvc169bdcmcxsdf';
+ return new Blob(
+ [ fileFakeData.substr(0, size) ],
+ { type: 'image/jpg' }
+ );
+ };
+
+ it("can upload profile image", function() {
+
+ var imageView = createImageView(true, false);
+ imageView.render();
+
+ var requests = AjaxHelpers.requests(this);
+
+ var imageName = 'profile_image.jpg';
+
+ // Initialize jquery file uploader
+ imageView.$('.upload-button-input').fileupload({
+ url: Helpers.IMAGE_UPLOAD_API_URL,
+ type: 'POST',
+ add: imageView.fileSelected,
+ done: imageView.imageChangeSucceeded,
+ fail: imageView.imageChangeFailed
+ });
+
+ // Remove button should not be present for default image
+ expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
+
+ // For default image, image title should be `Upload an image`
+ expect(imageView.$('.upload-button-title').text().trim()).toBe(imageView.titleAdd);
+
+ // Add image to upload queue, this will validate the image size and send POST request to upload image
+ imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(60)]});
+
+ // Verify image upload progress message
+ expect(imageView.$('.upload-button-title').text().trim()).toBe(imageView.titleUploading);
+
+ // Verify if POST request received for image upload
+ AjaxHelpers.expectRequest(requests, 'POST', Helpers.IMAGE_UPLOAD_API_URL, new FormData());
+
+ // Send 204 NO CONTENT to confirm the image upload success
+ AjaxHelpers.respondWithNoContent(requests);
+
+ // 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
+ var data = {profile_image: {
+ image_url_large: '/media/profile-images/' + imageName,
+ has_image: true
+ }};
+ AjaxHelpers.respondWithJson(requests, data);
+
+ // Verify uploaded image name
+ expect(imageView.$('.image-frame').attr('src')).toContain(imageName);
+
+ // Remove button should be present after successful image upload
+ expect(imageView.$('.u-field-remove-button').css('display') !== 'none').toBeTruthy();
+
+ // After image upload, image title should be `Change image`
+ expect(imageView.$('.upload-button-title').text().trim()).toBe(imageView.titleEdit);
+ });
+
+ it("can remove profile image", function() {
+ var imageView = createImageView(true, true);
+ imageView.render();
+
+ var requests = AjaxHelpers.requests(this);
+
+ imageView.$('.u-field-remove-button').click();
+
+ // Verify image remove progress message
+ expect(imageView.$('.remove-button-title').text().trim()).toBe(imageView.titleRemoving);
+
+ // Verify if POST request received for image remove
+ AjaxHelpers.expectRequest(requests, 'POST', Helpers.IMAGE_REMOVE_API_URL, null);
+
+ // Send 204 NO CONTENT to confirm the image removal success
+ AjaxHelpers.respondWithNoContent(requests);
+
+ // Upon successful image removal, account settings model will be fetched to get the default image url
+ // So we need to send the response for that GET
+ var data = {profile_image: {
+ image_url_large: '/media/profile-images/default.jpg',
+ has_image: false
+ }};
+ AjaxHelpers.respondWithJson(requests, data);
+
+ // Remove button should not be present for default image
+ expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
+ });
+
+ it("can't remove default profile image", function() {
+ var imageView = createImageView(true, false);
+ imageView.render();
+
+ spyOn(imageView, 'clickedRemoveButton');
+
+ // Remove button should not be present for default image
+ expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
+
+ imageView.$('.u-field-remove-button').click();
+
+ // Remove button click handler should not be called
+ expect(imageView.clickedRemoveButton).not.toHaveBeenCalled();
+ });
+
+ it("can't upload image having size greater than max size", function() {
+ var imageView = createImageView(true, false);
+ imageView.render();
+
+ // Initialize jquery file uploader
+ imageView.$('.upload-button-input').fileupload({
+ url: Helpers.IMAGE_UPLOAD_API_URL,
+ type: 'POST',
+ add: imageView.fileSelected,
+ done: imageView.imageChangeSucceeded,
+ fail: imageView.imageChangeFailed
+ });
+
+ // Add image to upload queue, this will validate the image size
+ imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(70)]});
+
+ // Verify error message
+ expect($('.message-banner').text().trim()).toBe('Your image must be smaller than 64 Bytes in size.');
+ });
+
+ it("can't upload image having size less than min size", function() {
+ var imageView = createImageView(true, false);
+ imageView.render();
+
+ // Initialize jquery file uploader
+ imageView.$('.upload-button-input').fileupload({
+ url: Helpers.IMAGE_UPLOAD_API_URL,
+ type: 'POST',
+ add: imageView.fileSelected,
+ done: imageView.imageChangeSucceeded,
+ fail: imageView.imageChangeFailed
+ });
+
+ // Add image to upload queue, this will validate the image size
+ imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(10)]});
+
+ // Verify error message
+ expect($('.message-banner').text().trim()).toBe('Your image must be at least 16 Bytes in size.');
+ });
+
+ it("can't upload/remove image if parental consent required", function() {
+ var imageView = createImageView(true, false, 64, 16, '');
+ imageView.render();
+
+ spyOn(imageView, 'clickedUploadButton');
+ spyOn(imageView, 'clickedRemoveButton');
+
+ expect(imageView.$('.u-field-upload-button').css('display') === 'none').toBeTruthy();
+ expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
+
+ imageView.$('.u-field-upload-button').click();
+ imageView.$('.u-field-remove-button').click();
+
+ expect(imageView.clickedUploadButton).not.toHaveBeenCalled();
+ expect(imageView.clickedRemoveButton).not.toHaveBeenCalled();
+ });
+
+ it("can't upload image on others profile", function() {
+ var imageView = createImageView(false);
+ imageView.render();
+
+ spyOn(imageView, 'clickedUploadButton');
+ spyOn(imageView, 'clickedRemoveButton');
+
+ expect(imageView.$('.u-field-upload-button').css('display') === 'none').toBeTruthy();
+ expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
+
+ imageView.$('.u-field-upload-button').click();
+ imageView.$('.u-field-remove-button').click();
+
+ expect(imageView.clickedUploadButton).not.toHaveBeenCalled();
+ expect(imageView.clickedRemoveButton).not.toHaveBeenCalled();
+ });
+
+ it("shows message if we try to navigate away during image upload/remove", function() {
+ var imageView = createImageView(true, false);
+ spyOn(imageView, 'onBeforeUnload');
+ imageView.render();
+
+ // Initialize jquery file uploader
+ imageView.$('.upload-button-input').fileupload({
+ url: Helpers.IMAGE_UPLOAD_API_URL,
+ type: 'POST',
+ add: imageView.fileSelected,
+ done: imageView.imageChangeSucceeded,
+ fail: imageView.imageChangeFailed
+ });
+
+ // Add image to upload queue, this will validate the image size and send POST request to upload image
+ imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(60)]});
+
+ // Verify image upload progress message
+ expect(imageView.$('.upload-button-title').text().trim()).toBe(imageView.titleUploading);
+
+ $(window).trigger('beforeunload');
+
+ expect(imageView.onBeforeUnload).toHaveBeenCalled();
+ });
+
+ it('renders message correctly', function() {
+ var messageSelector = '.message-banner';
+ var messageView = new MessageBannerView({
+ el: $(messageSelector)
+ });
+
+ messageView.showMessage('I am message view');
+ // Verify error message
+ expect($(messageSelector).text().trim()).toBe('I am message view');
+
+ messageView.hideMessage();
+ expect($(messageSelector).text().trim()).toBe('');
+ });
+ });
+ });
diff --git a/lms/static/js/spec/student_profile/learner_profile_view_spec.js b/lms/static/js/spec/student_profile/learner_profile_view_spec.js
index 00826017a5..fd869a9e06 100644
--- a/lms/static/js/spec/student_profile/learner_profile_view_spec.js
+++ b/lms/static/js/spec/student_profile/learner_profile_view_spec.js
@@ -24,6 +24,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
accountSettingsData.requires_parental_consent = false;
accountSettingsModel.set(accountSettingsData);
accountSettingsModel.set({'profile_is_public': profileIsPublic});
+ accountSettingsModel.set({'profile_image': Helpers.PROFILE_IMAGE});
var accountPreferencesModel = new AccountPreferencesModel();
accountPreferencesModel.set({account_privacy: accountPrivacy});
@@ -51,7 +52,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
el: $('.message-banner')
});
- var profileImageFieldView = new FieldsView.ImageFieldView({
+ var profileImageFieldView = new LearnerProfileFields.ProfileImageFieldView({
model: accountSettingsModel,
valueAttribute: "profile_image",
editable: editable,
@@ -69,7 +70,6 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
});
var sectionOneFieldViews = [
- usernameFieldView,
new FieldViews.DropdownFieldView({
model: accountSettingsModel,
required: false,
@@ -117,6 +117,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
preferencesModel: accountPreferencesModel,
accountPrivacyFieldView: accountPrivacyFieldView,
usernameFieldView: usernameFieldView,
+ profileImageFieldView: profileImageFieldView,
sectionOneFieldViews: sectionOneFieldViews,
sectionTwoFieldViews: sectionTwoFieldViews
});
@@ -128,7 +129,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
TemplateHelpers.installTemplate('templates/fields/field_dropdown');
TemplateHelpers.installTemplate('templates/fields/field_textarea');
TemplateHelpers.installTemplate('templates/fields/field_image');
- TemplateHelpers.installTemplate('templates/message_banner');
+ TemplateHelpers.installTemplate('templates/fields/message_banner');
TemplateHelpers.installTemplate('templates/student_profile/learner_profile');
});
diff --git a/lms/static/js/student_profile/views/learner_profile_fields.js b/lms/static/js/student_profile/views/learner_profile_fields.js
index e5c6e13d61..071fca5fe6 100644
--- a/lms/static/js/student_profile/views/learner_profile_fields.js
+++ b/lms/static/js/student_profile/views/learner_profile_fields.js
@@ -70,9 +70,14 @@
imageChangeFailed: function (e, data) {
this.setCurrentStatus('');
- if (_.contains([400, 404], data.jqXHR.status)) {
+ this.showImageChangeFailedMessage(data.jqXHR.status, data.jqXHR.responseText);
+ this.render();
+ },
+
+ showImageChangeFailedMessage: function (status, responseText) {
+ if (_.contains([400, 404], status)) {
try {
- var errors = JSON.parse(data.jqXHR.responseText);
+ var errors = JSON.parse(responseText);
this.showErrorMessage(errors.user_message);
} catch (error) {
this.showErrorMessage(this.errorMessage);
@@ -80,7 +85,6 @@
} else {
this.showErrorMessage(this.errorMessage);
}
- this.render();
},
showErrorMessage: function (message) {
diff --git a/lms/static/js/views/fields.js b/lms/static/js/views/fields.js
index 2a8c1b7619..932f4fb2d5 100644
--- a/lms/static/js/views/fields.js
+++ b/lms/static/js/views/fields.js
@@ -548,7 +548,8 @@
return this;
},
- showErrorMessage: function () {
+ showErrorMessage: function (message) {
+ return message;
},
imageUrl: function () {
@@ -593,7 +594,7 @@
}
},
- clickedUploadButton: function () {
+ clickedUploadButton: function (e, data) {
$(this.uploadButtonSelector).fileupload({
url: this.options.imageUploadUrl,
type: 'POST',
@@ -603,7 +604,7 @@
});
},
- clickedRemoveButton: function () {
+ clickedRemoveButton: function (e, data) {
var view = this;
this.setCurrentStatus('removing');
this.setUploadButtonVisibility('none');
@@ -615,7 +616,7 @@
view.imageChangeSucceeded();
},
error: function (xhr, status, error) {
- view.imageChangeFailed();
+ view.showImageChangeFailedMessage(xhr.status, xhr.responseText);
}
});
},
@@ -627,8 +628,11 @@
imageChangeFailed: function (e, data) {
},
+ showImageChangeFailedMessage: function (status, responseText) {
+ },
+
fileSelected: function (e, data) {
- if (this.validateImageSize(data.files[0].size)) {
+ if (_.isUndefined(data.files[0].size) || this.validateImageSize(data.files[0].size)) {
data.formData = {file: data.files[0]};
this.setCurrentStatus('uploading');
this.setRemoveButtonVisibility('none');
@@ -681,6 +685,7 @@
},
onBeforeUnload: function () {
+ console.log('Do you really want to go away?');
var status = this.getCurrentStatus();
if (status === 'uploading') {
return gettext("Upload is in progress. To avoid errors, stay on this page until the process is complete.");
diff --git a/lms/static/sass/views/_learner-profile.scss b/lms/static/sass/views/_learner-profile.scss
index 06ea05ea3c..2679d6af98 100644
--- a/lms/static/sass/views/_learner-profile.scss
+++ b/lms/static/sass/views/_learner-profile.scss
@@ -30,6 +30,7 @@
background: transparent !important;
border: none !important;
padding: 0;
+ -webkit-tap-highlight-color: transparent;
}
.u-field-image {
diff --git a/lms/templates/message_banner.underscore b/lms/templates/fields/message_banner.underscore
similarity index 100%
rename from lms/templates/message_banner.underscore
rename to lms/templates/fields/message_banner.underscore
diff --git a/lms/templates/student_profile/learner_profile.html b/lms/templates/student_profile/learner_profile.html
index 29475aa614..741025156e 100644
--- a/lms/templates/student_profile/learner_profile.html
+++ b/lms/templates/student_profile/learner_profile.html
@@ -10,7 +10,7 @@
<%block name="bodyclass">view-profile%block>
<%block name="header_extras">
- % for template_name in ["field_dropdown", "field_image", "field_textarea", "field_readonly"]:
+ % for template_name in ["field_dropdown", "field_image", "field_textarea", "field_readonly", "message_banner"]:
@@ -21,12 +21,6 @@
<%static:include path="student_profile/${template_name}.underscore" />
% endfor
-
- % for template_name in ["message_banner"]:
-
- % endfor
%block>