Merge pull request #3068 from fantasticfears/category_slug

support setting category slug
This commit is contained in:
Régis Hanol 2015-01-02 11:55:27 +01:00
commit 9fcaf090ec
11 changed files with 92 additions and 15 deletions

View file

@ -146,9 +146,9 @@ export default ObjectController.extend(ModalFunctionality, {
}).catch(function(error) { }).catch(function(error) {
if (error && error.responseText) { if (error && error.responseText) {
self.flash($.parseJSON(error.responseText).errors[0]); self.flash($.parseJSON(error.responseText).errors[0], 'error');
} else { } else {
self.flash(I18n.t('generic_error')); self.flash(I18n.t('generic_error'), 'error');
} }
self.set('saving', false); self.set('saving', false);
}); });

View file

@ -58,6 +58,7 @@ Discourse.Category = Discourse.Model.extend({
return Discourse.ajax(url, { return Discourse.ajax(url, {
data: { data: {
name: this.get('name'), name: this.get('name'),
slug: this.get('slug'),
color: this.get('color'), color: this.get('color'),
text_color: this.get('text_color'), text_color: this.get('text_color'),
secure: this.get('secure'), secure: this.get('secure'),

View file

@ -1,8 +1,14 @@
<form> <form>
<section class='field'> <section class='field'>
<section class="field-item">
<label>{{i18n 'category.name'}}</label> <label>{{i18n 'category.name'}}</label>
{{text-field value=name placeholderKey="category.name_placeholder" maxlength="50"}} {{text-field value=name placeholderKey="category.name_placeholder" maxlength="50"}}
</section> </section>
<section class="field-item">
<label>{{i18n 'category.slug'}}</label>
{{text-field value=slug placeholderKey="category.slug_placeholder" maxlength="255"}}
</section>
</section>
{{#if canSelectParentCategory}} {{#if canSelectParentCategory}}
<section class='field'> <section class='field'>

View file

@ -130,6 +130,10 @@
section.field { section.field {
margin-bottom: 20px; margin-bottom: 20px;
} }
section.field .field-item {
display: inline-block;
margin-right: 10px;
}
} }
.reply-where-modal { .reply-where-modal {

View file

@ -95,6 +95,19 @@ class CategoriesController < ApplicationController
end end
end end
def update_slug
@category = Category.find(params[:category_id].to_i)
guardian.ensure_can_edit!(@category)
custom_slug = params[:slug].to_s
if custom_slug.present? && @category.update_attributes(slug: custom_slug)
render json: success_json
else
render_json_error(@category)
end
end
def set_notifications def set_notifications
category_id = params[:category_id].to_i category_id = params[:category_id].to_i
notification_level = params[:notification_level].to_i notification_level = params[:notification_level].to_i

View file

@ -201,12 +201,14 @@ SQL
end end
def ensure_slug def ensure_slug
if name.present? return unless name.present?
self.name.strip! self.name.strip!
if slug.present? if slug.present?
# custom slug # santized custom slug
errors.add(:slug, "is already in use") if duplicate_slug? self.slug = Slug.for(slug)
errors.add(:slug, 'is already in use') if duplicate_slug?
else else
# auto slug # auto slug
self.slug = Slug.for(name) self.slug = Slug.for(name)
@ -214,7 +216,6 @@ SQL
self.slug = '' if duplicate_slug? self.slug = '' if duplicate_slug?
end end
end end
end
def slug_for_url def slug_for_url
slug.present? ? self.slug : "#{self.id}-category" slug.present? ? self.slug : "#{self.id}-category"

View file

@ -1281,6 +1281,8 @@ en:
delete: 'Delete Category' delete: 'Delete Category'
create: 'New Category' create: 'New Category'
save: 'Save Category' save: 'Save Category'
slug: 'Category Slug'
slug_placeholder: '(Optional) dashed-words for url'
creation_error: There has been an error during the creation of the category. creation_error: There has been an error during the creation of the category.
save_error: There was an error saving the category. save_error: There was an error saving the category.
name: "Category Name" name: "Category Name"

View file

@ -325,6 +325,7 @@ Discourse::Application.routes.draw do
post "category/uploads" => "categories#upload" post "category/uploads" => "categories#upload"
post "category/:category_id/move" => "categories#move" post "category/:category_id/move" => "categories#move"
post "category/:category_id/notifications" => "categories#set_notifications" post "category/:category_id/notifications" => "categories#set_notifications"
put "category/:category_id/slug" => "categories#update_slug"
get "c/:id/show" => "categories#show" get "c/:id/show" => "categories#show"
get "c/:category.rss" => "list#category_feed", format: :rss get "c/:category.rss" => "list#category_feed", format: :rss

View file

@ -203,4 +203,42 @@ describe CategoriesController do
end end
describe 'update_slug' do
it 'requires the user to be logged in' do
lambda { xhr :put, :update_slug, category_id: 'category'}.should raise_error(Discourse::NotLoggedIn)
end
describe 'logged in' do
let(:valid_attrs) { {id: @category.id, slug: 'fff'} }
before do
@user = log_in(:admin)
@category = Fabricate(:happy_category, user: @user)
end
it 'rejects blank' do
xhr :put, :update_slug, category_id: @category.id, slug: nil
response.status.should == 422
end
it 'accepts valid custom slug' do
xhr :put, :update_slug, category_id: @category.id, slug: 'valid-slug'
response.should be_success
category = Category.find(@category.id)
category.slug.should == 'valid-slug'
end
it 'accepts not well formed custom slug' do
xhr :put, :update_slug, category_id: @category.id, slug: ' valid slug'
response.should be_success
category = Category.find(@category.id)
category.slug.should == 'valid-slug'
end
it 'rejects invalid custom slug' do
xhr :put, :update_slug, category_id: @category.id, slug: ' '
response.status.should == 422
end
end
end
end end

View file

@ -7,3 +7,9 @@ Fabricator(:diff_category, from: :category) do
name "Different Category" name "Different Category"
user user
end end
Fabricator(:happy_category, from: :category) do
name 'Happy Category'
slug 'happy'
user
end

View file

@ -198,6 +198,11 @@ describe Category do
c.slug.should eq("cats-category") c.slug.should eq("cats-category")
end end
it 'and be sanitized' do
c = Fabricate(:category, name: 'Cats', slug: ' invalid slug')
c.slug.should == 'invalid-slug'
end
it 'fails if custom slug is duplicate with existing' do it 'fails if custom slug is duplicate with existing' do
c1 = Fabricate(:category, name: "Cats", slug: "cats") c1 = Fabricate(:category, name: "Cats", slug: "cats")
c2 = Fabricate.build(:category, name: "More Cats", slug: "cats") c2 = Fabricate.build(:category, name: "More Cats", slug: "cats")