diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9504f22a04a..8d313386cb9 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -107,6 +107,14 @@ module ApplicationHelper AgeWords.age_words(secs) end + def short_date(dt) + if dt.year == Time.now.year + I18n.l(dt, format: :short_no_year) + else + I18n.l(dt, format: :date_only) + end + end + def guardian @guardian ||= Guardian.new(current_user) end diff --git a/app/helpers/user_notifications_helper.rb b/app/helpers/user_notifications_helper.rb index 8fca6d8ce26..e65ea04a6c1 100644 --- a/app/helpers/user_notifications_helper.rb +++ b/app/helpers/user_notifications_helper.rb @@ -48,9 +48,9 @@ module UserNotificationsHelper doc.css('div').first end - def email_excerpt(html, posts_count) + def email_excerpt(html, posts_count=nil) # only include 1st paragraph when more than 1 posts - html = first_paragraph_from(html).to_s if posts_count > 1 + html = first_paragraph_from(html).to_s if posts_count.nil? || posts_count > 1 PrettyText.format_for_email(html).html_safe end @@ -93,4 +93,8 @@ module UserNotificationsHelper PrettyText.format_for_email(I18n.t(i18n_key)).html_safe end + def email_image_url(basename) + UrlHelper.absolute("#{Discourse.base_uri}/images/emails/#{basename}") + end + end diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb index 79fd5d548fd..6a6e3acb141 100644 --- a/app/mailers/user_notifications.rb +++ b/app/mailers/user_notifications.rb @@ -99,28 +99,22 @@ class UserNotifications < ActionMailer::Base @last_seen_at = short_date(user.last_seen_at || user.created_at) - # A list of topics to show the user - @featured_topics = Topic.for_digest(user, min_date, limit: SiteSetting.digest_topics, top_order: true).to_a + @preheader_text = I18n.t('user_notifications.digest.preheader', last_seen_at: @last_seen_at) - # Don't send email unless there is content in it - if @featured_topics.present? - featured_topic_ids = @featured_topics.map(&:id) + @new_topics_count = Topic.new_since_last_seen(user, min_date).count + @unread_messages = user.unread_private_messages + @unread_notifications = user.unread_notifications - @new_topics_since_seen = Topic.new_since_last_seen(user, min_date, featured_topic_ids).count - if @new_topics_since_seen > SiteSetting.digest_topics - category_counts = Topic.new_since_last_seen(user, min_date, featured_topic_ids).group(:category_id).count + topics_for_digest = Topic.for_digest(user, min_date, limit: SiteSetting.digest_topics + 3, top_order: true).to_a - @new_by_category = [] - if category_counts.present? - Category.where(id: category_counts.keys).each do |c| - @new_by_category << [c, category_counts[c.id]] - end - @new_by_category.sort_by! {|c| -c[1]} - end - end + @popular_topics = topics_for_digest[0,SiteSetting.digest_topics] + @popular_posts = SiteSetting.digest_posts > 0 ? Post.where("post_number > ?", 1).where("score > ?", 5.0).order("score DESC").limit(SiteSetting.digest_posts) : [] + @other_new_for_you = topics_for_digest.size > SiteSetting.digest_topics ? topics_for_digest[SiteSetting.digest_topics..-1] : [] - @featured_topics, @new_topics = @featured_topics[0..4], @featured_topics[5..-1] + topic_lookup = TopicUser.lookup_for(user, @other_new_for_you) + @other_new_for_you.each { |t| t.user_data = topic_lookup[t.id] } + if @popular_topics.present? opts = { from_alias: I18n.t('user_notifications.digest.from', site_name: SiteSetting.title), subject: I18n.t('user_notifications.digest.subject_template', site_name: @site_name, date: short_date(Time.now)), @@ -132,6 +126,7 @@ class UserNotifications < ActionMailer::Base end end + def user_replied(user, opts) opts[:allow_reply_by_email] = true opts[:use_site_subject] = true @@ -421,7 +416,8 @@ class UserNotifications < ActionMailer::Base @date = short_date(Time.now) @base_url = Discourse.base_url @site_name = SiteSetting.email_prefix.presence || SiteSetting.title - @header_color = ColorScheme.hex_for_name('header_background') + @header_color = ColorScheme.hex_for_name('header_primary') + @header_bgcolor = ColorScheme.hex_for_name('header_background') @anchor_color = ColorScheme.hex_for_name('tertiary') @markdown_linker = MarkdownLinker.new(@base_url) @unsubscribe_key = UnsubscribeKey.create_key_for(@user, "digest") diff --git a/app/models/topic.rb b/app/models/topic.rb index d328c5c45e9..a8786ac781f 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -373,9 +373,9 @@ class Topic < ActiveRecord::Base end # Using the digest query, figure out what's new for a user since last seen - def self.new_since_last_seen(user, since, featured_topic_ids) + def self.new_since_last_seen(user, since, featured_topic_ids=nil) topics = Topic.for_digest(user, since) - topics.where("topics.id NOT IN (?)", featured_topic_ids) + featured_topic_ids ? topics.where("topics.id NOT IN (?)", featured_topic_ids) : topics end def meta_data=(data) diff --git a/app/views/user_notifications/digest.html.erb b/app/views/user_notifications/digest.html.erb index d8b7faf7bd1..0e5aefa9a64 100644 --- a/app/views/user_notifications/digest.html.erb +++ b/app/views/user_notifications/digest.html.erb @@ -1,88 +1,403 @@ - - - <%- if I18n.t('user_notifications.digest.custom.html.header').present? %> - + + + + + + + + + + + + + + +
- <%= raw(t 'user_notifications.digest.custom.html.header') %> -
+ + + <%= SiteSetting.title %> <%- end %> - - - - + +
+ + + <%- if logo_url.blank? %> + <%= SiteSetting.title %> <%- else %> - - - <%- if logo_url.blank? %> - <%= SiteSetting.title %> - <%- else %> - - <%- end %> - -
- <%= raw(t 'user_notifications.digest.why', site_link: html_site_link(@anchor_color), last_seen_at: @last_seen_at) %> + - <%- if @featured_topics.present? %> -
-

<%=t 'user_notifications.digest.top_topics' %>

- - - <%- @featured_topics.each_with_index do |t, i| %> - - - <%- if t.best_post.present? && !t.best_post.user_deleted %> -
- <%= email_excerpt(t.best_post.cooked, @featured_topics.size) %> -
- <%- end %> - - <%= digest_custom_html("below_post_#{i+1}") %> - - <%- if i < @featured_topics.size - 1 %><% end %> - - <%- end %> - <%- end %> - - <%= digest_custom_html("above_popular_topics") %> - - <%- if @new_topics.present? %> -
-

<%=t 'user_notifications.digest.other_new_topics' %>

- - <%- @new_topics.each do |t| %> - - <%- end -%> - - <%- end -%> - - <%= digest_custom_html("below_popular_topics") %> - - <%- if @new_topics_since_seen > 0 %> - <%- if @new_by_category.present? %> -

<%= t('user_notifications.digest.more_topics_category', last_seen_at: @last_seen_at, new_topics_since_seen: @new_topics_since_seen) %>

-
- <%- @new_by_category.first(10).each do |c| %> - - <%= c[0].name %> <%= c[1] %> - - <%- end %> -
- <%- else %> -

<%= t('user_notifications.digest.more_topics', last_seen_at: @last_seen_at, new_topics_since_seen: @new_topics_since_seen) %>

- <%- end %> - <%- end -%> -
+ + + + + + +
+
+ + + + + + +
 
+
+
+ + + + + + +
+ +
+
<%=t 'user_notifications.digest.since_last_visit' %>
+ + + + + + + + + + + + + + + + +
+ <%= @new_topics_count -%> + + <%= @unread_messages -%> + + <%= @unread_notifications -%> +
+ <%=t 'user_notifications.digest.new_topics' %> + + <%=t 'user_notifications.digest.unread_messages' %> + + <%=t 'user_notifications.digest.unread_notifications' %> +
+ +
<%=t 'user_notifications.digest.popular_topics' %>
+ + +
+ + + + + + +
+ +<% @popular_topics.each_with_index do |t, i| %> + + + + + + + + +
+

+ <%= category_badge(t.category, inline_style: true, absolute_url: true) %> +

+
+

+ <%= short_date(t.created_at) %> +

+
+ + + + + + + <% if t.image_url.present? %> + + <% end %> + + + +
;"> +

+ + <%= t.title -%> + +

+
+ +
+ + + + + + + + +
+ + +
<%= t.user.try(:username) -%>
+ <% if t.user.try(:name).present? %> +

<%= t.user.name -%>

+ <% end %> +
+ +<%- if t.first_post.present? && !t.first_post.user_deleted %> + + + + + + +
+ <%= email_excerpt(t.first_post.cooked) %> +
+<%- end %> + + + + + + + + + + +
+ +

<%= t.like_count -%>

+
+ +

<%= t.posts_count - 1 -%>

+
+ <% t.posters_summary.each do |ps| %> + <% if ps.user %> + + <% end %> + <% end %> + + + <%=t 'user_notifications.digest.join_the_discussion' %> + +
+
+ + +
 
+
+ + +<%= digest_custom_html("below_post_#{i+1}") %> + +<% end %> + +
+
+ +
+ + + + + + +
 
+
+
+ +<% if @popular_posts.present? %> + + + + + +
+

+ <%=t 'user_notifications.digest.popular_posts' %> +

+
+ + + + + + + +
  + +<% @popular_posts.each do |post| %> + + + + + + + + +
+ <%= email_excerpt(post.cooked) %> +
+ + + + + + + +
+ +
+ + + + + + + + + +
+ + +
<%= post.user.username -%>
+

<%= post.user.name -%>

+
+

+ <%=t 'user_notifications.digest.from_topic_label' %> + <%= post.topic.title -%> +

+ + <%=t 'user_notifications.digest.join_the_discussion' %> + +
+ +
+ + +
 
+
+ + +<% end %> + +<% end %> + + + +<% if @other_new_for_you.present? %> +
<%=t 'user_notifications.digest.more_new' %>
+ + +<%= digest_custom_html("above_popular_topics") %> + + + + +<% @other_new_for_you.each do |t| %> + + + + + + + + + + + + + + + +<% end %> + + +
+

+ <%= t.user_data ? (t.highest_post_number - t.user_data.last_read_post_number) : t.highest_post_number %> +

+
+ + <%= t.title -%> + + +

<%= t.category.try(:name) -%>

+
+ <% t.posters_summary[0,2].each do |ps| %> + <% if ps.user %> + + <% end %> + <% end %> + + +

<%= t.like_count -%>

+
+ +

<%= t.posts_count - 1 -%>

+
 
+ +<%= digest_custom_html("below_popular_topics") %> + +<% end %> + + +
 
+ + + <%= digest_custom_html("above_footer") %> <%= digest_custom_html("below_footer") %> + + +
                                    +                        
+ + + + \ No newline at end of file diff --git a/app/views/user_notifications/digest.text.erb b/app/views/user_notifications/digest.text.erb index 07d5c4870e4..b1c92a07bfd 100644 --- a/app/views/user_notifications/digest.text.erb +++ b/app/views/user_notifications/digest.text.erb @@ -3,10 +3,16 @@ site_link: site_link, last_seen_at: @last_seen_at) %> -<%- if @featured_topics.present? %> -### <%=t 'user_notifications.digest.top_topics' %> +<%= @new_topics_count -%> <%=t 'user_notifications.digest.new_topics' %> +<%= @unread_messages -%> <%=t 'user_notifications.digest.unread_messages' %> +<%= @unread_notifications -%> <%=t 'user_notifications.digest.unread_notifications' %> -<%- @featured_topics.each_with_index do |t,i| %> +-------------------------------------------------------------------------------- + +<%- if @popular_topics.present? %> +### <%=t 'user_notifications.digest.popular_topics' %> + +<%- @popular_topics.each_with_index do |t,i| %> <%= raw(@markdown_linker.create(t.title, t.relative_url)) %> <%- if t.best_post.present? %> @@ -18,14 +24,26 @@ <%- end %> <%- end %> <%= digest_custom_text("above_popular_topics") %> -<%- if @new_topics.present? %> -**<%=t 'user_notifications.digest.other_new_topics' %>** -<%- @new_topics.each do |t| %> +<%- if @popular_posts.present? %> +### <%=t 'user_notifications.digest.popular_posts' %> + +<%- @popular_posts.each_with_index do |post,i| %> +<%= post.user.username -%> <%=t 'user_notifications.digest.from_topic_label' -%> <%= raw(@markdown_linker.create(post.topic.title, post.topic.relative_url)) %> + + <%= raw(post.excerpt(1000, strip_links: true, text_entities: true, markdown_images: true)) %> +-------------------------------------------------------------------------------- + +<%- end %> +<%- end %> + +<%- if @other_new_for_you.present? %> +**<%=t 'user_notifications.digest.more_new' %>** + +<%- @other_new_for_you.each do |t| %> * <%= raw(@markdown_linker.create(t.title, t.relative_url)) %> - <%= t.posts_count %> - <%- if t.category %>[<%= t.category.name %>]<%- end %> <%- end -%> - -<%- end -%> +<%- end %> <%= digest_custom_text("below_popular_topics") %> @@ -38,4 +56,4 @@ <%= raw(@markdown_linker.references) %> -<%= digest_custom_text("below_footer") %> \ No newline at end of file +<%= digest_custom_text("below_footer") %> diff --git a/app/views/user_notifications/mailing_list.html.erb b/app/views/user_notifications/mailing_list.html.erb index c6b4240542b..749ee60867e 100644 --- a/app/views/user_notifications/mailing_list.html.erb +++ b/app/views/user_notifications/mailing_list.html.erb @@ -1,7 +1,7 @@
-
+ <% if logo_url.blank? %> <%= SiteSetting.title %> diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 26622bfe558..eeef7a6c84e 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1279,6 +1279,7 @@ en: default_avatars: "URLs to avatars that will be used by default for new users until they change them." automatically_download_gravatars: "Download Gravatars for users upon account creation or email change." digest_topics: "The maximum number of topics to display in the email summary." + digest_posts: "The maximum number of popular posts to display in the email summary." digest_min_excerpt_length: "Minimum post excerpt in the email summary, in characters." delete_digest_email_after_days: "Suppress summary emails for users not seen on the site for more than (n) days." digest_suppress_categories: "Suppress these categories from summary emails." @@ -2427,16 +2428,21 @@ en: digest: why: "A brief summary of %{site_link} since your last visit on %{last_seen_at}" + since_last_visit: "Since your last visit" + new_topics: "New Topics" + unread_messages: "Unread Messages" + unread_notifications: "Unread Notifications" + popular_topics: "Popular Topics" + follow_topic: "Follow this topic" + join_the_discussion: "Join the discussion" + popular_posts: "Popular Posts" + from_topic_label: "From" + more_new: "New in topics and categories you follow" subject_template: "[%{site_name}] Summary" - new_activity: "New activity on your topics and posts:" - top_topics: "Popular posts" - other_new_topics: "Popular topics" unsubscribe: "This summary is sent from %{site_link} when we haven't seen you in a while. To unsubscribe %{unsubscribe_link}." click_here: "click here" from: "%{site_name} summary" - read_more: "Read More" - more_topics: "There were %{new_topics_since_seen} other new topics." - more_topics_category: "More new topics:" + preheader: "A brief summary since your last visit on %{last_seen_at}" custom: html: header: '' diff --git a/config/site_settings.yml b/config/site_settings.yml index 0005bc48ba8..9be481803ec 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -584,7 +584,10 @@ email: private_email_time_window_seconds: 20 email_posts_context: 5 digest_min_excerpt_length: 100 - digest_topics: 20 + digest_topics: + default: 5 + min: 1 + digest_posts: 3 delete_digest_email_after_days: 365 digest_suppress_categories: type: category_list diff --git a/public/images/emails/comment.png b/public/images/emails/comment.png new file mode 100644 index 00000000000..77c849f282f Binary files /dev/null and b/public/images/emails/comment.png differ diff --git a/public/images/emails/heart.png b/public/images/emails/heart.png new file mode 100644 index 00000000000..f1fb65dad57 Binary files /dev/null and b/public/images/emails/heart.png differ diff --git a/public/images/emails/right_triangle.png b/public/images/emails/right_triangle.png new file mode 100644 index 00000000000..d377e840e4f Binary files /dev/null and b/public/images/emails/right_triangle.png differ