Skip to content

Commit

Permalink
Move back to message created_at ordering
Browse files Browse the repository at this point in the history
When a message is approved later about where it should appear in the thread isn't clear but
given it was using created at we should just stick with it for now

This also adds some message loading via AJAX specs
  • Loading branch information
nikolai-b committed Jan 1, 2022
1 parent 638a9a5 commit 7ed6ca4
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 15 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/thread_scroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ $(document).ready(function () {
}
var obs = new IntersectionObserver(function (entries) {
if (lastViewedMessage && entries[0] && entries[0].isIntersecting) {
$.ajax({url: window.location.pathname, data: {initiallyLoadedFrom: document.querySelector('[data-initially-loaded-from]').dataset.initiallyLoadedFrom}, dataType: 'script'})
$.ajax({url: window.location.pathname, data: {initiallyLoadedFrom: initiallyLoadedFrom.dataset.initiallyLoadedFrom}, dataType: 'script'})
obs.unobserve(lastViewedMessage)
}
}, options)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/message_threads_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def show
@view_from = @messages.detect { |m| m.created_at >= last_viewed } || @messages.last
end

@initially_loaded_from = @messages.first.updated_at
@initially_loaded_from = @messages.first&.created_at&.iso8601

@library_items = Library::Item.find_by_tags_from(thread).limit(5)
@tag_panel = TagPanelDecorator.new(thread, form_url: thread_tags_path(thread))
Expand All @@ -47,7 +47,7 @@ def show
end
format.js do
messages = thread.messages.approved
initially_loaded_from = Time.zone.parse(params["initiallyLoadedFrom"])
initially_loaded_from = Time.zone.iso8601(params["initiallyLoadedFrom"])
messages = messages.before_date(initially_loaded_from)

@messages = messages.includes(
Expand Down
6 changes: 3 additions & 3 deletions app/models/message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ class Message < ApplicationRecord
scope :approved, -> { where(status: [nil, "approved"]) }
scope :mod_queued, -> { where(status: "mod_queued") }
scope :in_group, ->(group_id) { includes(:thread).where(message_threads: { group_id: group_id }).references(:thread) }
scope :after_date, ->(date) { where(arel_table[:updated_at].gteq(date)) }
scope :before_date, ->(date) { where(arel_table[:updated_at].lteq(date)) }
scope :after_date, ->(date) { where(arel_table[:created_at].gteq(date)) }
scope :before_date, ->(date) { where(arel_table[:created_at].lteq(date)) }

validates :created_by, presence: true
validates :body, presence: true, unless: :components?
Expand Down Expand Up @@ -92,7 +92,7 @@ class Message < ApplicationRecord
end

def self.after_date_with_n_before(after_date:, n_before:)
after_date(after_date).or(where(id: before_date(after_date).reorder(updated_at: :desc).limit(n_before + 1).ids))
after_date(after_date).or(where(id: before_date(after_date).reorder(created_at: :desc).limit(n_before + 1).ids))
end

def censor!
Expand Down
34 changes: 30 additions & 4 deletions spec/controllers/message_threads_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
let(:thread) { create(:message_thread) }

describe "thread views" do
let!(:message_a) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 4.days) }
let!(:message_b) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 3.days) }
let!(:message_c) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 2.days) }
let!(:message_4) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 4.days, created_by: message_2.created_by) }
let!(:message_3) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 3.days, created_by: message_2.created_by) }
let!(:message_2) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 2.days) }

context "as a guest" do
it "should not assign a message to view from" do
Expand Down Expand Up @@ -44,7 +44,33 @@
it "should assign the first of the new messages" do
create(:thread_view, thread: thread, user: user, viewed_at: Time.now.in_time_zone - 3.5.days)
get :show, params: { id: thread.id }
expect(assigns(:view_from)).to eql(message_b)
expect(assigns(:view_from)).to eq(message_3)
expect(assigns(:initially_loaded_from)).to eq(message_4.created_at.in_time_zone("London").iso8601)
end
end

context "when there are more than 6 previously read messages" do
let!(:message_9) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 9.days, created_by: message_2.created_by) }
let!(:message_8) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 8.days, created_by: message_2.created_by) }
let!(:message_7) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 7.days, created_by: message_2.created_by) }
let!(:message_6) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 6.days, created_by: message_2.created_by) }
let!(:message_5) { create(:message, thread: thread, created_at: Time.now.in_time_zone - 5.days, created_by: message_2.created_by) }

context "with HTML" do
it "only shows the last 6" do
create(:thread_view, thread: thread, user: user, viewed_at: Time.now.in_time_zone)
get :show, params: { id: thread.id }
expect(assigns(:view_from)).to eq(message_2)
expect(assigns(:initially_loaded_from)).to eq(message_7.created_at.in_time_zone("London").iso8601)
expect(assigns(:messages)).to eq [message_7, message_6, message_5, message_4, message_3, message_2]
end
end

context "with JS (and initially_loaded_from)" do
it "shows messages before the initially_loaded_from" do
get :show, params: { id: thread.id, format: :js, initiallyLoadedFrom: message_7.created_at.in_time_zone("London").iso8601 }, xhr: true
expect(assigns(:messages)).to eq [message_9, message_8]
end
end
end
end
Expand Down
10 changes: 5 additions & 5 deletions spec/models/message_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@
end

describe ".after_date_with_n_before" do
let!(:message_1) { create(:message, updated_at: 4.hours.ago) }
let!(:message_2) { create(:message, updated_at: 3.hours.ago, thread: message_1.thread, created_by: message_1.created_by) }
let!(:message_3) { create(:message, updated_at: 2.hours.ago, thread: message_1.thread, created_by: message_1.created_by) }
let!(:message_4) { create(:message, updated_at: 1.hour.ago, thread: message_1.thread, created_by: message_1.created_by) }
let!(:message_1) { create(:message, created_at: 4.hours.ago) }
let!(:message_2) { create(:message, created_at: 3.hours.ago, thread: message_1.thread, created_by: message_1.created_by) }
let!(:message_3) { create(:message, created_at: 2.hours.ago, thread: message_1.thread, created_by: message_1.created_by) }
let!(:message_4) { create(:message, created_at: 1.hour.ago, thread: message_1.thread, created_by: message_1.created_by) }

it do
expect(message_1.thread.messages.approved.after_date_with_n_before(after_date: message_3.updated_at, n_before: 1)).to eq [
expect(message_1.thread.messages.approved.after_date_with_n_before(after_date: message_3.created_at, n_before: 1)).to eq [
message_2, message_3, message_4
]
end
Expand Down

5 comments on commit 7ed6ca4

@mvl22
Copy link
Member

@mvl22 mvl22 commented on 7ed6ca4 Jan 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the initial created time is the right one to use, not the approval time, as otherwise the logical order of the arguments presented by users in the discussion gets disrupted. E.g. this would be wrong

User 1: Do you agree?
User 1: Glad you agree.
User 2: Yes I do.

where the User 2 message got delayed. Clearly this would be wrong. So created time is best.

@nikolai-b
Copy link
Contributor Author

@nikolai-b nikolai-b commented on 7ed6ca4 Jan 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But User 1 would only see "Yes I do" after it was approved so they couldn't be glad. The argument for approved time is that now new messages can appear anywhere in the message thread so:

  • seen message
  • newly approved unseen message
  • another seen message

Making the newly approved message hard to spot.

@nikolai-b
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree that created at is a good order as the thread might have moved on by the time the message gets approved. Here threaded email handles it well listing the messages, probably in created at order, but the message where approval was delayed is marked as unread.

@mvl22
Copy link
Member

@mvl22 mvl22 commented on 7ed6ca4 Jan 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But User 1 would only see "Yes I do" after it was approved so they couldn't be glad.

Yes, good point...

My general point is that the created date does reflect properly the views of the user at the time they posted. I think it could end up quite misleading if, for instance, someone replies (but it is delayed), the conversion moves on, that user has changed their mind, and then their previous view then appears just because it got stuck in moderation for whatever reason.

I think the moderation system is akin to a delivery delay, as if an e-mail had got temporarily delayed. In that scenario, the e-mail still shows its original sending time.

@mvl22
Copy link
Member

@mvl22 mvl22 commented on 7ed6ca4 Jan 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is really a problem of messages that are unseen, in web context only, due to a later one having been seen, perhaps the correct solution is ultimately:

  • Use the created_at date
  • If a message gets delayed due to moderation, any cases where a user following that thread has a later last-viewed number, that number is rewound to the delayed message.

I think that solves the problem, but I don't think it's a priority to implement. Sure, they'll re-read the non-delayed 'subsequent' messages, but that's not a huge issue.

If you agree this is the correct solution, could you create this as a new ticket and we can have it sitting there till later. Unless it's quick to implement.

Please sign in to comment.