FEATURE: Allow users to tone down digest emails (#7353)

FEATURE: Allow users to tone down digest emails (#7353)

  • FEATURE: Allow user to tone down email digest insteand of only unsubscribing

  • Reordered options and select the next slowest frequency by default

diff --git a/app/controllers/email_controller.rb b/app/controllers/email_controller.rb
index b4c8f0b..7f24d0f 100644
--- a/app/controllers/email_controller.rb
+++ b/app/controllers/email_controller.rb
@@ -16,6 +16,7 @@ class EmailController < ApplicationController
       if @user = key.user
         post = key.post
         @topic = post&.topic || key.topic
+        @digest_unsubscribe = !@topic && !SiteSetting.disable_digest_emails
         @type = key.unsubscribe_key_type
         @not_found = false
 
@@ -35,6 +36,8 @@ class EmailController < ApplicationController
                 .count
             end
           end
+        else
+          @digest_frequencies = digest_frequencies(@user)
         end
       end
     end
@@ -85,8 +88,13 @@ class EmailController < ApplicationController
       updated = true
     end
 
-    if params["disable_digest_emails"]
-      user.user_option.update_columns(email_digests: false)
+    if params['digest_after_minutes']
+      digest_frequency = params['digest_after_minutes'].to_i
+
+      user.user_option.update_columns(
+        digest_after_minutes: digest_frequency,
+        email_digests: digest_frequency.positive?
+      )
       updated = true
     end
 
@@ -123,4 +131,29 @@ class EmailController < ApplicationController
     @topic = topic if topic && Guardian.new(nil).can_see?(topic)
   end
 
+  private
+
+  def digest_frequencies(user)
+    frequency_in_minutes = user.user_option.digest_after_minutes
+    frequencies = DigestEmailSiteSetting.values.dup
+    never = frequencies.delete_at(0)
+    allowed_frequencies = %w[never weekly every_month every_six_months]
+
+    result = frequencies.reduce(frequencies: [], current: nil, selected: nil, take_next: false) do |memo, v|
+      memo[:current] = v[:name] if v[:value] == frequency_in_minutes
+      next(memo) unless allowed_frequencies.include?(v[:name])
+
+      memo.tap do |m|
+        m[:selected] = v[:value] if m[:take_next]
+        m[:frequencies] << [I18n.t("unsubscribe.digest_frequency.#{v[:name]}"), v[:value]]
+        m[:take_next] = !m[:take_next] && m[:current]
+      end
+    end
+
+    result.slice(:frequencies, :current, :selected).tap do |r|
+      r[:frequencies] << [I18n.t("unsubscribe.digest_frequency.#{never[:name]}"), never[:value]]
+      r[:selected] ||= never[:value]
+      r[:current] ||= never[:name]
+    end
+  end
 end
diff --git a/app/views/email/unsubscribe.html.erb b/app/views/email/unsubscribe.html.erb
index 762cd8a..aee145e 100644
--- a/app/views/email/unsubscribe.html.erb
+++ b/app/views/email/unsubscribe.html.erb
@@ -52,15 +52,26 @@
         </p>
       <% end %>
 
-      <% if !@topic %>
-        <% unless SiteSetting.disable_digest_emails %>
+      <% if @digest_unsubscribe %>
           <p>
-          <label>
-          <%= check_box_tag 'disable_digest_emails', 1, @type=="digest" %>
-          <%= t 'unsubscribe.disable_digest_emails' %>
-          </label>
+          
+          <% if @digest_frequencies[:current] %>
+            <h3>
+            <%= t(
+              'unsubscribe.digest_frequency.title', 
+              frequency: t("unsubscribe.digest_frequency.#{@digest_frequencies[:current]}")
+            ) %>
+            </h3>
+            <br/>
+          <% end %>
+          
+          <label><%= t 'unsubscribe.digest_frequency.select_title' %></label>
+          <%= 
+            select_tag :digest_after_minutes, 
+            options_for_select(@digest_frequencies[:frequencies], @digest_frequencies[:selected]), 
+            class: 'combobox' 
+          %>
           </p>
-        <% end %>
       <% end %>
 
       <p>
@@ -71,7 +82,8 @@
       </p>
 
       <br/>
-      <%= submit_tag t('unsubscribe.title'), class: 'btn btn-danger' %>
+      <% text = @type=='digest' ? t('unsubscribe.submit') : t('unsubscribe.title') %>
+      <%= submit_tag text, class: 'btn btn-danger' %>
     <%- end %>
 
 
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 68d599d..a008d44 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -893,8 +893,8 @@ en:
         remove: "This topic is no longer a banner. It will no longer appear at the top of every page."
 
   unsubscribed:
-    title: "Unsubscribed!"
-    description: "<b>%{email}</b> has been unsubscribed. To change your email settings <a href='%{url}'>visit your user preferences</a>."
+    title: "Email preferences updated!"
+    description: "email preferences for <b>%{email}</b> were updated. To change your email settings <a href='%{url}'>visit your user preferences</a>."
     topic_description: "To re-subscribe to %{link}, use the notification control at the bottom or right of the topic."
     private_topic_description: "To re-subscribe, use the notification control at the bottom or right of the topic."
 
@@ -904,11 +904,23 @@ en:
     mute_topic: "Mute all notifications for this topic, %{link}"
     unwatch_category: "Stop watching all topics in %{category}"
     mailing_list_mode: "Turn off mailing list mode"
-    disable_digest_emails: "Stop sending me summary emails"
     all: "Don't send me any mail from %{sitename}"
     different_user_description: "You are currently logged in as a different user than the one we emailed. Please log out, or enter anonymous mode, and try again."
     not_found_description: "Sorry, we couldn't find this unsubscribe. It's possible the link in your email has expired?"
     log_out: "Log Out"
+    submit: "Save preferences"
+    digest_frequency:
+      title: "You are receiving summary emails %{frequency}"
+      select_title: 'Set summary emails frequency to:'
+      
+      never: 'never'
+      every_30_minutes: "every 30 minutes"
+      every_hour: "hourly"
+      daily: "daily"
+      weekly: "weekly"
+      every_month: "every month"
+      every_six_months: "every six months"
+
 
   user_api_key:
     title: "Authorize application access"
diff --git a/spec/requests/email_controller_spec.rb b/spec/requests/email_controller_spec.rb
index df4be4f..3af77b3 100644
--- a/spec/requests/email_controller_spec.rb
+++ b/spec/requests/email_controller_spec.rb
@@ -11,10 +11,10 @@ RSpec.describe EmailController do
       expect(response.status).to eq(404)
     end
 
-    it 'can fully unsubscribe' do
-      user = Fabricate(:user)
-      key = UnsubscribeKey.create_key_for(user, "all")
+    let(:user) { Fabricate(:user) }
+    let(:key) { UnsubscribeKey.create_key_for(user, "all") }
 
+    it 'can fully unsubscribe' do
       user.user_option.update_columns(email_digests: true,
                                       email_level: UserOption.email_level_types[:never],
                                       email_messages_level: UserOption.email_level_types[:never])
@@ -37,9 +37,6 @@ RSpec.describe EmailController do
     end
 
     it 'can disable mailing list' do
-      user = Fabricate(:user)
-      key = UnsubscribeKey.create_key_for(user, "all")
-
       user.user_option.update_columns(mailing_list_mode: true)
 
       post "/email/unsubscribe/#{key}.json",
@@ -52,19 +49,31 @@ RSpec.describe EmailController do
       expect(user.user_option.mailing_list_mode).to eq(false)
     end
 
-    it 'can disable digest' do
-      user = Fabricate(:user)
-      key = UnsubscribeKey.create_key_for(user, "all")
+    it 'Can change digest frequency' do
+      weekly_interval_minutes = 10080
+      user.user_option.update_columns(email_digests: true, digest_after_minutes: 0)
 
-      user.user_option.update_columns(email_digests: true)
+      post "/email/unsubscribe/#{key}.json",
+        params: { digest_after_minutes: weekly_interval_minutes.to_s }
+
+      expect(response.status).to eq(302)
+
+      user.user_option.reload
+
+      expect(user.user_option.digest_after_minutes).to eq(weekly_interval_minutes)
+    end
+
+    it 'Can disable email digests setting frequency to zero' do
+      user.user_option.update_columns(email_digests: true, digest_after_minutes: 10080)
 
       post "/email/unsubscribe/#{key}.json",

[... diff too long, it was truncated ...]

GitHub sha: 12a5c69a

1 Like