mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-30 10:58:31 -05:00
REFACTOR: Convert profile background uploader to be an ember component
This commit is contained in:
parent
06880c28f8
commit
4088fba4f2
16 changed files with 118 additions and 107 deletions
|
@ -0,0 +1,61 @@
|
||||||
|
export default Em.Component.extend({
|
||||||
|
uploading: false,
|
||||||
|
uploadProgress: 0,
|
||||||
|
|
||||||
|
backgroundStyle: function() {
|
||||||
|
var imageUrl = this.get('imageUrl');
|
||||||
|
if (Em.isNone(imageUrl)) { return; }
|
||||||
|
|
||||||
|
return "background-image: url(" + imageUrl + ")";
|
||||||
|
}.property('imageUrl'),
|
||||||
|
|
||||||
|
_initializeUploader: function() {
|
||||||
|
var $upload = this.$('input[type=file]'), // note: we can't cache this as fileupload replaces the input after upload
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
$upload.fileupload({
|
||||||
|
url: this.get('uploadUrl'),
|
||||||
|
dataType: "json",
|
||||||
|
fileInput: $upload,
|
||||||
|
formData: { image_type: this.get('type') }
|
||||||
|
});
|
||||||
|
|
||||||
|
$upload.on('fileuploadsubmit', function (e, data) {
|
||||||
|
var result = Discourse.Utilities.validateUploadedFiles(data.files, true);
|
||||||
|
self.setProperties({ uploadProgress: 0, uploading: result });
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
$upload.on("fileuploadprogressall", function(e, data) {
|
||||||
|
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||||
|
self.set("uploadProgress", progress);
|
||||||
|
});
|
||||||
|
$upload.on("fileuploaddone", function(e, data) {
|
||||||
|
if(data.result.url) {
|
||||||
|
self.set('imageUrl', data.result.url);
|
||||||
|
} else {
|
||||||
|
bootbox.alert(I18n.t('post.errors.upload'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$upload.on("fileuploadfail", function(e, data) {
|
||||||
|
Discourse.Utilities.displayErrorForUpload(data);
|
||||||
|
});
|
||||||
|
$upload.on("fileuploadalways", function() {
|
||||||
|
self.setProperties({ uploading: false, uploadProgress: 0});
|
||||||
|
});
|
||||||
|
}.on('didInsertElement'),
|
||||||
|
|
||||||
|
_destroyUploader: function() {
|
||||||
|
this.$('input[type=file]').fileupload('destroy');
|
||||||
|
}.on('willDestroyElement'),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
selectFile: function() {
|
||||||
|
this.$('input[type=file]').click();
|
||||||
|
},
|
||||||
|
|
||||||
|
trash: function() {
|
||||||
|
this.set('imageUrl', null);
|
||||||
|
this.sendAction('clear');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -66,7 +66,14 @@ export default Discourse.ObjectController.extend({
|
||||||
return this.get('saving') ? I18n.t('saving') : I18n.t('save');
|
return this.get('saving') ? I18n.t('saving') : I18n.t('save');
|
||||||
}.property('saving'),
|
}.property('saving'),
|
||||||
|
|
||||||
|
imageUploadUrl: Discourse.computed.url('username', '/users/%@/preferences/user_image'),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
||||||
|
clearProfileBackground: function() {
|
||||||
|
this.get('model').clearProfileBackground();
|
||||||
|
},
|
||||||
|
|
||||||
save: function() {
|
save: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.setProperties({ saving: true, saved: false });
|
this.setProperties({ saving: true, saved: false });
|
||||||
|
|
|
@ -354,8 +354,6 @@ Discourse.User = Discourse.Model.extend({
|
||||||
return Discourse.ajax("/users/" + this.get("username_lower") + "/preferences/profile_background/clear", {
|
return Discourse.ajax("/users/" + this.get("username_lower") + "/preferences/profile_background/clear", {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: { }
|
data: { }
|
||||||
}).then(function() {
|
|
||||||
user.set('profile_background', null);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -63,12 +63,6 @@ Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
||||||
avatarSelector.send('closeModal');
|
avatarSelector.send('closeModal');
|
||||||
},
|
},
|
||||||
|
|
||||||
showProfileBackgroundFileSelector: function() {
|
|
||||||
$("#profile-background-input").click();
|
|
||||||
},
|
|
||||||
clearProfileBackground: function() {
|
|
||||||
this.modelFor('user').clearProfileBackground();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<input type="file" accept="image/*" style="display:none" />
|
||||||
|
<div class="uploaded-image-preview" class="input-xxlarge" {{bind-attr style="backgroundStyle"}}>
|
||||||
|
<div class="image-upload-controls">
|
||||||
|
<button {{action selectFile}} class="btn pad-left no-text"><i class="fa fa-picture-o"></i></button>
|
||||||
|
{{#if backgroundStyle}}
|
||||||
|
<button {{action trash}} class="btn btn-danger pad-left no-text"><i class="fa fa-trash-o"></i></button>
|
||||||
|
{{/if}}
|
||||||
|
<span {{bind-attr class=":btn uploading::hidden"}}>{{i18n upload_selector.uploading}} {{uploadProgress}}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -4,6 +4,7 @@
|
||||||
{{#unless isUncategorizedCategory}}
|
{{#unless isUncategorizedCategory}}
|
||||||
{{edit-category-tab selectedTab=selectedTab tab="security"}}
|
{{edit-category-tab selectedTab=selectedTab tab="security"}}
|
||||||
{{edit-category-tab selectedTab=selectedTab tab="settings"}}
|
{{edit-category-tab selectedTab=selectedTab tab="settings"}}
|
||||||
|
{{edit-category-tab selectedTab=selectedTab tab="images"}}
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
@ -92,18 +92,10 @@
|
||||||
<div class="control-group pref-profile-bg">
|
<div class="control-group pref-profile-bg">
|
||||||
<label class="control-label">{{i18n user.change_profile_background.title}}</label>
|
<label class="control-label">{{i18n user.change_profile_background.title}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="file" id="profile-background-input" accept="image/*" style="display:none" />
|
{{image-uploader uploadUrl=imageUploadUrl
|
||||||
<div id="profile-background-preview" class="input-xxlarge" {{bind-attr style="profileBackground"}}>
|
imageUrl=profile_background
|
||||||
<div id="profile-background-controls">
|
type="profile_background"
|
||||||
<button {{action showProfileBackgroundFileSelector}} class="btn pad-left no-text"><i class="fa fa-picture-o"></i></button>
|
clear="clearProfileBackground"}}
|
||||||
{{#if profileBackground}}
|
|
||||||
<button {{action clearProfileBackground}} class="btn btn-danger pad-left no-text"><i class="fa fa-trash-o"></i></button>
|
|
||||||
{{/if}}
|
|
||||||
{{#if view.uploading}}
|
|
||||||
<span class="btn">{{i18n upload_selector.uploading}} {{view.uploadProgress}}%</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -37,7 +37,7 @@ Discourse.AvatarSelectorView = Discourse.ModalBodyView.extend({
|
||||||
url: Discourse.getURL("/users/" + this.get("controller.username") + "/preferences/user_image"),
|
url: Discourse.getURL("/users/" + this.get("controller.username") + "/preferences/user_image"),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
fileInput: $upload,
|
fileInput: $upload,
|
||||||
formData: { user_image_type: "avatar" }
|
formData: { image_type: "avatar" }
|
||||||
});
|
});
|
||||||
|
|
||||||
// when a file has been selected
|
// when a file has been selected
|
||||||
|
|
|
@ -1,55 +1,4 @@
|
||||||
/**
|
|
||||||
This view handles rendering of a user's preferences
|
|
||||||
|
|
||||||
@class PreferencesView
|
|
||||||
@extends Discourse.View
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.PreferencesView = Discourse.View.extend({
|
Discourse.PreferencesView = Discourse.View.extend({
|
||||||
templateName: 'user/preferences',
|
templateName: 'user/preferences',
|
||||||
classNames: ['user-preferences'],
|
classNames: ['user-preferences']
|
||||||
|
|
||||||
uploading: false,
|
|
||||||
uploadProgress: 0,
|
|
||||||
|
|
||||||
didInsertElement: function() {
|
|
||||||
var self = this;
|
|
||||||
var $upload = $("#profile-background-input");
|
|
||||||
|
|
||||||
this._super();
|
|
||||||
|
|
||||||
$upload.fileupload({
|
|
||||||
url: Discourse.getURL("/users/" + this.get('controller.model.username') + "/preferences/user_image"),
|
|
||||||
dataType: "json",
|
|
||||||
fileInput: $upload,
|
|
||||||
formData: { user_image_type: "profile_background" }
|
|
||||||
});
|
|
||||||
|
|
||||||
$upload.on('fileuploadsubmit', function (e, data) {
|
|
||||||
var result = Discourse.Utilities.validateUploadedFiles(data.files, true);
|
|
||||||
self.setProperties({ uploadProgress: 0, uploading: result });
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
$upload.on("fileuploadprogressall", function(e, data) {
|
|
||||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
|
||||||
self.set("uploadProgress", progress);
|
|
||||||
});
|
|
||||||
$upload.on("fileuploaddone", function(e, data) {
|
|
||||||
if(data.result.url) {
|
|
||||||
self.set("controller.model.profile_background", data.result.url);
|
|
||||||
} else {
|
|
||||||
bootbox.alert(I18n.t('post.errors.upload'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$upload.on("fileuploadfail", function(e, data) {
|
|
||||||
Discourse.Utilities.displayErrorForUpload(data);
|
|
||||||
});
|
|
||||||
$upload.on("fileuploadalways", function() {
|
|
||||||
self.setProperties({ uploading: false, uploadProgress: 0});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
willDestroyElement: function() {
|
|
||||||
$("#profile-background-input").fileupload("destroy");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,3 +29,14 @@
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uploaded-image-preview {
|
||||||
|
height: 270px;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-upload-controls {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -43,19 +43,6 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#profile-background-preview {
|
|
||||||
height: 270px;
|
|
||||||
|
|
||||||
background-position: center center;
|
|
||||||
background-size: cover;
|
|
||||||
|
|
||||||
background-color: $primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
#profile-background-controls {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.static {
|
.static {
|
||||||
color: $primary;
|
color: $primary;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -10,3 +10,10 @@
|
||||||
color: scale-color($primary, $lightness: 50%);
|
color: scale-color($primary, $lightness: 50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uploaded-image-preview {
|
||||||
|
height: 150px;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
|
|
@ -63,13 +63,6 @@
|
||||||
padding: 5px 8px;
|
padding: 5px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#profile-background-preview {
|
|
||||||
height: 150px;
|
|
||||||
background-position: center center;
|
|
||||||
background-size: cover;
|
|
||||||
background-color: $primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bio-composer #wmd-quote-post {
|
.bio-composer #wmd-quote-post {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,12 +333,12 @@ class UsersController < ApplicationController
|
||||||
|
|
||||||
# LEGACY: used by the API
|
# LEGACY: used by the API
|
||||||
def upload_avatar
|
def upload_avatar
|
||||||
params[:user_image_type] = "avatar"
|
params[:image_type] = "avatar"
|
||||||
upload_user_image
|
upload_user_image
|
||||||
end
|
end
|
||||||
|
|
||||||
def upload_user_image
|
def upload_user_image
|
||||||
params.require(:user_image_type)
|
params.require(:image_type)
|
||||||
user = fetch_user_from_params
|
user = fetch_user_from_params
|
||||||
guardian.ensure_can_edit!(user)
|
guardian.ensure_can_edit!(user)
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ class UsersController < ApplicationController
|
||||||
upload = Upload.create_for(user.id, image.file, image.filename, image.filesize)
|
upload = Upload.create_for(user.id, image.file, image.filename, image.filesize)
|
||||||
|
|
||||||
if upload.errors.empty?
|
if upload.errors.empty?
|
||||||
case params[:user_image_type]
|
case params[:image_type]
|
||||||
when "avatar"
|
when "avatar"
|
||||||
upload_avatar_for(user, upload)
|
upload_avatar_for(user, upload)
|
||||||
when "profile_background"
|
when "profile_background"
|
||||||
|
|
|
@ -1158,6 +1158,7 @@ en:
|
||||||
change_in_category_topic: "Edit Description"
|
change_in_category_topic: "Edit Description"
|
||||||
already_used: 'This color has been used by another category'
|
already_used: 'This color has been used by another category'
|
||||||
security: "Security"
|
security: "Security"
|
||||||
|
images: "Images"
|
||||||
auto_close_label: "Auto-close topics after:"
|
auto_close_label: "Auto-close topics after:"
|
||||||
auto_close_units: "hours"
|
auto_close_units: "hours"
|
||||||
email_in: "Custom incoming email address:"
|
email_in: "Custom incoming email address:"
|
||||||
|
|
|
@ -1126,7 +1126,7 @@ describe UsersController do
|
||||||
ActionDispatch::Http::UploadedFile.new({ filename: 'logo.png', tempfile: logo })
|
ActionDispatch::Http::UploadedFile.new({ filename: 'logo.png', tempfile: logo })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an error without a user_image_type param' do
|
it 'raises an error without a image_type param' do
|
||||||
lambda { xhr :put, :upload_user_image, username: user.username }.should raise_error(ActionController::ParameterMissing)
|
lambda { xhr :put, :upload_user_image, username: user.username }.should raise_error(ActionController::ParameterMissing)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1134,19 +1134,19 @@ describe UsersController do
|
||||||
|
|
||||||
it 'raises an error when you don\'t have permission to upload an user image' do
|
it 'raises an error when you don\'t have permission to upload an user image' do
|
||||||
Guardian.any_instance.expects(:can_edit?).with(user).returns(false)
|
Guardian.any_instance.expects(:can_edit?).with(user).returns(false)
|
||||||
xhr :post, :upload_user_image, username: user.username, user_image_type: "avatar"
|
xhr :post, :upload_user_image, username: user.username, image_type: "avatar"
|
||||||
response.should be_forbidden
|
response.should be_forbidden
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rejects large images' do
|
it 'rejects large images' do
|
||||||
SiteSetting.stubs(:max_image_size_kb).returns(1)
|
SiteSetting.stubs(:max_image_size_kb).returns(1)
|
||||||
xhr :post, :upload_user_image, username: user.username, file: user_image, user_image_type: "avatar"
|
xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "avatar"
|
||||||
response.status.should eq 422
|
response.status.should eq 422
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rejects unauthorized images' do
|
it 'rejects unauthorized images' do
|
||||||
SiteSetting.stubs(:authorized_extensions).returns(".txt")
|
SiteSetting.stubs(:authorized_extensions).returns(".txt")
|
||||||
xhr :post, :upload_user_image, username: user.username, file: user_image, user_image_type: "avatar"
|
xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "avatar"
|
||||||
response.status.should eq 422
|
response.status.should eq 422
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1154,7 +1154,7 @@ describe UsersController do
|
||||||
upload = Fabricate(:upload)
|
upload = Fabricate(:upload)
|
||||||
Upload.expects(:create_for).returns(upload)
|
Upload.expects(:create_for).returns(upload)
|
||||||
# enqueues the user_image generator job
|
# enqueues the user_image generator job
|
||||||
xhr :post, :upload_user_image, username: user.username, file: user_image, user_image_type: "avatar"
|
xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "avatar"
|
||||||
# returns the url, width and height of the uploaded image
|
# returns the url, width and height of the uploaded image
|
||||||
json = JSON.parse(response.body)
|
json = JSON.parse(response.body)
|
||||||
json['url'].should == "/uploads/default/1/1234567890123456.png"
|
json['url'].should == "/uploads/default/1/1234567890123456.png"
|
||||||
|
@ -1166,7 +1166,7 @@ describe UsersController do
|
||||||
it 'is successful for profile backgrounds' do
|
it 'is successful for profile backgrounds' do
|
||||||
upload = Fabricate(:upload)
|
upload = Fabricate(:upload)
|
||||||
Upload.expects(:create_for).returns(upload)
|
Upload.expects(:create_for).returns(upload)
|
||||||
xhr :post, :upload_user_image, username: user.username, file: user_image, user_image_type: "profile_background"
|
xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "profile_background"
|
||||||
user.reload
|
user.reload
|
||||||
|
|
||||||
user.user_profile.profile_background.should == "/uploads/default/1/1234567890123456.png"
|
user.user_profile.profile_background.should == "/uploads/default/1/1234567890123456.png"
|
||||||
|
@ -1191,13 +1191,13 @@ describe UsersController do
|
||||||
|
|
||||||
it 'rejects large images' do
|
it 'rejects large images' do
|
||||||
SiteSetting.stubs(:max_image_size_kb).returns(1)
|
SiteSetting.stubs(:max_image_size_kb).returns(1)
|
||||||
xhr :post, :upload_user_image, username: user.username, file: user_image_url, user_image_type: "profile_background"
|
xhr :post, :upload_user_image, username: user.username, file: user_image_url, image_type: "profile_background"
|
||||||
response.status.should eq 422
|
response.status.should eq 422
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rejects unauthorized images' do
|
it 'rejects unauthorized images' do
|
||||||
SiteSetting.stubs(:authorized_extensions).returns(".txt")
|
SiteSetting.stubs(:authorized_extensions).returns(".txt")
|
||||||
xhr :post, :upload_user_image, username: user.username, file: user_image_url, user_image_type: "profile_background"
|
xhr :post, :upload_user_image, username: user.username, file: user_image_url, image_type: "profile_background"
|
||||||
response.status.should eq 422
|
response.status.should eq 422
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1205,7 +1205,7 @@ describe UsersController do
|
||||||
upload = Fabricate(:upload)
|
upload = Fabricate(:upload)
|
||||||
Upload.expects(:create_for).returns(upload)
|
Upload.expects(:create_for).returns(upload)
|
||||||
# enqueues the user_image generator job
|
# enqueues the user_image generator job
|
||||||
xhr :post, :upload_avatar, username: user.username, file: user_image_url, user_image_type: "avatar"
|
xhr :post, :upload_avatar, username: user.username, file: user_image_url, image_type: "avatar"
|
||||||
json = JSON.parse(response.body)
|
json = JSON.parse(response.body)
|
||||||
json['url'].should == "/uploads/default/1/1234567890123456.png"
|
json['url'].should == "/uploads/default/1/1234567890123456.png"
|
||||||
json['width'].should == 100
|
json['width'].should == 100
|
||||||
|
@ -1216,7 +1216,7 @@ describe UsersController do
|
||||||
it 'is successful for profile backgrounds' do
|
it 'is successful for profile backgrounds' do
|
||||||
upload = Fabricate(:upload)
|
upload = Fabricate(:upload)
|
||||||
Upload.expects(:create_for).returns(upload)
|
Upload.expects(:create_for).returns(upload)
|
||||||
xhr :post, :upload_user_image, username: user.username, file: user_image_url, user_image_type: "profile_background"
|
xhr :post, :upload_user_image, username: user.username, file: user_image_url, image_type: "profile_background"
|
||||||
user.reload
|
user.reload
|
||||||
user.user_profile.profile_background.should == "/uploads/default/1/1234567890123456.png"
|
user.user_profile.profile_background.should == "/uploads/default/1/1234567890123456.png"
|
||||||
|
|
||||||
|
@ -1229,7 +1229,7 @@ describe UsersController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should handle malformed urls" do
|
it "should handle malformed urls" do
|
||||||
xhr :post, :upload_user_image, username: user.username, file: "foobar", user_image_type: "profile_background"
|
xhr :post, :upload_user_image, username: user.username, file: "foobar", image_type: "profile_background"
|
||||||
response.status.should eq 422
|
response.status.should eq 422
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue