diff --git a/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb b/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb index cee49c8..75e3184 100644 --- a/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb +++ b/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb @@ -7,7 +7,8 @@ class Channel::MicrosoftTeams::V3 < Integration {key: :alert_resolved, type: :boolean, default: false}, {key: :alert_dropped, type: :boolean, default: false}, {key: :outgoing_rules, type: :string, default: nil}, - {key: :time_zone, type: :string, default: nil} + {key: :time_zone, type: :string, default: nil}, + {key: :compact_message, type: :boolean, default: false} ] store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option" @@ -22,6 +23,7 @@ class Channel::MicrosoftTeams::V3 < Integration self.option_alert_dropped ||= false self.option_outgoing_rules ||= "" self.option_time_zone ||= "UTC" + self.option_compact_message ||= false end def converts_to @@ -82,6 +84,12 @@ def _alert end def _blocks + facts = if option_compact_message + _compact_facts + else + _full_facts + end + { "@type": "MessageCard", "@context": "http://schema.org/extensions", @@ -89,33 +97,8 @@ def _blocks summary: _title, sections: [{ activityTitle: _title, - activitySubtitle: _alert.description&.try(:to_plain_text), - facts: [ - { - name: "Status", - value: _alert.status.upcase - }, - { - name: "Urgency", - value: _alert.urgency.upcase - }, - { - name: "Created", - value: _alert.created_at.in_time_zone(option_time_zone).iso8601 - }, - { - name: "Source", - value: _alert.source&.name - }, - { - name: "Destinations", - value: _alert.alert_destinations&.map { |d| d.destination.name }&.join(", ") - }, - { - name: "User", - value: _alert.alert_responders&.where(role: :incident_commander)&.includes(account_user: :user)&.first&.account_user&.name - } - ], + activitySubtitle: option_compact_message ? nil : _alert.description&.try(:to_plain_text), + facts: facts, markdown: true }], potentialAction: [ @@ -131,6 +114,48 @@ def _blocks } end + def _compact_facts + [ + { + name: "Status", + value: _alert.status.upcase + }, + { + name: "User", + value: _alert.alert_responders&.where(role: :incident_commander)&.includes(account_user: :user)&.first&.account_user&.name + } + ] + end + + def _full_facts + [ + { + name: "Status", + value: _alert.status.upcase + }, + { + name: "Urgency", + value: _alert.urgency.upcase + }, + { + name: "Created", + value: _alert.created_at.in_time_zone(option_time_zone).iso8601 + }, + { + name: "Source", + value: _alert.source&.name + }, + { + name: "Destinations", + value: _alert.alert_destinations&.map { |d| d.destination.name }&.join(", ") + }, + { + name: "User", + value: _alert.alert_responders&.where(role: :incident_commander)&.includes(account_user: :user)&.first&.account_user&.name + } + ] + end + def _title return @_title if @_title.present? diff --git a/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb b/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb index d201019..0fe9ddc 100644 --- a/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb +++ b/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb @@ -7,7 +7,8 @@ class Channel::MicrosoftTeams::V4 < Integration {key: :alert_resolved, type: :boolean, default: false}, {key: :alert_dropped, type: :boolean, default: false}, {key: :outgoing_rules, type: :string, default: nil}, - {key: :time_zone, type: :string, default: nil} + {key: :time_zone, type: :string, default: nil}, + {key: :compact_message, type: :boolean, default: false} ] store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option" @@ -22,6 +23,7 @@ class Channel::MicrosoftTeams::V4 < Integration self.option_alert_dropped ||= false self.option_outgoing_rules ||= "" self.option_time_zone ||= "UTC" + self.option_compact_message ||= false end def adapter_supports_incoming? @@ -78,6 +80,12 @@ def _alert end def _blocks + body = if option_compact_message + _compact_body + else + _full_body + end + { type: "message", attachments: [ @@ -86,105 +94,140 @@ def _blocks contentUrl: nil, content: { type: "AdaptiveCard", - body: [ + body: body, + actions: [ { - type: "Container", - backgroundImage: _color, - items: [ - { - type: "TextBlock", - size: "Large", - weight: "Bolder", - text: _title - }, - { - type: "ColumnSet", - columns: [ - { - type: "Column", - items: [ - { - type: "TextBlock", - weight: "Bolder", - text: _title, - wrap: true - }, - { - type: "TextBlock", - spacing: "None", - text: "Created #{_alert.created_at.in_time_zone(option_time_zone).iso8601}", - wrap: true - } - ], - width: "stretch" - } - ] - } - ] - }, + type: "Action.OpenUrl", + title: "View", + url: Rails.application.routes.url_helpers.try(:alert_url, _alert, script_name: "/#{_alert.account_id}"), + style: "positive" + } + ], + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + version: "1.2" + } + } + ] + } + end + + def _compact_body + [ + { + type: "Container", + backgroundImage: _color, + items: [ + { + type: "TextBlock", + size: "Large", + weight: "Bolder", + text: _title + }, + { + type: "FactSet", + facts: [ { - type: "Container", - items: [ - { - type: "FactSet", - facts: [ - { - title: "Status:", - value: _alert.status&.upcase - }, { - title: "Urgency:", - value: _alert.urgency&.upcase - }, { - title: "Source:", - value: _alert.source&.name - }, { - title: "Destinations:", - value: _alert.alert_destinations&.map { |d| d.destination.name }&.join(", ") - }, { - title: "User:", - value: _alert.alert_responders&.where(role: :incident_commander)&.includes(account_user: :user)&.first&.account_user&.name - } - ], - spacing: "None" - } - ], - spacing: "Medium" + title: "Status:", + value: _alert.status&.upcase }, { - type: "Container", + title: "User:", + value: _alert.alert_responders&.where(role: :incident_commander)&.includes(account_user: :user)&.first&.account_user&.name + } + ], + spacing: "ExtraSmall" + } + ] + } + ] + end + + def _full_body + [ + { + type: "Container", + backgroundImage: _color, + items: [ + { + type: "TextBlock", + size: "Large", + weight: "Bolder", + text: _title + }, + { + type: "ColumnSet", + columns: [ + { + type: "Column", items: [ { type: "TextBlock", - text: _alert.description&.try(:to_plain_text), - wrap: true, - separator: true, - maxLines: 24 + weight: "Bolder", + text: _title, + wrap: true }, { - type: "FactSet", - facts: _alert.additional_data&.map { |ad| {title: ad["label"], value: Array(ad["value"]).join(", ")} } || [], - spacing: "Medium", - separator: true + type: "TextBlock", + spacing: "None", + text: "Created #{_alert.created_at.in_time_zone(option_time_zone).iso8601}", + wrap: true } ], - spacing: "Medium", - separator: true + width: "stretch" } - ], - actions: [ + ] + } + ] + }, + { + type: "Container", + items: [ + { + type: "FactSet", + facts: [ { - type: "Action.OpenUrl", - title: "View", - url: Rails.application.routes.url_helpers.try(:alert_url, _alert, script_name: "/#{_alert.account_id}"), - style: "positive" + title: "Status:", + value: _alert.status&.upcase + }, { + title: "Urgency:", + value: _alert.urgency&.upcase + }, { + title: "Source:", + value: _alert.source&.name + }, { + title: "Destinations:", + value: _alert.alert_destinations&.map { |d| d.destination.name }&.join(", ") + }, { + title: "User:", + value: _alert.alert_responders&.where(role: :incident_commander)&.includes(account_user: :user)&.first&.account_user&.name } ], - "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", - version: "1.2" + spacing: "None" } - } - ] - } + ], + spacing: "Medium" + }, + { + type: "Container", + items: [ + { + type: "TextBlock", + text: _alert.description&.try(:to_plain_text), + wrap: true, + separator: true, + maxLines: 24 + }, + { + type: "FactSet", + facts: _alert.additional_data&.map { |ad| {title: ad["label"], value: Array(ad["value"]).join(", ")} } || [], + spacing: "Medium", + separator: true + } + ], + spacing: "Medium", + separator: true + } + ] end def _title diff --git a/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb b/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb index 0309c28..eede42e 100644 --- a/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb +++ b/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb @@ -17,6 +17,7 @@ :alert_acknowledged, :alert_resolved, :alert_dropped, + :compact_message, ] %> <% opts.each do |opt| %> diff --git a/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb b/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb index 0793999..31c09c3 100644 --- a/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb +++ b/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb @@ -30,6 +30,7 @@ :alert_acknowledged, :alert_resolved, :alert_dropped, + :compact_message, ] %> <% opts.each do |opt| %> diff --git a/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb b/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb index 0309c28..eede42e 100644 --- a/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb +++ b/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb @@ -17,6 +17,7 @@ :alert_acknowledged, :alert_resolved, :alert_dropped, + :compact_message, ] %> <% opts.each do |opt| %> diff --git a/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb b/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb index 0793999..31c09c3 100644 --- a/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb +++ b/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb @@ -30,6 +30,7 @@ :alert_acknowledged, :alert_resolved, :alert_dropped, + :compact_message, ] %> <% opts.each do |opt| %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 5ab7fc4..0d9ec43 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -16,6 +16,7 @@ en: option_alert_resolved_hint_html: "Send when the alert is marked resolved" option_alert_dropped_hint_html: "Send when the alert is dropped" option_alert_handoff_hint_html: "Send when the alert has been handed off" + option_compact_message_hint_html: "Show only alert title, status, and assigned user in the message box" option_comment_created_hint_html: "Send when a comment is created" option_comment_updated_hint_html: "Send when a comment is updated" option_comment_destroyed_hint_html: "Send when a comment is deleted" @@ -197,6 +198,7 @@ en: option_event_reminder_going_on_call: "event_reminder.going_on_call" option_event_reminder_going_off_call: "event_reminder.going_off_call" option_outgoing_rules: "Outgoing Rules" + option_compact_message: "Compact Message?" "pager_tree/integrations/apex_ping/v3": option_api_key: "API Key" "pager_tree/integrations/channel/hangouts/v3": diff --git a/test/models/pager_tree/integrations/channel/microsoft_teams/v3_test.rb b/test/models/pager_tree/integrations/channel/microsoft_teams/v3_test.rb index 36d79ad..bf3c979 100644 --- a/test/models/pager_tree/integrations/channel/microsoft_teams/v3_test.rb +++ b/test/models/pager_tree/integrations/channel/microsoft_teams/v3_test.rb @@ -150,5 +150,26 @@ class Channel::MicrosoftTeams::V3Test < ActiveSupport::TestCase assert_equal @expected_payload.to_json, outgoing_webhook_delivery.body.to_json end + + test "compact_message mode shows only alert, status, and user" do + assert_no_performed_jobs + + @integration.option_compact_message = true + @integration.adapter_outgoing_event = OutgoingEvent.new(**@data) + outgoing_webhook_delivery = @integration.adapter_process_outgoing + + assert_enqueued_jobs 1 + + body = outgoing_webhook_delivery.body.as_json + + # Should have compact facts with only status and user + facts = body["sections"][0]["facts"] + assert_equal 2, facts.length + assert_equal "Status", facts[0]["name"] + assert_equal "User", facts[1]["name"] + + # activitySubtitle should be nil in compact mode + assert_nil body["sections"][0]["activitySubtitle"] + end end end diff --git a/test/models/pager_tree/integrations/channel/microsoft_teams/v4_test.rb b/test/models/pager_tree/integrations/channel/microsoft_teams/v4_test.rb index cfe6fc5..fb6a3a0 100644 --- a/test/models/pager_tree/integrations/channel/microsoft_teams/v4_test.rb +++ b/test/models/pager_tree/integrations/channel/microsoft_teams/v4_test.rb @@ -210,5 +210,41 @@ class Channel::MicrosoftTeams::V4Test < ActiveSupport::TestCase assert_equal @expected_payload.to_json, outgoing_webhook_delivery.body.to_json end + + test "compact_message mode shows only alert, status, and user" do + assert_no_performed_jobs + + @integration.option_compact_message = true + @integration.adapter_outgoing_event = OutgoingEvent.new(**@data) + outgoing_webhook_delivery = @integration.adapter_process_outgoing + + assert_enqueued_jobs 1 + + body = outgoing_webhook_delivery.body.as_json + card_body = body["attachments"][0]["content"]["body"] + + # Should have only one container (the colored one with title, status, and user) + assert_equal 1, card_body.length + + # Check the container has the correct structure + container = card_body[0] + assert_equal "Container", container["type"] + assert_equal "https://pagertree.com/assets/img/icon/yellow-square.png", container["backgroundImage"] + + # Check items in the colored container + items = container["items"] + assert_equal 2, items.length + + # First item should be the title + assert_equal "TextBlock", items[0]["type"] + assert_equal "Alert ##{@alert.tiny_id} #{@alert.title}", items[0]["text"] + + # Second item should be the facts (status and user only) + assert_equal "FactSet", items[1]["type"] + facts = items[1]["facts"] + assert_equal 2, facts.length + assert_equal "Status:", facts[0]["title"] + assert_equal "User:", facts[1]["title"] + end end end