Skip to content
Extraits de code Groupes Projets
Valider f6e3c1b8 rédigé par Dennis Collinson's avatar Dennis Collinson
Parcourir les fichiers

seperate interactions from posts

Lazily load post interactions on show page
hella refactorz
parent 871d3cc6
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 216 ajouts et 127 suppressions
......@@ -7,5 +7,18 @@ app.collections.Comments = Backbone.Collection.extend({
initialize : function(models, options) {
this.post = options.post
},
make : function(text){
var self = this
var comment = new app.models.Comment({text: text })
, deferred = comment.save({}, {url : self.url()})
comment.set({author: app.currentUser.toJSON(), parent: self.post })
this.add(comment)
return deferred
}
});
app.collections.Reshares = Backbone.Collection.extend({
model: app.models.Reshare,
url : "/reshares"
});
app.models.Participation = Backbone.Model.extend({ });
......@@ -2,27 +2,27 @@ app.models.Post = Backbone.Model.extend(_.extend({}, app.models.formatDateMixin,
urlRoot : "/posts",
initialize : function() {
this.setupCollections();
this.bind("change", this.setupCollections, this)
this.interactions = new app.models.Post.Interactions(_.extend({post : this}, this.get("interactions")))
this.delegateToInteractions()
},
setupCollections: function() {
this.comments = new app.collections.Comments(this.get("comments") || this.get("last_three_comments"), {post : this});
this.likes = this.likes || new app.collections.Likes([], {post : this}); // load in the user like initially
this.participations = this.participations || new app.collections.Participations([], {post : this}); // load in the user like initially
delegateToInteractions : function(){
this.comments = this.interactions.comments
this.likes = this.interactions.likes
this.comment = function(){
this.interactions.comment.apply(this.interactions, arguments)
}
},
setFrameName : function(){
var templatePicker = new app.models.Post.TemplatePicker(this)
this.set({frame_name : templatePicker.getFrameName()})
this.set({frame_name : new app.models.Post.TemplatePicker(this).getFrameName()})
},
interactedAt : function() {
return this.timeOf("interacted_at");
},
createReshareUrl : "/reshares",
reshare : function(){
return this._reshare = this._reshare || new app.models.Reshare({root_guid : this.get("guid")});
},
......@@ -31,15 +31,6 @@ app.models.Post = Backbone.Model.extend(_.extend({}, app.models.formatDateMixin,
return this.get("author")
},
toggleLike : function() {
var userLike = this.get("user_like")
if(userLike) {
this.unlike()
} else {
this.like()
}
},
toggleFavorite : function(options){
this.set({favorite : !this.get("favorite")})
......@@ -47,40 +38,6 @@ app.models.Post = Backbone.Model.extend(_.extend({}, app.models.formatDateMixin,
if(options.save){ this.save() }
},
like : function() {
var self = this;
this.likes.create({}, {success : function(resp){
self.set(resp)
self.trigger('interacted', self)
}});
},
unlike : function() {
var self = this;
var likeModel = new app.models.Like(this.get("user_like"));
likeModel.url = this.likes.url + "/" + likeModel.id;
likeModel.destroy({success : function(model, resp) {
self.set(resp);
self.trigger('interacted', this)
}});
},
comment : function (text) {
var self = this
, postComments = this.comments;
postComments.create({"text": text}, {
url : postComments.url(),
wait:true, // added a wait for the time being. 0.5.3 was not optimistic, but 0.9.2 is.
error:function () {
alert(Diaspora.I18n.t("failed_to_post_message"));
}
});
},
headline : function() {
var headline = this.get("text").trim()
, newlineIdx = headline.indexOf("\n")
......
//require ../post
app.models.Post.Interactions = Backbone.Model.extend({
url : function(){
return this.post.url() + "/interactions"
},
initialize : function(options){
this.post = options.post
this.comments = new app.collections.Comments(this.get("comments"), {post : this.post})
this.likes = new app.collections.Likes(this.get("likes"), {post : this.post});
this.reshares = new app.collections.Reshares(this.get("reshares"), {post : this.post});
},
parse : function(resp){
this.comments.reset(resp.comments)
this.likes.reset(resp.likes)
this.reshares.reset(resp.reshares)
var comments = this.comments
, likes = this.likes
, reshares = this.reshares
return {
comments : comments,
likes : likes,
reshares : reshares,
fetched : true
}
},
likesCount : function(){
return (this.get("fetched") ? this.likes.models.length : this.get("likes_count") )
},
resharesCount : function(){
return this.get("fetched") ? this.reshares.models.length : this.get("reshares_count")
},
commentsCount : function(){
return this.get("fetched") ? this.comments.models.length : this.get("comments_count")
},
userLike : function(){
return this.likes.select(function(like){ return like.get("author").guid == app.currentUser.get("guid")})[0]
},
userReshare : function(){
return this.reshares.select(function(reshare){ return reshare.get("author").guid == app.currentUser.get("guid")})[0]
},
toggleLike : function() {
if(this.userLike()) {
this.unlike()
} else {
this.like()
}
},
like : function() {
var self = this;
this.likes.create({}, {success : function(){
self.trigger("change")
self.set({"likes_count" : self.get("likes_count") + 1})
}})
},
unlike : function() {
var self = this;
this.userLike().destroy({success : function(model, resp) {
self.trigger('change')
self.set({"likes_count" : self.get("likes_count") - 1})
}});
},
comment : function (text) {
var self = this;
this.comments.make(text).fail(function () {
alert(Diaspora.I18n.t("failed_to_post_message"));
}).done(function() {
self.trigger('change') //updates after sync
});
this.trigger("change") //updates count in an eager manner
},
reshare : function(){
var interactions = this
, reshare = this.post.reshare()
reshare.save({}, {
success : function(resp){
var flash = new Diaspora.Widgets.FlashMessages;
flash.render({
success: true,
notice: Diaspora.I18n.t("reshares.successful")
});
}
}).done(function(){
interactions.reshares.add(reshare)
}).done(function(){
interactions.trigger("change")
});
},
userCanReshare : function(){
var isReshare = this.post.get("post_type") == "Reshare"
, rootExists = (isReshare ? this.post.get("root") : true)
, publicPost = this.post.get("public")
, userIsNotAuthor = this.post.get("author").diaspora_id != app.currentUser.get("diaspora_id")
, userIsNotRootAuthor = rootExists && (isReshare ? this.post.get("root").author.diaspora_id != app.currentUser.get("diaspora_id") : true)
return publicPost && app.currentUser.authenticated() && userIsNotAuthor && userIsNotRootAuthor;
}
});
\ No newline at end of file
app.models.Reshare = app.models.Post.extend({
urlRoot : "/reshares",
rootPost : function(){
this._rootPost = this._rootPost || new app.models.Post(this.get("root"));
return this._rootPost
......
......@@ -9,8 +9,10 @@ app.pages.PostViewer = app.views.Base.extend({
},
initialize : function(options) {
this.model = new app.models.Post({ id : options.id });
var post = this.model = new app.models.Post({ id : options.id });
this.model.preloadOrFetch().done(_.bind(this.initViews, this));
this.model.interactions.fetch() //async, yo, might want to throttle this later.
this.bindEvents()
},
......
......@@ -31,8 +31,9 @@ app.views.CommentStream = app.views.Base.extend({
presenter: function(){
return _.extend(this.defaultPresenter(), {
moreCommentsCount : (this.model.get("comments_count") - 3),
showExpandCommentsLink : (this.model.get("comments_count") > 3)
moreCommentsCount : (this.model.interactions.commentsCount() - 3),
showExpandCommentsLink : (this.model.interactions.commentsCount() > 3),
commentsCount : this.model.interactions.commentsCount()
})
},
......
......@@ -4,11 +4,15 @@ app.views.Comment = app.views.Content.extend({
className : "comment media",
events : function() {
return _.extend(app.views.Content.prototype.events, {
return _.extend({}, app.views.Content.prototype.events, {
"click .comment_delete": "destroyModel"
});
},
initialize : function(){
this.model.on("change", this.render, this)
},
presenter : function() {
return _.extend(this.defaultPresenter(), {
canRemove: this.canRemove(),
......
app.views.Feedback = app.views.Base.extend({
templateName: "feedback",
className : "info",
......@@ -10,47 +9,30 @@ app.views.Feedback = app.views.Base.extend({
},
initialize : function() {
this.model.bind('interacted', this.render, this);
this.model.interactions.on('change', this.render, this);
},
presenter : function() {
return _.extend(this.defaultPresenter(), {
userCanReshare : this.userCanReshare()
var interactions = this.model.interactions
return _.extend(this.defaultPresenter(),{
commentsCount : interactions.commentsCount(),
likesCount : interactions.likesCount(),
resharesCount : interactions.resharesCount(),
userCanReshare : interactions.userCanReshare(),
userLike : interactions.userLike(),
userReshare : interactions.userReshare(),
})
},
toggleLike: function(evt) {
if(evt) { evt.preventDefault(); }
this.model.toggleLike();
this.model.interactions.toggleLike();
},
resharePost : function(evt) {
if(evt) { evt.preventDefault(); }
if(!window.confirm(Diaspora.I18n.t("reshares.post", {name: this.model.reshareAuthor().name}))) { return }
var reshare = this.model.reshare()
var model = this.model
reshare.save({}, {
url: this.model.createReshareUrl,
success : function(resp){
var flash = new Diaspora.Widgets.FlashMessages;
flash.render({
success: true,
notice: Diaspora.I18n.t("reshares.successful")
});
model.trigger("interacted")
}
});
},
userCanReshare : function() {
var isReshare = this.model.get("post_type") == "Reshare"
var rootExists = (isReshare ? this.model.get("root") : true)
var publicPost = this.model.get("public");
var userIsNotAuthor = this.model.get("author").diaspora_id != app.currentUser.get("diaspora_id");
var userIsNotRootAuthor = rootExists && (isReshare ? this.model.get("root").author.diaspora_id != app.currentUser.get("diaspora_id") : true)
return publicPost && app.currentUser.authenticated() && userIsNotAuthor && userIsNotRootAuthor;
this.model.interactions.reshare();
}
});
......@@ -10,23 +10,19 @@ app.views.LikesInfo = app.views.StreamObject.extend({
tooltipSelector : ".avatar",
initialize : function() {
this.model.bind('expandedLikes', this.render, this)
this.model.interactions.bind('change', this.render, this)
},
presenter : function() {
return _.extend(this.defaultPresenter(), {
likes : this.model.likes.models
likes : this.model.interactions.likes.toJSON(),
likesCount : this.model.interactions.likesCount(),
likes_fetched : this.model.interactions.get("fetched"),
})
},
showAvatars : function(evt){
if(evt) { evt.preventDefault() }
var self = this;
this.model.likes.fetch()
.done(function(resp){
// set like attribute and like collection
self.model.set({likes : self.model.likes.reset(resp)})
self.model.trigger("expandedLikes")
})
this.model.interactions.fetch()
}
});
......@@ -18,6 +18,11 @@ app.views.PostViewerFeedback = app.views.Feedback.extend({
tooltipSelector : ".label, .home-button",
initialize : function(){
this.model.interactions.on("change", this.render, this)
},
postRenderTemplate : function() {
this.sneakyVisiblity()
},
......@@ -36,5 +41,4 @@ app.views.PostViewerFeedback = app.views.Feedback.extend({
alert("you must be logged in to do that!")
return false;
}
});
\ No newline at end of file
......@@ -5,7 +5,8 @@ app.views.PostViewerInteractions = app.views.Base.extend({
subviews : {
"#post-feedback" : "feedbackView",
"#post-reactions" : "reactionsView",
"#new-post-comment" : "newCommentView"
"#new-post-comment" : "newCommentView",
".interaction_counts" : "interactionCountsView"
},
templateName: "post-viewer/interactions",
......@@ -18,7 +19,7 @@ app.views.PostViewerInteractions = app.views.Base.extend({
},
initViews : function() {
this.reactionsView = new app.views.PostViewerReactions({ model : this.model })
this.reactionsView = new app.views.PostViewerReactions({ model : this.model.interactions })
/* subviews that require user */
this.feedbackView = new app.views.PostViewerFeedback({ model : this.model })
......
......@@ -10,7 +10,7 @@ app.views.PostViewerNewComment = app.views.Base.extend({
scrollableArea : "#post-reactions",
initialize : function(){
this.model.comments.bind("sync", this.clearAndReactivateForm, this)
this.model.interactions.comments.bind("sync", this.clearAndReactivateForm, this)
},
postRenderTemplate : function() {
......@@ -25,7 +25,6 @@ app.views.PostViewerNewComment = app.views.Base.extend({
},
clearAndReactivateForm : function() {
this.model.trigger("interacted")
this.toggleFormState()
this.$("textarea").val("")
.css('height', '18px')
......
......@@ -7,7 +7,16 @@ app.views.PostViewerReactions = app.views.Base.extend({
tooltipSelector : ".avatar",
initialize : function() {
this.model.bind('interacted', this.render, this);
this.model.on('change', this.render, this);
this.model.comments.bind("add", this.appendComment, this)
},
presenter : function(){
return {
likes : this.model.likes.toJSON(),
comments : this.model.comments.toJSON(),
reshares : this.model.reshares.toJSON()
}
},
postRenderTemplate : function() {
......@@ -21,14 +30,15 @@ app.views.PostViewerReactions = app.views.Base.extend({
/* copy pasta from commentStream */
appendComment: function(comment) {
// Set the post as the comment's parent, so we can check
// on post ownership in the Comment view.
comment.set({parent : this.model.toJSON()})
// Set the post as the comment's parent, so we can check on post ownership in the Comment view.
// model was post on old view, is interactions on new view
var parent = this.model.get("post_type") ? this.model.toJSON : this.model.post.toJSON()
comment.set({parent : parent})
this.$("#post-comments").append(new app.views.Comment({
model: comment,
className : "post-comment media"
}).render().el);
}
});
\ No newline at end of file
......@@ -11,7 +11,7 @@
<div class="comments"> </div>
{{#if loggedIn}}
<div class="comment no-border media new_comment_form_wrapper {{#unless comments_count}} hidden {{/unless}}">
<div class="comment no-border media new_comment_form_wrapper {{#unless commentsCount}} hidden {{/unless}}">
{{#with current_user}}
<a href="/people/{{guid}}" class="img">
{{{personImage this}}}
......
......@@ -15,7 +15,7 @@
<a href="#" class="like_action" rel='nofollow'>
{{#if user_like}}
{{#if userLike}}
{{t "stream.unlike"}}
{{else}}
{{t "stream.like"}}
......
{{#if likes_count}}
{{#if likesCount}}
<div class="comment">
<div class="media">
<span class="img">
......@@ -6,21 +6,20 @@
</span>
<div class="bd">
{{#unless likes.length}}
{{#unless likes_fetched}}
<a href="#" class="expand_likes grey">
{{t "stream.likes" count=likes_count}}
{{t "stream.likes" count=likesCount}}
</a>
{{else}}
{{#each likes}}
{{#with attributes.author}}
{{#with author}}
<a href="/people/{{guid}}">
<img src="{{avatar.small}}" class="avatar micro" title="{{name}}"/>
</a>
{{/with}}
{{/each}}
{{/unless}}
</div>
</div>
......
<a href="#" rel="auth-required" class="label like" title="{{#if user_like}} {{t "viewer.unlike"}} {{else}} {{t "viewer.like"}} {{/if}}">
{{#if user_like}}
<a href="#" rel="auth-required" class="label like" title="{{#if userLike}} {{t "viewer.unlike"}} {{else}} {{t "viewer.like"}} {{/if}}">
{{#if userLike}}
<i class="icon-heart icon-red"></i>
{{else}}
<i class="icon-heart icon-white"></i>
{{/if}}
{{likes_count}}
{{likesCount}}
</a>
{{#if userCanReshare}}
<a href="#" rel="auth-required" class="label reshare" title="{{#if user_reshare}} {{t "viewer.reshared"}} {{else}} {{t "viewer.reshare"}} {{/if}}">
{{#if user_reshare}}
<a href="#" rel="auth-required" class="label reshare" title="{{#if userReshare}} {{t "viewer.reshared"}} {{else}} {{t "viewer.reshare"}} {{/if}}">
{{#if userReshare}}
<i class="icon-retweet icon-blue"></i>
{{else}}
<i class="icon-retweet icon-white"></i>
{{/if}}
{{reshares_count}}
{{resharesCount}}
</a>
{{else}}
<a class="label reshare-viewonly" title="{{#if user_reshare}} {{t "viewer.reshared"}} {{else}} {{t "viewer.reshare"}} {{/if}}">
{{#if user_reshare}}
<a class="label reshare-viewonly" title="{{#if userReshare}} {{t "viewer.reshared"}} {{else}} {{t "viewer.reshare"}} {{/if}}">
{{#if userReshare}}
<i class="icon-retweet icon-blue"></i>
{{else}}
<i class="icon-retweet icon-white"></i>
{{/if}}
{{reshares_count}}
{{resharesCount}}
</a>
{{/if}}
<a href="#" class="label comment" rel="invoke-interaction-pane" title="{{t "viewer.comment"}}">
<i class="icon-comment icon-white"></i>
{{comments_count}}
{{commentsCount}}
</a>
<!-- this acts as a dock underlay -->
......
......@@ -38,9 +38,9 @@
<i class="icon-time timestamp" title="{{created_at}}" rel="tooltip"></i>
<i class="icon-chevron-right permalink" title="View Post" rel="tooltip"></i>
<i class="icon-heart"></i> {{likes_count}}
<i class="icon-retweet"></i> {{reshares_count}}
<i class="icon-comment"></i> {{comments_count}}
<i class="icon-heart"></i> {{likesCount}}
<i class="icon-retweet"></i> {{resharesCount}}
<i class="icon-comment"></i> {{commentsCount}}
</div>
</div>
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter