Merge branch 'stable' into develop

This commit is contained in:
Dennis Schubert 2015-06-08 00:49:55 +02:00
commit e0420d733a
11 changed files with 87 additions and 67 deletions

View file

@ -90,6 +90,7 @@ Ruby 2.0 is no longer officially supported.
* Fix broken default avatars in the database [#6014](https://github.com/diaspora/diaspora/pull/6014) * Fix broken default avatars in the database [#6014](https://github.com/diaspora/diaspora/pull/6014)
* Only strip text direction codepoints around hashtags [#6067](https://github.com/diaspora/diaspora/issues/6067) * Only strip text direction codepoints around hashtags [#6067](https://github.com/diaspora/diaspora/issues/6067)
* Fix selected week on admin weekly stats page [#6079](https://github.com/diaspora/diaspora/pull/6079) * Fix selected week on admin weekly stats page [#6079](https://github.com/diaspora/diaspora/pull/6079)
* Fix that some unread conversations may be hidden [#6060](https://github.com/diaspora/diaspora/pull/6060)
## Features ## Features
* Hide post title of limited post in comment notification email [#5843](https://github.com/diaspora/diaspora/pull/5843) * Hide post title of limited post in comment notification email [#5843](https://github.com/diaspora/diaspora/pull/5843)

View file

@ -5,35 +5,29 @@ class ConversationsController < ApplicationController
respond_to :html, :mobile, :json, :js respond_to :html, :mobile, :json, :js
def index def index
@conversations = current_user.conversations.paginate( @visibilities = ConversationVisibility.includes(:conversation)
:page => params[:page], :per_page => 15) .order("conversations.updated_at DESC")
.where(person_id: current_user.person_id)
.paginate(page: params[:page], per_page: 15)
@visibilities = current_user.conversation_visibilities.paginate( if params[:conversation_id]
:page => params[:page], :per_page => 15) @conversation = Conversation.joins(:conversation_visibilities)
.where(conversation_visibilities: {
person_id: current_user.person_id,
conversation_id: params[:conversation_id]
}).first
@conversation = Conversation.joins(:conversation_visibilities).where( if @conversation
:conversation_visibilities => {:person_id => current_user.person_id, :conversation_id => params[:conversation_id]}).first @first_unread_message_id = @conversation.first_unread_message(current_user).try(:id)
@conversation.set_read(current_user)
@unread_counts = {} end
@visibilities.each { |v| @unread_counts[v.conversation_id] = v.unread }
@first_unread_message_id = @conversation.try(:first_unread_message, current_user).try(:id)
if @conversation
@conversation.set_read(current_user)
end end
@authors = {}
@conversations.each { |c| @authors[c.id] = c.last_author }
@ordered_participants = {}
@conversations.each { |c| @ordered_participants[c.id] = (c.messages.map{|m| m.author}.reverse + c.participants).uniq }
gon.contacts = contacts_data gon.contacts = contacts_data
respond_with do |format| respond_with do |format|
format.html format.html
format.json { render :json => @conversations, :status => 200 } format.json { render json: @visibilities.map(&:conversation), status: 200 }
end end
end end

View file

@ -72,11 +72,15 @@ class Conversation < ActiveRecord::Base
end end
def last_author def last_author
return unless @last_author.present? || self.messages.size > 0 return unless @last_author.present? || messages.size > 0
@last_author_id ||= self.messages.pluck(:author_id).last @last_author_id ||= messages.pluck(:author_id).last
@last_author ||= Person.includes(:profile).where(id: @last_author_id).first @last_author ||= Person.includes(:profile).where(id: @last_author_id).first
end end
def ordered_participants
@ordered_participants ||= (messages.map(&:author).reverse + participants).uniq
end
def subject def subject
self[:subject].blank? ? "no subject" : self[:subject] self[:subject].blank? ? "no subject" : self[:subject]
end end

View file

@ -69,8 +69,8 @@ class User < ActiveRecord::Base
has_many :blocks has_many :blocks
has_many :ignored_people, :through => :blocks, :source => :person has_many :ignored_people, :through => :blocks, :source => :person
has_many :conversation_visibilities, -> { order 'updated_at DESC' }, through: :person has_many :conversation_visibilities, through: :person
has_many :conversations, -> { order 'updated_at DESC' }, through: :conversation_visibilities has_many :conversations, through: :conversation_visibilities
has_many :notifications, :foreign_key => :recipient_id has_many :notifications, :foreign_key => :recipient_id

View file

@ -2,11 +2,13 @@
-# licensed under the Affero General Public License version 3 or later. See -# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file. -# the COPYRIGHT file.
- conversation = visibility.conversation
.conversation-wrapper{ :"data-conversation-path" => conversation_path(conversation) } .conversation-wrapper{ :"data-conversation-path" => conversation_path(conversation) }
.stream_element.conversation{:data=>{:guid=>conversation.id}, :class => conversation_class(conversation, unread_counts[conversation.id].to_i, selected_conversation_id)} .stream_element.conversation{data: {guid: conversation.id},
class: conversation_class(conversation, visibility.unread, @conversation.try(:id))}
.media .media
.img .img
- other_participants = ordered_participants[conversation.id] - [current_user.person] - other_participants = conversation.ordered_participants - [current_user.person]
- if other_participants.first.present? - if other_participants.first.present?
= person_image_tag(other_participants.first) = person_image_tag(other_participants.first)
- if other_participants.count > 1 - if other_participants.count > 1
@ -16,18 +18,17 @@
.bg .bg
.badge.badge-dafault.message_count .badge.badge-dafault.message_count
= conversation.messages.size = conversation.messages.size
- unread_count = unread_counts[conversation.id].to_i - if visibility.unread > 0
- if unread_count > 0
.badge.badge-important.unread_message_count .badge.badge-important.unread_message_count
= unread_count = visibility.unread
.subject .subject
%div{ :class => direction_for(conversation.subject) } %div{ :class => direction_for(conversation.subject) }
= conversation.subject = conversation.subject
.timestamp .timestamp
= timeago(conversation.updated_at) = timeago(conversation.updated_at)
.last_author .last_author
- if authors[conversation.id].present? - if conversation.last_author.present?
= authors[conversation.id].name = conversation.last_author.name
.last_message .last_message
- if conversation.messages.present? - if conversation.messages.present?
%em %em

View file

@ -1,20 +1,20 @@
- conversation = visibility.conversation
%a.conversation{ :href => conversation_path(conversation) } %a.conversation{ :href => conversation_path(conversation) }
.stream_element.conversation{:data=>{:guid=>conversation.id}, :class => ('unread' if unread_counts[conversation.id].to_i > 0)} .stream_element.conversation{data: {guid: conversation.id}, class: ("unread" if visibility.unread > 0)}
.media .media
.img .img
= person_image_tag(conversation.author, size: :thumb_small) = person_image_tag(conversation.author, size: :thumb_small)
.bg .bg
= render(:partial => 'conversation_subject', = render partial: "conversation_subject",
:locals => { :conversation => conversation, locals: { conversation: conversation, unread_count: visibility.unread }
:unread_count => unread_counts[conversation.id].to_i })
.last_author .last_author
.timestamp .timestamp
= timeago(conversation.updated_at) = timeago(conversation.updated_at)
- if authors[conversation.id].present? - if conversation.last_author.present?
= authors[conversation.id].name = conversation.last_author.name
- if conversation.participants.size > 2 - if conversation.participants.size > 2
%span.participant_count %span.participant_count

View file

@ -10,22 +10,21 @@
#left_pane #left_pane
#left_pane_header #left_pane_header
%h3 %h3
.pull-right{ class: ("hidden" unless @conversation)} .pull-right{ class: ("hidden" unless @visibilities)}
= link_to t('.new_conversation'), conversations_path, class: 'btn btn-default' = link_to t('.new_conversation'), conversations_path, class: 'btn btn-default'
= t('.inbox') = t('.inbox')
#conversation_inbox #conversation_inbox
.stream.conversations .stream.conversations
- if @conversations.count > 0 - if @visibilities.count > 0
= render partial: 'conversations/conversation', collection: @conversations, = render partial: "conversations/conversation", collection: @visibilities, as: :visibility
locals: { authors: @authors, ordered_participants: @ordered_participants,
unread_counts: @unread_counts, selected_conversation_id: @conversation.try(:id) }
- else - else
#no_conversations #no_conversations
= t('.no_messages') = t('.no_messages')
= will_paginate @conversations, previous_label: '&laquo;', next_label: '&raquo;',inner_window: 1, = will_paginate @visibilities, previous_label: "&laquo;", next_label: "&raquo;",inner_window: 1,
renderer: WillPaginate::ActionView::BootstrapLinkRenderer renderer: WillPaginate::ActionView::BootstrapLinkRenderer
.col-md-8 .col-md-8
- if @conversation - if @conversation
.stream_container .stream_container

View file

@ -16,13 +16,12 @@
#conversation_inbox #conversation_inbox
.stream.conversations .stream.conversations
- if @conversations.count > 0 - if @visibilities.count > 0
= render partial: 'conversations/conversation', collection: @conversations, = render partial: "conversations/conversation", collection: @visibilities, as: :visibility
locals: { authors: @authors, unread_counts: @unread_counts }
- else - else
.no-messages .no-messages
%i %i
= t('.no_messages') = t('.no_messages')
= will_paginate @conversations, previous_label: '&laquo;', next_label: '&raquo;', inner_window: 1, outer_window: 0, = will_paginate @visibilities, previous_label: "&laquo;", next_label: "&raquo;", inner_window: 1, outer_window: 0,
renderer: WillPaginate::ActionView::BootstrapLinkRenderer renderer: WillPaginate::ActionView::BootstrapLinkRenderer

View file

@ -58,38 +58,48 @@ describe ConversationsController, :type => :controller do
end end
end end
describe '#index' do describe "#index" do
before do before do
hash = { hash = {
:author => alice.person, author: alice.person,
:participant_ids => [alice.contacts.first.person.id, alice.person.id], participant_ids: [alice.contacts.first.person.id, alice.person.id],
:subject => 'not spam', subject: "not spam",
:messages_attributes => [ {:author => alice.person, :text => 'cool stuff'} ] messages_attributes: [{author: alice.person, text: "cool stuff"}]
} }
@conversations = Array.new(3) { Conversation.create(hash) } @conversations = Array.new(3) { Conversation.create(hash) }
@visibilities = @conversations.map {|conversation|
conversation.conversation_visibilities.find {|visibility| visibility.person == alice.person }
}
end end
it 'succeeds' do it "succeeds" do
get :index get :index
expect(response).to be_success expect(response).to be_success
expect(assigns[:conversations]).to match_array(@conversations) expect(assigns[:visibilities]).to match_array(@visibilities)
end end
it 'succeeds with json' do it "succeeds with json" do
get :index, :format => :json get :index, format: :json
expect(response).to be_success expect(response).to be_success
json = JSON.parse(response.body) json = JSON.parse(response.body)
expect(json.first['conversation']).to be_present expect(json.first["conversation"]).to be_present
end end
it 'retrieves all conversations for a user' do it "retrieves all conversations for a user" do
get :index get :index
expect(assigns[:conversations].count).to eq(3) expect(assigns[:visibilities].count).to eq(3)
end end
it 'does not let you access conversations where you are not a recipient' do it "retrieves a conversation" do
get :index, conversation_id: @conversations.first.id
expect(response).to be_success
expect(assigns[:visibilities]).to match_array(@visibilities)
expect(assigns[:conversation]).to eq(@conversations.first)
end
it "does not let you access conversations where you are not a recipient" do
sign_in :user, eve sign_in :user, eve
get :index, :conversation_id => @conversations.first.id get :index, conversation_id: @conversations.first.id
expect(assigns[:conversation]).to be_nil expect(assigns[:conversation]).to be_nil
end end
end end

View file

@ -3,6 +3,9 @@ describe("app.views.Conversations", function(){
context("for unread conversations", function() { context("for unread conversations", function() {
beforeEach(function() { beforeEach(function() {
spec.loadFixture("conversations_unread"); spec.loadFixture("conversations_unread");
// select second conversation that is still unread
$(".conversation-wrapper > .conversation.selected").removeClass("selected")
$(".conversation-wrapper > .conversation.unread").addClass("selected")
}); });
it("removes the unread class from the conversation", function() { it("removes the unread class from the conversation", function() {
@ -21,16 +24,16 @@ describe("app.views.Conversations", function(){
var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">3</div></div>"; var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">3</div></div>";
$("header").append(badge); $("header").append(badge);
expect($("#conversations_badge .badge_count").text().trim()).toEqual("3"); expect($("#conversations_badge .badge_count").text().trim()).toEqual("3");
expect($(".conversation-wrapper > .conversation.selected .unread_message_count").text().trim()).toEqual("2"); expect($(".conversation-wrapper > .conversation .unread_message_count").text().trim()).toEqual("1");
new app.views.Conversations(); new app.views.Conversations();
expect($("#conversations_badge .badge_count").text().trim()).toEqual("1"); expect($("#conversations_badge .badge_count").text().trim()).toEqual("2");
}); });
it("removes the badge_count in the header if there are no unread messages left", function() { it("removes the badge_count in the header if there are no unread messages left", function() {
var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">2</div></div>"; var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">1</div></div>";
$("header").append(badge); $("header").append(badge);
expect($("#conversations_badge .badge_count").text().trim()).toEqual("2"); expect($("#conversations_badge .badge_count").text().trim()).toEqual("1");
expect($(".conversation-wrapper > .conversation.selected .unread_message_count").text().trim()).toEqual("2"); expect($(".conversation-wrapper > .conversation.selected .unread_message_count").text().trim()).toEqual("1");
new app.views.Conversations(); new app.views.Conversations();
expect($("#conversations_badge .badge_count").text().trim()).toEqual("0"); expect($("#conversations_badge .badge_count").text().trim()).toEqual("0");
expect($("#conversations_badge .badge_count")).toHaveClass("hidden"); expect($("#conversations_badge .badge_count")).toHaveClass("hidden");

View file

@ -32,6 +32,15 @@ describe Conversation, :type => :model do
end end
end end
describe "#ordered_participants" do
it "returns the ordered participants" do
cnv = Conversation.create(@create_hash)
Message.create(author: @user2.person, created_at: Time.now + 100, text: "last", conversation_id: cnv.id)
expect(cnv.ordered_participants.first).to eq(@user2.person)
expect(cnv.ordered_participants.last).to eq(@user1.person)
end
end
describe '#first_unread_message' do describe '#first_unread_message' do
before do before do
@cnv = Conversation.create(@create_hash) @cnv = Conversation.create(@create_hash)