pager_tree-integrations 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +61 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/pager_tree_integrations_manifest.js +1 -0
  6. data/app/assets/stylesheets/pager_tree/integrations/application.css +15 -0
  7. data/app/controllers/pager_tree/integrations/application_controller.rb +6 -0
  8. data/app/controllers/pager_tree/integrations/live_call_routing/twilio/v3_controller.rb +49 -0
  9. data/app/helpers/pager_tree/integrations/application_helper.rb +9 -0
  10. data/app/jobs/pager_tree/integrations/application_job.rb +6 -0
  11. data/app/jobs/pager_tree/integrations/outgoing_webhook_job.rb +12 -0
  12. data/app/mailers/pager_tree/integrations/application_mailer.rb +8 -0
  13. data/app/models/pager_tree/integrations/additional_datum.rb +41 -0
  14. data/app/models/pager_tree/integrations/alert.rb +60 -0
  15. data/app/models/pager_tree/integrations/apex_ping/v3.rb +69 -0
  16. data/app/models/pager_tree/integrations/application_record.rb +7 -0
  17. data/app/models/pager_tree/integrations/email/v3.rb +150 -0
  18. data/app/models/pager_tree/integrations/integration.rb +130 -0
  19. data/app/models/pager_tree/integrations/live_call_routing/twilio/v3.rb +332 -0
  20. data/app/models/pager_tree/integrations/outgoing_event.rb +25 -0
  21. data/app/models/pager_tree/integrations/outgoing_webhook/v3.rb +75 -0
  22. data/app/models/pager_tree/integrations/outgoing_webhook_delivery/hook_relay.rb +98 -0
  23. data/app/models/pager_tree/integrations/outgoing_webhook_delivery.rb +22 -0
  24. data/app/views/layouts/pager_tree/integrations/application.html.erb +15 -0
  25. data/app/views/pager_tree/integrations/apex_ping/v3/_form_options.html.erb +0 -0
  26. data/app/views/pager_tree/integrations/apex_ping/v3/_show_options.html.erb +0 -0
  27. data/app/views/pager_tree/integrations/email/v3/_form_options.html.erb +11 -0
  28. data/app/views/pager_tree/integrations/email/v3/_show_options.html.erb +17 -0
  29. data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_form_options.html.erb +80 -0
  30. data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_show_options.html.erb +181 -0
  31. data/app/views/pager_tree/integrations/outgoing_webhook/v3/_form_options.html.erb +50 -0
  32. data/app/views/pager_tree/integrations/outgoing_webhook/v3/_show_options.html.erb +61 -0
  33. data/app/views/shared/_password_visibility_button.html.erb +8 -0
  34. data/config/locales/en.yml +87 -0
  35. data/config/routes.rb +12 -0
  36. data/db/migrate/20220208195853_create_active_storage_tables.active_storage.rb +58 -0
  37. data/db/migrate/20220208195854_create_deferred_request_deferred_requests.deferred_request.rb +13 -0
  38. data/db/migrate/20220208195855_create_pager_tree_integrations_integrations.rb +10 -0
  39. data/db/migrate/20220215200426_create_pager_tree_integrations_outgoing_webhook_deliveries.rb +12 -0
  40. data/lib/generators/integration/USAGE +11 -0
  41. data/lib/generators/integration/integration_generator.rb +14 -0
  42. data/lib/generators/integration/templates/_form_options.html.erb.tt +8 -0
  43. data/lib/generators/integration/templates/_show_options.html.erb.tt +14 -0
  44. data/lib/generators/integration/templates/model.rb.tt +64 -0
  45. data/lib/generators/integration/templates/test.rb.tt +87 -0
  46. data/lib/pager_tree/integrations/engine.rb +11 -0
  47. data/lib/pager_tree/integrations/env.rb +36 -0
  48. data/lib/pager_tree/integrations/version.rb +5 -0
  49. data/lib/pager_tree/integrations.rb +29 -0
  50. data/lib/tasks/pager_tree/integrations_tasks.rake +4 -0
  51. metadata +152 -0
@@ -0,0 +1,98 @@
1
+ module PagerTree::Integrations
2
+ class OutgoingWebhookDelivery::HookRelay < OutgoingWebhookDelivery
3
+ extend ::PagerTree::Integrations::Env
4
+
5
+ define_model_callbacks :deliver
6
+
7
+ def self.hook_relay_account_id
8
+ find_value_by_name(:hook_relay, :account_id)
9
+ end
10
+
11
+ def self.hook_relay_hook_id
12
+ find_value_by_name(:hook_relay, :hook_id)
13
+ end
14
+
15
+ def self.hook_relay_api_key
16
+ find_value_by_name(:hook_relay, :api_key)
17
+ end
18
+
19
+ def hook_relay_hook_url
20
+ "https://api.hookrelay.dev/hooks/#{OutgoingWebhookDelivery::HookRelay.hook_relay_account_id}/#{OutgoingWebhookDelivery::HookRelay.hook_relay_hook_id}"
21
+ end
22
+
23
+ def hook_relay_delivery_url
24
+ "https://app.hookrelay.dev/api/v1/accounts/#{OutgoingWebhookDelivery::HookRelay.hook_relay_account_id}/hooks/#{OutgoingWebhookDelivery::HookRelay.hook_relay_hook_id}/deliveries/#{thirdparty_id}"
25
+ end
26
+
27
+ def deliver_later
28
+ OutgoingWebhookJob.perform_later(id, :deliver)
29
+ end
30
+
31
+ def deliver
32
+ run_callbacks :deliver do
33
+ begin
34
+ hook_relay_options = {
35
+ headers: {
36
+ HR_TARGET_URL: url
37
+ }
38
+ }
39
+
40
+ pagertree_options = {
41
+ headers: {
42
+ Accept: "*/*",
43
+ 'User-Agent': "pagertree outgoing webhook service; ref: #{resource&.id}; report: support@pagertree.com",
44
+ 'Content-Type': "application/json"
45
+ }
46
+ }
47
+
48
+ auth_options = {}
49
+ if auth.is_a?(Hash) && (username = auth.dig(:username)).present? && (password = auth.dig(:password)).present?
50
+ auth_options = {
51
+ headers: {
52
+ Authorization: Base64.strict_encode64("#{username}:#{password}")
53
+ }
54
+ }
55
+ end
56
+
57
+ options = OutgoingWebhookDelivery::HTTP_OPTIONS
58
+ .deep_merge(hook_relay_options)
59
+ .deep_merge(pagertree_options)
60
+ .deep_merge(auth_options)
61
+
62
+ response = HTTParty.post(hook_relay_hook_url, body: body.to_json, **options)
63
+
64
+ self.thirdparty_id = response["id"]
65
+ self.status = :sent
66
+ rescue => exception
67
+ Rails.logger.error(exception)
68
+ self.status = :failure
69
+ end
70
+ save!
71
+ end # run_callbacks
72
+ end
73
+
74
+ def delivery
75
+ return @delivery if @delivery
76
+ return {} unless thirdparty_id
77
+
78
+ options = {
79
+ headers: {
80
+ 'Content-Type': "application/json",
81
+ Authorization: "Bearer #{OutgoingWebhookDelivery::HookRelay.hook_relay_api_key}"
82
+ },
83
+ timeout: 15
84
+ }
85
+
86
+ @delivery = ::HTTParty.get(hook_relay_delivery_url, **options)
87
+ @delivery
88
+ end
89
+
90
+ def request
91
+ delivery&.dig("request")
92
+ end
93
+
94
+ def responses
95
+ delivery&.dig("responses") || []
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,22 @@
1
+ module PagerTree::Integrations
2
+ class OutgoingWebhookDelivery < PagerTree::Integrations.outgoing_webhook_delivery_parent_class.constantize
3
+ self.table_name = PagerTree::Integrations.outgoing_webhook_delivery_table_name
4
+
5
+ serialize :data, JSON
6
+ encrypts :data
7
+
8
+ store_accessor :data, *[:url, :body, :auth].map(&:to_s)
9
+
10
+ HTTP_OPTIONS = {
11
+ headers: {'Content-Type': "application/json"},
12
+ timeout: 15
13
+ }
14
+
15
+ belongs_to :resource, polymorphic: true
16
+ enum status: {queued: 0, sent: 1, success: 2, failure: 3, retrying: 4, cancelled: 5, stored: 6, insufficent_funds: 7}
17
+
18
+ def self.factory(**params)
19
+ PagerTree::Integrations.outgoing_webhook_delivery_factory_class.constantize.new(**params)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Pager tree integrations</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "pager_tree/integrations/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
@@ -0,0 +1,11 @@
1
+ <div class="form-group">
2
+ <%= form.label :option_allow_spam %>
3
+ <%= form.check_box :option_allow_spam, class: "form-checkbox" %>
4
+ <p class="form-hint"><%== t(".option_allow_spam_hint_html") %></p>
5
+ </div>
6
+
7
+ <div class="form-group">
8
+ <%= form.label :option_dedup_threads %>
9
+ <%= form.check_box :option_dedup_threads, class: "form-checkbox" %>
10
+ <p class="form-hint"><%== t(".option_dedup_threads_hint_html") %></p>
11
+ </div>
@@ -0,0 +1,17 @@
1
+ <div class="sm:col-span-1">
2
+ <dt class="text-sm font-medium text-gray-500">
3
+ <%= t("activerecord.attributes.pager_tree/integrations/email/v3.option_allow_spam") %>
4
+ </dt>
5
+ <dd class="mt-1 text-sm text-gray-900">
6
+ <%= render partial: "shared/components/badge_enabled", locals: { enabled: integration.option_allow_spam } %>
7
+ </dd>
8
+ </div>
9
+
10
+ <div class="sm:col-span-1">
11
+ <dt class="text-sm font-medium text-gray-500">
12
+ <%= t("activerecord.attributes.pager_tree/integrations/email/v3.option_dedup_threads") %>
13
+ </dt>
14
+ <dd class="mt-1 text-sm text-gray-900">
15
+ <%= render partial: "shared/components/badge_enabled", locals: { enabled: integration.option_dedup_threads } %>
16
+ </dd>
17
+ </div>
@@ -0,0 +1,80 @@
1
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
2
+ <div class="form-group">
3
+ <%= form.label :option_account_sid %>
4
+ <%= form.text_field :option_account_sid, class: "form-control" %>
5
+ <p class="form-hint"><%== t(".option_account_sid_hint_html") %></p>
6
+ </div>
7
+
8
+ <div class="form-group" data-controller="password-visibility">
9
+ <%= form.label :option_api_key %>
10
+ <%= form.password_field :option_api_key, value: form.object.option_api_key, class: "form-control", data: { password_visibility_target: "input"} %>
11
+ <div class="flex justify-between">
12
+ <p class="form-hint"><%== t(".option_api_key_hint_html") %></p>
13
+ <%= render partial: "shared/password_visibility_button" %>
14
+ </div>
15
+ </div>
16
+
17
+ <div class="form-group" data-controller="password-visibility">
18
+ <%= form.label :option_api_secret %>
19
+ <%= form.password_field :option_api_secret, value: form.object.option_api_secret, class: "form-control", data: { password_visibility_target: "input"} %>
20
+ <div class="flex justify-between">
21
+ <p class="form-hint"><%== t(".option_api_secret_hint_html") %></p>
22
+ <%= render partial: "shared/password_visibility_button" %>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="form-group">
27
+ <%= form.label :option_welcome_media %>
28
+ <%= form.file_field :option_welcome_media, accept: "audio/*", class: "file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-gray-50 file:text-gray-700 hover:file:bg-gray-100" %>
29
+ <p class="form-hint"><%== t(".option_welcome_media_hint_html") %></p>
30
+ </div>
31
+
32
+ <div class="form-group">
33
+ <%= form.label :option_please_wait_media %>
34
+ <%= form.file_field :option_please_wait_media, accept: "audio/*", class: "file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-gray-50 file:text-gray-700 hover:file:bg-gray-100" %>
35
+ <p class="form-hint"><%== t(".option_please_wait_media_hint_html") %></p>
36
+ </div>
37
+
38
+ <div class="form-group">
39
+ <%= form.label :option_music_media %>
40
+ <%= form.file_field :option_music_media, accept: "audio/*", class: "file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-gray-50 file:text-gray-700 hover:file:bg-gray-100" %>
41
+ <p class="form-hint"><%== t(".option_music_media_hint_html") %></p>
42
+ </div>
43
+
44
+ <div class="form-group">
45
+ <%= form.label :option_connect_now_media %>
46
+ <%= form.file_field :option_connect_now_media, accept: "audio/*", class: "file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-gray-50 file:text-gray-700 hover:file:bg-gray-100" %>
47
+ <p class="form-hint"><%== t(".option_connect_now_media_hint_html") %></p>
48
+ </div>
49
+
50
+ <div class="form-group">
51
+ <%= form.label :option_no_answer_media %>
52
+ <%= form.file_field :option_no_answer_media, accept: "audio/*", class: "file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-gray-50 file:text-gray-700 hover:file:bg-gray-100" %>
53
+ <p class="form-hint"><%== t(".option_no_answer_media_hint_html") %></p>
54
+ </div>
55
+
56
+ <div class="form-group">
57
+ <%= form.label :option_no_answer_thank_you_media %>
58
+ <%= form.file_field :option_no_answer_thank_you_media, accept: "audio/*", class: "file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-gray-50 file:text-gray-700 hover:file:bg-gray-100" %>
59
+ <p class="form-hint"><%== t(".option_no_answer_thank_you_media_hint_html") %></p>
60
+ </div>
61
+
62
+ <div class="form-group">
63
+ <%= form.label :option_force_input %>
64
+ <%= form.check_box :option_force_input, class: "form-checkbox" %>
65
+ <p class="form-hint"><%== t(".option_force_input_hint_html") %></p>
66
+ </div>
67
+
68
+ <div class="form-group">
69
+ <%= form.label :option_record %>
70
+ <%= form.check_box :option_record, class: "form-checkbox" %>
71
+ <p class="form-hint"><%== t(".option_record_hint_html") %></p>
72
+ </div>
73
+
74
+ <div class="form-group" data-controller="tagify">
75
+ <%= form.label :option_record_emails_list %>
76
+ <%= form.text_field :option_record_emails_list, class: "form-control", data: { tagify_target: "input" } %>
77
+ <p class="form-hint"><%== t(".option_record_emails_list_hint_html") %></p>
78
+ </div>
79
+
80
+ </div>
@@ -0,0 +1,181 @@
1
+ <div class="sm:col-span-2">
2
+ <dt class="text-sm font-medium text-gray-500">
3
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_account_sid") %>
4
+ </dt>
5
+ <dd class="mt-1 text-sm text-gray-900">
6
+ <div class="flex items-center gap-2">
7
+ <p class="text-sm truncate">
8
+ <%= integration.option_account_sid %>
9
+ </p>
10
+ </div>
11
+ </dd>
12
+ </div>
13
+
14
+ <div class="sm:col-span-1">
15
+ <dt class="text-sm font-medium text-gray-500">
16
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_api_key") %>
17
+ </dt>
18
+ <dd class="mt-1 text-sm text-gray-900">
19
+ <div class="flex items-center gap-2">
20
+ <p class="text-sm truncate">
21
+ <%= mask integration.option_api_key %>
22
+ </p>
23
+ </div>
24
+ </dd>
25
+ </div>
26
+
27
+ <div class="sm:col-span-1">
28
+ <dt class="text-sm font-medium text-gray-500">
29
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_api_secret") %>
30
+ </dt>
31
+ <dd class="mt-1 text-sm text-gray-900">
32
+ <div class="flex items-center gap-2">
33
+ <p class="text-sm truncate">
34
+ <%= mask integration.option_api_secret %>
35
+ </p>
36
+ </div>
37
+ </dd>
38
+ </div>
39
+
40
+ <div class="sm:col-span-2">
41
+ <dt class="text-sm font-medium text-gray-500">
42
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_welcome_media") %>
43
+ </dt>
44
+ <dd class="mt-1 text-sm text-gray-900">
45
+ <div class="flex items-center gap-2">
46
+ <p class="text-sm truncate">
47
+ <% if integration.option_welcome_media.present? %>
48
+ <%= link_to integration.option_welcome_media.blob.filename, integration.option_welcome_media, target: "_blank" %>
49
+ <% else %>
50
+ (<%= t("pager_tree.integrations.common.none") %>)
51
+ <% end %>
52
+ </p>
53
+ <%= link_to t("delete"), main_app.integration_attachment_path(integration, integration.option_welcome_media.id), method: :delete, class: "btn btn-small btn-danger outline", data: { confirm: t("are_you_sure") } if integration.option_welcome_media.present? %>
54
+ </div>
55
+ </dd>
56
+ </div>
57
+
58
+ <div class="sm:col-span-2">
59
+ <dt class="text-sm font-medium text-gray-500">
60
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_please_wait_media") %>
61
+ </dt>
62
+ <dd class="mt-1 text-sm text-gray-900">
63
+ <div class="flex items-center gap-2">
64
+ <p class="text-sm truncate">
65
+ <% if integration.option_please_wait_media.present? %>
66
+ <%= link_to integration.option_please_wait_media.blob.filename, integration.option_please_wait_media, target: "_blank" %>
67
+ <% else %>
68
+ (<%= link_to t("pager_tree.integrations.common.default"), integration.option_please_wait_media_url, target: "_blank" %>)
69
+ <% end %>
70
+ </p>
71
+ <%= link_to t("delete"), main_app.integration_attachment_path(integration, integration.option_please_wait_media.id), method: :delete, class: "btn btn-small btn-danger outline", data: { confirm: t("are_you_sure") } if integration.option_please_wait_media.present? %>
72
+ </div>
73
+ </dd>
74
+ </div>
75
+
76
+ <div class="sm:col-span-2">
77
+ <dt class="text-sm font-medium text-gray-500">
78
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_music_media") %>
79
+ </dt>
80
+ <dd class="mt-1 text-sm text-gray-900">
81
+ <div class="flex items-center gap-2">
82
+ <p class="text-sm truncate">
83
+ <% if integration.option_music_media.present? %>
84
+ <%= link_to integration.option_music_media.blob.filename, integration.option_music_media, target: "_blank" %>
85
+ <% else %>
86
+ (<%= link_to t("pager_tree.integrations.common.default"), integration.option_music_media_url, target: "_blank" %>)
87
+ <% end %>
88
+ </p>
89
+ <%= link_to t("delete"), main_app.integration_attachment_path(integration, integration.option_music_media.id), method: :delete, class: "btn btn-small btn-danger outline", data: { confirm: t("are_you_sure") } if integration.option_music_media.present? %>
90
+ </div>
91
+ </dd>
92
+ </div>
93
+
94
+ <div class="sm:col-span-2">
95
+ <dt class="text-sm font-medium text-gray-500">
96
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_connect_now_media") %>
97
+ </dt>
98
+ <dd class="mt-1 text-sm text-gray-900">
99
+ <div class="flex items-center gap-2">
100
+ <p class="text-sm truncate">
101
+ <% if integration.option_connect_now_media.present? %>
102
+ <%= link_to integration.option_connect_now_media.blob.filename, integration.option_connect_now_media, target: "_blank" %>
103
+ <% else %>
104
+ (<%= link_to t("pager_tree.integrations.common.default"), integration.option_connect_now_media_url, target: "_blank" %>)
105
+ <% end %>
106
+ </p>
107
+ <%= link_to t("delete"), main_app.integration_attachment_path(integration, integration.option_connect_now_media.id), method: :delete, class: "btn btn-small btn-danger outline", data: { confirm: t("are_you_sure") } if integration.option_connect_now_media.present? %>
108
+ </div>
109
+ </dd>
110
+ </div>
111
+
112
+ <div class="sm:col-span-2">
113
+ <dt class="text-sm font-medium text-gray-500">
114
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_record") %>
115
+ </dt>
116
+ <dd class="mt-1 text-sm text-gray-900">
117
+ <%= render partial: "shared/components/badge_enabled", locals: { enabled: integration.option_record } %>
118
+ </dd>
119
+ </div>
120
+
121
+ <div class="sm:col-span-2">
122
+ <dt class="text-sm font-medium text-gray-500">
123
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_no_answer_media") %>
124
+ </dt>
125
+ <dd class="mt-1 text-sm text-gray-900">
126
+ <div class="flex items-center gap-2">
127
+ <p class="text-sm truncate">
128
+ <% if integration.option_no_answer_media.present? %>
129
+ <%= link_to integration.option_no_answer_media.blob.filename, integration.option_no_answer_media, target: "_blank" %>
130
+ <% else %>
131
+ (<%= t("pager_tree.integrations.common.default") %>)
132
+ <% end %>
133
+ </p>
134
+ </div>
135
+ </dd>
136
+ </div>
137
+
138
+ <div class="sm:col-span-2">
139
+ <dt class="text-sm font-medium text-gray-500">
140
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_no_answer_thank_you_media") %>
141
+ </dt>
142
+ <dd class="mt-1 text-sm text-gray-900">
143
+ <div class="flex items-center gap-2">
144
+ <p class="text-sm truncate">
145
+ <% if integration.option_no_answer_thank_you_media.present? %>
146
+ <%= link_to integration.option_no_answer_thank_you_media.blob.filename, integration.option_no_answer_thank_you_media, target: "_blank" %>
147
+ <% else %>
148
+ (<%= t("pager_tree.integrations.common.default") %>)
149
+ <% end %>
150
+ </p>
151
+ </div>
152
+ </dd>
153
+ </div>
154
+
155
+ <div class="sm:col-span-2">
156
+ <dt class="text-sm font-medium text-gray-500">
157
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_record_emails_list") %>
158
+ </dt>
159
+ <dd class="mt-1 text-sm text-gray-900">
160
+ <div class="flex items-center gap-2">
161
+ <% integration.option_record_emails.each do |email| %>
162
+ <p class="text-sm truncate">
163
+ <%= link_to email, "mailto:#{email}" %>
164
+ </p>
165
+ <% end %>
166
+ <p class="hidden only:flex text-sm truncate">
167
+ (<%= t("pager_tree.integrations.common.none") %>)
168
+ </p>
169
+ </div>
170
+ </dd>
171
+ </div>
172
+
173
+ <div class="sm:col-span-1">
174
+ <dt class="text-sm font-medium text-gray-500">
175
+ <%= t("activerecord.attributes.pager_tree/integrations/live_call_routing/twilio/v3.option_force_input") %>
176
+ </dt>
177
+ <dd class="mt-1 text-sm text-gray-900">
178
+ <%= render partial: "shared/components/badge_enabled", locals: { enabled: integration.option_force_input } %>
179
+ </dd>
180
+ </div>
181
+
@@ -0,0 +1,50 @@
1
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
2
+ <div class="form-group">
3
+ <%= form.label :option_webhook_url %>
4
+ <%= form.text_field :option_webhook_url, class: "form-control" %>
5
+ <p class="form-hint"><%== t(".option_webhook_url_hint_html") %></p>
6
+ </div>
7
+
8
+ <div class="form-group">
9
+ <%= form.label :option_username %>
10
+ <%= form.text_field :option_username, class: "form-control" %>
11
+ <p class="form-hint"><%== t(".option_username_hint_html") %></p>
12
+ </div>
13
+
14
+ <div class="form-group">
15
+ <%= form.label :option_password %>
16
+ <%= form.text_field :option_password, class: "form-control" %>
17
+ <p class="form-hint"><%== t(".option_password_hint_html") %></p>
18
+ </div>
19
+
20
+ <%
21
+ opts = [
22
+ :alert_created,
23
+ :alert_open,
24
+ :alert_acknowledged,
25
+ :alert_rejected,
26
+ :alert_timeout,
27
+ :alert_resolved,
28
+ :alert_dropped,
29
+ :alert_handoff,
30
+ :send_linked
31
+ ]
32
+ %>
33
+ <% opts.each do |opt| %>
34
+ <div class="form-group">
35
+ <%= form.label "option_#{opt.to_s}".to_sym %>
36
+ <%= form.check_box "option_#{opt.to_s}".to_sym, class: "form-checkbox" %>
37
+ <p class="form-hint"><%== t(".option_#{opt.to_s}_hint_html") %></p>
38
+ </div>
39
+ <% end %>
40
+
41
+ </div>
42
+
43
+ <div class="grid grid-cols-1 gap-4">
44
+ <%= tag.div class: "form-group", data: {controller: "code-editor", code_editor_language_value: "handlebars", code_editor_read_only_value: false } do %>
45
+ <%= form.label :option_template %>
46
+ <%= form.hidden_field :option_template, class: "form-control", data: {code_editor_target: "form"} %>
47
+ <%= tag.div class: "h-96", data: {code_editor_target: "editor"} do %><%= form.object.option_template %><% end %>
48
+ <p class="form-hint"><%== t(".option_template_hint_html") %></p>
49
+ <% end %>
50
+ </div>
@@ -0,0 +1,61 @@
1
+ <div class="sm:col-span-2">
2
+ <dt class="text-sm font-medium text-gray-500">
3
+ <%= t("activerecord.attributes.pager_tree/integrations/outgoing_webhook/v3.option_webhook_url") %>
4
+ </dt>
5
+ <dd class="mt-1 text-sm text-gray-900">
6
+ <div class="flex items-center gap-2">
7
+ <p class="text-sm truncate">
8
+ <%= integration.option_webhook_url %>
9
+ </p>
10
+ </div>
11
+ </dd>
12
+ </div>
13
+
14
+ <div class="sm:col-span-1">
15
+ <dt class="text-sm font-medium text-gray-500">
16
+ <%= t("activerecord.attributes.pager_tree/integrations/outgoing_webhook/v3.option_username") %>
17
+ </dt>
18
+ <dd class="mt-1 text-sm text-gray-900">
19
+ <div class="flex items-center gap-2">
20
+ <p class="text-sm truncate">
21
+ <%= mask integration.option_username %>
22
+ </p>
23
+ </div>
24
+ </dd>
25
+ </div>
26
+
27
+ <div class="sm:col-span-1">
28
+ <dt class="text-sm font-medium text-gray-500">
29
+ <%= t("activerecord.attributes.pager_tree/integrations/outgoing_webhook/v3.option_password") %>
30
+ </dt>
31
+ <dd class="mt-1 text-sm text-gray-900">
32
+ <div class="flex items-center gap-2">
33
+ <p class="text-sm truncate">
34
+ <%= mask integration.option_password %>
35
+ </p>
36
+ </div>
37
+ </dd>
38
+ </div>
39
+
40
+ <%
41
+ opts = [
42
+ :alert_created,
43
+ :alert_open,
44
+ :alert_acknowledged,
45
+ :alert_rejected,
46
+ :alert_timeout,
47
+ :alert_resolved,
48
+ :alert_dropped,
49
+ :alert_handoff,
50
+ ]
51
+ %>
52
+ <% opts.each do |opt| %>
53
+ <div class="sm:col-span-1">
54
+ <dt class="text-sm font-medium text-gray-500">
55
+ <%= t("activerecord.attributes.pager_tree/integrations/outgoing_webhook/v3.option_#{opt.to_s}") %>
56
+ </dt>
57
+ <dd class="mt-1 text-sm text-gray-900">
58
+ <%= render partial: "shared/components/badge_enabled", locals: { enabled: integration.send("option_#{opt.to_s}") } %>
59
+ </dd>
60
+ </div>
61
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <div class="password-visibility-toggle">
2
+ <%= tag.button data: { action: "password-visibility#toggle", password_visibility_target: "icon"} do %>
3
+ <%= fa_icon "eye" %>
4
+ <% end %>
5
+ <%= tag.button class: "hidden", data: { action: "password-visibility#toggle", password_visibility_target: "icon"} do %>
6
+ <%= fa_icon "eye-slash" %>
7
+ <% end %>
8
+ </div>
@@ -0,0 +1,87 @@
1
+ en:
2
+ pager_tree:
3
+ integrations:
4
+ common:
5
+ default: "default"
6
+ none: "none"
7
+ apex_ping:
8
+ v3:
9
+ form_options:
10
+ email:
11
+ v3:
12
+ form_options:
13
+ option_allow_spam_hint_html: "Allow emails marked as SPAM to create alerts"
14
+ option_dedup_threads_hint_html: "Ignore emails from same thread (ex: Prevents new alerts for replys on emails (aka: RE:RE:RE...))"
15
+ live_call_routing:
16
+ twilio:
17
+ v3:
18
+ form_options:
19
+ option_account_sid_hint_html: "Twilio Account SID"
20
+ option_api_key_hint_html: "Twilio API Key"
21
+ option_api_secret_hint_html: "Twilio API Secret"
22
+ option_welcome_media_hint_html: "A recording that will be played first to caller (ex: \"Hello, you have reached the Devop's on-call support line.\")"
23
+ option_please_wait_media_hint_html: "A recording to be played before wait music music (default: <a href='https://app.pagertree.com/assets/sounds/please-wait.mp3' target='_blank'>Please wait while you are being connected.</a>)"
24
+ option_music_media_hint_html: "A recording or wait music to be played while the caller waits for someone to acknowledge the alert (default: <a href='http://com.twilio.sounds.music.s3.amazonaws.com/oldDog_-_endless_goodbye_%28instr.%29.mp3' target='_blank'>Endless Goodbye</a>)"
25
+ option_connect_now_media_hint_html: "A recording played before connecting the caller to the acknowledger (default: <a href='https://app.pagertree.com/assets/sounds/you-are-now-being-connected.mp3' target='_blank'>You are now being connected.</a>)"
26
+ option_no_answer_media_hint_html: "A recording to be played when no one answers"
27
+ option_no_answer_thank_you_media_hint_html: "A recording played after the caller leaves a voicemail"
28
+ option_force_input_hint_html: "Force the caller to select a team (even if the integration only has one team)"
29
+ option_record_hint_html: "Record a voicemail when no one acknowledges the call"
30
+ option_record_emails_list_hint_html: "List of email addresses to notify when a voicemail has been recorded"
31
+ outgoing_webhook:
32
+ v3:
33
+ form_options:
34
+ option_webhook_url_hint_html: "URL to POST to"
35
+ option_username_hint_html: "Basic auth username (optional)"
36
+ option_password_hint_html: "Basic auth password (optional)"
37
+ option_alert_created_hint_html: "Send when the alert is created (before its routed)"
38
+ option_alert_open_hint_html: "Send when the alert is marked open (it has been routed)"
39
+ option_alert_acknowledged_hint_html: "Send when a user has acknowledged the alert"
40
+ option_alert_rejected_hint_html: "Send when a user has rejected the alert"
41
+ option_alert_timeout_hint_html: "Send when the alert has timed out a layer"
42
+ option_alert_resolved_hint_html: "Send when the alert is marked resolved"
43
+ option_alert_dropped_hint_html: "Send when the alert is dropped"
44
+ option_alert_handoff_hint_html: "Send when the alert has been handed off"
45
+ option_template_hint_html: "A handlebars template describing the body that should be posted. See <a href='https://pagertree.com/knowledge-base/outgoing-webhooks/#custom-format' target='_blank'>docs</a> for details."
46
+ option_send_linked_hint_html: "Send linked data (source, source_log, user, team)"
47
+ # SCAFFOLD_INTEGRATION
48
+
49
+
50
+ activerecord:
51
+ attributes:
52
+ "pager_tree/integrations/integration":
53
+ option_title_template_enabled: "Title Template"
54
+ option_description_template_enabled: "Description Template"
55
+ "pager_tree/integrations/apex_ping/v3":
56
+ option_api_key: "API Key"
57
+ "pager_tree/integrations/email/v3":
58
+ option_allow_spam: "Allow Spam"
59
+ option_dedup_threads: "Dedup Threads"
60
+ "pager_tree/integrations/outgoing_webhook/v3":
61
+ option_webhook_url: "URL"
62
+ option_username: "Username"
63
+ option_password: "Password"
64
+ option_alert_created: "alert.created"
65
+ option_alert_open: "alert.open"
66
+ option_alert_acknowledged: "alert.acknowledged"
67
+ option_alert_rejected: "alert.rejected"
68
+ option_alert_timeout: "alert.timeout"
69
+ option_alert_resolved: "alert.resolved"
70
+ option_alert_dropped: "alert.dropped"
71
+ option_alert_handoff: "alert.handoff"
72
+ option_template: "JSON Template"
73
+ option_send_linked: "Send Linked"
74
+ "pager_tree/integrations/live_call_routing/twilio/v3":
75
+ option_account_sid: "Twilio Account SID"
76
+ option_api_key: "Twilio API Key"
77
+ option_api_secret: "Twilio API Secret"
78
+ option_welcome_media: "Welcome Recording"
79
+ option_please_wait_media: "Before Wait Music Recording"
80
+ option_music_media: "Wait Music Recording"
81
+ option_connect_now_media: "Before Connect Recording"
82
+ option_no_answer_media: "Voicemail Greeting Recording"
83
+ option_no_answer_thank_you_media: "After Voicemail Recording"
84
+ option_force_input: "Force Caller Input"
85
+ option_record: "Voicemail"
86
+ option_record_emails_list: "Voicemail Emails"
87
+ # SCAFFOLD_ACTIVE_RECORD
data/config/routes.rb ADDED
@@ -0,0 +1,12 @@
1
+ PagerTree::Integrations::Engine.routes.draw do
2
+ namespace :live_call_routing do
3
+ namespace :twilio do
4
+ resources :v3, only: [], controller: "v3" do
5
+ member do
6
+ get :music
7
+ post :queue_status
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end