mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 08:51:05 +08:00
Show the entire history of replies above a post when you expend "in reply to"
This commit is contained in:
@ -253,10 +253,29 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Toggle the star on the topic
|
// Toggle the star on the topic
|
||||||
toggleStar: function(e) {
|
toggleStar: function() {
|
||||||
this.get('content').toggleStar();
|
this.get('content').toggleStar();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Toggle the replies this post is a reply to
|
||||||
|
|
||||||
|
@method showReplyHistory
|
||||||
|
**/
|
||||||
|
toggleReplyHistory: function(post) {
|
||||||
|
var replyHistory = post.get('replyHistory'),
|
||||||
|
topicController = this;
|
||||||
|
|
||||||
|
if (replyHistory.length > 0) {
|
||||||
|
replyHistory.clear();
|
||||||
|
} else {
|
||||||
|
post.set('loadingReplyHistory', true);
|
||||||
|
topicController.get('postStream').findReplyHistory(post).then(function () {
|
||||||
|
post.set('loadingReplyHistory', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clears the pin from a topic for the currently logged in user
|
Clears the pin from a topic for the currently logged in user
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
**/
|
**/
|
||||||
Discourse.Post = Discourse.Model.extend({
|
Discourse.Post = Discourse.Model.extend({
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
this.set('replyHistory', []);
|
||||||
|
},
|
||||||
|
|
||||||
shareUrl: function() {
|
shareUrl: function() {
|
||||||
var user = Discourse.User.current();
|
var user = Discourse.User.current();
|
||||||
var userSuffix = user ? '?u=' + user.get('username_lower') : '';
|
var userSuffix = user ? '?u=' + user.get('username_lower') : '';
|
||||||
@ -383,12 +387,6 @@ Discourse.Post.reopenClass({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
loadByPostNumber: function(topicId, postId) {
|
|
||||||
return Discourse.ajax("/posts/by_number/" + topicId + "/" + postId + ".json").then(function (result) {
|
|
||||||
return Discourse.Post.create(result);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
loadQuote: function(postId) {
|
loadQuote: function(postId) {
|
||||||
return Discourse.ajax("/posts/" + postId + ".json").then(function(result) {
|
return Discourse.ajax("/posts/" + postId + ".json").then(function(result) {
|
||||||
var post = Discourse.Post.create(result);
|
var post = Discourse.Post.create(result);
|
||||||
|
@ -459,6 +459,26 @@ Discourse.PostStream = Em.Object.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the "thread" of posts in the history of a post.
|
||||||
|
|
||||||
|
@method findReplyHistory
|
||||||
|
@param {Discourse.Post} post the post whose history we want
|
||||||
|
@returns {Array} the posts in the history.
|
||||||
|
**/
|
||||||
|
findReplyHistory: function(post) {
|
||||||
|
var postStream = this,
|
||||||
|
url = "/posts/" + post.get('id') + "/reply-history.json";
|
||||||
|
|
||||||
|
return Discourse.ajax(url).then(function(result) {
|
||||||
|
return result.map(function (p) {
|
||||||
|
return postStream.storePost(Discourse.Post.create(p));
|
||||||
|
});
|
||||||
|
}).then(function (replyHistory) {
|
||||||
|
post.set('replyHistory', replyHistory);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the closest post number given a postNumber that may not exist in the stream.
|
Returns the closest post number given a postNumber that may not exist in the stream.
|
||||||
For example, if the user asks for a post that's deleted or otherwise outside the range.
|
For example, if the user asks for a post that's deleted or otherwise outside the range.
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
<div class='span11 topic-body'>
|
<div class='span11 topic-body'>
|
||||||
<div class="topic-meta-data-inside">
|
<div class="topic-meta-data-inside">
|
||||||
<div class='post-info post-date'>{{unboundAgeWithTooltip created_at}}</div>
|
<div class='post-info post-date'>{{unboundAgeWithTooltip created_at}}</div>
|
||||||
{{#if view.previousPost}}<a href='{{unbound url}}' class="post-info arrow" title="{{i18n topic.jump_reply_up}}"><i class='icon icon-arrow-up'></i></a>{{/if}}
|
{{#if view.parentView.previousPost}}<a href='{{unbound url}}' class="post-info arrow" title="{{i18n topic.jump_reply_up}}"><i class='icon icon-arrow-up'></i></a>{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{{unbound cooked}}}
|
{{{unbound cooked}}}
|
||||||
{{#unless view.previousPost}}<a href='{{unbound url}}' class="arrow" title="{{i18n topic.jump_reply_down}}"><i class='icon icon-arrow-down'></i></a>{{/unless}}
|
{{#unless view.parentView.previousPost}}<a href='{{unbound url}}' class="arrow" title="{{i18n topic.jump_reply_down}}"><i class='icon icon-arrow-down'></i></a>{{/unless}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
<div class='row'>
|
<div class='row'>
|
||||||
<section class='embedded-posts top parent-post span14 offset2' style='display:none'>
|
{{view Discourse.ReplyHistory contentBinding="replyHistory"}}
|
||||||
{{#if view.parentPost}}
|
|
||||||
{{view Discourse.ParentView contentBinding="view.parentPost" postViewBinding="view"}}
|
|
||||||
{{/if}}
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<article class='boxed' {{bindAttr id="postElementId"}} {{bindAttr data-post-id="id"}} data-user-id="{{unbound user_id}}">
|
<article class='boxed' {{bindAttr id="postElementId"}} {{bindAttr data-post-id="id"}} data-user-id="{{unbound user_id}}">
|
||||||
<div class='row'>
|
<div class='row'>
|
||||||
{{#if showUserReplyTab}}
|
{{#if showUserReplyTab}}
|
||||||
<a href='#' {{action toggleParent target="view"}} class='reply-to-tab'>
|
<a href='#' {{action toggleReplyHistory this}} class='reply-to-tab'>
|
||||||
{{#if loadingParent}}
|
{{#if loadingReplyHistory}}
|
||||||
{{i18n loading}}
|
{{i18n loading}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{i18n post.in_reply_to}}
|
{{i18n post.in_reply_to}}
|
||||||
@ -31,7 +27,7 @@
|
|||||||
<div class='topic-body span14'>
|
<div class='topic-body span14'>
|
||||||
<button {{action selectPost this}} {{bindAttr class=":post-select controller.multiSelect::hidden"}}>{{view.selectText}}</button>
|
<button {{action selectPost this}} {{bindAttr class=":post-select controller.multiSelect::hidden"}}>{{view.selectText}}</button>
|
||||||
|
|
||||||
<div {{bindAttr class="showUserReplyTab:avoid-tab view.repliesHidden:bottom-round :contents :regular view.extraClass"}}>
|
<div {{bindAttr class="showUserReplyTab:avoid-tab view.repliesShown::bottom-round :contents :regular view.extraClass"}}>
|
||||||
{{#unless controller.multiSelect}}
|
{{#unless controller.multiSelect}}
|
||||||
<div class='topic-meta-data-inside'>
|
<div class='topic-meta-data-inside'>
|
||||||
{{#if hasHistory}}
|
{{#if hasHistory}}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
the world ain't all sunshine and rainbows
|
@ -1,29 +0,0 @@
|
|||||||
/*global Markdown:true*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
A control to support embedding a post as a parent of the current post (in reply to)
|
|
||||||
|
|
||||||
@class ParentView
|
|
||||||
@extends Discourse.EmbeddedPostView
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.ParentView = Discourse.EmbeddedPostView.extend({
|
|
||||||
previousPost: true,
|
|
||||||
|
|
||||||
// Nice animation for when the replies appear
|
|
||||||
didInsertElement: function() {
|
|
||||||
this._super();
|
|
||||||
|
|
||||||
var $parentPost = this.get('postView').$('section.parent-post');
|
|
||||||
|
|
||||||
// Animate unless we're on a touch device
|
|
||||||
if (Discourse.get('touch')) {
|
|
||||||
$parentPost.show();
|
|
||||||
} else {
|
|
||||||
$parentPost.slideDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
@ -19,7 +19,8 @@ Discourse.PostMenuView = Discourse.View.extend({
|
|||||||
'post.bookmarkClass',
|
'post.bookmarkClass',
|
||||||
'post.bookmarkTooltip',
|
'post.bookmarkTooltip',
|
||||||
'post.shareUrl',
|
'post.shareUrl',
|
||||||
'post.topic.deleted_at'),
|
'post.topic.deleted_at',
|
||||||
|
'post.replies.length'),
|
||||||
|
|
||||||
render: function(buffer) {
|
render: function(buffer) {
|
||||||
var post = this.get('post');
|
var post = this.get('post');
|
||||||
@ -55,12 +56,16 @@ Discourse.PostMenuView = Discourse.View.extend({
|
|||||||
buffer.push("<span class='badge-posts'>" + reply_count + "</span>");
|
buffer.push("<span class='badge-posts'>" + reply_count + "</span>");
|
||||||
buffer.push(I18n.t("post.has_replies", { count: reply_count }));
|
buffer.push(I18n.t("post.has_replies", { count: reply_count }));
|
||||||
|
|
||||||
var icon = this.get('postView.repliesShown') ? 'icon-chevron-up' : 'icon-chevron-down';
|
var icon = (this.get('post.replies.length') > 0) ? 'icon-chevron-up' : 'icon-chevron-down';
|
||||||
return buffer.push("<i class='icon " + icon + "'></i></button>");
|
return buffer.push("<i class='icon " + icon + "'></i></button>");
|
||||||
},
|
},
|
||||||
|
|
||||||
clickReplies: function() {
|
clickReplies: function() {
|
||||||
this.get('postView').showReplies();
|
if (this.get('post.replies.length') > 0) {
|
||||||
|
this.set('post.replies', []);
|
||||||
|
} else {
|
||||||
|
this.get('post').loadReplies();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Delete button
|
// Delete button
|
||||||
|
@ -12,8 +12,7 @@ Discourse.PostView = Discourse.GroupedView.extend({
|
|||||||
classNameBindings: ['postTypeClass',
|
classNameBindings: ['postTypeClass',
|
||||||
'selected',
|
'selected',
|
||||||
'post.hidden:hidden',
|
'post.hidden:hidden',
|
||||||
'post.deleted',
|
'post.deleted'],
|
||||||
'parentPost:replies-above'],
|
|
||||||
postBinding: 'content',
|
postBinding: 'content',
|
||||||
|
|
||||||
postTypeClass: function() {
|
postTypeClass: function() {
|
||||||
@ -44,56 +43,7 @@ Discourse.PostView = Discourse.GroupedView.extend({
|
|||||||
return this.get('selected') ? I18n.t('topic.multi_select.selected', { count: this.get('controller.selectedPostsCount') }) : I18n.t('topic.multi_select.select');
|
return this.get('selected') ? I18n.t('topic.multi_select.selected', { count: this.get('controller.selectedPostsCount') }) : I18n.t('topic.multi_select.select');
|
||||||
}.property('selected', 'controller.selectedPostsCount'),
|
}.property('selected', 'controller.selectedPostsCount'),
|
||||||
|
|
||||||
repliesHidden: Em.computed.not('repliesShown'),
|
repliesShown: Em.computed.gt('post.replies.length', 0),
|
||||||
|
|
||||||
// Click on the replies button
|
|
||||||
showReplies: function() {
|
|
||||||
var postView = this;
|
|
||||||
if (this.get('repliesShown')) {
|
|
||||||
this.set('repliesShown', false);
|
|
||||||
} else {
|
|
||||||
this.get('post').loadReplies().then(function() {
|
|
||||||
postView.set('repliesShown', true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Toggle visibility of parent post
|
|
||||||
toggleParent: function(e) {
|
|
||||||
var postView = this;
|
|
||||||
var post = this.get('post');
|
|
||||||
var $parent = this.$('.parent-post');
|
|
||||||
var inReplyTo = post.get('reply_to_post_number');
|
|
||||||
|
|
||||||
if (post.get('post_number') - 1 === inReplyTo) {
|
|
||||||
// true means ... avoid scroll if possible
|
|
||||||
Discourse.TopicView.jumpToPost(post.get('topic_id'), inReplyTo, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.get('parentPost')) {
|
|
||||||
$('nav', $parent).removeClass('toggled');
|
|
||||||
// Don't animate on touch
|
|
||||||
if (Discourse.get('touch')) {
|
|
||||||
$parent.hide();
|
|
||||||
this.set('parentPost', null);
|
|
||||||
} else {
|
|
||||||
$parent.slideUp(function() { postView.set('parentPost', null); });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.set('loadingParent', true);
|
|
||||||
$('nav', $parent).addClass('toggled');
|
|
||||||
|
|
||||||
Discourse.Post.loadByPostNumber(post.get('topic_id'), inReplyTo).then(function(result) {
|
|
||||||
postView.set('loadingParent', false);
|
|
||||||
// Give the post a reference back to the topic
|
|
||||||
result.topic = postView.get('post.topic');
|
|
||||||
postView.set('parentPost', result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
updateQuoteElements: function($aside, desc) {
|
updateQuoteElements: function($aside, desc) {
|
||||||
var navLink = "";
|
var navLink = "";
|
||||||
@ -143,7 +93,7 @@ Discourse.PostView = Discourse.GroupedView.extend({
|
|||||||
if ($aside.data('topic')) {
|
if ($aside.data('topic')) {
|
||||||
topic_id = $aside.data('topic');
|
topic_id = $aside.data('topic');
|
||||||
}
|
}
|
||||||
Discourse.ajax("/posts/by_number/" + topic_id + "/" + ($aside.data('post'))).then(function (result) {
|
Discourse.ajax("/posts/by_number/" + topic_id + "/" + $aside.data('post')).then(function (result) {
|
||||||
var parsed = $(result.cooked);
|
var parsed = $(result.cooked);
|
||||||
parsed.replaceText(originalText, "<span class='highlighted'>" + originalText + "</span>");
|
parsed.replaceText(originalText, "<span class='highlighted'>" + originalText + "</span>");
|
||||||
$blockQuote.showHtml(parsed);
|
$blockQuote.showHtml(parsed);
|
||||||
|
@ -7,24 +7,10 @@
|
|||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
Discourse.RepliesView = Ember.CollectionView.extend({
|
Discourse.RepliesView = Ember.CollectionView.extend({
|
||||||
templateName: 'replies',
|
|
||||||
tagName: 'section',
|
tagName: 'section',
|
||||||
classNames: ['replies-list', 'embedded-posts', 'bottom'],
|
classNameBindings: [':embedded-posts', ':bottom', 'hidden'],
|
||||||
itemViewClass: Discourse.EmbeddedPostView,
|
itemViewClass: Discourse.EmbeddedPostView,
|
||||||
|
hidden: Em.computed.equal('content.length', 0)
|
||||||
repliesShownChanged: function() {
|
|
||||||
var $this = this.$();
|
|
||||||
if (this.get('parentView.repliesShown')) {
|
|
||||||
Em.run.schedule('afterRender', function() {
|
|
||||||
$this.slideDown();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Em.run.schedule('afterRender', function() {
|
|
||||||
$this.slideUp();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}.observes('parentView.repliesShown')
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
17
app/assets/javascripts/discourse/views/reply_history.js
Normal file
17
app/assets/javascripts/discourse/views/reply_history.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
Lists previous posts in the history of a post.
|
||||||
|
|
||||||
|
@class ReplyHistory
|
||||||
|
@extends Discourse.EmbeddedPostView
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.ReplyHistory = Em.CollectionView.extend({
|
||||||
|
tagName: 'section',
|
||||||
|
classNameBindings: [':embedded-posts', ':top', ':span14', ':offset2', 'hidden'],
|
||||||
|
itemViewClass: Discourse.EmbeddedPostView,
|
||||||
|
hidden: Em.computed.equal('content.length', 0),
|
||||||
|
previousPost: true
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -423,7 +423,6 @@
|
|||||||
.embedded-posts.bottom {
|
.embedded-posts.bottom {
|
||||||
@include border-radius-bottom(4px);
|
@include border-radius-bottom(4px);
|
||||||
border-bottom: 1px solid #b9b9b9;
|
border-bottom: 1px solid #b9b9b9;
|
||||||
display: none;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.arrow {
|
.arrow {
|
||||||
float: right;
|
float: right;
|
||||||
@ -432,7 +431,7 @@
|
|||||||
}
|
}
|
||||||
.embedded-posts.top {
|
.embedded-posts.top {
|
||||||
@include border-radius-top(4px);
|
@include border-radius-top(4px);
|
||||||
border-top: 1px solid #b9b9b9;
|
border-top: 1px solid #ddd;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,8 +443,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.reply {
|
div.reply {
|
||||||
border-left: 1px solid #b9b9b9;
|
border-left: 1px solid #ddd;
|
||||||
border-right: 1px solid #b9b9b9;
|
border-right: 1px solid #ddd;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
@ -466,7 +465,7 @@
|
|||||||
}
|
}
|
||||||
.topic-body {
|
.topic-body {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
border: 1px solid #b9b9b9;
|
border: 1px solid #ddd;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
color: black;
|
color: black;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
@ -593,9 +592,6 @@
|
|||||||
color: $dark_gray;
|
color: $dark_gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.replies-above .boxed .topic-body .contents {
|
|
||||||
@include border-radius-top(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ require_dependency 'distributed_memoizer'
|
|||||||
class PostsController < ApplicationController
|
class PostsController < ApplicationController
|
||||||
|
|
||||||
# Need to be logged in for all actions here
|
# Need to be logged in for all actions here
|
||||||
before_filter :ensure_logged_in, except: [:show, :replies, :by_number, :short_link, :versions]
|
before_filter :ensure_logged_in, except: [:show, :replies, :by_number, :short_link, :versions, :reply_history]
|
||||||
|
|
||||||
skip_before_filter :store_incoming_links, only: [:short_link]
|
skip_before_filter :store_incoming_links, only: [:short_link]
|
||||||
skip_before_filter :check_xhr, only: [:markdown,:short_link]
|
skip_before_filter :check_xhr, only: [:markdown,:short_link]
|
||||||
@ -113,6 +113,13 @@ class PostsController < ApplicationController
|
|||||||
render_post_json(@post)
|
render_post_json(@post)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reply_history
|
||||||
|
@post = Post.where(id: params[:id]).first
|
||||||
|
guardian.ensure_can_see!(@post)
|
||||||
|
|
||||||
|
render_serialized(@post.reply_history, PostSerializer)
|
||||||
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@post = find_post_from_params
|
@post = find_post_from_params
|
||||||
@post.revert_to(params[:version].to_i) if params[:version].present?
|
@post.revert_to(params[:version].to_i) if params[:version].present?
|
||||||
|
@ -335,6 +335,21 @@ class Post < ActiveRecord::Base
|
|||||||
private_posts.with_topic_subtype(topic_subtype).where('posts.created_at > ?', since_days_ago.days.ago).group('date(posts.created_at)').order('date(posts.created_at)').count
|
private_posts.with_topic_subtype(topic_subtype).where('posts.created_at > ?', since_days_ago.days.ago).group('date(posts.created_at)').order('date(posts.created_at)').count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def reply_history
|
||||||
|
post_ids = Post.exec_sql("WITH RECURSIVE breadcrumb(id, reply_to_post_number) AS (
|
||||||
|
SELECT p.id, p.reply_to_post_number FROM posts AS p
|
||||||
|
WHERE p.id = :post_id
|
||||||
|
UNION
|
||||||
|
SELECT p.id, p.reply_to_post_number FROM posts AS p, breadcrumb
|
||||||
|
WHERE breadcrumb.reply_to_post_number = p.post_number
|
||||||
|
AND p.topic_id = :topic_id
|
||||||
|
) SELECT id from breadcrumb ORDER by id", post_id: id, topic_id: topic_id).to_a
|
||||||
|
|
||||||
|
post_ids.map! {|r| r['id'].to_i }.reject! {|post_id| post_id == id}
|
||||||
|
Post.where(id: post_ids).includes(:user, :topic).order(:id).to_a
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ Discourse::Application.routes.draw do
|
|||||||
|
|
||||||
|
|
||||||
get 'posts/by_number/:topic_id/:post_number' => 'posts#by_number'
|
get 'posts/by_number/:topic_id/:post_number' => 'posts#by_number'
|
||||||
|
get 'posts/:id/reply-history' => 'posts#reply_history'
|
||||||
resources :posts do
|
resources :posts do
|
||||||
get 'versions'
|
get 'versions'
|
||||||
put 'bookmark'
|
put 'bookmark'
|
||||||
|
@ -13,7 +13,6 @@ describe PostsController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe 'show' do
|
describe 'show' do
|
||||||
|
|
||||||
let(:user) { log_in }
|
let(:user) { log_in }
|
||||||
let(:post) { Fabricate(:post, user: user) }
|
let(:post) { Fabricate(:post, user: user) }
|
||||||
|
|
||||||
@ -52,9 +51,26 @@ describe PostsController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'reply_history' do
|
||||||
|
let(:user) { log_in }
|
||||||
|
let(:post) { Fabricate(:post, user: user) }
|
||||||
|
|
||||||
|
it 'ensures the user can see the post' do
|
||||||
|
Guardian.any_instance.expects(:can_see?).with(post).returns(false)
|
||||||
|
xhr :get, :reply_history, id: post.id
|
||||||
|
response.should be_forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'suceeds' do
|
||||||
|
Post.any_instance.expects(:reply_history)
|
||||||
|
xhr :get, :reply_history, id: post.id
|
||||||
|
response.should be_success
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
describe 'versions' do
|
describe 'versions' do
|
||||||
|
|
||||||
shared_examples 'posts_controller versions examples' do
|
shared_examples 'posts_controller versions examples' do
|
||||||
|
@ -711,7 +711,6 @@ describe Post do
|
|||||||
|
|
||||||
|
|
||||||
context 'sort_order' do
|
context 'sort_order' do
|
||||||
|
|
||||||
context 'regular topic' do
|
context 'regular topic' do
|
||||||
|
|
||||||
let!(:p1) { Fabricate(:post, post_args) }
|
let!(:p1) { Fabricate(:post, post_args) }
|
||||||
@ -722,6 +721,20 @@ describe Post do
|
|||||||
Post.regular_order.should == [p1, p2, p3]
|
Post.regular_order.should == [p1, p2, p3]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "reply_history" do
|
||||||
|
|
||||||
|
let!(:p1) { Fabricate(:post, post_args) }
|
||||||
|
let!(:p2) { Fabricate(:post, post_args.merge(reply_to_post_number: p1.post_number)) }
|
||||||
|
let!(:p3) { Fabricate(:post, post_args) }
|
||||||
|
let!(:p4) { Fabricate(:post, post_args.merge(reply_to_post_number: p2.post_number)) }
|
||||||
|
|
||||||
|
it "returns the posts in reply to this post" do
|
||||||
|
p4.reply_history.should == [p1, p2]
|
||||||
|
p3.reply_history.should be_blank
|
||||||
|
p2.reply_history.should == [p1]
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -261,6 +261,22 @@ asyncTestDiscourse("loadIntoIdentityMap with post ids", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
asyncTestDiscourse("loading a post's history", function() {
|
||||||
|
var postStream = buildStream(1234);
|
||||||
|
expect(3);
|
||||||
|
|
||||||
|
var post = Discourse.Post.create({id: 4321});
|
||||||
|
|
||||||
|
var secondPost = Discourse.Post.create({id: 2222});
|
||||||
|
|
||||||
|
this.stub(Discourse, "ajax").returns(Ember.RSVP.resolve([secondPost]));
|
||||||
|
postStream.findReplyHistory(post).then(function() {
|
||||||
|
ok(Discourse.ajax.calledOnce, "it made the ajax request");
|
||||||
|
present(postStream.findLoadedPost(2222), "it stores the returned post in the identity map");
|
||||||
|
present(post.get('replyHistory'), "it sets the replyHistory attribute for the post");
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("staging and undoing a new post", function() {
|
test("staging and undoing a new post", function() {
|
||||||
var postStream = buildStream(10101, [1]);
|
var postStream = buildStream(10101, [1]);
|
||||||
|
@ -12,6 +12,7 @@ test('defaults', function() {
|
|||||||
var post = Discourse.Post.create({id: 1});
|
var post = Discourse.Post.create({id: 1});
|
||||||
blank(post.get('deleted_at'), "it has no deleted_at by default");
|
blank(post.get('deleted_at'), "it has no deleted_at by default");
|
||||||
blank(post.get('deleted_by'), "there is no deleted_by by default");
|
blank(post.get('deleted_by'), "there is no deleted_by by default");
|
||||||
|
equal(post.get('replyHistory.length'), 0, "there is no reply history by default");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('new_user', function() {
|
test('new_user', function() {
|
||||||
|
Reference in New Issue
Block a user