mirror of
https://github.com/discourse/discourse.git
synced 2024-11-26 19:13:39 +08:00
FEATURE: Can upload images to categories
This commit is contained in:
parent
9000c358d1
commit
e22688a204
|
@ -13,7 +13,19 @@ export default Em.Component.extend(UploadMixin, {
|
||||||
this.set('imageUrl', data.result.url);
|
this.set('imageUrl', data.result.url);
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteDone: function() {
|
actions: {
|
||||||
this.set('imageUrl', null);
|
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'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
**/
|
**/
|
||||||
export default Discourse.ObjectController.extend(Discourse.ModalFunctionality, {
|
export default Discourse.ObjectController.extend(Discourse.ModalFunctionality, {
|
||||||
foregroundColors: ['FFFFFF', '000000'],
|
foregroundColors: ['FFFFFF', '000000'],
|
||||||
|
categoryUploadUrl: '/category/uploads',
|
||||||
|
|
||||||
parentCategories: function() {
|
parentCategories: function() {
|
||||||
return Discourse.Category.list().filter(function (c) {
|
return Discourse.Category.list().filter(function (c) {
|
||||||
|
|
|
@ -53,18 +53,6 @@ export default Em.Mixin.create({
|
||||||
actions: {
|
actions: {
|
||||||
selectFile: function() {
|
selectFile: function() {
|
||||||
this.$('input[type=file]').click();
|
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'));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,7 +68,9 @@ Discourse.Category = Discourse.Model.extend({
|
||||||
position: this.get('position'),
|
position: this.get('position'),
|
||||||
email_in: this.get('email_in'),
|
email_in: this.get('email_in'),
|
||||||
email_in_allow_strangers: this.get('email_in_allow_strangers'),
|
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'
|
type: this.get('id') ? 'PUT' : 'POST'
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
|
@ -94,6 +94,7 @@
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{image-uploader uploadUrl=imageUploadUrl
|
{{image-uploader uploadUrl=imageUploadUrl
|
||||||
imageUrl=profile_background
|
imageUrl=profile_background
|
||||||
|
instantDelete="true"
|
||||||
type="profile_background"}}
|
type="profile_background"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -186,3 +186,9 @@ animation: modal .25s;
|
||||||
.uploaded-avatar {
|
.uploaded-avatar {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uploaded-image-preview {
|
||||||
|
width: 400px;
|
||||||
|
max-height: 150px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,19 @@ class CategoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
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
|
def move
|
||||||
guardian.ensure_can_create!(Category)
|
guardian.ensure_can_create!(Category)
|
||||||
|
|
||||||
|
@ -105,7 +118,7 @@ class CategoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,11 @@ module Jobs
|
||||||
def execute(args)
|
def execute(args)
|
||||||
return unless SiteSetting.clean_up_uploads?
|
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
|
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 upload_id from post_uploads)")
|
||||||
.where("id NOT IN (SELECT custom_upload_id from user_avatars)")
|
.where("id NOT IN (SELECT custom_upload_id from user_avatars)")
|
||||||
.where("id NOT IN (SELECT gravatar_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|
|
.find_each do |upload|
|
||||||
upload.destroy
|
upload.destroy
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,9 @@ class BasicCategorySerializer < ApplicationSerializer
|
||||||
:read_restricted,
|
:read_restricted,
|
||||||
:permission,
|
:permission,
|
||||||
:parent_category_id,
|
:parent_category_id,
|
||||||
:notification_level
|
:notification_level,
|
||||||
|
:logo_url,
|
||||||
|
:background_url
|
||||||
|
|
||||||
def include_parent_category_id?
|
def include_parent_category_id?
|
||||||
parent_category_id
|
parent_category_id
|
||||||
|
|
|
@ -1146,6 +1146,8 @@ en:
|
||||||
name: "Category Name"
|
name: "Category Name"
|
||||||
description: "Description"
|
description: "Description"
|
||||||
topic: "category topic"
|
topic: "category topic"
|
||||||
|
logo: "Category Logo Image"
|
||||||
|
background_image: "Category Background Image"
|
||||||
badge_colors: "Badge colors"
|
badge_colors: "Badge colors"
|
||||||
background_color: "Background color"
|
background_color: "Background color"
|
||||||
foreground_color: "Foreground color"
|
foreground_color: "Foreground color"
|
||||||
|
|
|
@ -275,6 +275,7 @@ Discourse::Application.routes.draw do
|
||||||
|
|
||||||
resources :categories, :except => :show
|
resources :categories, :except => :show
|
||||||
get "category/:id/show" => "categories#show"
|
get "category/:id/show" => "categories#show"
|
||||||
|
post "category/uploads" => "categories#upload"
|
||||||
post "category/:category_id/move" => "categories#move"
|
post "category/:category_id/move" => "categories#move"
|
||||||
get "category/:category.rss" => "list#category_feed", format: :rss
|
get "category/:category.rss" => "list#category_feed", format: :rss
|
||||||
get "category/:parent_category/:category.rss" => "list#category_feed", format: :rss
|
get "category/:parent_category/:category.rss" => "list#category_feed", format: :rss
|
||||||
|
|
6
db/migrate/20140627193814_add_images_to_categories.rb
Normal file
6
db/migrate/20140627193814_add_images_to_categories.rb
Normal 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
|
|
@ -95,6 +95,37 @@ describe CategoriesController do
|
||||||
|
|
||||||
end
|
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
|
describe "update" do
|
||||||
|
|
||||||
it "requires the user to be logged in" do
|
it "requires the user to be logged in" do
|
||||||
|
|
|
@ -1272,7 +1272,7 @@ describe UsersController do
|
||||||
describe '.destroy_user_image' do
|
describe '.destroy_user_image' do
|
||||||
|
|
||||||
it 'raises an error when not logged in' 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
|
end
|
||||||
|
|
||||||
context 'while logged in' do
|
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
|
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)
|
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
|
response.should be_forbidden
|
||||||
end
|
end
|
||||||
|
|
||||||
it "requires the `image_type` param" do
|
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
|
end
|
||||||
|
|
||||||
it "only allows certain `image_types`" do
|
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
|
end
|
||||||
|
|
||||||
it 'can clear the profile background' do
|
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 == ""
|
user.reload.user_profile.profile_background.should == ""
|
||||||
response.should be_success
|
response.should be_success
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user