More refactoring to support extensibility of history

This commit is contained in:
Robin Ward 2015-01-28 11:01:01 -05:00
parent 4a46d4ee35
commit 8fc477ab07
11 changed files with 105 additions and 86 deletions

View file

@ -0,0 +1,4 @@
export default Ember.Component.extend({
tagName: 'span',
classNameBindings: [':fa-stack'],
});

View file

@ -81,23 +81,14 @@ export default ObjectController.extend(ModalFunctionality, {
} }
}.property("category_id_changes"), }.property("category_id_changes"),
wikiDiff: function() { wikiDisabled: function() {
var changes = this.get("wiki_changes"); var changes = this.get("wiki_changes");
if (changes) { return changes && !changes['current'];
return changes["current"] ? }.property('wiki_changes'),
'<span class="fa-stack"><i class="fa fa-pencil-square-o fa-stack-2x"></i></span>' :
'<span class="fa-stack"><i class="fa fa-pencil-square-o fa-stack-2x"></i><i class="fa fa-ban fa-stack-2x"></i></span>';
}
}.property("wiki_changes"),
postTypeDiff: function () { postTypeDisabled: function () {
var moderator = Discourse.Site.currentProp('post_types.moderator_action');
var changes = this.get("post_type_changes"); var changes = this.get("post_type_changes");
if (changes) { return (changes && changes['current'] !== this.site.get('post_types.moderator_action'));
return changes["current"] === moderator ?
'<span class="fa-stack"><i class="fa fa-shield fa-stack-2x"></i></span>' :
'<span class="fa-stack"><i class="fa fa-shield fa-stack-2x"></i><i class="fa fa-ban fa-stack-2x"></i></span>';
}
}.property("post_type_changes"), }.property("post_type_changes"),
titleDiff: function() { titleDiff: function() {

View file

@ -1,5 +1,13 @@
export function iconHTML(icon, label) { import registerUnbound from 'discourse/helpers/register-unbound';
var html = "<i class='fa fa-" + icon + "'";
export function iconClasses(icon, modifier) {
var classes = "fa fa-" + icon;
if (modifier) { classes += " fa-" + modifier; }
return classes;
}
export function iconHTML(icon, label, modifier) {
var html = "<i class='" + iconClasses(icon, modifier) + "'";
if (label) { html += " aria-hidden='true'"; } if (label) { html += " aria-hidden='true'"; }
html += "></i>"; html += "></i>";
if (label) { if (label) {
@ -8,9 +16,7 @@ export function iconHTML(icon, label) {
return html; return html;
} }
Handlebars.registerHelper('fa-icon', function(icon, options) {
var label;
if (options.hash) { label = options.hash.label; }
return new Handlebars.SafeString(iconHTML(icon, label)); registerUnbound('fa-icon', function(icon, params) {
return new Handlebars.SafeString(iconHTML(icon, params.label, params.modifier));
}); });

View file

@ -470,7 +470,7 @@ Discourse.Post.reopenClass({
loadRevision: function(postId, version) { loadRevision: function(postId, version) {
return Discourse.ajax("/posts/" + postId + "/revisions/" + version + ".json").then(function (result) { return Discourse.ajax("/posts/" + postId + "/revisions/" + version + ".json").then(function (result) {
return Em.Object.create(result); return Ember.Object.create(result);
}); });
}, },

View file

@ -0,0 +1,5 @@
{{fa-icon icon modifier="stack-2x"}}
{{#if disabled}}
{{fa-icon "ban" modifier="stack-2x"}}
{{/if}}

View file

@ -40,10 +40,10 @@
&rarr; {{bound-avatar-template user_changes.current.avatar_template "small"}} {{user_changes.current.username}} &rarr; {{bound-avatar-template user_changes.current.avatar_template "small"}} {{user_changes.current.username}}
{{/if}} {{/if}}
{{#if wiki_changes}} {{#if wiki_changes}}
&mdash; {{{wikiDiff}}} &mdash; {{disabled-icon icon="pencil-square-o" secondary=wikiDisabled}}
{{/if}} {{/if}}
{{#if post_type_changes}} {{#if post_type_changes}}
&mdash; {{{postTypeDiff}}} &mdash; {{disabled-icon icon="shield" disabled=postTypeDisabled}}
{{/if}} {{/if}}
{{#if category_id_changes}} {{#if category_id_changes}}
&mdash; {{{previousCategory}}} &rarr; {{{currentCategory}}} &mdash; {{{previousCategory}}} &rarr; {{{currentCategory}}}
@ -65,12 +65,12 @@
{{/if}} {{/if}}
{{#if wiki_changes}} {{#if wiki_changes}}
<div class="row"> <div class="row">
{{{wikiDiff}}} {{disabled-icon icon="pencil-square-o" secondary=wikiDisabled}}
</div> </div>
{{/if}} {{/if}}
{{#if post_type_changes}} {{#if post_type_changes}}
<div class="row"> <div class="row">
{{{postTypeDiff}}} {{disabled-icon icon="shield" disabled=postTypeDisabled}}
</div> </div>
{{/if}} {{/if}}
{{#if category_id_changes}} {{#if category_id_changes}}
@ -79,6 +79,9 @@
</div> </div>
{{/if}} {{/if}}
{{/if}} {{/if}}
{{plugin-outlet "post-revisions"}}
<div class="row"> <div class="row">
{{{bodyDiff}}} {{{bodyDiff}}}
</div> </div>

View file

@ -414,7 +414,7 @@ class PostsController < ApplicationController
result[:is_warning] = (params[:is_warning] == "true") result[:is_warning] = (params[:is_warning] == "true")
end end
PostRevisor.tracked_fields.keys.each do |f| PostRevisor.tracked_topic_fields.keys.each do |f|
params.permit(f => []) params.permit(f => [])
result[f] = params[f] if params.has_key?(f) result[f] = params[f] if params.has_key?(f)
end end

View file

@ -126,7 +126,7 @@ class TopicsController < ApplicationController
guardian.ensure_can_edit!(topic) guardian.ensure_can_edit!(topic)
changes = {} changes = {}
PostRevisor.tracked_fields.keys.each do |f| PostRevisor.tracked_topic_fields.keys.each do |f|
changes[f] = params[f] if params.has_key?(f) changes[f] = params[f] if params.has_key?(f)
end end

View file

@ -40,9 +40,7 @@ class PostRevisionSerializer < ApplicationSerializer
end end
end end
add_compared_field :category_id
add_compared_field :wiki add_compared_field :wiki
add_compared_field :post_type
def previous_hidden def previous_hidden
previous["hidden"] previous["hidden"]
@ -167,19 +165,27 @@ class PostRevisionSerializer < ApplicationSerializer
return @all_revisions if @all_revisions return @all_revisions if @all_revisions
post_revisions = PostRevision.where(post_id: object.post_id).order(:number).to_a post_revisions = PostRevision.where(post_id: object.post_id).order(:number).to_a
latest_modifications = {
"raw" => [post.raw],
"cooked" => [post.cooked],
"edit_reason" => [post.edit_reason],
"wiki" => [post.wiki],
"post_type" => [post.post_type],
"user_id" => [post.user_id]
}
# For the topic fields, let's get the values from a serializer
PostRevisor.tracked_topic_fields.keys.each do |field|
if topic.respond_to?(field)
latest_modifications[field.to_s] = [topic.send(field)]
end
end
post_revisions << PostRevision.new( post_revisions << PostRevision.new(
number: post_revisions.last.number + 1, number: post_revisions.last.number + 1,
hidden: post.hidden, hidden: post.hidden,
modifications: { modifications: latest_modifications
"raw" => [post.raw],
"cooked" => [post.cooked],
"edit_reason" => [post.edit_reason],
"wiki" => [post.wiki],
"post_type" => [post.post_type],
"user_id" => [post.user_id],
"title" => [topic.title],
"category_id" => [topic.category_id],
}
) )
@all_revisions = [] @all_revisions = []

View file

@ -3,29 +3,35 @@ require_dependency 'pinned_check'
class TopicViewSerializer < ApplicationSerializer class TopicViewSerializer < ApplicationSerializer
include PostStreamSerializerMixin include PostStreamSerializerMixin
# These attributes will be delegated to the topic def self.attributes_from_topic(*list)
def self.topic_attributes [list].flatten.each do |attribute|
[:id, attributes(attribute)
:title, class_eval %{def #{attribute}
:fancy_title, object.topic.#{attribute}
:posts_count, end}
:created_at, end
:views,
:reply_count,
:participant_count,
:like_count,
:last_posted_at,
:visible,
:closed,
:archived,
:has_summary,
:archetype,
:slug,
:category_id,
:word_count,
:deleted_at]
end end
attributes_from_topic :id,
:title,
:fancy_title,
:posts_count,
:created_at,
:views,
:reply_count,
:participant_count,
:like_count,
:last_posted_at,
:visible,
:closed,
:archived,
:has_summary,
:archetype,
:slug,
:category_id,
:word_count,
:deleted_at
attributes :draft, attributes :draft,
:draft_key, :draft_key,
:draft_sequence, :draft_sequence,
@ -45,14 +51,6 @@ class TopicViewSerializer < ApplicationSerializer
:chunk_size, :chunk_size,
:bookmarked :bookmarked
# Define a delegator for each attribute of the topic we want
attributes(*topic_attributes)
topic_attributes.each do |ta|
class_eval %{def #{ta}
object.topic.#{ta}
end}
end
# TODO: Split off into proper object / serializer # TODO: Split off into proper object / serializer
def details def details
result = { result = {

View file

@ -4,7 +4,7 @@ class PostRevisor
# Helps us track changes to a topic. # Helps us track changes to a topic.
# #
# It's passed to `Topic.track_field` callbacks so they can record if they # It's passed to `track_topic_fields` callbacks so they can record if they
# changed a value or not. This is needed for things like custom fields. # changed a value or not. This is needed for things like custom fields.
class TopicChanges class TopicChanges
attr_reader :topic, :user attr_reader :topic, :user
@ -47,13 +47,29 @@ class PostRevisor
@topic = topic || post.topic @topic = topic || post.topic
end end
def self.tracked_fields def self.tracked_topic_fields
@@tracked_fields ||= {} @@tracked_topic_fields ||= {}
@@tracked_fields @@tracked_topic_fields
end end
def self.track_field(field, &block) def self.track_topic_field(field, &block)
tracked_fields[field] = block tracked_topic_fields[field] = block
# Define it in the serializer unless it already has been defined
unless PostRevisionSerializer.instance_methods(false).include?("#{field}_changes".to_sym)
PostRevisionSerializer.add_compared_field(field)
end
end
# Fields we want to record revisions for by default
track_topic_field(:title) do |tc, title|
tc.record_change('title', tc.topic.title, title)
tc.topic.title = title
end
track_topic_field(:category_id) do |tc, category_id|
tc.record_change('category_id', tc.topic.category_id, category_id)
tc.check_result(tc.topic.change_category_to_id(category_id))
end end
# AVAILABLE OPTIONS: # AVAILABLE OPTIONS:
@ -139,7 +155,7 @@ class PostRevisor
end end
def topic_changed? def topic_changed?
PostRevisor.tracked_fields.keys.any? {|f| @fields.has_key?(f)} PostRevisor.tracked_topic_fields.keys.any? {|f| @fields.has_key?(f)}
end end
def revise_post def revise_post
@ -217,7 +233,7 @@ class PostRevisor
def update_topic def update_topic
Topic.transaction do Topic.transaction do
PostRevisor.tracked_fields.each do |f, cb| PostRevisor.tracked_topic_fields.each do |f, cb|
if !@topic_changes.errored? && @fields.has_key?(f) if !@topic_changes.errored? && @fields.has_key?(f)
cb.call(@topic_changes, @fields[f]) cb.call(@topic_changes, @fields[f])
end end
@ -360,13 +376,3 @@ class PostRevisor
end end
# Fields we want to record revisions for by default
PostRevisor.track_field(:title) do |tc, title|
tc.record_change('title', tc.topic.title, title)
tc.topic.title = title
end
PostRevisor.track_field(:category_id) do |tc, category_id|
tc.record_change('category_id', tc.topic.category_id, category_id)
tc.check_result(tc.topic.change_category_to_id(category_id))
end