FIX: Associate category logo and background to uploads record.

This commit is contained in:
Guo Xiang Tan 2016-12-02 15:15:34 +08:00
parent beb8245d04
commit 9a800107cb
19 changed files with 105 additions and 45 deletions

View File

@ -1,2 +1,40 @@
import { buildCategoryPanel } from 'discourse/components/edit-category-panel'; import { buildCategoryPanel } from 'discourse/components/edit-category-panel';
export default buildCategoryPanel('images'); import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
export default buildCategoryPanel('images').extend({
@computed('category.uploaded_background.url')
backgroundImageUrl(uploadedBackgroundUrl) {
return uploadedBackgroundUrl || '';
},
@computed('category.uploaded_background.id')
backgroundImageId(uploadedBackgroundId) {
return uploadedBackgroundId || null;
},
@computed('category.uploaded_logo.url')
logoImageUrl(uploadedLogoUrl) {
return uploadedLogoUrl || '';
},
@computed('category.uploaded_logo.id')
logoImageId(uploadedLogoId) {
return uploadedLogoId || null;
},
@observes("backgroundImageUrl", "backgroundImageId")
_setBackgroundUpload() {
this.set("category.uploaded_background", Ember.Object.create({
id: this.get('backgroundImageId'),
url: this.get('backgroundImageUrl')
}));
},
@observes("logoImageUrl", "logoImageId")
_setLogoUpload() {
this.set("category.uploaded_logo", Ember.Object.create({
id: this.get('logoImageId'),
url: this.get('logoImageUrl')
}));
}
});

View File

@ -12,11 +12,13 @@ export default Em.Component.extend(UploadMixin, {
uploadDone(upload) { uploadDone(upload) {
this.set("imageUrl", upload.url); this.set("imageUrl", upload.url);
this.set("imageId", upload.id);
}, },
actions: { actions: {
trash() { trash() {
this.set("imageUrl", null); this.set("imageUrl", null);
this.set("imageId", null);
} }
} }
}); });

View File

@ -91,8 +91,8 @@ const Category = RestModel.extend({
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'), uploaded_logo_id: this.get('uploaded_logo.id'),
background_url: this.get('background_url'), uploaded_background_id: this.get('uploaded_background.id'),
allow_badges: this.get('allow_badges'), allow_badges: this.get('allow_badges'),
custom_fields: this.get('custom_fields'), custom_fields: this.get('custom_fields'),
topic_template: this.get('topic_template'), topic_template: this.get('topic_template'),

View File

@ -11,7 +11,7 @@
</thead> </thead>
<tbody> <tbody>
{{#each categories as |c|}} {{#each categories as |c|}}
<tr data-category-id={{c.id}} class="{{if c.description_excerpt 'has-description' 'no-description'}} {{if c.logo_url 'has-logo' 'no-logo'}}"> <tr data-category-id={{c.id}} class="{{if c.description_excerpt 'has-description' 'no-description'}} {{if c.uploaded_logo.url 'has-logo' 'no-logo'}}">
<td class="category" style={{border-color c.color}}> <td class="category" style={{border-color c.color}}>
<div> <div>
{{category-title-link category=c}} {{category-title-link category=c}}

View File

@ -5,7 +5,7 @@
<span class="category-name">{{category.name}}</span> <span class="category-name">{{category.name}}</span>
{{#if category.logo_url}} {{#if category.uploaded_logo.url}}
<div>{{cdn-img src=category.logo_url class="category-logo"}}</div> <div>{{cdn-img src=category.uploaded_logo.url class="category-logo"}}</div>
{{/if}} {{/if}}
</a> </a>

View File

@ -1,9 +1,16 @@
<section class='field'> <section class='field'>
<label>{{i18n 'category.logo'}}</label> <label>{{i18n 'category.logo'}}</label>
{{image-uploader imageUrl=category.logo_url type="category_logo" class="no-repeat"}} {{image-uploader
imageId=logoImageId
imageUrl=logoImageUrl
type="category_logo"
class="no-repeat"}}
</section> </section>
<section class='field'> <section class='field'>
<label>{{i18n 'category.background_image'}}</label> <label>{{i18n 'category.background_image'}}</label>
{{image-uploader imageUrl=category.background_url type="category_background"}} {{image-uploader
imageId=backgroundImageId
imageUrl=backgroundImageUrl
type="category_background"}}
</section> </section>

View File

@ -233,8 +233,8 @@ class CategoriesController < ApplicationController
:parent_category_id, :parent_category_id,
:auto_close_hours, :auto_close_hours,
:auto_close_based_on_last_post, :auto_close_based_on_last_post,
:logo_url, :uploaded_logo_id,
:background_url, :uploaded_background_id,
:slug, :slug,
:allow_badges, :allow_badges,
:topic_template, :topic_template,

View File

@ -21,12 +21,12 @@ module Jobs
.joins("LEFT JOIN users u ON u.uploaded_avatar_id = uploads.id") .joins("LEFT JOIN users u ON u.uploaded_avatar_id = uploads.id")
.joins("LEFT JOIN user_avatars ua ON (ua.gravatar_upload_id = uploads.id OR ua.custom_upload_id = uploads.id)") .joins("LEFT JOIN user_avatars ua ON (ua.gravatar_upload_id = uploads.id OR ua.custom_upload_id = uploads.id)")
.joins("LEFT JOIN user_profiles up ON up.profile_background = uploads.url OR up.card_background = uploads.url") .joins("LEFT JOIN user_profiles up ON up.profile_background = uploads.url OR up.card_background = uploads.url")
.joins("LEFT JOIN categories c ON c.logo_url = uploads.url OR c.background_url = uploads.url") .joins("LEFT JOIN categories c ON c.uploaded_logo_id = uploads.id OR c.uploaded_background_id = uploads.id")
.where("pu.upload_id IS NULL") .where("pu.upload_id IS NULL")
.where("u.uploaded_avatar_id IS NULL") .where("u.uploaded_avatar_id IS NULL")
.where("ua.gravatar_upload_id IS NULL AND ua.custom_upload_id IS NULL") .where("ua.gravatar_upload_id IS NULL AND ua.custom_upload_id IS NULL")
.where("up.profile_background IS NULL AND up.card_background IS NULL") .where("up.profile_background IS NULL AND up.card_background IS NULL")
.where("c.logo_url IS NULL AND c.background_url IS NULL") .where("c.uploaded_logo_id IS NULL AND c.uploaded_background_id IS NULL")
.where("uploads.url NOT IN (?)", ignore_urls) .where("uploads.url NOT IN (?)", ignore_urls)
result.find_each do |upload| result.find_each do |upload|

View File

@ -15,6 +15,8 @@ class Category < ActiveRecord::Base
belongs_to :user belongs_to :user
belongs_to :latest_post, class_name: "Post" belongs_to :latest_post, class_name: "Post"
belongs_to :uploaded_logo, class_name: "Upload"
belongs_to :uploaded_background, class_name: "Upload"
has_many :topics has_many :topics
has_many :category_users has_many :category_users
@ -38,9 +40,6 @@ class Category < ActiveRecord::Base
validate :email_in_validator validate :email_in_validator
validates :logo_url, upload_url: true, if: :logo_url_changed?
validates :background_url, upload_url: true, if: :background_url_changed?
validate :ensure_slug validate :ensure_slug
before_save :apply_permissions before_save :apply_permissions
before_save :downcase_email before_save :downcase_email

View File

@ -49,7 +49,13 @@ class CategoryList
end end
def find_categories def find_categories
@categories = Category.includes(:topic_only_relative_url, subcategories: [:topic_only_relative_url]).secured(@guardian) @categories = Category.includes(
:uploaded_background,
:uploaded_logo,
:topic_only_relative_url,
subcategories: [:topic_only_relative_url]
).secured(@guardian)
@categories = @categories.where(suppress_from_homepage: false) if @options[:is_homepage] @categories = @categories.where(suppress_from_homepage: false) if @options[:is_homepage]
@categories = @categories.where("categories.parent_category_id = ?", @options[:parent_category_id].to_i) if @options[:parent_category_id].present? @categories = @categories.where("categories.parent_category_id = ?", @options[:parent_category_id].to_i) if @options[:parent_category_id].present?

View File

@ -28,6 +28,7 @@ class Site
def categories def categories
@categories ||= begin @categories ||= begin
categories = Category categories = Category
.includes(:uploaded_logo, :uploaded_background)
.secured(@guardian) .secured(@guardian)
.joins('LEFT JOIN topics t on t.id = categories.topic_id') .joins('LEFT JOIN topics t on t.id = categories.topic_id')
.select('categories.*, t.slug topic_slug') .select('categories.*, t.slug topic_slug')

View File

@ -11,8 +11,6 @@ class BasicCategorySerializer < ApplicationSerializer
:description, :description,
:description_text, :description_text,
:topic_url, :topic_url,
:logo_url,
:background_url,
:read_restricted, :read_restricted,
:permission, :permission,
:parent_category_id, :parent_category_id,
@ -23,6 +21,9 @@ class BasicCategorySerializer < ApplicationSerializer
:sort_order, :sort_order,
:sort_ascending :sort_ascending
has_one :uploaded_logo, embed: :object, serializer: CategoryUploadSerializer
has_one :uploaded_background, embed: :object, serializer: CategoryUploadSerializer
def include_parent_category_id? def include_parent_category_id?
parent_category_id parent_category_id
end end

View File

@ -0,0 +1,3 @@
class CategoryUploadSerializer < ApplicationSerializer
attributes :id, :url
end

View File

@ -0,0 +1,21 @@
class AddUploadsToCategories < ActiveRecord::Migration
def up
add_column :categories, :uploaded_logo_id, :integer, index: true
add_column :categories, :uploaded_background_id, :integer, index: true
transaction do
Category.find_each do |category|
logo_upload = Upload.find_by(url: category.logo_url)
category.uploaded_logo_id = logo_upload.id if logo_upload
background_upload = Upload.find_by(url: category.background_url)
category.uploaded_background_id = background_upload.id if background_upload
category.save!
end
end
remove_column :categories, :logo_url, :string
remove_column :categories, :background_url, :string
end
end

View File

@ -24,7 +24,7 @@ module ImportExport
CATEGORY_ATTRS = [:id, :name, :color, :created_at, :user_id, :slug, :description, :text_color, CATEGORY_ATTRS = [:id, :name, :color, :created_at, :user_id, :slug, :description, :text_color,
:auto_close_hours, :logo_url, :background_url, :auto_close_based_on_last_post, :auto_close_hours, :auto_close_based_on_last_post,
:topic_template, :suppress_from_homepage, :permissions_params] :topic_template, :suppress_from_homepage, :permissions_params]
def export_categories def export_categories

View File

@ -23,7 +23,7 @@ class DiscourseSassImporter < Sass::Importers::Filesystem
"plugins_desktop" => DiscoursePluginRegistry.desktop_stylesheets, "plugins_desktop" => DiscoursePluginRegistry.desktop_stylesheets,
"plugins_variables" => DiscoursePluginRegistry.sass_variables, "plugins_variables" => DiscoursePluginRegistry.sass_variables,
"theme_variables" => [ColorScheme::BASE_COLORS_FILE], "theme_variables" => [ColorScheme::BASE_COLORS_FILE],
"category_backgrounds" => Proc.new { |c| "body.category-#{c.full_slug} { background-image: url(#{apply_cdn(c.background_url)}) }\n" } "category_backgrounds" => Proc.new { |c| "body.category-#{c.full_slug} { background-image: url(#{apply_cdn(c.uploaded_background.url)}) }\n" }
} }
end end
@ -53,8 +53,8 @@ class DiscourseSassImporter < Sass::Importers::Filesystem
end end
when "category_backgrounds" when "category_backgrounds"
contents = "" contents = ""
Category.where('background_url IS NOT NULL').each do |c| Category.where('uploaded_background_id IS NOT NULL').each do |c|
contents << special_imports[name].call(c) if c.background_url.present? contents << special_imports[name].call(c) if c.uploaded_background
end end
else else
stylesheets = special_imports[name] stylesheets = special_imports[name]

View File

@ -160,7 +160,7 @@ class DiscourseStylesheets
def digest def digest
@digest ||= begin @digest ||= begin
theme = (cs = ColorScheme.enabled) ? "#{cs.id}-#{cs.version}" : false theme = (cs = ColorScheme.enabled) ? "#{cs.id}-#{cs.version}" : false
category_updated = Category.where("background_url IS NOT NULL and background_url != ''").last_updated_at category_updated = Category.where("uploaded_background_id IS NOT NULL").last_updated_at
if theme || category_updated > 0 if theme || category_updated > 0
Digest::SHA1.hexdigest "#{RailsMultisite::ConnectionManagement.current_db}-#{theme}-#{DiscourseStylesheets.last_file_updated}-#{category_updated}" Digest::SHA1.hexdigest "#{RailsMultisite::ConnectionManagement.current_db}-#{theme}-#{DiscourseStylesheets.last_file_updated}-#{category_updated}"

View File

@ -55,7 +55,7 @@ describe Jobs::CleanUpUploads do
it "does not delete category logo uploads" do it "does not delete category logo uploads" do
category_logo_upload = fabricate_upload category_logo_upload = fabricate_upload
Fabricate(:category, logo_url: category_logo_upload.url) Fabricate(:category, uploaded_logo: category_logo_upload)
Jobs::CleanUpUploads.new.execute(nil) Jobs::CleanUpUploads.new.execute(nil)
@ -64,13 +64,13 @@ describe Jobs::CleanUpUploads do
end end
it "does not delete category background url uploads" do it "does not delete category background url uploads" do
category_background_url = fabricate_upload category_logo_upload = fabricate_upload
Fabricate(:category, background_url: category_background_url.url) Fabricate(:category, uploaded_background: category_logo_upload)
Jobs::CleanUpUploads.new.execute(nil) Jobs::CleanUpUploads.new.execute(nil)
expect(Upload.find_by(id: @upload.id)).to eq(nil) expect(Upload.find_by(id: @upload.id)).to eq(nil)
expect(Upload.find_by(id: category_background_url.id)).to eq(category_background_url) expect(Upload.find_by(id: category_logo_upload.id)).to eq(category_logo_upload)
end end
it "does not delete post uploads" do it "does not delete post uploads" do

View File

@ -12,24 +12,6 @@ describe Category do
is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_category_id) is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_category_id)
end end
context "url validation" do
let(:user) { Fabricate(:user) }
let(:upload) { Fabricate(:upload) }
it "ensures logo_url is valid" do
expect(Fabricate.build(:category, user: user, logo_url: "---%")).not_to be_valid
expect(Fabricate.build(:category, user: user, logo_url: "http://example.com/made-up.jpg")).not_to be_valid
expect(Fabricate.build(:category, user: user, logo_url: upload.url)).to be_valid
end
it "ensures background_url is valid" do
expect(Fabricate.build(:category, user: user, background_url: ";test")).not_to be_valid
expect(Fabricate.build(:category, user: user, background_url: "http://example.com/no.jpg")).not_to be_valid
expect(Fabricate.build(:category, user: user, background_url: upload.url)).to be_valid
end
end
it 'validates uniqueness in case insensitive way' do it 'validates uniqueness in case insensitive way' do
Fabricate(:category, name: "Cats") Fabricate(:category, name: "Cats")
cats = Fabricate.build(:category, name: "cats") cats = Fabricate.build(:category, name: "cats")