pager_tree-integrations 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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