mirror of
https://github.com/discourse/discourse.git
synced 2025-02-02 12:04:17 +08:00
Can edit category descriptions, they show up in a title
attribute
This commit is contained in:
parent
2d9942ceef
commit
532b1f5450
|
@ -40,16 +40,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
categoryLink: function(category) {
|
categoryLink: function(category) {
|
||||||
var color, name;
|
var color, name, description, result;
|
||||||
if (!category) {
|
if (!category) return "";
|
||||||
return "";
|
|
||||||
}
|
|
||||||
color = Em.get(category, 'color');
|
color = Em.get(category, 'color');
|
||||||
name = Em.get(category, 'name');
|
name = Em.get(category, 'name');
|
||||||
return "<a href=\"/category/" +
|
description = Em.get(category, 'description');
|
||||||
(this.categoryUrlId(category)) +
|
|
||||||
"\" class=\"badge-category excerptable\" data-excerpt-size=\"medium\" style=\"background-color: #" + color + "\">" +
|
// Build the HTML link
|
||||||
name + "</a>";
|
result = "<a href=\"/category/" +
|
||||||
|
this.categoryUrlId(category) +
|
||||||
|
"\" class=\"badge-category excerptable\" data-excerpt-size=\"medium\" ";
|
||||||
|
|
||||||
|
// Add description if we have it
|
||||||
|
if (description) result += "title=\"" + description + "\" ";
|
||||||
|
|
||||||
|
return result + "style=\"background-color: #" + color + "\">" + name + "</a>";
|
||||||
},
|
},
|
||||||
avatarUrl: function(username, size, template) {
|
avatarUrl: function(username, size, template) {
|
||||||
var rawSize;
|
var rawSize;
|
||||||
|
|
|
@ -312,6 +312,7 @@
|
||||||
post.set('cooked', jQuery('#wmd-preview').html());
|
post.set('cooked', jQuery('#wmd-preview').html());
|
||||||
this.set('composeState', CLOSED);
|
this.set('composeState', CLOSED);
|
||||||
post.save(function(savedPost) {
|
post.save(function(savedPost) {
|
||||||
|
|
||||||
var idx, postNumber, posts;
|
var idx, postNumber, posts;
|
||||||
posts = _this.get('topic.posts');
|
posts = _this.get('topic.posts');
|
||||||
/* perhaps our post came from elsewhere eg. draft
|
/* perhaps our post came from elsewhere eg. draft
|
||||||
|
|
|
@ -144,22 +144,25 @@
|
||||||
url: "/posts/" + (this.get('id')),
|
url: "/posts/" + (this.get('id')),
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: {
|
data: {
|
||||||
post: {
|
post: { raw: this.get('raw') },
|
||||||
raw: this.get('raw')
|
|
||||||
},
|
|
||||||
image_sizes: this.get('imageSizes')
|
image_sizes: this.get('imageSizes')
|
||||||
},
|
},
|
||||||
success: function(result) {
|
success: function(result) {
|
||||||
return typeof complete === "function" ? complete(Discourse.Post.create(result)) : void 0;
|
|
||||||
|
console.log(result)
|
||||||
|
|
||||||
|
// If we received a category update, update it
|
||||||
|
if (result.category) Discourse.get('site').updateCategory(result.category);
|
||||||
|
|
||||||
|
return typeof complete === "function" ? complete(Discourse.Post.create(result.post)) : void 0;
|
||||||
},
|
},
|
||||||
error: function(result) {
|
error: function(result) {
|
||||||
return typeof error === "function" ? error(result) : void 0;
|
return typeof error === "function" ? error(result) : void 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
/* We're saving a post
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
// We're saving a post
|
||||||
data = {
|
data = {
|
||||||
post: this.getProperties('raw', 'topic_id', 'reply_to_post_number', 'category'),
|
post: this.getProperties('raw', 'topic_id', 'reply_to_post_number', 'category'),
|
||||||
archetype: this.get('archetype'),
|
archetype: this.get('archetype'),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
window.Discourse.Site = Discourse.Model.extend({
|
window.Discourse.Site = Discourse.Model.extend({
|
||||||
|
|
||||||
notificationLookup: (function() {
|
notificationLookup: (function() {
|
||||||
var result;
|
var result;
|
||||||
result = [];
|
result = [];
|
||||||
|
@ -9,6 +10,7 @@
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}).property('notification_types'),
|
}).property('notification_types'),
|
||||||
|
|
||||||
flagTypes: (function() {
|
flagTypes: (function() {
|
||||||
var postActionTypes;
|
var postActionTypes;
|
||||||
postActionTypes = this.get('post_action_types');
|
postActionTypes = this.get('post_action_types');
|
||||||
|
@ -17,8 +19,14 @@
|
||||||
}
|
}
|
||||||
return postActionTypes.filterProperty('is_flag', true);
|
return postActionTypes.filterProperty('is_flag', true);
|
||||||
}).property('post_action_types.@each'),
|
}).property('post_action_types.@each'),
|
||||||
|
|
||||||
postActionTypeById: function(id) {
|
postActionTypeById: function(id) {
|
||||||
return this.get("postActionByIdLookup.action" + id);
|
return this.get("postActionByIdLookup.action" + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateCategory: function(newCategory) {
|
||||||
|
var existingCategory = this.get('categories').findProperty('id', Em.get(newCategory, 'id'));
|
||||||
|
if (existingCategory) existingCategory.mergeAttributes(newCategory);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,17 @@
|
||||||
<label>{{i18n category.name}}</label>
|
<label>{{i18n category.name}}</label>
|
||||||
{{view Discourse.TextField valueBinding="view.category.name" placeholderKey="category.name_placeholder"}}
|
{{view Discourse.TextField valueBinding="view.category.name" placeholderKey="category.name_placeholder"}}
|
||||||
|
|
||||||
{{#if view.category.excerpt}}
|
<div class='description-controls' style="margin-bottom: 20px">
|
||||||
<label>{{i18n category.description}}</label>
|
<label>{{i18n category.description}}</label>
|
||||||
<p>{{view.category.excerpt}} <a href="{{unbound view.category.topic_url}}">{{i18n category.topic}}</a></p>
|
|
||||||
{{/if}}
|
{{#if view.category.description}}
|
||||||
|
{{view.category.description}}
|
||||||
|
<a href="#" {{action showCategoryTopic target="view"}}>{{i18n category.change_in_category_topic}}</a>
|
||||||
|
{{else}}
|
||||||
|
{{i18n category.no_description}} <a {{action showCategoryTopic target="view"}} href="#">{{i18n category.change_in_category_topic}}</a>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>{{i18n category.color}}</label>
|
<label>{{i18n category.color}}</label>
|
||||||
|
|
||||||
|
|
|
@ -1,64 +1,72 @@
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
window.Discourse.EditCategoryView = window.Discourse.ModalBodyView.extend({
|
/**
|
||||||
|
A modal view for editing the basic aspects of a category
|
||||||
|
|
||||||
|
@class EditCategoryView
|
||||||
|
@extends Discourse.ModalBodyView
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.EditCategoryView = Discourse.ModalBodyView.extend({
|
||||||
templateName: 'modal/edit_category',
|
templateName: 'modal/edit_category',
|
||||||
appControllerBinding: 'Discourse.appController',
|
appControllerBinding: 'Discourse.appController',
|
||||||
|
|
||||||
disabled: (function() {
|
disabled: (function() {
|
||||||
if (this.get('saving')) {
|
if (this.get('saving')) return true;
|
||||||
return true;
|
if (!this.get('category.name')) return true;
|
||||||
}
|
if (!this.get('category.color')) return true;
|
||||||
if (!this.get('category.name')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!this.get('category.color')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}).property('category.name', 'category.color'),
|
}).property('category.name', 'category.color'),
|
||||||
|
|
||||||
colorStyle: (function() {
|
colorStyle: (function() {
|
||||||
return "background-color: #" + (this.get('category.color')) + ";";
|
return "background-color: #" + (this.get('category.color')) + ";";
|
||||||
}).property('category.color'),
|
}).property('category.color'),
|
||||||
|
|
||||||
title: (function() {
|
title: (function() {
|
||||||
if (this.get('category.id')) {
|
if (this.get('category.id')) return Em.String.i18n("category.edit_long");
|
||||||
return "Edit Category";
|
return "Create Category";
|
||||||
} else {
|
|
||||||
return "Create Category";
|
|
||||||
}
|
|
||||||
}).property('category.id'),
|
}).property('category.id'),
|
||||||
|
|
||||||
buttonTitle: (function() {
|
buttonTitle: (function() {
|
||||||
if (this.get('saving')) {
|
if (this.get('saving')) return Em.String.i18n("saving");
|
||||||
return "Saving...";
|
return this.get('title');
|
||||||
} else {
|
|
||||||
return this.get('title');
|
|
||||||
}
|
|
||||||
}).property('title', 'saving'),
|
}).property('title', 'saving'),
|
||||||
|
|
||||||
didInsertElement: function() {
|
didInsertElement: function() {
|
||||||
this._super();
|
this._super();
|
||||||
if (this.get('category')) {
|
if (this.get('category')) {
|
||||||
return this.set('id', this.get('category.slug'));
|
this.set('id', this.get('category.slug'));
|
||||||
} else {
|
} else {
|
||||||
return this.set('category', Discourse.Category.create({
|
this.set('category', Discourse.Category.create({ color: 'AB9364' }));
|
||||||
color: 'AB9364'
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showCategoryTopic: function() {
|
||||||
|
jQuery('#discourse-modal').modal('hide');
|
||||||
|
Discourse.routeTo(this.get('category.topic_url'));
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
saveSuccess: function(result) {
|
saveSuccess: function(result) {
|
||||||
jQuery('#discourse-modal').modal('hide');
|
jQuery('#discourse-modal').modal('hide');
|
||||||
window.location = "/category/" + (Discourse.Utilities.categoryUrlId(result.category));
|
window.location = "/category/" + (Discourse.Utilities.categoryUrlId(result.category));
|
||||||
},
|
},
|
||||||
|
|
||||||
saveCategory: function() {
|
saveCategory: function() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
this.set('saving', true);
|
this.set('saving', true);
|
||||||
return this.get('category').save({
|
return this.get('category').save({
|
||||||
success: function(result) {
|
success: function(result) {
|
||||||
return _this.saveSuccess(result);
|
_this.saveSuccess(result);
|
||||||
},
|
},
|
||||||
error: function(errors) {
|
error: function(errors) {
|
||||||
_this.displayErrors(errors);
|
_this.displayErrors(errors);
|
||||||
return _this.set('saving', false);
|
_this.set('saving', false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
|
@ -35,23 +35,32 @@ class PostsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
requires_parameter(:post)
|
requires_parameter(:post)
|
||||||
|
|
||||||
@post = Post.where(id: params[:id]).first
|
post = Post.where(id: params[:id]).first
|
||||||
@post.image_sizes = params[:image_sizes] if params[:image_sizes].present?
|
post.image_sizes = params[:image_sizes] if params[:image_sizes].present?
|
||||||
guardian.ensure_can_edit!(@post)
|
guardian.ensure_can_edit!(post)
|
||||||
if @post.revise(current_user, params[:post][:raw])
|
|
||||||
TopicLink.extract_from(@post)
|
revisor = PostRevisor.new(post)
|
||||||
|
if revisor.revise!(current_user, params[:post][:raw])
|
||||||
|
TopicLink.extract_from(post)
|
||||||
end
|
end
|
||||||
|
|
||||||
if @post.errors.present?
|
if post.errors.present?
|
||||||
render_json_error(@post)
|
render_json_error(post)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
post_serializer = PostSerializer.new(@post, scope: guardian, root: false)
|
post_serializer = PostSerializer.new(post, scope: guardian, root: false)
|
||||||
post_serializer.draft_sequence = DraftSequence.current(current_user, @post.topic.draft_key)
|
post_serializer.draft_sequence = DraftSequence.current(current_user, post.topic.draft_key)
|
||||||
link_counts = TopicLinkClick.counts_for(@post.topic, [@post])
|
link_counts = TopicLinkClick.counts_for(post.topic, [post])
|
||||||
post_serializer.single_post_link_counts = link_counts[@post.id] if link_counts.present?
|
post_serializer.single_post_link_counts = link_counts[post.id] if link_counts.present?
|
||||||
render_json_dump(post_serializer)
|
|
||||||
|
|
||||||
|
result = {post: post_serializer.as_json}
|
||||||
|
if revisor.category_changed.present?
|
||||||
|
result[:category] = CategorySerializer.new(revisor.category_changed, scope: guardian, root: false).as_json
|
||||||
|
end
|
||||||
|
|
||||||
|
render_json_dump(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_number
|
def by_number
|
||||||
|
|
|
@ -44,19 +44,6 @@ class Category < ActiveRecord::Base
|
||||||
topics_week = (#{topics_week})")
|
topics_week = (#{topics_week})")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use the first paragraph of the topic's first post as the excerpt
|
|
||||||
def excerpt
|
|
||||||
if topic.present?
|
|
||||||
first_post = topic.posts.order(:post_number).first
|
|
||||||
body = first_post.cooked
|
|
||||||
matches = body.scan(/\<p\>(.*)\<\/p\>/)
|
|
||||||
if matches and matches[0] and matches[0][0]
|
|
||||||
return matches[0][0]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def topic_url
|
def topic_url
|
||||||
topic.try(:relative_url)
|
topic.try(:relative_url)
|
||||||
end
|
end
|
||||||
|
@ -67,11 +54,17 @@ class Category < ActiveRecord::Base
|
||||||
|
|
||||||
after_create do
|
after_create do
|
||||||
topic = Topic.create!(title: I18n.t("category.topic_prefix", category: name), user: user, visible: false)
|
topic = Topic.create!(title: I18n.t("category.topic_prefix", category: name), user: user, visible: false)
|
||||||
topic.posts.create!(raw: SiteSetting.category_post_template, user: user)
|
|
||||||
|
post_contents = I18n.t("category.post_template", replace_paragraph: I18n.t("category.replace_paragraph"))
|
||||||
|
topic.posts.create!(raw: post_contents, user: user)
|
||||||
update_column(:topic_id, topic.id)
|
update_column(:topic_id, topic.id)
|
||||||
topic.update_column(:category_id, self.id)
|
topic.update_column(:category_id, self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.post_template
|
||||||
|
I18n.t("category.post_template", replace_paragraph: I18n.t("category.replace_paragraph"))
|
||||||
|
end
|
||||||
|
|
||||||
# We cache the categories in the site json, so we need to invalidate it when they change
|
# We cache the categories in the site json, so we need to invalidate it when they change
|
||||||
def invalidate_site_cache
|
def invalidate_site_cache
|
||||||
Site.invalidate_cache
|
Site.invalidate_cache
|
||||||
|
|
|
@ -100,8 +100,6 @@ class SiteSetting < ActiveRecord::Base
|
||||||
setting(:best_of_score_threshold, 15)
|
setting(:best_of_score_threshold, 15)
|
||||||
setting(:best_of_posts_required, 50)
|
setting(:best_of_posts_required, 50)
|
||||||
setting(:best_of_likes_required, 1)
|
setting(:best_of_likes_required, 1)
|
||||||
setting(:category_post_template,
|
|
||||||
"[Replace this first paragraph with a short description of your new category. Try to keep it below 200 characters.]\n\nUse this space below for a longer description, as well as to establish any rules or discussion!")
|
|
||||||
|
|
||||||
# we need to think of a way to force users to enter certain settings, this is a minimal config thing
|
# we need to think of a way to force users to enter certain settings, this is a minimal config thing
|
||||||
setting(:notification_email, 'info@discourse.org')
|
setting(:notification_email, 'info@discourse.org')
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
class CategorySerializer < ApplicationSerializer
|
class CategorySerializer < ApplicationSerializer
|
||||||
attributes :id, :name, :color, :slug, :topic_count
|
|
||||||
|
attributes :id,
|
||||||
|
:name,
|
||||||
|
:color,
|
||||||
|
:slug,
|
||||||
|
:topic_count,
|
||||||
|
:description,
|
||||||
|
:topic_url
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -519,6 +519,7 @@ en:
|
||||||
category:
|
category:
|
||||||
none: '(no category)'
|
none: '(no category)'
|
||||||
edit: 'edit'
|
edit: 'edit'
|
||||||
|
edit_long: "Edit Category"
|
||||||
view: 'View Topics in Category'
|
view: 'View Topics in Category'
|
||||||
delete: 'Delete Category'
|
delete: 'Delete Category'
|
||||||
create: 'Create Category'
|
create: 'Create Category'
|
||||||
|
@ -531,6 +532,8 @@ en:
|
||||||
color_placeholder: "Any web color"
|
color_placeholder: "Any web color"
|
||||||
delete_confirm: "Are you sure you want to delete that category?"
|
delete_confirm: "Are you sure you want to delete that category?"
|
||||||
list: "List Categories"
|
list: "List Categories"
|
||||||
|
no_description: "There is no description for this category."
|
||||||
|
change_in_category_topic: "visit category topic to edit the description"
|
||||||
|
|
||||||
flagging:
|
flagging:
|
||||||
title: 'Why are you flagging this post?'
|
title: 'Why are you flagging this post?'
|
||||||
|
|
|
@ -228,7 +228,6 @@ nl:
|
||||||
exclude_rel_nofollow_domains: "Een commagescheiden lijst van domeinen waar 'nofollow' niet is toegevoegd. (voorbeelddomein.com zal automatisch sub.voorbeelddomein.com toestaan)"
|
exclude_rel_nofollow_domains: "Een commagescheiden lijst van domeinen waar 'nofollow' niet is toegevoegd. (voorbeelddomein.com zal automatisch sub.voorbeelddomein.com toestaan)"
|
||||||
post_excerpt_maxlength: "Maximale lengte in karakters van een post-uittreksel."
|
post_excerpt_maxlength: "Maximale lengte in karakters van een post-uittreksel."
|
||||||
post_onebox_maxlength: "Maximale lengte van een 'oneboxed' discourse post."
|
post_onebox_maxlength: "Maximale lengte van een 'oneboxed' discourse post."
|
||||||
category_post_template: "De post-template die verschijnt wanneer je een categorie aanmaakt"
|
|
||||||
new_topics_rollup: "Hoeveel topics er aan een topic-lijst kunnen worden toegevoegd voordat de lijst oprolt."
|
new_topics_rollup: "Hoeveel topics er aan een topic-lijst kunnen worden toegevoegd voordat de lijst oprolt."
|
||||||
onebox_max_chars: "Het maximaal aantal karakters dat een 'onebox' zal importeren in een lap text."
|
onebox_max_chars: "Het maximaal aantal karakters dat een 'onebox' zal importeren in een lap text."
|
||||||
logo_url: "Het logo van je site bijv: http://xyz.com/x.png"
|
logo_url: "Het logo van je site bijv: http://xyz.com/x.png"
|
||||||
|
|
|
@ -62,6 +62,8 @@ en:
|
||||||
|
|
||||||
category:
|
category:
|
||||||
topic_prefix: "Category definition for %{category}"
|
topic_prefix: "Category definition for %{category}"
|
||||||
|
replace_paragraph: "[Replace this first paragraph with a short description of your new category. Try to keep it below 200 characters.]"
|
||||||
|
post_template: "%{replace_paragraph}\n\nUse this space below for a longer description, as well as to establish any rules or discussion!"
|
||||||
|
|
||||||
trust_levels:
|
trust_levels:
|
||||||
new:
|
new:
|
||||||
|
@ -254,7 +256,6 @@ en:
|
||||||
exclude_rel_nofollow_domains: "A comma delimited list of domains where nofollow is not added (tld.com will automatically allow sub.tld.com as well)"
|
exclude_rel_nofollow_domains: "A comma delimited list of domains where nofollow is not added (tld.com will automatically allow sub.tld.com as well)"
|
||||||
post_excerpt_maxlength: "Maximum length in chars of a post's excerpt."
|
post_excerpt_maxlength: "Maximum length in chars of a post's excerpt."
|
||||||
post_onebox_maxlength: "Maximum length of a oneboxed discourse post."
|
post_onebox_maxlength: "Maximum length of a oneboxed discourse post."
|
||||||
category_post_template: "The post template that appears once you create a category"
|
|
||||||
new_topics_rollup: "How many topics can be inserted on the topic list before rolling up."
|
new_topics_rollup: "How many topics can be inserted on the topic list before rolling up."
|
||||||
onebox_max_chars: "The maximum amount of characters a onebox will import in a text blob."
|
onebox_max_chars: "The maximum amount of characters a onebox will import in a text blob."
|
||||||
logo_url: "The logo for your site eg: http://xyz.com/x.png"
|
logo_url: "The logo for your site eg: http://xyz.com/x.png"
|
||||||
|
|
|
@ -261,7 +261,6 @@ fr:
|
||||||
exclude_rel_nofollow_domains: "Une liste séparée par des virgules contenant les noms de domaines de premier niveau pour lesquels il faut ajouter un attribut nofollow (exemple.com va automatiquement fonctionner aussi avec sous.domaine.exemple.com)"
|
exclude_rel_nofollow_domains: "Une liste séparée par des virgules contenant les noms de domaines de premier niveau pour lesquels il faut ajouter un attribut nofollow (exemple.com va automatiquement fonctionner aussi avec sous.domaine.exemple.com)"
|
||||||
post_excerpt_maxlength: "Longueur maximale d'un extrait de message."
|
post_excerpt_maxlength: "Longueur maximale d'un extrait de message."
|
||||||
post_onebox_maxlength: "Longueur maximale d'un message emboîté."
|
post_onebox_maxlength: "Longueur maximale d'un message emboîté."
|
||||||
category_post_template: "Le modèle de message qui va apparaitre quand vous créez une catégorie"
|
|
||||||
new_topics_rollup: "Combien de discussions peuvent être insérées dans la liste des discussions avant de remonter."
|
new_topics_rollup: "Combien de discussions peuvent être insérées dans la liste des discussions avant de remonter."
|
||||||
onebox_max_chars: "Nombre maximal de caractères qu'une boîte peut importer en blob de texte."
|
onebox_max_chars: "Nombre maximal de caractères qu'une boîte peut importer en blob de texte."
|
||||||
logo_url: "Le logo de votre site, par exemple: http://xyz.com/x.png"
|
logo_url: "Le logo de votre site, par exemple: http://xyz.com/x.png"
|
||||||
|
|
|
@ -255,7 +255,6 @@ nl:
|
||||||
exclude_rel_nofollow_domains: "Een commagescheiden lijst van domeinen waar 'nofollow' niet is toegevoegd. (voorbeelddomein.com zal automatisch sub.voorbeelddomein.com toestaan)"
|
exclude_rel_nofollow_domains: "Een commagescheiden lijst van domeinen waar 'nofollow' niet is toegevoegd. (voorbeelddomein.com zal automatisch sub.voorbeelddomein.com toestaan)"
|
||||||
post_excerpt_maxlength: "Maximale lengte in karakters van een post-uittreksel."
|
post_excerpt_maxlength: "Maximale lengte in karakters van een post-uittreksel."
|
||||||
post_onebox_maxlength: "Maximale lengte van een 'oneboxed' discourse post."
|
post_onebox_maxlength: "Maximale lengte van een 'oneboxed' discourse post."
|
||||||
category_post_template: "De post-template die verschijnt wanneer je een categorie aanmaakt"
|
|
||||||
new_topics_rollup: "Hoeveel topics er aan een topic-lijst kunnen worden toegevoegd voordat de lijst oprolt."
|
new_topics_rollup: "Hoeveel topics er aan een topic-lijst kunnen worden toegevoegd voordat de lijst oprolt."
|
||||||
onebox_max_chars: "Het maximaal aantal karakters dat een 'onebox' zal importeren in een lap tekst."
|
onebox_max_chars: "Het maximaal aantal karakters dat een 'onebox' zal importeren in een lap tekst."
|
||||||
logo_url: "Het logo van je site bijv: http://xyz.com/x.png"
|
logo_url: "Het logo van je site bijv: http://xyz.com/x.png"
|
||||||
|
|
25
db/migrate/20130221215017_add_description_to_categories.rb
Normal file
25
db/migrate/20130221215017_add_description_to_categories.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
class AddDescriptionToCategories < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
add_column :categories, :description, :text, null: true
|
||||||
|
|
||||||
|
# While we're at it, remove unused columns
|
||||||
|
remove_column :categories, :top1_topic_id
|
||||||
|
remove_column :categories, :top2_topic_id
|
||||||
|
remove_column :categories, :top1_user_id
|
||||||
|
remove_column :categories, :top2_user_id
|
||||||
|
|
||||||
|
# Migrate excerpts over
|
||||||
|
Category.all.each do |c|
|
||||||
|
excerpt = c.excerpt
|
||||||
|
unless excerpt == I18n.t("category.replace_paragraph")
|
||||||
|
c.update_column(:description, c.excerpt)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :categories, :description
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1222,10 +1222,6 @@ CREATE TABLE categories (
|
||||||
name character varying(50) NOT NULL,
|
name character varying(50) NOT NULL,
|
||||||
color character varying(6) DEFAULT 'AB9364'::character varying NOT NULL,
|
color character varying(6) DEFAULT 'AB9364'::character varying NOT NULL,
|
||||||
topic_id integer,
|
topic_id integer,
|
||||||
top1_topic_id integer,
|
|
||||||
top2_topic_id integer,
|
|
||||||
top1_user_id integer,
|
|
||||||
top2_user_id integer,
|
|
||||||
topic_count integer DEFAULT 0 NOT NULL,
|
topic_count integer DEFAULT 0 NOT NULL,
|
||||||
created_at timestamp without time zone NOT NULL,
|
created_at timestamp without time zone NOT NULL,
|
||||||
updated_at timestamp without time zone NOT NULL,
|
updated_at timestamp without time zone NOT NULL,
|
||||||
|
@ -1233,7 +1229,8 @@ CREATE TABLE categories (
|
||||||
topics_year integer,
|
topics_year integer,
|
||||||
topics_month integer,
|
topics_month integer,
|
||||||
topics_week integer,
|
topics_week integer,
|
||||||
slug character varying(255) NOT NULL
|
slug character varying(255) NOT NULL,
|
||||||
|
description text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1242,7 +1239,7 @@ CREATE TABLE categories (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE categories_id_seq
|
CREATE SEQUENCE categories_id_seq
|
||||||
START WITH 5
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1327,7 +1324,7 @@ CREATE TABLE draft_sequences (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE draft_sequences_id_seq
|
CREATE SEQUENCE draft_sequences_id_seq
|
||||||
START WITH 20
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1361,7 +1358,7 @@ CREATE TABLE drafts (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE drafts_id_seq
|
CREATE SEQUENCE drafts_id_seq
|
||||||
START WITH 2
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1394,7 +1391,7 @@ CREATE TABLE email_logs (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE email_logs_id_seq
|
CREATE SEQUENCE email_logs_id_seq
|
||||||
START WITH 3
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1429,7 +1426,7 @@ CREATE TABLE email_tokens (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE email_tokens_id_seq
|
CREATE SEQUENCE email_tokens_id_seq
|
||||||
START WITH 3
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1642,7 +1639,7 @@ CREATE TABLE onebox_renders (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE onebox_renders_id_seq
|
CREATE SEQUENCE onebox_renders_id_seq
|
||||||
START WITH 2
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1676,7 +1673,7 @@ CREATE TABLE post_action_types (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE post_action_types_id_seq
|
CREATE SEQUENCE post_action_types_id_seq
|
||||||
START WITH 6
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1807,7 +1804,7 @@ CREATE TABLE posts (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE posts_id_seq
|
CREATE SEQUENCE posts_id_seq
|
||||||
START WITH 16
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1898,7 +1895,7 @@ CREATE TABLE site_settings (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE site_settings_id_seq
|
CREATE SEQUENCE site_settings_id_seq
|
||||||
START WITH 4
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -1930,7 +1927,7 @@ CREATE TABLE topic_allowed_users (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE topic_allowed_users_id_seq
|
CREATE SEQUENCE topic_allowed_users_id_seq
|
||||||
START WITH 3
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -2122,7 +2119,7 @@ CREATE TABLE topics (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE topics_id_seq
|
CREATE SEQUENCE topics_id_seq
|
||||||
START WITH 16
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -2228,7 +2225,7 @@ CREATE TABLE user_actions (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE user_actions_id_seq
|
CREATE SEQUENCE user_actions_id_seq
|
||||||
START WITH 40
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -2292,7 +2289,7 @@ CREATE TABLE user_visits (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE user_visits_id_seq
|
CREATE SEQUENCE user_visits_id_seq
|
||||||
START WITH 4
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -2359,7 +2356,7 @@ CREATE TABLE users (
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE SEQUENCE users_id_seq
|
CREATE SEQUENCE users_id_seq
|
||||||
START WITH 3
|
START WITH 1
|
||||||
INCREMENT BY 1
|
INCREMENT BY 1
|
||||||
NO MINVALUE
|
NO MINVALUE
|
||||||
NO MAXVALUE
|
NO MAXVALUE
|
||||||
|
@ -4579,3 +4576,5 @@ INSERT INTO schema_migrations (version) VALUES ('20130208220635');
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20130213021450');
|
INSERT INTO schema_migrations (version) VALUES ('20130213021450');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20130213203300');
|
INSERT INTO schema_migrations (version) VALUES ('20130213203300');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20130221215017');
|
|
@ -1,5 +1,8 @@
|
||||||
require 'edit_rate_limiter'
|
require 'edit_rate_limiter'
|
||||||
class PostRevisor
|
class PostRevisor
|
||||||
|
|
||||||
|
attr_reader :category_changed
|
||||||
|
|
||||||
def initialize(post)
|
def initialize(post)
|
||||||
@post = post
|
@post = post
|
||||||
end
|
end
|
||||||
|
@ -8,6 +11,7 @@ class PostRevisor
|
||||||
@user, @new_raw, @opts = user, new_raw, opts
|
@user, @new_raw, @opts = user, new_raw, opts
|
||||||
return false if not should_revise?
|
return false if not should_revise?
|
||||||
revise_post
|
revise_post
|
||||||
|
update_category_description
|
||||||
post_process_post
|
post_process_post
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -76,6 +80,25 @@ class PostRevisor
|
||||||
@post.save
|
@post.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_category_description
|
||||||
|
# If we're revising the first post, we might have to update the category description
|
||||||
|
return unless @post.post_number == 1
|
||||||
|
|
||||||
|
# Is there a category with our topic id?
|
||||||
|
category = Category.where(topic_id: @post.topic_id).first
|
||||||
|
return unless category.present?
|
||||||
|
|
||||||
|
# If found, update its description
|
||||||
|
body = @post.cooked
|
||||||
|
matches = body.scan(/\<p\>(.*)\<\/p\>/)
|
||||||
|
if matches and matches[0] and matches[0][0]
|
||||||
|
new_description = matches[0][0]
|
||||||
|
new_description = nil if new_description == I18n.t("category.replace_paragraph")
|
||||||
|
category.update_column(:description, new_description)
|
||||||
|
@category_changed = category
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def post_process_post
|
def post_process_post
|
||||||
@post.invalidate_oneboxes = true
|
@post.invalidate_oneboxes = true
|
||||||
@post.trigger_post_process
|
@post.trigger_post_process
|
||||||
|
|
|
@ -43,6 +43,11 @@ describe PostRevisor do
|
||||||
it "doesn't change the last_version_at" do
|
it "doesn't change the last_version_at" do
|
||||||
post.last_version_at.should == first_version_at
|
post.last_version_at.should == first_version_at
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "doesn't update a category" do
|
||||||
|
subject.category_changed.should be_blank
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'revision much later' do
|
describe 'revision much later' do
|
||||||
|
@ -55,6 +60,10 @@ describe PostRevisor do
|
||||||
post.reload
|
post.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "doesn't update a category" do
|
||||||
|
subject.category_changed.should be_blank
|
||||||
|
end
|
||||||
|
|
||||||
it 'updates the cached_version' do
|
it 'updates the cached_version' do
|
||||||
post.cached_version.should == 2
|
post.cached_version.should == 2
|
||||||
end
|
end
|
||||||
|
@ -82,6 +91,10 @@ describe PostRevisor do
|
||||||
post.last_version_at.to_i.should == revised_at.to_i
|
post.last_version_at.to_i.should == revised_at.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "doesn't update a category" do
|
||||||
|
subject.category_changed.should be_blank
|
||||||
|
end
|
||||||
|
|
||||||
context "after second window" do
|
context "after second window" do
|
||||||
|
|
||||||
let!(:new_revised_at) {revised_at + 2.minutes}
|
let!(:new_revised_at) {revised_at + 2.minutes}
|
||||||
|
@ -102,6 +115,68 @@ describe PostRevisor do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'category topic' do
|
||||||
|
|
||||||
|
let!(:category) do
|
||||||
|
category = Fabricate(:category)
|
||||||
|
category.update_column(:topic_id, topic.id)
|
||||||
|
category
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:new_description) { "this is my new description." }
|
||||||
|
|
||||||
|
it "should have to description by default" do
|
||||||
|
category.description.should be_blank
|
||||||
|
end
|
||||||
|
|
||||||
|
context "one paragraph description" do
|
||||||
|
before do
|
||||||
|
subject.revise!(post.user, new_description)
|
||||||
|
category.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true for category_changed" do
|
||||||
|
subject.category_changed.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "updates the description of the category" do
|
||||||
|
category.description.should == new_description
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "multiple paragraph description" do
|
||||||
|
before do
|
||||||
|
subject.revise!(post.user, "#{new_description}\n\nOther content goes here.")
|
||||||
|
category.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the changed category info" do
|
||||||
|
subject.category_changed.should == category
|
||||||
|
end
|
||||||
|
|
||||||
|
it "updates the description of the category" do
|
||||||
|
category.description.should == new_description
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when updating back to the original paragraph' do
|
||||||
|
before do
|
||||||
|
category.update_column(:description, 'this is my description')
|
||||||
|
subject.revise!(post.user, Category.post_template)
|
||||||
|
category.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it "puts the description back to nothing" do
|
||||||
|
category.description.should be_blank
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true for category_changed" do
|
||||||
|
subject.category_changed.should == category
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
describe 'rate limiter' do
|
describe 'rate limiter' do
|
||||||
let(:changed_by) { Fabricate(:coding_horror) }
|
let(:changed_by) { Fabricate(:coding_horror) }
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ describe PostsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "calls revise with valid parameters" do
|
it "calls revise with valid parameters" do
|
||||||
Post.any_instance.expects(:revise).with(post.user, 'edited body')
|
PostRevisor.any_instance.expects(:revise!).with(post.user, 'edited body')
|
||||||
xhr :put, :update, update_params
|
xhr :put, :update, update_params
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,10 @@ describe Category do
|
||||||
@category.slug.should == 'amazing-category'
|
@category.slug.should == 'amazing-category'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'has a default description' do
|
||||||
|
@category.description.should be_blank
|
||||||
|
end
|
||||||
|
|
||||||
it 'has one topic' do
|
it 'has one topic' do
|
||||||
Topic.where(category_id: @category).count.should == 1
|
Topic.where(category_id: @category).count.should == 1
|
||||||
end
|
end
|
||||||
|
@ -107,14 +111,12 @@ describe Category do
|
||||||
@topic.posts.count.should == 1
|
@topic.posts.count.should == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should have an excerpt' do
|
|
||||||
@category.excerpt.should be_present
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should have a topic url' do
|
it 'should have a topic url' do
|
||||||
@category.topic_url.should be_present
|
@category.topic_url.should be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe "trying to change the category topic's category" do
|
describe "trying to change the category topic's category" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
@ -166,8 +168,7 @@ describe Category do
|
||||||
context 'with regular topics' do
|
context 'with regular topics' do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@category.topics << Fabricate(:topic,
|
@category.topics << Fabricate(:topic, user: @category.user)
|
||||||
user: @category.user)
|
|
||||||
Category.update_stats
|
Category.update_stats
|
||||||
@category.reload
|
@category.reload
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user