Merge pull request #9613 from opf/feature/38690-email-design-daily-reminder
[38690] Email design - Daily Reminderspull/9630/head
commit
4a1148acb2
After Width: | Height: | Size: 52 KiB |
@ -0,0 +1,75 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 the OpenProject GmbH |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See docs/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
module MailNotificationHelper |
||||||
|
include ::ColorsHelper |
||||||
|
|
||||||
|
def logo_tag(**options) |
||||||
|
current_logo = CustomStyle.current.logo unless CustomStyle.current.nil? |
||||||
|
|
||||||
|
if current_logo.present? |
||||||
|
logo_file = current_logo.local_file |
||||||
|
logo = File.read(logo_file) |
||||||
|
suffix = MIME::Types.type_for(logo_file.path).first.content_type |
||||||
|
else |
||||||
|
logo = Rails.application.assets["logo_openproject_narrow.svg"] |
||||||
|
suffix = "svg+xml" |
||||||
|
end |
||||||
|
|
||||||
|
email_image_tag(logo, suffix, options) |
||||||
|
end |
||||||
|
|
||||||
|
def email_image_tag(image, suffix, **options) |
||||||
|
image_string = image.to_s |
||||||
|
base64_string = Base64.strict_encode64(image_string) |
||||||
|
|
||||||
|
image_tag "data:image/#{suffix};base64,#{base64_string}", **options |
||||||
|
end |
||||||
|
|
||||||
|
def unique_reasons_of_notifications(notifications) |
||||||
|
notifications |
||||||
|
.map(&:reason_mail_digest) |
||||||
|
.uniq |
||||||
|
end |
||||||
|
|
||||||
|
def notifications_path(id) |
||||||
|
notifications_center_url(['details', id, 'activity']) |
||||||
|
end |
||||||
|
|
||||||
|
def type_color(type, default_fallback) |
||||||
|
color_id = selected_color(type) |
||||||
|
color_id ? Color.find(color_id).hexcode : default_fallback |
||||||
|
end |
||||||
|
|
||||||
|
def status_colors(status) |
||||||
|
color_id = selected_color(status) |
||||||
|
Color.find(color_id).color_styles.map { |k, v| "#{k}:#{v};" }.join(' ') if color_id |
||||||
|
end |
||||||
|
end |
@ -1,58 +1,65 @@ |
|||||||
<div style="color: #777; font-weight: bold"> |
<%= render partial: 'mailer/notification_mailer_header', |
||||||
<%= digest_timespan_text %> |
locals: { |
||||||
</div> |
summary: "#{I18n.t(:'mail.digests.you_have')} #{digest_summary_text(@notification_ids.length, @mentioned_count)}" |
||||||
|
} %> |
||||||
|
|
||||||
<% @notifications_by_project.each do |project, notifications_by_work_package| %> |
<% @aggregated_notifications.first(DigestMailer::MAX_SHOWN_WORK_PACKAGES).each do | work_package, notifications_by_work_package| %> |
||||||
<section style="margin-bottom: 3em; margin-top: 5em"> |
<%= render layout: 'mailer/notification_row', |
||||||
<h1 style="font-size: 2em; margin-bottom: 1.5em"><%= link_to_project(project, only_path: false) %></h1> |
locals: { |
||||||
|
work_package: work_package, |
||||||
<% notifications_by_work_package.each do |work_package, notifications| %> |
notifications_by_work_package: notifications_by_work_package |
||||||
<section style="margin-bottom: 3em;"> |
} do %> |
||||||
<h2 style="margin-bottom: 1em; font-size: 1.5em;"><%= link_to_work_package work_package, status: true, only_path: false, no_hidden: true %></h2> |
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="font-size: 12px;"> |
||||||
|
<% notifications_by_work_package.each do | notification | %> |
||||||
<% notifications.sort_by(&:created_at).each do |notification| %> |
<% if notification.journal.notes.present? %> |
||||||
|
<tr style="color: #878787; line-height: 20px; font-size: 14px;"> |
||||||
<table width="100%" border="0" cellpadding="0" cellspacing="0"> |
<td> |
||||||
<tr> |
<%= digest_comment_text(notification) %> |
||||||
<td width="20px"></td> |
<%= digest_notification_timestamp_text(notification) %> |
||||||
<td style="font-weight: normal; font-size: 1.1em;"> |
</td> |
||||||
<%= digest_notification_timestamp_text(notification) %> |
</tr> |
||||||
</td> |
<% end %> |
||||||
<td style="text-align: right"> |
<% notification.journal.details.each do |detail| %> |
||||||
<%= I18n.t( |
<tr style="color: #878787; line-height: 20px; font-size: 14px;"> |
||||||
:"mail.digests.work_packages.reason.#{notification.reason_mail_digest || :unknown}", |
<td> |
||||||
default: '-') %> |
<%= notification.journal.render_detail(detail, only_path: false) %> |
||||||
</td> |
<%= digest_notification_timestamp_text(notification) %> |
||||||
<td width="20px"></td> |
</td> |
||||||
</tr> |
</tr> |
||||||
</table> |
<% end %> |
||||||
|
<% end %> |
||||||
<% journal = notification.journal %> |
</table> |
||||||
<table width="100%" border="0" cellpadding="0" cellspacing="0"> |
<% end %> |
||||||
<tr> |
<% end %> |
||||||
<td width="20px"></td> |
|
||||||
<td> |
|
||||||
<%= format_text(journal.notes, |
|
||||||
only_path: false, |
|
||||||
object: notification.resource, |
|
||||||
project: notification.project) %> |
|
||||||
|
|
||||||
<% if journal.notes.present? && journal.details.any? %> |
|
||||||
<div style="margin-bottom: 2em"></div> |
|
||||||
<% end %> |
|
||||||
|
|
||||||
<ul> |
|
||||||
<% journal.details.each do |detail| %> |
|
||||||
<li><%= journal.render_detail(detail, only_path: false) %></li> |
|
||||||
<% end %> |
|
||||||
</ul> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
|
|
||||||
<div style="margin-bottom: 3em"></div> |
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="margin: 30px 0;"> |
||||||
|
<tr> |
||||||
|
<td width="100%"> |
||||||
|
<% if @aggregated_notifications.length > DigestMailer::MAX_SHOWN_WORK_PACKAGES %> |
||||||
|
<span style="font-size: 14px; line-height: 28px"> |
||||||
|
<% number_of_overflowing_work_packages = @aggregated_notifications.length - DigestMailer::MAX_SHOWN_WORK_PACKAGES %> |
||||||
|
<% if number_of_overflowing_work_packages === 1 %> |
||||||
|
<%= I18n.t(:'mail.digests.work_packages.more_to_see_singular') %> |
||||||
|
<% else %> |
||||||
|
<%= I18n.t(:'mail.digests.work_packages.more_to_see_plural', number: number_of_overflowing_work_packages) %> |
||||||
<% end %> |
<% end %> |
||||||
</section> |
</span> |
||||||
<% end %> |
<a |
||||||
</section> |
target="_blank" |
||||||
<% end %> |
style="background-color: #D1E5F5; |
||||||
|
padding: 8px 12px; |
||||||
|
color: #1A67A3; |
||||||
|
border: 1px solid #1A67A3; |
||||||
|
border-radius: 16px; |
||||||
|
text-decoration: none; |
||||||
|
white-space: nowrap;"> |
||||||
|
<%= I18n.t(:'mail.digests.work_packages.see_all') %> |
||||||
|
</a> |
||||||
|
<% end %> |
||||||
|
</td> |
||||||
|
<td> |
||||||
|
<%= render partial: 'mailer/notification_settings_button' %> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</table> |
||||||
|
|
||||||
|
@ -1,36 +1,43 @@ |
|||||||
<%= digest_timespan_text %> |
<%= I18n.t(:'mail.salutation', user: @user.firstname) %> |
||||||
|
<%= "#{I18n.t(:'mail.digests.you_have')} #{digest_summary_text(@notification_ids.length, @mentioned_count)}" %> |
||||||
|
<%= "-" * 100 %> |
||||||
|
|
||||||
<% @notifications_by_project.each do |project, notifications_by_work_package| %> |
<% @aggregated_notifications.first(DigestMailer::MAX_SHOWN_WORK_PACKAGES).each do | work_package, notifications_by_work_package| %> |
||||||
|
|
||||||
<%= "=" * (project.name.length + 4) %> |
<%= "=" * (('# ' + work_package.id.to_s + work_package.subject).length + 4) %> |
||||||
= <%= project.name %> = |
= #<%= work_package.id %> <%= work_package.subject %> = |
||||||
<%= "=" * (project.name.length + 4) %> |
<%= "=" * (('# ' + work_package.id.to_s + work_package.subject).length + 4) %> |
||||||
|
|
||||||
<% notifications_by_work_package.each do |work_package, notifications| %> |
<% notifications_by_work_package.each do | notification | %> |
||||||
|
<%= "-" * 20 %> |
||||||
|
|
||||||
<%= "*" * (work_package.to_s.length + 4) %> |
<% unique_reasons = unique_reasons_of_notifications(notifications_by_work_package) %> |
||||||
* <%= work_package.to_s %> * |
<%= digest_notification_timestamp_text( |
||||||
<%= "*" * (work_package.to_s.length + 4) %> |
notification, |
||||||
|
html: false, |
||||||
|
extended_text: true) %> (<% unique_reasons.each_with_index do |reason, index| %><%= I18n.t(:"mail.digests.work_packages.reason.#{reason || :unknown}", default: '-') %><%= ', ' unless unique_reasons.size-1 == index %><% end %>) |
||||||
|
|
||||||
<% notifications.sort_by(&:created_at).each do |notification| %> |
<% journal = notification.journal %> |
||||||
|
<% if journal.notes.present? %> |
||||||
|
<%= I18n.t(:label_comment_added) %>: |
||||||
|
<%= journal.notes %> |
||||||
|
|
||||||
<%= "-" * 20 %> |
<% end %> |
||||||
|
<% journal.details.each do |detail| %> |
||||||
|
* <%= journal.render_detail(detail, only_path: false, no_html: true) %> |
||||||
|
<% end %> |
||||||
|
|
||||||
<%= digest_notification_timestamp_text(notification, html: false) %> (<%= I18n.t('mail.digests.work_packages.reason.prefix', |
<%= "-" * 20 %> |
||||||
reason: I18n.t(:"mail.digests.work_packages.reason.#{notification.reason_mail_digest}")) %>) |
<% end %> |
||||||
|
|
||||||
<% journal = notification.journal %> |
|
||||||
<% if journal.notes.present? %> |
|
||||||
<%= journal.notes %> |
|
||||||
|
|
||||||
<% end %> |
|
||||||
<% journal.details.each do |detail| %> |
|
||||||
* <%= journal.render_detail(detail, only_path: false, no_html: true) %> |
|
||||||
<% end %> |
<% end %> |
||||||
<% end %> |
|
||||||
|
|
||||||
<%= "-" * 20 %> |
|
||||||
|
|
||||||
|
<%= "-" * 100 %> |
||||||
|
|
||||||
|
<% if @aggregated_notifications.length > DigestMailer::MAX_SHOWN_WORK_PACKAGES %> |
||||||
|
<% number_of_overflowing_work_packages = @aggregated_notifications.length - DigestMailer::MAX_SHOWN_WORK_PACKAGES %> |
||||||
|
<% if number_of_overflowing_work_packages === 1 %> |
||||||
|
<%= I18n.t(:'mail.digests.work_packages.more_to_see_singular') %> <%= I18n.t(:'mail.digests.work_packages.login_to_see_all') %> |
||||||
|
<% else %> |
||||||
|
<%= I18n.t(:'mail.digests.work_packages.more_to_see_plural', number: number_of_overflowing_work_packages) %> <%= I18n.t(:'mail.digests.work_packages.login_to_see_all') %> |
||||||
<% end %> |
<% end %> |
||||||
<% end %> |
<% end %> |
||||||
|
@ -0,0 +1,30 @@ |
|||||||
|
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="border-bottom: 1px solid #cccccc; margin-bottom: 32px;"> |
||||||
|
<tr> |
||||||
|
<td width="100%" style="padding-top: 8px; padding-left: 12px;"> |
||||||
|
<table> |
||||||
|
<tr> |
||||||
|
<td style="font-size: 24px; color: #333333; padding-bottom: 5px;"> |
||||||
|
<%= I18n.t(:'mail.salutation', user: @user.firstname) %> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td style="font-size:16px; color: #1A67A3; font-weight: bold; padding-bottom: 10px;"> |
||||||
|
<%= summary %> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td style="padding: 10px 0 32px 0;"> |
||||||
|
<a href="<%= notifications_center_url %>" |
||||||
|
target="_blank" |
||||||
|
style="background: #D1E5F5; padding: 8px 12px; color: #1A67A3; border: 1px solid #1A67A3; border-radius: 16px; text-decoration: none;"> |
||||||
|
<%= I18n.t(:'mail.notification.center') %> |
||||||
|
</a> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</table> |
||||||
|
</td> |
||||||
|
<td style="width: 96px; height: 96px; vertical-align: top;"> |
||||||
|
<%= logo_tag({ alt: "#{Setting.app_title} #{I18n.t(:'mail.logo_alt_text')}", style: "height: 96px;"}) %> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</table> |
@ -0,0 +1,57 @@ |
|||||||
|
<a style="border: 1px solid #E0E0E0; |
||||||
|
margin-bottom: 16px; |
||||||
|
padding: 12px 12px 16px 12px; |
||||||
|
border-radius: 10px; |
||||||
|
text-decoration: none; |
||||||
|
display: block;" |
||||||
|
href="<%= notifications_path(work_package.id) %>" |
||||||
|
target="_blank"> |
||||||
|
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="margin-bottom: 9px; font-size: 14px;"> |
||||||
|
<tr> |
||||||
|
<td > |
||||||
|
<div style="color: #333333; |
||||||
|
background-color: #FFFFFF; |
||||||
|
<%= status_colors(work_package.status) %> |
||||||
|
white-space: nowrap; |
||||||
|
padding: 2px 12px; |
||||||
|
height: 16px;"> |
||||||
|
<%= work_package.status %> |
||||||
|
</div> |
||||||
|
</td> |
||||||
|
<td width="100%" style="padding-left: 8px; |
||||||
|
color: #878787;"> |
||||||
|
|
||||||
|
#<%= work_package.id %> - <%= work_package.project %> |
||||||
|
<% unique_reasons = unique_reasons_of_notifications(notifications_by_work_package) %> |
||||||
|
<%= ' - ' unless unique_reasons.length === 1 && unique_reasons.first.nil? %> |
||||||
|
<% unique_reasons.each_with_index do |reason, index| %> |
||||||
|
<%= I18n.t( |
||||||
|
:"mail.digests.work_packages.reason.#{reason || :unknown}", |
||||||
|
default: '') %><%= ', ' unless unique_reasons.size-1 == index %> |
||||||
|
<% end %> |
||||||
|
</td> |
||||||
|
<td style="text-align: right;"> |
||||||
|
<span style="background-color: #00A3FF; |
||||||
|
color: white; |
||||||
|
border-radius: 8px; |
||||||
|
padding: 0px 8px; |
||||||
|
font-size: 14px;"> |
||||||
|
<%= notifications_by_work_package.length %> |
||||||
|
</span> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</table> |
||||||
|
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="margin-bottom: 9px; font-size: 16px; font-weight: bold;"> |
||||||
|
<tr> |
||||||
|
<td style="color: <%= type_color(work_package.type, '#333333') %>; |
||||||
|
white-space: nowrap;"> |
||||||
|
<%= work_package.type.to_s.upcase %> |
||||||
|
</td> |
||||||
|
<td width="100%" style="padding-left: 5px; color: #333333;"> |
||||||
|
<%= work_package.subject %> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</table> |
||||||
|
|
||||||
|
<%= yield %> |
||||||
|
</a> |
@ -0,0 +1,5 @@ |
|||||||
|
<a href="<%= my_reminders_url %>" |
||||||
|
target="_blank" |
||||||
|
style="padding: 8px 12px; color: #333333; border: 1px solid #878787; border-radius: 16px; text-decoration: none; white-space: nowrap;"> |
||||||
|
<%= I18n.t(:'mail.notification.settings') %> |
||||||
|
</a> |
Loading…
Reference in new issue