FEATURE: Can upload images to categories

This commit is contained in:
Robin Ward 2014-06-27 15:35:25 -04:00
parent 9000c358d1
commit e22688a204
15 changed files with 102 additions and 24 deletions

View file

@ -13,7 +13,19 @@ export default Em.Component.extend(UploadMixin, {
this.set('imageUrl', data.result.url);
},
deleteDone: function() {
this.set('imageUrl', null);
actions: {
trash: function() {
this.set('imageUrl', null);
// Do we want to signal the delete to the server right away?
if (this.get('instantDelete')) {
Discourse.ajax(this.get('uploadUrl'), {
type: 'DELETE',
data: { image_type: this.get('type') }
}).then(null, function() {
bootbox.alert(I18n.t('generic_error'));
});
}
}
}
});

View file

@ -9,6 +9,7 @@
**/
export default Discourse.ObjectController.extend(Discourse.ModalFunctionality, {
foregroundColors: ['FFFFFF', '000000'],
categoryUploadUrl: '/category/uploads',
parentCategories: function() {
return Discourse.Category.list().filter(function (c) {

View file

@ -53,18 +53,6 @@ export default Em.Mixin.create({
actions: {
selectFile: function() {
this.$('input[type=file]').click();
},
trash: function() {
var self = this;
Discourse.ajax(this.get('uploadUrl'), {
type: 'DELETE',
data: { image_type: this.get('type') }
}).then(function() {
self.deleteDone();
}).catch(function() {
bootbox.alert(I18n.t('generic_error'));
});
}
}
});

View file

@ -68,7 +68,9 @@ Discourse.Category = Discourse.Model.extend({
position: this.get('position'),
email_in: this.get('email_in'),
email_in_allow_strangers: this.get('email_in_allow_strangers'),
parent_category_id: this.get('parent_category_id')
parent_category_id: this.get('parent_category_id'),
logo_url: this.get('logo_url'),
background_url: this.get('background_url')
},
type: this.get('id') ? 'PUT' : 'POST'
});

View file

@ -0,0 +1,9 @@
<section class='field'>
<label>{{i18n category.logo}}</label>
{{image-uploader uploadUrl=categoryUploadUrl imageUrl=logo_url type="logo"}}
</section>
<section class='field'>
<label>{{i18n category.background_image}}</label>
{{image-uploader uploadUrl=categoryUploadUrl imageUrl=background_url type="background"}}
</section>

View file

@ -94,6 +94,7 @@
<div class="controls">
{{image-uploader uploadUrl=imageUploadUrl
imageUrl=profile_background
instantDelete="true"
type="profile_background"}}
</div>
</div>

View file

@ -186,3 +186,9 @@ animation: modal .25s;
.uploaded-avatar {
margin-top: 20px;
}
.uploaded-image-preview {
width: 400px;
max-height: 150px;
margin-bottom: 10px;
}

View file

@ -26,6 +26,19 @@ class CategoriesController < ApplicationController
end
end
def upload
params.require(:image_type)
guardian.ensure_can_create!(Category)
file = params[:file] || params[:files].first
upload = Upload.create_for(current_user.id, file.tempfile, file.original_filename, File.size(file.tempfile))
if upload.errors.blank?
render json: { url: upload.url, width: upload.width, height: upload.height }
else
render status: 422, text: upload.errors.full_messages
end
end
def move
guardian.ensure_can_create!(Category)
@ -105,7 +118,7 @@ class CategoriesController < ApplicationController
end
end
params.permit(*required_param_keys, :position, :email_in, :email_in_allow_strangers, :parent_category_id, :auto_close_hours, :permissions => [*p.try(:keys)])
params.permit(*required_param_keys, :position, :email_in, :email_in_allow_strangers, :parent_category_id, :auto_close_hours, :logo_url, :background_url, :permissions => [*p.try(:keys)])
end
end

View file

@ -6,7 +6,11 @@ module Jobs
def execute(args)
return unless SiteSetting.clean_up_uploads?
uploads_used_as_profile_backgrounds = UserProfile.uniq.where("profile_background IS NOT NULL AND profile_background != ''").pluck(:profile_background)
ignore_urls = []
ignore_urls << UserProfile.uniq.where("profile_background IS NOT NULL AND profile_background != ''").pluck(:profile_background)
ignore_urls << Category.uniq.where("logo_url IS NOT NULL AND logo_url != ''").pluck(:logo_url)
ignore_urls << Category.uniq.where("background_url IS NOT NULL AND background_url != ''").pluck(:background_url)
ignore_urls.flatten!
grace_period = [SiteSetting.clean_orphan_uploads_grace_period_hours, 1].max
@ -14,7 +18,7 @@ module Jobs
.where("id NOT IN (SELECT upload_id from post_uploads)")
.where("id NOT IN (SELECT custom_upload_id from user_avatars)")
.where("id NOT IN (SELECT gravatar_upload_id from user_avatars)")
.where("url NOT IN (?)", uploads_used_as_profile_backgrounds)
.where("url NOT IN (?)", ignore_urls)
.find_each do |upload|
upload.destroy
end

View file

@ -12,7 +12,9 @@ class BasicCategorySerializer < ApplicationSerializer
:read_restricted,
:permission,
:parent_category_id,
:notification_level
:notification_level,
:logo_url,
:background_url
def include_parent_category_id?
parent_category_id

View file

@ -1146,6 +1146,8 @@ en:
name: "Category Name"
description: "Description"
topic: "category topic"
logo: "Category Logo Image"
background_image: "Category Background Image"
badge_colors: "Badge colors"
background_color: "Background color"
foreground_color: "Foreground color"

View file

@ -275,6 +275,7 @@ Discourse::Application.routes.draw do
resources :categories, :except => :show
get "category/:id/show" => "categories#show"
post "category/uploads" => "categories#upload"
post "category/:category_id/move" => "categories#move"
get "category/:category.rss" => "list#category_feed", format: :rss
get "category/:parent_category/:category.rss" => "list#category_feed", format: :rss

View file

@ -0,0 +1,6 @@
class AddImagesToCategories < ActiveRecord::Migration
def change
add_column :categories, :logo_url, :string
add_column :categories, :background_url, :string
end
end

View file

@ -95,6 +95,37 @@ describe CategoriesController do
end
describe "upload" do
it "requires the user to be logged in" do
lambda { xhr :post, :upload, image_type: 'logo'}.should raise_error(Discourse::NotLoggedIn)
end
describe "logged in" do
let!(:user) { log_in(:admin) }
let(:logo) { File.new("#{Rails.root}/spec/fixtures/images/logo.png") }
let(:upload) do
ActionDispatch::Http::UploadedFile.new({ filename: 'logo.png', tempfile: logo })
end
it "raises an error when you don't have permission to upload" do
Guardian.any_instance.expects(:can_create?).with(Category).returns(false)
xhr :post, :upload, image_type: 'logo', file: upload
response.should be_forbidden
end
it "requires the `image_type` param" do
-> { xhr :post, :upload }.should raise_error(ActionController::ParameterMissing)
end
it "calls Upload.create_for" do
Upload.expects(:create_for).returns(Upload.new)
xhr :post, :upload, image_type: 'logo', file: upload
response.should be_success
end
end
end
describe "update" do
it "requires the user to be logged in" do

View file

@ -1272,7 +1272,7 @@ describe UsersController do
describe '.destroy_user_image' do
it 'raises an error when not logged in' do
lambda { xhr :put, :destroy_user_image, type: 'profile_background', username: 'asdf' }.should raise_error(Discourse::NotLoggedIn)
lambda { xhr :delete, :destroy_user_image, type: 'profile_background', username: 'asdf' }.should raise_error(Discourse::NotLoggedIn)
end
context 'while logged in' do
@ -1281,20 +1281,20 @@ describe UsersController do
it 'raises an error when you don\'t have permission to clear the profile background' do
Guardian.any_instance.expects(:can_edit?).with(user).returns(false)
xhr :put, :destroy_user_image, username: user.username, image_type: 'profile_background'
xhr :delete, :destroy_user_image, username: user.username, image_type: 'profile_background'
response.should be_forbidden
end
it "requires the `image_type` param" do
-> { xhr :put, :destroy_user_image, username: user.username }.should raise_error(ActionController::ParameterMissing)
-> { xhr :delete, :destroy_user_image, username: user.username }.should raise_error(ActionController::ParameterMissing)
end
it "only allows certain `image_types`" do
-> { xhr :put, :destroy_user_image, username: user.username, image_type: 'wat' }.should raise_error(Discourse::InvalidParameters)
-> { xhr :delete, :destroy_user_image, username: user.username, image_type: 'wat' }.should raise_error(Discourse::InvalidParameters)
end
it 'can clear the profile background' do
xhr :put, :destroy_user_image, image_type: 'profile_background', username: user.username
xhr :delete, :destroy_user_image, image_type: 'profile_background', username: user.username
user.reload.user_profile.profile_background.should == ""
response.should be_success
end