diff --git a/app/assets/javascripts/discourse/models/action_summary.js b/app/assets/javascripts/discourse/models/action_summary.js index ffcc1901117..80517ae147f 100644 --- a/app/assets/javascripts/discourse/models/action_summary.js +++ b/app/assets/javascripts/discourse/models/action_summary.js @@ -22,17 +22,22 @@ Discourse.ActionSummary = Discourse.Model.extend({ } }.property('count', 'acted', 'actionType'), - canAlsoAction: function() { - if (this.get('hidden')) return false; - return this.get('can_act'); - }.property('can_act', 'hidden'), + canAlsoAction: Em.computed.and('can_act', 'actionType.notCustomFlag'), + usersCollapsed: Em.computed.not('usersExpanded'), + usersExpanded: Em.computed.gt('users.length', 0), // Remove it removeAction: function() { - this.set('acted', false); - this.set('count', this.get('count') - 1); - this.set('can_act', true); - return this.set('can_undo', false); + this.setProperties({ + acted: false, + count: this.get('count') - 1, + can_act: true, + can_undo: false + }); + + if (this.get('usersExpanded')) { + this.get('users').removeObject(Discourse.User.current()); + } }, // Perform this action @@ -42,10 +47,12 @@ Discourse.ActionSummary = Discourse.Model.extend({ var action = this.get('actionType.name_key'); // Mark it as acted - this.set('acted', true); - this.set('count', this.get('count') + 1); - this.set('can_act', false); - this.set('can_undo', true); + this.setProperties({ + acted: true, + count: this.get('count') + 1, + can_act: false, + can_undo: true + }); if(action === 'notify_moderators' || action === 'notify_user') { this.set('can_undo',false); @@ -53,8 +60,8 @@ Discourse.ActionSummary = Discourse.Model.extend({ } // Add ourselves to the users who liked it if present - if (this.present('users')) { - this.users.pushObject(Discourse.User.current()); + if (this.get('usersExpanded')) { + this.get('users').addObject(Discourse.User.current()); } // Create our post action @@ -113,7 +120,11 @@ Discourse.ActionSummary = Discourse.Model.extend({ var users = Em.A(); actionSummary.set('users', users); _.each(result,function(user) { - users.pushObject(Discourse.User.create(user)); + if (user.id === Discourse.User.current('id')) { + users.pushObject(Discourse.User.current()); + } else { + users.pushObject(Discourse.User.create(user)); + } }); }); } diff --git a/app/assets/javascripts/discourse/models/post.js b/app/assets/javascripts/discourse/models/post.js index 551ad65a18f..7ef7de00da6 100644 --- a/app/assets/javascripts/discourse/models/post.js +++ b/app/assets/javascripts/discourse/models/post.js @@ -186,6 +186,11 @@ Discourse.Post = Discourse.Model.extend({ }, recover: function() { + this.setProperties({ + deleted_at: null, + deleted_by: null + }); + return Discourse.ajax("/posts/" + (this.get('id')) + "/recover", { type: 'PUT', cache: false }); }, diff --git a/app/assets/javascripts/discourse/models/post_action_type.js b/app/assets/javascripts/discourse/models/post_action_type.js index c3583967b98..b941ae25b2e 100644 --- a/app/assets/javascripts/discourse/models/post_action_type.js +++ b/app/assets/javascripts/discourse/models/post_action_type.js @@ -6,7 +6,9 @@ @namespace Discourse @module Discourse **/ -Discourse.PostActionType = Discourse.Model.extend({}); +Discourse.PostActionType = Discourse.Model.extend({ + notCustomFlag: Em.computed.not('is_custom_flag') +}); Discourse.PostActionType.reopenClass({ MAX_MESSAGE_LENGTH: 500 diff --git a/app/assets/javascripts/discourse/templates/post.js.handlebars b/app/assets/javascripts/discourse/templates/post.js.handlebars index 57323e820ea..405002912c1 100644 --- a/app/assets/javascripts/discourse/templates/post.js.handlebars +++ b/app/assets/javascripts/discourse/templates/post.js.handlebars @@ -55,6 +55,13 @@ {{view Discourse.RepliesView contentBinding="replies" postViewBinding="view"}} {{view Discourse.ActionsHistoryView contentBinding="actionsHistory"}} + + {{#if deleted_by}} +
+ {{i18n post.deleted_by}} {{avatar deleted_by imageSize="tiny"}} +
+ {{/if}} + {{view Discourse.TopicSummaryView postBinding="this"}} diff --git a/app/assets/javascripts/discourse/views/actions_history_view.js b/app/assets/javascripts/discourse/views/actions_history_view.js index 8ca6aee173e..04ffcae7a9a 100644 --- a/app/assets/javascripts/discourse/views/actions_history_view.js +++ b/app/assets/javascripts/discourse/views/actions_history_view.js @@ -10,24 +10,27 @@ Discourse.ActionsHistoryView = Discourse.View.extend({ tagName: 'section', classNameBindings: [':post-actions', 'hidden'], - hidden: Em.computed.empty('content'), - - shouldRerender: Discourse.View.renderIfChanged('content.@each', 'content.users.@each'), + shouldRerender: Discourse.View.renderIfChanged('content.@each', 'content.users.length'), // This was creating way too many bound ifs and subviews in the handlebars version. render: function(buffer) { if (!this.present('content')) return; - return this.get('content').forEach(function(c) { - var actionString, iconsHtml; + this.get('content').forEach(function(c) { buffer.push("
"); + var renderActionIf = function(property, dataAttribute, text) { + if (!c.get(property)) { return; } + buffer.push(" " + text + "."); + }; + // TODO multi line expansion for flags - var postUrl; - if (c.get('users')) { - iconsHtml = ""; + var iconsHtml = ""; + if (c.get('usersExpanded')) { + var postUrl; c.get('users').forEach(function(u) { + console.log(u); iconsHtml += ""; if (u.post_url) { postUrl = postUrl || u.post_url; @@ -42,44 +45,35 @@ Discourse.ActionsHistoryView = Discourse.View.extend({ }); var key = 'post.actions.people.' + c.get('actionType.name_key'); - if(postUrl) { - key = key + "_with_url"; - } + if (postUrl) { key = key + "_with_url"; } + buffer.push(" " + I18n.t(key, { icons: iconsHtml, postUrl: postUrl}) + "."); - } else { - buffer.push("" + (c.get('description')) + "."); - } - - if (c.get('can_act') && !c.get('actionType.is_custom_flag')) { - actionString = I18n.t("post.actions.it_too." + c.get('actionType.name_key')); - buffer.push(" " + actionString + "."); - } - - if (c.get('can_undo')) { - actionString = I18n.t("post.actions.undo." + c.get('actionType.name_key') ); - buffer.push(" " + actionString + "."); - } - - if (c.get('can_clear_flags')) { - buffer.push(" " + (I18n.t("post.actions.clear_flags", { count: c.count })) + "."); } + renderActionIf('usersCollapsed', 'who-acted', c.get('description')); + renderActionIf('canAlsoAction', 'act', I18n.t("post.actions.it_too." + c.get('actionType.name_key'))); + renderActionIf('can_undo', 'undo', I18n.t("post.actions.undo." + c.get('actionType.name_key'))); + renderActionIf('can_clear_flags', 'clear-flags', I18n.t("post.actions.clear_flags", { count: c.count })); buffer.push("
"); }); }, + actionTypeById: function(actionTypeId) { + return this.get('content').findProperty('id', actionTypeId); + }, + click: function(e) { - var $target, actionTypeId; - $target = $(e.target); + var $target = $(e.target), + actionTypeId; if (actionTypeId = $target.data('clear-flags')) { - this.get('controller').clearFlags(this.content.findProperty('id', actionTypeId)); + this.get('controller').clearFlags(this.actionTypeById(actionTypeId)); return false; } // User wants to know who actioned it if (actionTypeId = $target.data('who-acted')) { - this.get('controller').whoActed(this.content.findProperty('id', actionTypeId)); + this.get('controller').whoActed(this.actionTypeById(actionTypeId)); return false; } diff --git a/app/serializers/post_serializer.rb b/app/serializers/post_serializer.rb index c6da600ca95..05a6277cc30 100644 --- a/app/serializers/post_serializer.rb +++ b/app/serializers/post_serializer.rb @@ -118,6 +118,14 @@ class PostSerializer < BasicPostSerializer true end + def deleted_by + BasicUserSerializer.new(object.deleted_by, root: false).as_json + end + + def include_deleted_by? + object.deleted_by.present? + end + # Summary of the actions taken on this post def actions_summary result = [] diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 54a351247d0..f8cdc7cac55 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -732,6 +732,7 @@ en: continue_discussion: "Continuing the discussion from {{postLink}}:" follow_quote: "go to the quoted post" deleted_by_author: "(post removed by author)" + deleted_by: "deleted by" expand_collapse: "expand/collapse" has_replies: diff --git a/test/javascripts/models/post_test.js b/test/javascripts/models/post_test.js index cf19235f548..0320e671550 100644 --- a/test/javascripts/models/post_test.js +++ b/test/javascripts/models/post_test.js @@ -64,6 +64,11 @@ test('destroy by staff', function() { present(post.get('deleted_at'), "it has a `deleted_at` field."); equal(post.get('deleted_by'), user, "it has the user in the `deleted_by` field"); ok(Discourse.ajax.calledOnce, "it made an AJAX call"); + + post.recover(); + blank(post.get('deleted_at'), "it clears `deleted_at` when recovering"); + blank(post.get('deleted_by'), "it clears `deleted_by` when recovering"); + }); test('destroy by non-staff', function() {