pager_tree-integrations 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/README.md +61 -0
- data/Rakefile +8 -0
- data/app/assets/config/pager_tree_integrations_manifest.js +1 -0
- data/app/assets/stylesheets/pager_tree/integrations/application.css +15 -0
- data/app/controllers/pager_tree/integrations/application_controller.rb +6 -0
- data/app/controllers/pager_tree/integrations/live_call_routing/twilio/v3_controller.rb +49 -0
- data/app/helpers/pager_tree/integrations/application_helper.rb +9 -0
- data/app/jobs/pager_tree/integrations/application_job.rb +6 -0
- data/app/jobs/pager_tree/integrations/outgoing_webhook_job.rb +12 -0
- data/app/mailers/pager_tree/integrations/application_mailer.rb +8 -0
- data/app/models/pager_tree/integrations/additional_datum.rb +41 -0
- data/app/models/pager_tree/integrations/alert.rb +60 -0
- data/app/models/pager_tree/integrations/apex_ping/v3.rb +69 -0
- data/app/models/pager_tree/integrations/application_record.rb +7 -0
- data/app/models/pager_tree/integrations/email/v3.rb +150 -0
- data/app/models/pager_tree/integrations/integration.rb +130 -0
- data/app/models/pager_tree/integrations/live_call_routing/twilio/v3.rb +332 -0
- data/app/models/pager_tree/integrations/outgoing_event.rb +25 -0
- data/app/models/pager_tree/integrations/outgoing_webhook/v3.rb +75 -0
- data/app/models/pager_tree/integrations/outgoing_webhook_delivery/hook_relay.rb +98 -0
- data/app/models/pager_tree/integrations/outgoing_webhook_delivery.rb +22 -0
- data/app/views/layouts/pager_tree/integrations/application.html.erb +15 -0
- data/app/views/pager_tree/integrations/apex_ping/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/apex_ping/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/email/v3/_form_options.html.erb +11 -0
- data/app/views/pager_tree/integrations/email/v3/_show_options.html.erb +17 -0
- data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_form_options.html.erb +80 -0
- data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_show_options.html.erb +181 -0
- data/app/views/pager_tree/integrations/outgoing_webhook/v3/_form_options.html.erb +50 -0
- data/app/views/pager_tree/integrations/outgoing_webhook/v3/_show_options.html.erb +61 -0
- data/app/views/shared/_password_visibility_button.html.erb +8 -0
- data/config/locales/en.yml +87 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20220208195853_create_active_storage_tables.active_storage.rb +58 -0
- data/db/migrate/20220208195854_create_deferred_request_deferred_requests.deferred_request.rb +13 -0
- data/db/migrate/20220208195855_create_pager_tree_integrations_integrations.rb +10 -0
- data/db/migrate/20220215200426_create_pager_tree_integrations_outgoing_webhook_deliveries.rb +12 -0
- data/lib/generators/integration/USAGE +11 -0
- data/lib/generators/integration/integration_generator.rb +14 -0
- data/lib/generators/integration/templates/_form_options.html.erb.tt +8 -0
- data/lib/generators/integration/templates/_show_options.html.erb.tt +14 -0
- data/lib/generators/integration/templates/model.rb.tt +64 -0
- data/lib/generators/integration/templates/test.rb.tt +87 -0
- data/lib/pager_tree/integrations/engine.rb +11 -0
- data/lib/pager_tree/integrations/env.rb +36 -0
- data/lib/pager_tree/integrations/version.rb +5 -0
- data/lib/pager_tree/integrations.rb +29 -0
- data/lib/tasks/pager_tree/integrations_tasks.rake +4 -0
- 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>
|
File without changes
|
File without changes
|
@@ -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