diff --git a/app/controllers/email_settings_controller.rb b/app/controllers/email_smtp_settings_controller.rb
similarity index 94%
rename from app/controllers/email_settings_controller.rb
rename to app/controllers/email_smtp_settings_controller.rb
index 2c39053c..a8c76692 100644
--- a/app/controllers/email_settings_controller.rb
+++ b/app/controllers/email_smtp_settings_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class EmailSettingsController < ApplicationController
+class EmailSmtpSettingsController < ApplicationController
before_action :load_encrypted_config
authorize_resource :encrypted_config, only: :index
authorize_resource :encrypted_config, parent: false, only: :create
diff --git a/app/controllers/notifications_settings_controller.rb b/app/controllers/notifications_settings_controller.rb
new file mode 100644
index 00000000..2189ccda
--- /dev/null
+++ b/app/controllers/notifications_settings_controller.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+class NotificationsSettingsController < ApplicationController
+ before_action :load_bcc_config, only: :index
+ before_action :load_reminder_config, only: :index
+ authorize_resource :bcc_config, only: :index
+ authorize_resource :reminder_config, only: :index
+
+ before_action :build_account_config, only: :create
+ authorize_resource :account_config, only: :create
+
+ def index; end
+
+ def create
+ if @account_config.save
+ redirect_back fallback_location: settings_notifications_path, notice: 'Changes have been saved'
+ else
+ redirect_back fallback_location: settings_notifications_path, alert: 'Unable to save'
+ end
+ end
+
+ private
+
+ def build_account_config
+ @account_config =
+ AccountConfig.find_or_initialize_by(account: current_account, key: email_config_params[:key])
+
+ @account_config.assign_attributes(email_config_params)
+ end
+
+ def load_bcc_config
+ @bcc_config =
+ AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::BCC_EMAILS)
+ end
+
+ def load_reminder_config
+ @reminder_config =
+ AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::SUBMITTER_REMAILERS)
+ end
+
+ def email_config_params
+ params.require(:account_config).permit!.tap do |attrs|
+ attrs[:key] = nil unless attrs[:key].in?([AccountConfig::BCC_EMAILS, AccountConfig::SUBMITTER_REMAILERS])
+ end
+ end
+end
diff --git a/app/jobs/process_submitter_completion_job.rb b/app/jobs/process_submitter_completion_job.rb
index 3f3da35c..1da7a6c5 100644
--- a/app/jobs/process_submitter_completion_job.rb
+++ b/app/jobs/process_submitter_completion_job.rb
@@ -26,7 +26,8 @@ class ProcessSubmitterCompletionJob < ApplicationJob
user = submitter.submission.created_by_user || submitter.template.author
if submitter.template.account.users.exists?(id: user.id)
- bcc = submitter.submission.template.account.account_configs.find_by(key: 'bcc_emails')&.value
+ bcc = submitter.submission.template.account.account_configs
+ .find_by(key: AccountConfig::BCC_EMAILS)&.value
SubmitterMailer.completed_email(submitter, user, bcc:).deliver_later!
end
diff --git a/app/models/account_config.rb b/app/models/account_config.rb
index 45109be3..6f08c2e5 100644
--- a/app/models/account_config.rb
+++ b/app/models/account_config.rb
@@ -24,6 +24,8 @@ class AccountConfig < ApplicationRecord
SUBMITTER_INVITATION_EMAIL_KEY = 'submitter_invitation_email'
SUBMITTER_COMPLETED_EMAIL_KEY = 'submitter_completed_email'
SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY = 'submitter_documents_copy_email'
+ BCC_EMAILS = 'bcc_emails'
+ SUBMITTER_REMAILERS = 'submitter_reminders'
DEFAULT_VALUES = {
SUBMITTER_INVITATION_EMAIL_KEY => {
diff --git a/app/models/submission_event.rb b/app/models/submission_event.rb
index 3756b382..c5be0526 100644
--- a/app/models/submission_event.rb
+++ b/app/models/submission_event.rb
@@ -25,6 +25,7 @@
#
class SubmissionEvent < ApplicationRecord
belongs_to :submission
+ has_one :account, through: :submission
belongs_to :submitter, optional: true
attribute :data, :string, default: -> { {} }
@@ -36,6 +37,7 @@ class SubmissionEvent < ApplicationRecord
enum :event_type, {
send_email: 'send_email',
+ send_reminder_email: 'send_reminder_email',
send_sms: 'send_sms',
open_email: 'open_email',
click_email: 'click_email',
diff --git a/app/views/email_settings/index.html.erb b/app/views/email_smtp_settings/index.html.erb
similarity index 100%
rename from app/views/email_settings/index.html.erb
rename to app/views/email_smtp_settings/index.html.erb
diff --git a/app/views/notifications_settings/_bcc_form.html.erb b/app/views/notifications_settings/_bcc_form.html.erb
new file mode 100644
index 00000000..2459c6e4
--- /dev/null
+++ b/app/views/notifications_settings/_bcc_form.html.erb
@@ -0,0 +1,19 @@
+<%= form_for config, url: settings_notifications_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
+ <%= f.hidden_field :key %>
+
+ <%= f.label :value, class: 'label' do %>
+
+
+ Completed documents BCC address
+
+
+ <%= svg_icon('info_circle', class: 'w-4 h-4') %>
+
+
+ <% end %>
+ <%= f.email_field :value, autocomplete: 'off', class: 'base-input' %>
+
+
+ <%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %>
+
+<% end %>
diff --git a/app/views/notifications_settings/_email_stats.html.erb b/app/views/notifications_settings/_email_stats.html.erb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/views/notifications_settings/_reminder_banner.html.erb b/app/views/notifications_settings/_reminder_banner.html.erb
new file mode 100644
index 00000000..926e952d
--- /dev/null
+++ b/app/views/notifications_settings/_reminder_banner.html.erb
@@ -0,0 +1 @@
+<%= render 'reminder_placeholder' %>
diff --git a/app/views/notifications_settings/_reminder_form.html.erb b/app/views/notifications_settings/_reminder_form.html.erb
new file mode 100644
index 00000000..5c4254c3
--- /dev/null
+++ b/app/views/notifications_settings/_reminder_form.html.erb
@@ -0,0 +1,29 @@
+<%= form_for config, url: settings_notifications_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
+ <%= f.hidden_field :key %>
+
+
+ <%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %>
+
+<% end %>
diff --git a/app/views/notifications_settings/_reminder_placeholder.html.erb b/app/views/notifications_settings/_reminder_placeholder.html.erb
new file mode 100644
index 00000000..9414771e
--- /dev/null
+++ b/app/views/notifications_settings/_reminder_placeholder.html.erb
@@ -0,0 +1,11 @@
+
+ <%= svg_icon('info_circle', class: 'w-6 h-6') %>
+
+
Unlock with DocuSeal Pro
+
+ Send automatic email reminders to your recipients.
+
+ ">Learn More
+
+
+
diff --git a/app/views/notifications_settings/index.html.erb b/app/views/notifications_settings/index.html.erb
new file mode 100644
index 00000000..a106337a
--- /dev/null
+++ b/app/views/notifications_settings/index.html.erb
@@ -0,0 +1,14 @@
+
+ <%= render 'shared/settings_nav' %>
+
+
Email Notifications
+ <%= render 'email_stats' %>
+ <%= render 'bcc_form', config: @bcc_config %>
+
+
Signature Email Reminders
+
+ <%= render 'reminder_banner' %>
+ <%= render 'reminder_form', config: @reminder_config %>
+
+
+
diff --git a/app/views/shared/_settings_nav.html.erb b/app/views/shared/_settings_nav.html.erb
index 15d3ec4a..b4a18b2d 100644
--- a/app/views/shared/_settings_nav.html.erb
+++ b/app/views/shared/_settings_nav.html.erb
@@ -26,6 +26,11 @@
<% end %>
<% end %>
+ <% if can?(:read, AccountConfig) %>
+
+ <%= link_to 'Notifications', settings_notifications_path, class: 'text-base hover:bg-base-300' %>
+
+ <% end %>
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::ESIGN_CERTS_KEY, account: current_account)) %>
<%= link_to 'E-Signature', settings_esign_path, class: 'text-base hover:bg-base-300' %>
diff --git a/app/views/submissions/_email_stats.html.erb b/app/views/submissions/_email_stats.html.erb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/views/submissions/_send_email.html.erb b/app/views/submissions/_send_email.html.erb
index 1bee1be9..a2d197fb 100644
--- a/app/views/submissions/_send_email.html.erb
+++ b/app/views/submissions/_send_email.html.erb
@@ -1,9 +1,12 @@
<% is_smtp_configured = Accounts.can_send_emails?(current_account) %>
- <%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
- <%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !is_smtp_configured, checked: is_smtp_configured %>
-
Send emails
- <% end %>
+
+ <%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
+ <%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !is_smtp_configured, checked: is_smtp_configured %>
+ Send emails
+ <% end %>
+ <%= render 'email_stats' %>
+
<% unless is_smtp_configured %>
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
diff --git a/config/routes.rb b/config/routes.rb
index de9beea5..51eca223 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -78,9 +78,10 @@ Rails.application.routes.draw do
scope '/settings', as: :settings do
unless Docuseal.multitenant?
resources :storage, only: %i[index create], controller: 'storage_settings'
- resources :email, only: %i[index create], controller: 'email_settings'
+ resources :email, only: %i[index create], controller: 'email_smtp_settings'
resources :sms, only: %i[index], controller: 'sms_settings'
end
+ resources :notifications, only: %i[index create], controller: 'notifications_settings'
resource :esign, only: %i[show create new update destroy], controller: 'esign_settings'
resources :users, only: %i[index]
resource :personalization, only: %i[show create], controller: 'personalization_settings'
diff --git a/config/sidekiq.yml b/config/sidekiq.yml
index 36e2a6f3..70450bc2 100644
--- a/config/sidekiq.yml
+++ b/config/sidekiq.yml
@@ -1,6 +1,7 @@
queues:
- [default, 1]
- [mailers, 1]
+ - [recurrent, 1]
production:
:concurrency: 15
diff --git a/lib/account_configs.rb b/lib/account_configs.rb
index 6eaa79a7..4d17acfc 100644
--- a/lib/account_configs.rb
+++ b/lib/account_configs.rb
@@ -1,6 +1,19 @@
# frozen_string_literal: true
module AccountConfigs
+ REMINDER_DURATIONS = {
+ 'one_hour' => '1 hour',
+ 'two_hours' => '2 hours',
+ 'four_hours' => '4 hours',
+ 'eight_hours' => '8 hours',
+ 'twelve_hours' => '12 hours',
+ 'twenty_four_hours' => '24 hours',
+ 'two_days' => '2 days',
+ 'four_days' => '4 days',
+ 'eight_days' => '8 days',
+ 'fifteen_days' => '15 days'
+ }.freeze
+
module_function
def find_or_initialize_for_key(account, key)
diff --git a/lib/submission_events.rb b/lib/submission_events.rb
index 9ec2a6a1..7425f131 100644
--- a/lib/submission_events.rb
+++ b/lib/submission_events.rb
@@ -5,6 +5,7 @@ module SubmissionEvents
EVENT_NAMES = {
send_email: 'Email sent',
+ send_reminder_email: 'Reminder email sent',
send_sms: 'SMS sent',
open_email: 'Email opened',
click_email: 'Email link clicked',