Commit c2d83bd4 by muzaffaryousaf Committed by Andy Armstrong

Bok_choy tests for upload/remove profile image.

TNL-1538
parent ca1f2f77
...@@ -5,6 +5,8 @@ from . import BASE_URL ...@@ -5,6 +5,8 @@ from . import BASE_URL
from bok_choy.page_object import PageObject from bok_choy.page_object import PageObject
from .fields import FieldsMixin from .fields import FieldsMixin
from bok_choy.promise import EmptyPromise from bok_choy.promise import EmptyPromise
from .instructor_dashboard import InstructorDashboardPage
from selenium.webdriver import ActionChains
PROFILE_VISIBILITY_SELECTOR = '#u-field-select-account_privacy option[value="{}"]' PROFILE_VISIBILITY_SELECTOR = '#u-field-select-account_privacy option[value="{}"]'
...@@ -165,3 +167,109 @@ class LearnerProfilePage(FieldsMixin, PageObject): ...@@ -165,3 +167,109 @@ class LearnerProfilePage(FieldsMixin, PageObject):
""" """
self.wait_for_ajax() self.wait_for_ajax()
return self.q(css='#u-field-message-account_privacy').visible return self.q(css='#u-field-message-account_privacy').visible
@property
def profile_has_default_image(self):
"""
Return bool if image field has default photo or not.
"""
self.wait_for_field('image')
default_links = self.q(css='.image-frame').attrs('src')
return 'default-profile' in default_links[0] if default_links else False
def mouse_hover(self, element):
"""
Mouse over on given element.
"""
mouse_hover_action = ActionChains(self.browser).move_to_element(element)
mouse_hover_action.perform()
def profile_has_image_with_public_access(self):
"""
Check if image is present with remove/upload access.
"""
self.wait_for_field('image')
self.mouse_hover(self.browser.find_element_by_css_selector('.image-wrapper'))
self.wait_for_element_visibility('.u-field-upload-button', "upload button is visible")
return self.q(css='.u-field-upload-button').visible
def profile_has_image_with_private_access(self):
"""
Check if image is present with remove/upload access.
"""
self.wait_for_field('image')
return self.q(css='.u-field-upload-button').visible
def upload_file(self, filename):
"""
Helper method to upload an image file.
"""
self.wait_for_element_visibility('.u-field-upload-button', "upload button is visible")
file_path = InstructorDashboardPage.get_asset_path(filename)
# make the elements visible.
self.browser.execute_script('$(".u-field-upload-button").css("opacity",1);')
self.browser.execute_script('$(".upload-button-input").css("opacity",1);')
self.wait_for_element_visibility('.upload-button-input', "upload button is visible")
self.browser.execute_script('$(".upload-submit").show();')
# First send_keys will initialize the jquery auto upload plugin.
self.q(css='.upload-button-input').results[0].send_keys(file_path)
self.q(css='.upload-submit').first.click()
self.q(css='.upload-button-input').results[0].send_keys(file_path)
self.wait_for_ajax()
def upload_correct_image_file(self, filename):
"""
Selects the correct file and clicks the upload button.
"""
self._upload_file(filename)
@property
def image_upload_success(self):
"""
Returns the bool, if image is updated or not.
"""
self.wait_for_field('image')
self.wait_for_ajax()
self.wait_for_element_visibility('.image-frame', "image box is visible")
image_link = self.q(css='.image-frame').attrs('src')
return 'default-profile' not in image_link[0]
@property
def profile_image_message(self):
"""
Returns the text message for profile image.
"""
self.wait_for_field('image')
self.wait_for_ajax()
return self.q(css='.message-banner p').text[0]
def remove_profile_image(self):
"""
Removes the profile image.
"""
self.wait_for_field('image')
self.wait_for_ajax()
self.wait_for_element_visibility('.image-wrapper', "remove button is visible")
self.browser.execute_script('$(".u-field-remove-button").css("opacity",1);')
self.mouse_hover(self.browser.find_element_by_css_selector('.image-wrapper'))
self.wait_for_element_visibility('.u-field-remove-button', "remove button is visible")
self.q(css='.u-field-remove-button').first.click()
self.mouse_hover(self.browser.find_element_by_css_selector('.image-wrapper'))
self.wait_for_element_visibility('.u-field-upload-button', "upload button is visible")
return True
@property
def remove_link_present(self):
self.wait_for_field('image')
self.mouse_hover(self.browser.find_element_by_css_selector('.image-wrapper'))
return self.q(css='.u-field-remove-button').visible
...@@ -111,6 +111,13 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): ...@@ -111,6 +111,13 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest):
self.assertEqual(profile_page.age_limit_message_present, message is not None) self.assertEqual(profile_page.age_limit_message_present, message is not None)
self.assertIn(message, profile_page.profile_forced_private_message) self.assertIn(message, profile_page.profile_forced_private_message)
def assert_default_image_has_public_access(self, profile_page):
"""
Assert that profile image has public access.
"""
self.assertTrue(profile_page.profile_has_default_image)
self.assertTrue(profile_page.profile_has_image_with_public_access())
def test_dashboard_learner_profile_link(self): def test_dashboard_learner_profile_link(self):
""" """
Scenario: Verify that my profile link is present on dashboard page and we can navigate to correct page. Scenario: Verify that my profile link is present on dashboard page and we can navigate to correct page.
...@@ -320,6 +327,171 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): ...@@ -320,6 +327,171 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest):
) )
self.verify_profile_page_view_event(user_id, visibility=self.PRIVACY_PRIVATE) self.verify_profile_page_view_event(user_id, visibility=self.PRIVACY_PRIVATE)
def test_user_can_only_see_default_image_for_private_profile(self):
"""
Scenario: Default profile image behaves correctly for under age user.
Given that I am on my profile page with private access
And I can see default image
When I move my cursor to the image
Then i cannot see the upload/remove image text
And i cannot upload/remove the image.
"""
year_of_birth = datetime.now().year - 5
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PRIVATE)
self.verify_profile_forced_private_message(
username,
year_of_birth,
message='You must be over 13 to share a full profile.'
)
self.assertTrue(profile_page.profile_has_default_image)
self.assertFalse(profile_page.profile_has_image_with_private_access())
def test_user_can_see_default_image_for_public_profile(self):
"""
Scenario: Default profile image behaves correctly for public profile.
Given that I am on my profile page with public access
And I can see default image
When I move my cursor to the image
Then i can see the upload/remove image text
And i am able to upload new image
"""
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assert_default_image_has_public_access(profile_page)
def test_user_can_upload_the_profile_image_with_success(self):
"""
Scenario: Upload profile image works correctly.
Given that I am on my profile page with public access
And I can see default image
When I move my cursor to the image
Then i can see the upload/remove image text
When i upload new image via file uploader
Then i can see the changed image
And i can also see the latest image after reload.
"""
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assert_default_image_has_public_access(profile_page)
profile_page.upload_file(filename='image.jpg')
self.assertTrue(profile_page.image_upload_success)
profile_page.visit()
self.assertTrue(profile_page.image_upload_success)
def test_user_can_see_error_for_exceeding_max_file_size_limit(self):
"""
Scenario: Upload profile image does not work for > 1MB image file.
Given that I am on my profile page with public access
And I can see default image
When I move my cursor to the image
Then i can see the upload/remove image text
When i upload new > 1MB image via file uploader
Then i can see the error message for file size limit
And i can still see the default image after page reload.
"""
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assert_default_image_has_public_access(profile_page)
profile_page.upload_file(filename='larger_image.jpg')
self.assertEqual(profile_page.profile_image_message, "Your image must be smaller than 1 MB in size.")
profile_page.visit()
self.assertTrue(profile_page.profile_has_default_image)
def test_user_can_see_error_for_file_size_below_the_min_limit(self):
"""
Scenario: Upload profile image does not work for < 100 Bytes image file.
Given that I am on my profile page with public access
And I can see default image
When I move my cursor to the image
Then i can see the upload/remove image text
When i upload new < 100 Bytes image via file uploader
Then i can see the error message for minimum file size limit
And i can still see the default image after page reload.
"""
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assert_default_image_has_public_access(profile_page)
profile_page.upload_file(filename='list-icon-visited.png')
self.assertEqual(profile_page.profile_image_message, "Your image must be at least 100 bytes in size.")
profile_page.visit()
self.assertTrue(profile_page.profile_has_default_image)
def test_user_can_see_error_for_wrong_file_type(self):
"""
Scenario: Upload profile image does not work for wrong file types.
Given that I am on my profile page with public access
And I can see default image
When I move my cursor to the image
Then i can see the upload/remove image text
When i upload new csv file via file uploader
Then i can see the error message for wrong/unsupported file type
And i can still see the default image after page reload.
"""
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assert_default_image_has_public_access(profile_page)
profile_page.upload_file(filename='cohort_users_only_username.csv')
self.assertEqual(profile_page.profile_image_message, "Unsupported file type.")
profile_page.visit()
self.assertTrue(profile_page.profile_has_default_image)
def test_user_can_remove_profile_image(self):
"""
Scenario: Remove profile image works correctly.
Given that I am on my profile page with public access
And I can see default image
When I move my cursor to the image
Then i can see the upload/remove image text
When i click on the remove image link
Then i can see the default image
And i can still see the default image after page reload.
"""
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assert_default_image_has_public_access(profile_page)
profile_page.upload_file(filename='image.jpg')
self.assertTrue(profile_page.image_upload_success)
self.assertTrue(profile_page.remove_profile_image())
self.assertTrue(profile_page.profile_has_default_image)
profile_page.visit()
self.assertTrue(profile_page.profile_has_default_image)
def test_user_cannot_remove_default_image(self):
"""
Scenario: Remove profile image does not works for default images.
Given that I am on my profile page with public access
And I can see default image
When I move my cursor to the image
Then i can see only the upload image text
And i cannot see the remove image text
"""
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assert_default_image_has_public_access(profile_page)
self.assertFalse(profile_page.remove_link_present)
class DifferentUserLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): class DifferentUserLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest):
""" """
......
...@@ -131,6 +131,14 @@ MOCK_SEARCH_BACKING_FILE = ( ...@@ -131,6 +131,14 @@ MOCK_SEARCH_BACKING_FILE = (
import uuid import uuid
SECRET_KEY = uuid.uuid4().hex SECRET_KEY = uuid.uuid4().hex
# Set dummy values for profile image settings.
PROFILE_IMAGE_BACKEND = {
'class': 'storages.backends.overwrite.OverwriteStorage',
'options': {
'location': os.path.join(MEDIA_ROOT, 'profile-images/'),
'base_url': os.path.join(MEDIA_URL, 'profile-images/'),
},
}
##################################################################### #####################################################################
# Lastly, see if the developer has any local overrides. # Lastly, see if the developer has any local overrides.
try: try:
......
<div class="message-banner" aria-live="polite"></div>
<div class="wrapper-profile">
<div class="ui-loading-indicator">
<p>
<span class="spin">
<i class="icon fa fa-refresh"></i>
</span>
<span class="copy">
Loading
</span>
</p>
</div>
<div class="ui-loading-error is-hidden">
<i class="fa fa-exclamation-triangle message-error" aria-hidden=true></i>
<span class="copy">
An error occurred. Please reload the page.
</span>
</div>
</div>
...@@ -18,7 +18,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -18,7 +18,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
var requests; var requests;
beforeEach(function () { beforeEach(function () {
setFixtures('<div class="message-banner"></div><div class="wrapper-profile"><div class="ui-loading-indicator"><p><span class="spin"><i class="icon fa fa-refresh"></i></span> <span class="copy">Loading</span></p></div><div class="ui-loading-error is-hidden"><i class="fa fa-exclamation-triangle message-error" aria-hidden=true></i><span class="copy">An error occurred. Please reload the page.</span></div></div>'); loadFixtures('js/fixtures/student_profile/student_profile.html');
TemplateHelpers.installTemplate('templates/fields/field_readonly'); TemplateHelpers.installTemplate('templates/fields/field_readonly');
TemplateHelpers.installTemplate('templates/fields/field_dropdown'); TemplateHelpers.installTemplate('templates/fields/field_dropdown');
TemplateHelpers.installTemplate('templates/fields/field_textarea'); TemplateHelpers.installTemplate('templates/fields/field_textarea');
......
...@@ -124,7 +124,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -124,7 +124,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
}; };
beforeEach(function () { beforeEach(function () {
setFixtures('<div class="message-banner"></div><div class="wrapper-profile"><div class="ui-loading-indicator"><p><span class="spin"><i class="icon fa fa-refresh"></i></span> <span class="copy">Loading</span></p></div><div class="ui-loading-error is-hidden"><i class="fa fa-exclamation-triangle message-error" aria-hidden=true></i><span class="copy">An error occurred. Please reload the page.</span></div></div>'); loadFixtures('js/fixtures/student_profile/student_profile.html');
TemplateHelpers.installTemplate('templates/fields/field_readonly'); TemplateHelpers.installTemplate('templates/fields/field_readonly');
TemplateHelpers.installTemplate('templates/fields/field_dropdown'); TemplateHelpers.installTemplate('templates/fields/field_dropdown');
TemplateHelpers.installTemplate('templates/fields/field_textarea'); TemplateHelpers.installTemplate('templates/fields/field_textarea');
......
define(['backbone', 'jquery', 'underscore', 'js/views/message_banner'
],
function (Backbone, $, _, MessageBannerView) {
'use strict';
describe("MessageBannerView", function () {
beforeEach(function () {
setFixtures('<div class="message-banner"></div>');
TemplateHelpers.installTemplate("templates/fields/message_banner");
});
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('');
});
});
});
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
'js/student_profile/views/learner_profile_view', 'js/student_profile/views/learner_profile_view',
'js/student_account/views/account_settings_fields', 'js/student_account/views/account_settings_fields',
'js/views/message_banner' 'js/views/message_banner'
], function (gettext, $, _, Backbone, AccountSettingsModel, AccountPreferencesModel, FieldsView, ], function (gettext, $, _, Backbone, Logger, AccountSettingsModel, AccountPreferencesModel, FieldsView,
LearnerProfileFieldsView, LearnerProfileView, AccountSettingsFieldViews, MessageBannerView) { LearnerProfileFieldsView, LearnerProfileView, AccountSettingsFieldViews, MessageBannerView) {
return function (options) { return function (options) {
......
...@@ -48,21 +48,15 @@ ...@@ -48,21 +48,15 @@
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; var imageView = this.options.profileImageFieldView;
imageView.undelegateEvents();
this.$('.profile-image-field').append(imageView.render().el); this.$('.profile-image-field').append(imageView.render().el);
imageView.delegateEvents();
if (this.showFullProfile()) { if (this.showFullProfile()) {
_.each(this.options.sectionOneFieldViews, function (fieldView) { _.each(this.options.sectionOneFieldViews, function (fieldView) {
fieldView.undelegateEvents();
view.$('.profile-section-one-fields').append(fieldView.render().el); view.$('.profile-section-one-fields').append(fieldView.render().el);
fieldView.delegateEvents();
}); });
_.each(this.options.sectionTwoFieldViews, function (fieldView) { _.each(this.options.sectionTwoFieldViews, function (fieldView) {
fieldView.undelegateEvents();
view.$('.profile-section-two-fields').append(fieldView.render().el); view.$('.profile-section-two-fields').append(fieldView.render().el);
fieldView.delegateEvents();
}); });
} }
}, },
......
...@@ -225,6 +225,7 @@ ...@@ -225,6 +225,7 @@
value: this.modelValue(), value: this.modelValue(),
message: this.helpMessage message: this.helpMessage
})); }));
this.delegateEvents();
return this; return this;
}, },
...@@ -260,6 +261,7 @@ ...@@ -260,6 +261,7 @@
value: this.modelValue(), value: this.modelValue(),
message: this.helpMessage message: this.helpMessage
})); }));
this.delegateEvents();
return this; return this;
}, },
...@@ -308,7 +310,7 @@ ...@@ -308,7 +310,7 @@
selectOptions: this.options.options, selectOptions: this.options.options,
message: this.helpMessage message: this.helpMessage
})); }));
this.delegateEvents();
this.updateValueInField(); this.updateValueInField();
if (this.editable === 'toggle') { if (this.editable === 'toggle') {
...@@ -415,7 +417,7 @@ ...@@ -415,7 +417,7 @@
value: value, value: value,
message: this.helpMessage message: this.helpMessage
})); }));
this.delegateEvents();
this.title((this.modelValue() || this.mode === 'edit') ? this.options.title : this.indicators['plus'] + this.options.title); this.title((this.modelValue() || this.mode === 'edit') ? this.options.title : this.indicators['plus'] + this.options.title);
if (this.editable === 'toggle') { if (this.editable === 'toggle') {
...@@ -491,6 +493,7 @@ ...@@ -491,6 +493,7 @@
linkHref: this.options.linkHref, linkHref: this.options.linkHref,
message: this.helpMessage message: this.helpMessage
})); }));
this.delegateEvents();
return this; return this;
}, },
...@@ -523,7 +526,8 @@ ...@@ -523,7 +526,8 @@
events: { events: {
'click .u-field-upload-button': 'clickedUploadButton', 'click .u-field-upload-button': 'clickedUploadButton',
'click .u-field-remove-button': 'clickedRemoveButton' 'click .u-field-remove-button': 'clickedRemoveButton',
'click .upload-submit': 'clickedUploadButton'
}, },
initialize: function (options) { initialize: function (options) {
...@@ -543,6 +547,7 @@ ...@@ -543,6 +547,7 @@
removeButtonIcon: _.result(this, 'iconRemove'), removeButtonIcon: _.result(this, 'iconRemove'),
removeButtonTitle: _.result(this, 'removeButtonTitle') removeButtonTitle: _.result(this, 'removeButtonTitle')
})); }));
this.delegateEvents();
this.updateButtonsVisibility(); this.updateButtonsVisibility();
this.watchForPageUnload(); this.watchForPageUnload();
return this; return this;
...@@ -558,9 +563,9 @@ ...@@ -558,9 +563,9 @@
uploadButtonTitle: function () { uploadButtonTitle: function () {
if (this.isShowingPlaceholder()) { if (this.isShowingPlaceholder()) {
return _.result(this, 'titleAdd') return _.result(this, 'titleAdd');
} else { } else {
return _.result(this, 'titleEdit') return _.result(this, 'titleEdit');
} }
}, },
...@@ -569,7 +574,7 @@ ...@@ -569,7 +574,7 @@
}, },
isEditingAllowed: function () { isEditingAllowed: function () {
return true return true;
}, },
isShowingPlaceholder: function () { isShowingPlaceholder: function () {
...@@ -594,7 +599,7 @@ ...@@ -594,7 +599,7 @@
} }
}, },
clickedUploadButton: function (e, data) { clickedUploadButton: function () {
$(this.uploadButtonSelector).fileupload({ $(this.uploadButtonSelector).fileupload({
url: this.options.imageUploadUrl, url: this.options.imageUploadUrl,
type: 'POST', type: 'POST',
...@@ -604,24 +609,22 @@ ...@@ -604,24 +609,22 @@
}); });
}, },
clickedRemoveButton: function (e, data) { clickedRemoveButton: function () {
var view = this; var view = this;
this.setCurrentStatus('removing'); this.setCurrentStatus('removing');
this.setUploadButtonVisibility('none'); this.setUploadButtonVisibility('none');
this.showRemovalInProgressMessage(); this.showRemovalInProgressMessage();
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: this.options.imageRemoveUrl, url: this.options.imageRemoveUrl
success: function (data, status, xhr) { }).done(function () {
view.imageChangeSucceeded(); view.imageChangeSucceeded();
}, }).fail(function (jqXHR) {
error: function (xhr, status, error) { view.showImageChangeFailedMessage(jqXHR.status, jqXHR.responseText);
view.showImageChangeFailedMessage(xhr.status, xhr.responseText);
}
}); });
}, },
imageChangeSucceeded: function (e, data) { imageChangeSucceeded: function () {
this.render(); this.render();
}, },
...@@ -645,11 +648,19 @@ ...@@ -645,11 +648,19 @@
var humanReadableSize; var humanReadableSize;
if (imageBytes < this.options.imageMinBytes) { if (imageBytes < this.options.imageMinBytes) {
humanReadableSize = this.bytesToHumanReadable(this.options.imageMinBytes); humanReadableSize = this.bytesToHumanReadable(this.options.imageMinBytes);
this.showErrorMessage(interpolate_text(gettext("Your image must be at least {size} in size."), {size: humanReadableSize})); this.showErrorMessage(
interpolate_text(
gettext("Your image must be at least {size} in size."), {size: humanReadableSize}
)
);
return false; return false;
} else if (imageBytes > this.options.imageMaxBytes) { } else if (imageBytes > this.options.imageMaxBytes) {
humanReadableSize = this.bytesToHumanReadable(this.options.imageMaxBytes); humanReadableSize = this.bytesToHumanReadable(this.options.imageMaxBytes);
this.showErrorMessage(interpolate_text(gettext("Your image must be smaller than {size} in size."), {size: humanReadableSize})); this.showErrorMessage(
interpolate_text(
gettext("Your image must be smaller than {size} in size."), {size: humanReadableSize}
)
);
return false; return false;
} }
return true; return true;
...@@ -675,27 +686,25 @@ ...@@ -675,27 +686,25 @@
return this.$('.image-wrapper').attr('data-status'); return this.$('.image-wrapper').attr('data-status');
}, },
inProgress: function() {
var status = this.getCurrentStatus();
return _.isUndefined(status) ? false : true;
},
watchForPageUnload: function () { watchForPageUnload: function () {
$(window).on('beforeunload', this.onBeforeUnload); $(window).on('beforeunload', this.onBeforeUnload);
}, },
onBeforeUnload: function () { onBeforeUnload: function () {
console.log('Do you really want to go away?');
var status = this.getCurrentStatus(); var status = this.getCurrentStatus();
if (status === 'uploading') { if (status === 'uploading') {
return gettext("Upload is in progress. To avoid errors, stay on this page until the process is complete."); return gettext(
"Upload is in progress. To avoid errors, stay on this page until the process is complete."
);
} else if (status === 'removing') { } else if (status === 'removing') {
return gettext("Removal is in progress. To avoid errors, stay on this page until the process is complete."); return gettext(
"Removal is in progress. To avoid errors, stay on this page until the process is complete."
);
} }
}, },
bytesToHumanReadable: function (size) { bytesToHumanReadable: function (size) {
var units = ['Bytes', 'KB', 'MB']; var units = ['bytes', 'KB', 'MB'];
var i = 0; var i = 0;
while(size >= 1024) { while(size >= 1024) {
size /= 1024; size /= 1024;
......
...@@ -6,14 +6,18 @@ ...@@ -6,14 +6,18 @@
var MessageBannerView = Backbone.View.extend({ var MessageBannerView = Backbone.View.extend({
initialize: function (options) { initialize: function () {
this.template = _.template($('#message_banner-tpl').text()); this.template = _.template($('#message_banner-tpl').text());
}, },
render: function () { render: function () {
this.$el.html(this.template({ if (_.isUndefined(this.message) || _.isNull(this.message)) {
message: this.message this.$el.html('');
})); } else {
this.$el.html(this.template({
message: this.message
}));
}
return this; return this;
}, },
...@@ -23,10 +27,11 @@ ...@@ -23,10 +27,11 @@
}, },
hideMessage: function () { hideMessage: function () {
this.$el.html(''); this.message = null;
this.render();
} }
}); });
return MessageBannerView; return MessageBannerView;
}) });
}).call(this, define || RequireJS.define); }).call(this, define || RequireJS.define);
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
background: transparent !important; background: transparent !important;
border: none !important; border: none !important;
padding: 0; padding: 0;
-webkit-tap-highlight-color: transparent;
} }
.u-field-image { .u-field-image {
...@@ -43,16 +42,18 @@ ...@@ -43,16 +42,18 @@
.image-frame { .image-frame {
position: relative; position: relative;
width: 120px; width: $profile-image-dimension;
height: 120px; height: $profile-image-dimension;
border-radius: ($baseline/4);
} }
.u-field-upload-button { .u-field-upload-button {
width: 120px; width: $profile-image-dimension;
height: 120px; height: $profile-image-dimension;
position: absolute; position: absolute;
top: 0; top: 0;
opacity: 0; opacity: 0;
@include transition(all $tmg-f1 ease-in-out 0s);
i { i {
color: $white; color: $white;
...@@ -61,13 +62,15 @@ ...@@ -61,13 +62,15 @@
.upload-button-icon, .upload-button-title { .upload-button-icon, .upload-button-title {
text-align: center; text-align: center;
transform: translateY(45px); transform: translateY(35px);
display: block; display: block;
color: $white; color: $white;
margin-bottom: ($baseline/4);
line-height: 1.3em;
} }
.upload-button-input { .upload-button-input {
width: 120px; width: $profile-image-dimension;
height: 100%; height: 100%;
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -77,17 +80,24 @@ ...@@ -77,17 +80,24 @@
} }
.u-field-remove-button { .u-field-remove-button {
width: 120px; width: $profile-image-dimension;
height: 20px; height: $baseline;
opacity: 0; opacity: 0;
position: relative; position: relative;
margin-top: 2px; margin-top: 2px;
text-align: center; text-align: center;
&:focus, &:active {
box-shadow: none;
outline: 0;
}
} }
&:hover { &:hover {
.u-field-upload-button, .u-field-remove-button { .u-field-upload-button, .u-field-remove-button {
opacity: 1; opacity: 1;
background-color: $shadow-d2;
border-radius: ($baseline/4);
} }
} }
} }
......
...@@ -6,10 +6,11 @@ ...@@ -6,10 +6,11 @@
<span class="upload-button-title" aria-live="polite"><%= uploadButtonTitle %></span> <span class="upload-button-title" aria-live="polite"><%= uploadButtonTitle %></span>
<input class="upload-button-input" type="file" name="<%= id %>"/> <input class="upload-button-input" type="file" name="<%= id %>"/>
</label> </label>
<button class="upload-submit" type="button" hidden="true"><%= uploadButtonTitle %></button>
<button class="u-field-remove-button" type="button"> <button class="u-field-remove-button" type="button">
<span class="remove-button-icon" aria-hidden="true"><%= removeButtonIcon %></span> <span class="remove-button-icon" aria-hidden="true"><%= removeButtonIcon %></span>
<span class="remove-button-title" aria-live="polite"><%= removeButtonTitle %></span> <span class="remove-button-title" aria-live="polite"><%= removeButtonTitle %></span>
</button> </button>
</div> </div>
</div> </div>
\ No newline at end of file
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