diff --git a/app/assets/stylesheets/components/profile.css b/app/assets/stylesheets/components/profile.css index 2d7af31..7082a8d 100644 --- a/app/assets/stylesheets/components/profile.css +++ b/app/assets/stylesheets/components/profile.css @@ -218,6 +218,29 @@ text-decoration: underline; } +.activity-sender { + display: inline-flex; + align-items: center; + gap: var(--spacing-2); + color: var(--color-text-primary); + text-decoration: none; +} + +.activity-sender:hover .activity-sender-name { + text-decoration: underline; +} + +.activity-sender-avatar { + width: 32px; + height: 32px; + border-radius: 50%; + flex-shrink: 0; +} + +.activity-sender-name { + font-weight: var(--font-weight-medium); +} + .activity-filters { padding: var(--spacing-4); background: var(--color-bg-card); diff --git a/app/controllers/concerns/profile_activity.rb b/app/controllers/concerns/profile_activity.rb index e475605..2794605 100644 --- a/app/controllers/concerns/profile_activity.rb +++ b/app/controllers/concerns/profile_activity.rb @@ -44,7 +44,7 @@ def build_activity_entries(scope: nil, filters: nil) return [] if ids.blank? scope ||= Message.where(sender_person_id: ids) - messages = scope.includes(:topic, :attachments) + messages = scope.includes(:topic, :attachments, :sender, sender_person: :default_alias) .order(created_at: :desc) return [] if messages.empty? diff --git a/app/views/shared/profile/_recent_threads.html.slim b/app/views/shared/profile/_recent_threads.html.slim index bf945b5..09361c5 100644 --- a/app/views/shared/profile/_recent_threads.html.slim +++ b/app/views/shared/profile/_recent_threads.html.slim @@ -13,6 +13,7 @@ h2 Recent messages (last 30 days) - if activity_entries.any? + - show_sender = local_assigns.fetch(:show_sender, false) - summary = local_assigns[:activity_summary] || {} - total = summary[:total] || activity_entries.size - started = summary[:started_thread] || 0 @@ -45,11 +46,14 @@ thead tr th Activity + - if show_sender + th Sender th Thread th Sent tbody - activity_entries.each do |entry| - topic = entry[:topic] + - message = entry[:message] - types = entry[:activity_types] || [] tr td.activity-types @@ -65,8 +69,21 @@ span.activity-tag.tag-patch First patch - when :sent_followup_patch span.activity-tag.tag-patch Follow-up patch + - if show_sender + - sender_alias = message.sender_display_alias + td + - if sender_alias && message.sender_person + = link_to person_path(sender_alias.email), class: "activity-sender", data: { turbo_frame: "_top" } do + = image_tag sender_alias.gravatar_url(size: 32), class: "activity-sender-avatar", alt: sender_alias.name + span.activity-sender-name = sender_alias.name + - elsif sender_alias + .activity-sender + = image_tag sender_alias.gravatar_url(size: 32), class: "activity-sender-avatar", alt: sender_alias.name + span.activity-sender-name = sender_alias.name + - else + span.activity-sender-name Unknown td - = link_to topic.title, topic_path(topic, anchor: "message-#{entry[:message].id}"), class: "activity-topic", data: { turbo_frame: "_top" } + = link_to topic.title, topic_path(topic, anchor: "message-#{message.id}"), class: "activity-topic", data: { turbo_frame: "_top" } td = time_ago_in_words(entry[:sent_at]) | ago diff --git a/app/views/teams_profile/_recent_threads.html.slim b/app/views/teams_profile/_recent_threads.html.slim index 9eab29c..edb1b85 100644 --- a/app/views/teams_profile/_recent_threads.html.slim +++ b/app/views/teams_profile/_recent_threads.html.slim @@ -1 +1 @@ -= render "shared/profile/recent_threads", activity_entries: @activity_entries, activity_period: @activity_period, activity_summary: @activity_summary += render "shared/profile/recent_threads", activity_entries: @activity_entries, activity_period: @activity_period, activity_summary: @activity_summary, show_sender: true diff --git a/spec/requests/teams_profile_spec.rb b/spec/requests/teams_profile_spec.rb index e3ce56c..7364b33 100644 --- a/spec/requests/teams_profile_spec.rb +++ b/spec/requests/teams_profile_spec.rb @@ -87,5 +87,24 @@ def attach_verified_alias(user, email:, primary: true) get team_profile_path("non-existent") expect(response).to have_http_status(:not_found) end + + it "shows the sender column and links team activity rows to the sender profile" do + team.update!(visibility: :visible) + + member_alias = attach_verified_alias(member, email: "member@example.com") + create(:team_member, team: team, user: non_member, role: "member") + sender_alias = attach_verified_alias(non_member, email: "sender@example.com") + + topic = create(:topic, creator_alias: member_alias, title: "Sender activity thread") + create(:message, topic: topic, sender: sender_alias, sender_person_id: non_member.person.id, created_at: 2.days.ago, updated_at: 2.days.ago) + + get team_profile_path("test-team") + + expect(response).to have_http_status(:success) + expect(response.body).to include("