Merge pull request #1509 from basecamp/event-creator-tag
Fix event description in webhooks
This commit is contained in:
@@ -55,70 +55,6 @@ module EventsHelper
|
||||
tag.div class: "events__time-block", style: "grid-area: #{row}/#{col}", &
|
||||
end
|
||||
|
||||
def event_action_sentence(event)
|
||||
if event.action.comment_created?
|
||||
comment_event_action_sentence(event)
|
||||
else
|
||||
card_event_action_sentence(event)
|
||||
end
|
||||
end
|
||||
|
||||
def comment_event_action_sentence(event)
|
||||
"#{event_creator_name(event)} commented on #{event_card_title(event.eventable.card)}".html_safe
|
||||
end
|
||||
|
||||
def event_creator_name(event)
|
||||
tag.span data: { creator_id: event.creator.id } do
|
||||
safe_join([
|
||||
tag.span("You", data: { only_visible_to_you: true }),
|
||||
tag.span(h(event.creator.name), data: { only_visible_to_others: true })
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
def card_event_action_sentence(event)
|
||||
card = event.eventable
|
||||
|
||||
case event.action
|
||||
when "card_assigned"
|
||||
if event.assignees.include?(Current.user)
|
||||
"#{event_creator_name(event)} will handle #{event_card_title(card)}"
|
||||
else
|
||||
"#{event_creator_name(event)} assigned #{h event.assignees.pluck(:name).to_sentence} to #{event_card_title(card)}"
|
||||
end
|
||||
when "card_unassigned"
|
||||
"#{event_creator_name(event)} unassigned #{h(event.assignees.include?(Current.user) ? "yourself" : event.assignees.pluck(:name).to_sentence)} from #{event_card_title(card)}"
|
||||
when "card_published"
|
||||
"#{event_creator_name(event)} added #{event_card_title(card)}"
|
||||
when "card_closed"
|
||||
"#{event_creator_name(event)} moved #{event_card_title(card)} to “Done”"
|
||||
when "card_reopened"
|
||||
"#{event_creator_name(event)} reopened #{event_card_title(card)}"
|
||||
when "card_postponed"
|
||||
"#{event_creator_name(event)} moved #{event_card_title(card)} to “Not Now”"
|
||||
when "card_auto_postponed"
|
||||
"#{event_card_title(card)} was closed as “Not Now” due to inactivity"
|
||||
when "card_resumed"
|
||||
"#{event_creator_name(event)} resumed #{event_card_title(card)}"
|
||||
when "card_title_changed"
|
||||
"#{event_creator_name(event)} renamed #{event_card_title(card)} (was: “#{h event.particulars.dig('particulars', 'old_title')}”)"
|
||||
when "card_board_changed", "card_collection_changed"
|
||||
"#{event_creator_name(event)} moved #{event_card_title(card)} to “#{h (event.particulars.dig('particulars', 'new_board') || event.particulars.dig('particulars', 'new_collection'))}”"
|
||||
when "card_triaged"
|
||||
"#{event_creator_name(event)} moved #{event_card_title(card)} to “#{h event.particulars.dig('particulars', 'column')}”"
|
||||
when "card_sent_back_to_triage"
|
||||
"#{event_creator_name(event)} moved #{event_card_title(card)} back to “Maybe?”"
|
||||
end&.html_safe
|
||||
end
|
||||
|
||||
def event_card_title(card)
|
||||
tag.span card.title, class: "txt-underline"
|
||||
end
|
||||
|
||||
def event_due_date(event)
|
||||
event.particulars.dig("particulars", "due_date").to_date.strftime("%B %-d")
|
||||
end
|
||||
|
||||
def event_action_icon(event)
|
||||
case event.action
|
||||
when "card_assigned"
|
||||
|
||||
@@ -22,6 +22,10 @@ class Event < ApplicationRecord
|
||||
eventable
|
||||
end
|
||||
|
||||
def description_for(user)
|
||||
Event::Description.new(self, user)
|
||||
end
|
||||
|
||||
private
|
||||
def dispatch_webhooks
|
||||
Event::WebhookDispatchJob.perform_later(self)
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
class Event::Description
|
||||
include ActionView::Helpers::TagHelper
|
||||
include ERB::Util
|
||||
|
||||
attr_reader :event, :user
|
||||
|
||||
def initialize(event, user)
|
||||
@event = event
|
||||
@user = user
|
||||
end
|
||||
|
||||
def to_html
|
||||
to_sentence(creator_tag, card_title_tag).html_safe
|
||||
end
|
||||
|
||||
def to_plain_text
|
||||
to_sentence(creator_text, card.title)
|
||||
end
|
||||
|
||||
private
|
||||
def to_sentence(creator, card_title)
|
||||
if event.action.comment_created?
|
||||
comment_sentence(creator, card_title)
|
||||
else
|
||||
action_sentence(creator, card_title)
|
||||
end
|
||||
end
|
||||
|
||||
def creator_tag
|
||||
tag.span data: { creator_id: event.creator.id } do
|
||||
tag.span("You", data: { only_visible_to_you: true }) +
|
||||
tag.span(event.creator.name, data: { only_visible_to_others: true })
|
||||
end
|
||||
end
|
||||
|
||||
def card_title_tag
|
||||
tag.span card.title, class: "txt-underline"
|
||||
end
|
||||
|
||||
def creator_text
|
||||
event.creator == user ? "You" : h(event.creator.name)
|
||||
end
|
||||
|
||||
def card
|
||||
@card ||= event.action.comment_created? ? event.eventable.card : event.eventable
|
||||
end
|
||||
|
||||
def comment_sentence(creator, card_title)
|
||||
"#{creator} commented on #{card_title}"
|
||||
end
|
||||
|
||||
def action_sentence(creator, card_title)
|
||||
case event.action
|
||||
when "card_assigned"
|
||||
assigned_sentence(creator, card_title)
|
||||
when "card_unassigned"
|
||||
unassigned_sentence(creator, card_title)
|
||||
when "card_published"
|
||||
"#{creator} added #{card_title}"
|
||||
when "card_closed"
|
||||
%(#{creator} moved #{card_title} to "Done")
|
||||
when "card_reopened"
|
||||
"#{creator} reopened #{card_title}"
|
||||
when "card_postponed"
|
||||
%(#{creator} moved #{card_title} to "Not Now")
|
||||
when "card_auto_postponed"
|
||||
%(#{card_title} was closed as "Not Now" due to inactivity)
|
||||
when "card_resumed"
|
||||
"#{creator} resumed #{card_title}"
|
||||
when "card_title_changed"
|
||||
renamed_sentence(creator, card_title)
|
||||
when "card_board_changed", "card_collection_changed"
|
||||
moved_sentence(creator, card_title)
|
||||
when "card_triaged"
|
||||
triaged_sentence(creator, card_title)
|
||||
when "card_sent_back_to_triage"
|
||||
%(#{creator} moved #{card_title} back to "Maybe?")
|
||||
end
|
||||
end
|
||||
|
||||
def assigned_sentence(creator, card_title)
|
||||
if event.assignees.include?(user)
|
||||
"#{creator} will handle #{card_title}"
|
||||
else
|
||||
"#{creator} assigned #{h event.assignees.pluck(:name).to_sentence} to #{card_title}"
|
||||
end
|
||||
end
|
||||
|
||||
def unassigned_sentence(creator, card_title)
|
||||
assignees_text = event.assignees.include?(user) ? "yourself" : event.assignees.pluck(:name).to_sentence
|
||||
"#{creator} unassigned #{h(assignees_text)} from #{card_title}"
|
||||
end
|
||||
|
||||
def renamed_sentence(creator, card_title)
|
||||
old_title = event.particulars.dig("particulars", "old_title")
|
||||
%(#{creator} renamed #{card_title} (was: "#{h old_title}"))
|
||||
end
|
||||
|
||||
def moved_sentence(creator, card_title)
|
||||
new_location = event.particulars.dig("particulars", "new_board") || event.particulars.dig("particulars", "new_collection")
|
||||
%(#{creator} moved #{card_title} to "#{h new_location}")
|
||||
end
|
||||
|
||||
def triaged_sentence(creator, card_title)
|
||||
column = event.particulars.dig("particulars", "column")
|
||||
%(#{creator} moved #{card_title} to "#{h column}")
|
||||
end
|
||||
end
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<div class="flex flex-column min-width txt-small align-start txt-align-start" style="color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink));">
|
||||
<strong class="event__title txt-break overflow-line-clamp txt-tight-lines">
|
||||
<%= event_action_sentence(event) %>
|
||||
<%= event.description_for(Current.user).to_html %>
|
||||
</strong>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%= event_action_sentence(@event) %>
|
||||
<%= @event.description_for(Current.user).to_plain_text %>
|
||||
<% if @event.eventable %>
|
||||
<%= link_to "↗︎", polymorphic_url(@event.eventable) %>
|
||||
<% end %>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
require "test_helper"
|
||||
|
||||
class Event::DescriptionTest < ActiveSupport::TestCase
|
||||
test "generates html description for card published event" do
|
||||
description = events(:logo_published).description_for(users(:david))
|
||||
|
||||
assert_includes description.to_html, "added"
|
||||
assert_includes description.to_html, "logo"
|
||||
end
|
||||
|
||||
test "generates plain text description for card published event" do
|
||||
description = events(:logo_published).description_for(users(:david))
|
||||
|
||||
assert_includes description.to_plain_text, "You added"
|
||||
assert_includes description.to_plain_text, "logo"
|
||||
end
|
||||
|
||||
test "generates description for comment event" do
|
||||
description = events(:layout_commented).description_for(users(:jz))
|
||||
|
||||
assert_includes description.to_plain_text, "David commented on"
|
||||
end
|
||||
|
||||
test "uses 'You' when event creator is the current user" do
|
||||
description = events(:logo_published).description_for(users(:david))
|
||||
|
||||
assert_includes description.to_plain_text, "You added"
|
||||
end
|
||||
|
||||
test "uses creator name when event creator is not the current user" do
|
||||
description = events(:logo_published).description_for(users(:jz))
|
||||
|
||||
assert_includes description.to_plain_text, "David added"
|
||||
end
|
||||
end
|
||||
@@ -218,4 +218,44 @@ class Webhook::DeliveryTest < ActiveSupport::TestCase
|
||||
assert Webhook::Delivery.exists?(fresh_delivery.id)
|
||||
assert_not Webhook::Delivery.exists?(stale_delivery.id)
|
||||
end
|
||||
|
||||
test "renders 'You' when event creator is current user" do
|
||||
webhook = Webhook.create!(
|
||||
board: boards(:writebook),
|
||||
name: "Basecamp",
|
||||
url: "https://3.basecamp.com/123/integrations/webhook/buckets/456/chats/789/lines"
|
||||
)
|
||||
event = events(:logo_published)
|
||||
delivery = Webhook::Delivery.create!(webhook: webhook, event: event)
|
||||
|
||||
Current.session = sessions(:david)
|
||||
|
||||
request_stub = stub_request(:post, webhook.url)
|
||||
.with { |request| CGI.parse(request.body)["content"].first.include?("You added") }
|
||||
.to_return(status: 200)
|
||||
|
||||
delivery.deliver
|
||||
|
||||
assert_requested request_stub
|
||||
end
|
||||
|
||||
test "renders creator name when event creator is not current user" do
|
||||
webhook = Webhook.create!(
|
||||
board: boards(:writebook),
|
||||
name: "Basecamp",
|
||||
url: "https://3.basecamp.com/123/integrations/webhook/buckets/456/chats/789/lines"
|
||||
)
|
||||
event = events(:logo_published)
|
||||
delivery = Webhook::Delivery.create!(webhook: webhook, event: event)
|
||||
|
||||
Current.session = sessions(:kevin)
|
||||
|
||||
request_stub = stub_request(:post, webhook.url)
|
||||
.with { |request| CGI.parse(request.body)["content"].first.include?("David added") }
|
||||
.to_return(status: 200)
|
||||
|
||||
delivery.deliver
|
||||
|
||||
assert_requested request_stub
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user