[MM-37730] - Self-managed: Update email template to new branding - Batch Email (#18221)

* [MM-37730] - Self-managed: Update email template to new branding - Batch Email

* batch email fixes

* simplify email title

* More fixes

* fix tests

* fix group message name on card

* fix bracket issue

* style the count

* account for  merged changes

* change truncating rule
Этот коммит содержится в:
Allan Guwatudde
2021-09-16 22:08:31 +03:00
коммит произвёл GitHub
родитель acec8db7c5
Коммит ad5591cf75
6 изменённых файлов: 108 добавлений и 51 удалений

Просмотреть файл

@@ -10,6 +10,7 @@ import (
"io" "io"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"sync" "sync"
"time" "time"
@@ -23,13 +24,15 @@ const (
) )
type postData struct { type postData struct {
SenderName string SenderName string
ChannelName string ChannelName string
Message template.HTML Message template.HTML
MessageURL string MessageURL string
SenderPhoto string SenderPhoto string
PostPhoto string PostPhoto string
Time string Time string
ShowChannelIcon bool
OtherChannelMembersCount int
} }
func (es *Service) InitEmailBatching() { func (es *Service) InitEmailBatching() {
@@ -206,6 +209,18 @@ func (job *EmailBatchingJob) checkPendingNotifications(now time.Time, handler fu
} }
} }
/**
* If the name is longer than i characters, replace remaining characters with ...
*/
func truncateUserNames(name string, i int) string {
runes := []rune(name)
if len(runes) > i {
newString := string(runes[:i])
return newString + "..."
}
return name
}
func (es *Service) sendBatchedEmailNotification(userID string, notifications []*batchedNotification) { func (es *Service) sendBatchedEmailNotification(userID string, notifications []*batchedNotification) {
user, err := es.userService.GetUser(userID) user, err := es.userService.GetUser(userID)
if err != nil { if err != nil {
@@ -266,27 +281,38 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []*
"Month": translateFunc(tm.Month().String()), "Month": translateFunc(tm.Month().String()),
"Day": tm.Day(), "Day": tm.Day(),
"Year": tm.Year(), "Year": tm.Year(),
"Timezone": timezone, "TimeZone": timezone,
}) })
MessageURL := siteURL + "/" + notification.teamName + "/pl/" + notification.post.Id MessageURL := siteURL + "/" + notification.teamName + "/pl/" + notification.post.Id
channelName := channel.DisplayName channelDisplayName := channel.DisplayName
showChannelIcon := true
otherChannelMembersCount := 0
if threadsEnabled && notification.post.RootId != "" { if threadsEnabled && notification.post.RootId != "" {
props := map[string]interface{}{"channelName": channelName} props := map[string]interface{}{"channelName": channelDisplayName}
channelName = translateFunc("api.push_notification.title.collapsed_threads", props) channelDisplayName = translateFunc("api.push_notification.title.collapsed_threads", props)
if channel.Type == model.ChannelTypeDirect { if channel.Type == model.ChannelTypeDirect {
channelName = translateFunc("api.push_notification.title.collapsed_threads_dm") channelDisplayName = translateFunc("api.push_notification.title.collapsed_threads_dm")
} }
} }
if channel.Type == model.ChannelTypeGroup {
otherChannelMembersCount = len(strings.Split(channelDisplayName, ",")) - 1
showChannelIcon = false
channelDisplayName = truncateUserNames(channel.DisplayName, 11)
}
postsData = append(postsData, &postData{ postsData = append(postsData, &postData{
SenderPhoto: senderPhoto, SenderPhoto: senderPhoto,
SenderName: sender.GetDisplayName(displayNameFormat), SenderName: truncateUserNames(sender.GetDisplayName(displayNameFormat), 22),
Time: t, Time: t,
ChannelName: channelName, ChannelName: channelDisplayName,
Message: template.HTML(es.GetMessageForNotification(notification.post, translateFunc)), Message: template.HTML(es.GetMessageForNotification(notification.post, translateFunc)),
MessageURL: MessageURL, MessageURL: MessageURL,
ShowChannelIcon: showChannelIcon,
OtherChannelMembersCount: otherChannelMembersCount,
}) })
} }
} }
@@ -300,16 +326,9 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []*
"Day": tm.Day(), "Day": tm.Day(),
}) })
firstSender, err := es.userService.GetUser(notifications[0].post.UserId)
if err != nil {
mlog.Warn("Unable to find sender of post for batched email notification")
}
data := es.NewEmailTemplateData(user.Locale) data := es.NewEmailTemplateData(user.Locale)
data.Props["SiteURL"] = siteURL data.Props["SiteURL"] = siteURL
data.Props["Title"] = translateFunc("api.email_batching.send_batched_email_notification.title", len(notifications)-1, map[string]interface{}{ data.Props["Title"] = translateFunc("api.email_batching.send_batched_email_notification.title")
"SenderName": firstSender.GetDisplayName(displayNameFormat),
})
data.Props["SubTitle"] = translateFunc("api.email_batching.send_batched_email_notification.subTitle") data.Props["SubTitle"] = translateFunc("api.email_batching.send_batched_email_notification.subTitle")
data.Props["Button"] = translateFunc("api.email_batching.send_batched_email_notification.button") data.Props["Button"] = translateFunc("api.email_batching.send_batched_email_notification.button")
data.Props["ButtonURL"] = siteURL data.Props["ButtonURL"] = siteURL
@@ -324,7 +343,7 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []*
mlog.Error("Unable to render email", mlog.Err(renderErr)) mlog.Error("Unable to render email", mlog.Err(renderErr))
} }
if nErr := es.SendNotificationMail(user.Email, subject, renderedPage); nErr != nil { if nErr := es.SendMailWithEmbeddedFiles(user.Email, subject, renderedPage, embeddedFiles); nErr != nil {
mlog.Warn("Unable to send batched email notification", mlog.String("email", user.Email), mlog.Err(nErr)) mlog.Warn("Unable to send batched email notification", mlog.String("email", user.Email), mlog.Err(nErr))
} }
} }

Просмотреть файл

@@ -186,13 +186,15 @@ func truncateUserNames(name string, i int) string {
} }
type postData struct { type postData struct {
SenderName string SenderName string
ChannelName string ChannelName string
Message template.HTML Message template.HTML
MessageURL string MessageURL string
SenderPhoto string SenderPhoto string
PostPhoto string PostPhoto string
Time string Time string
ShowChannelIcon bool
OtherChannelMembersCount int
} }
/** /**

Просмотреть файл

@@ -1611,10 +1611,7 @@
}, },
{ {
"id": "api.email_batching.send_batched_email_notification.title", "id": "api.email_batching.send_batched_email_notification.title",
"translation": { "translation": "You have new messages"
"one": "{{ .SenderName }} sent you new message",
"other": "{{ .SenderName }} and {{.Count}} others sent you new messages"
}
}, },
{ {
"id": "api.emoji.create.duplicate.app_error", "id": "api.emoji.create.duplicate.app_error",

Просмотреть файл

@@ -71,9 +71,9 @@
max-width: 100%; max-width: 100%;
} }
.mj-column-per-50 { .mj-column-per-33-333333333333336 {
width: 50% !important; width: 33.333333333333336% !important;
max-width: 50%; max-width: 33.333333333333336%;
} }
.mj-column-per-90 { .mj-column-per-90 {
@@ -88,9 +88,9 @@
max-width: 100%; max-width: 100%;
} }
.moz-text-html .mj-column-per-50 { .moz-text-html .mj-column-per-33-333333333333336 {
width: 50% !important; width: 33.333333333333336% !important;
max-width: 50%; max-width: 33.333333333333336%;
} }
.moz-text-html .mj-column-per-90 { .moz-text-html .mj-column-per-90 {
@@ -255,6 +255,7 @@
background: rgba(63, 67, 80, 0.08); background: rgba(63, 67, 80, 0.08);
border-radius: 4px; border-radius: 4px;
display: flex; display: flex;
padding-left: 4px;
} }
.channelLogo { .channelLogo {
@@ -275,6 +276,13 @@
padding: 2px 6px 2px 0px; padding: 2px 6px 2px 0px;
} }
.gmChannelCount {
background-color: rgba(63, 67, 80, 0.2);
padding: 0 5px;
border-radius: 2px;
margin-right: 2px;
}
.senderMessage div { .senderMessage div {
text-align: left !important; text-align: left !important;
font-size: 14px !important; font-size: 14px !important;
@@ -427,8 +435,8 @@
<td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0px;text-align:center;">
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="width:552px;" ><![endif]--> <!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="width:552px;" ><![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0;line-height:0;text-align:left;display:inline-block;width:100%;direction:ltr;"> <div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0;line-height:0;text-align:left;display:inline-block;width:100%;direction:ltr;">
<!--[if mso | IE]><table border="0" cellpadding="0" cellspacing="0" role="presentation" ><tr><td style="vertical-align:top;width:276px;" ><![endif]--> <!--[if mso | IE]><table border="0" cellpadding="0" cellspacing="0" role="presentation" ><tr><td style="vertical-align:top;width:184px;" ><![endif]-->
<div class="mj-column-per-50 mj-outlook-group-fix messageAvatarCol" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:50%;"> <div class="mj-column-per-33-333333333333336 mj-outlook-group-fix messageAvatarCol" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:33%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody> <tbody>
<tr> <tr>
@@ -436,8 +444,8 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
<tbody> <tbody>
<tr> <tr>
<td style="width:276px;"> <td style="width:184px;">
<img alt="" height="auto" src="cid:{{.SenderPhoto}}" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="276" /> <img alt="" height="auto" src="cid:{{.SenderPhoto}}" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="184" />
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -460,8 +468,15 @@
{{end}} {{end}}
{{if .ChannelName}} {{if .ChannelName}}
<div class="channelBg"> <div class="channelBg">
{{if .ShowChannelIcon}}
<div class="channelLogo"><img src="{{$.Props.SiteURL}}/static/images/channel_icon.png" width=10px height=10px></img></div> <div class="channelLogo"><img src="{{$.Props.SiteURL}}/static/images/channel_icon.png" width=10px height=10px></img></div>
<div class="channelName">{{.ChannelName}}</div> {{end}}
<div class="channelName">
{{if .OtherChannelMembersCount}}
<span class="gmChannelCount">{{.OtherChannelMembersCount}}</span>
{{end}}
{{.ChannelName}}
</div>
</div> </div>
{{end}} {{end}}
</div> </div>
@@ -472,6 +487,13 @@
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#000000;">{{.Message}}</div> <div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#000000;">{{.Message}}</div>
</td> </td>
</tr> </tr>
</tbody>
</table>
</div>
<!--[if mso | IE]></td><td style="vertical-align:top;width:552px;" ><![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tbody>
{{if .MessageURL}} {{if .MessageURL}}
<tr> <tr>
<td align="center" vertical-align="middle" class="messageButton" style="font-size:0px;padding:16px 0px 0px 0px;word-break:break-word;"> <td align="center" vertical-align="middle" class="messageButton" style="font-size:0px;padding:16px 0px 0px 0px;word-break:break-word;">

Просмотреть файл

@@ -14,8 +14,15 @@
{{end}} {{end}}
{{if .ChannelName}} {{if .ChannelName}}
<div class="channelBg"> <div class="channelBg">
<div class="channelLogo"><img src="{{$.Props.SiteURL}}/static/images/channel_icon.png" width=10px height=10px></img></div> {{if .ShowChannelIcon}}
<div class="channelName">{{.ChannelName}}</div> <div class="channelLogo"><img src="{{$.Props.SiteURL}}/static/images/channel_icon.png" width=10px height=10px></img></div>
{{end}}
<div class="channelName">
{{if .OtherChannelMembersCount}}
<span class="gmChannelCount">{{.OtherChannelMembersCount}}</span>
{{end}}
{{.ChannelName}}
</div>
</div> </div>
{{end}} {{end}}
</div> </div>
@@ -25,6 +32,8 @@
<mj-text css-class="senderMessage" padding="0px"> <mj-text css-class="senderMessage" padding="0px">
{{.Message}} {{.Message}}
</mj-text> </mj-text>
</mj-column>
<mj-column width=100%>
<mj-raw>{{if .MessageURL}}</mj-raw> <mj-raw>{{if .MessageURL}}</mj-raw>
<mj-button href="{{.MessageURL}}" padding="16px 0px 0px 0px" css-class="messageButton">{{$.Props.MessageButton}}</mj-button> <mj-button href="{{.MessageURL}}" padding="16px 0px 0px 0px" css-class="messageButton">{{$.Props.MessageButton}}</mj-button>
<mj-raw>{{end}}</mj-raw> <mj-raw>{{end}}</mj-raw>

Просмотреть файл

@@ -152,6 +152,7 @@
background: rgba(63, 67, 80, 0.08); background: rgba(63, 67, 80, 0.08);
border-radius: 4px; border-radius: 4px;
display: flex; display: flex;
padding-left: 4px;
} }
.channelLogo { .channelLogo {
@@ -171,6 +172,13 @@
color: rgba(63, 67, 80, 0.64); color: rgba(63, 67, 80, 0.64);
padding: 2px 6px 2px 0px; padding: 2px 6px 2px 0px;
} }
.gmChannelCount {
background-color: rgba(63, 67, 80, 0.2);
padding: 0 5px;
border-radius: 2px;
margin-right: 2px;
}
.senderMessage div { .senderMessage div {
text-align: left !important; text-align: left !important;