mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Set batched notification email timestamps to user TZ (#26121)
* refactor: migrate getFormattedPostTime to utils Move app.getFormattedPostTime to utils and export along with its struct * Set batch notification post times to user TZ * default useMilitaryTime to false in batched email If there is an error reading the user's preference for useMilitaryTime, default to false, as that should be the default value if the user never sets it. --------- Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
c9fc6297f3
commit
96e5e17d13
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/mattermost/mattermost/server/public/model"
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
||||||
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
||||||
|
"github.com/mattermost/mattermost/server/v8/channels/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -278,6 +279,13 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var useMilitaryTime bool
|
||||||
|
if data, err := es.store.Preference().Get(user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameUseMilitaryTime); err != nil {
|
||||||
|
useMilitaryTime = false
|
||||||
|
} else {
|
||||||
|
useMilitaryTime = data.Value == "true"
|
||||||
|
}
|
||||||
|
|
||||||
if emailNotificationContentsType == model.EmailNotificationContentsFull {
|
if emailNotificationContentsType == model.EmailNotificationContentsFull {
|
||||||
for i, notification := range notifications {
|
for i, notification := range notifications {
|
||||||
sender, errSender := es.userService.GetUser(notification.post.UserId)
|
sender, errSender := es.userService.GetUser(notification.post.UserId)
|
||||||
@ -300,17 +308,9 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []*
|
|||||||
embeddedFiles[senderPhoto] = bytes.NewReader(senderProfileImage)
|
embeddedFiles[senderPhoto] = bytes.NewReader(senderProfileImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
tm := time.Unix(notification.post.CreateAt/1000, 0)
|
formattedTime := utils.GetFormattedPostTime(user, notification.post, useMilitaryTime, translateFunc)
|
||||||
timezone, _ := tm.Zone()
|
|
||||||
|
|
||||||
t := translateFunc("api.email_batching.send_batched_email_notification.time", map[string]any{
|
t := translateFunc("api.email_batching.send_batched_email_notification.time", formattedTime)
|
||||||
"Hour": tm.Hour(),
|
|
||||||
"Minute": fmt.Sprintf("%02d", tm.Minute()),
|
|
||||||
"Month": translateFunc(tm.Month().String()),
|
|
||||||
"Day": tm.Day(),
|
|
||||||
"Year": tm.Year(),
|
|
||||||
"TimeZone": timezone,
|
|
||||||
})
|
|
||||||
|
|
||||||
MessageURL := siteURL + "/" + notification.teamName + "/pl/" + notification.post.Id
|
MessageURL := siteURL + "/" + notification.teamName + "/pl/" + notification.post.Id
|
||||||
|
|
||||||
@ -346,13 +346,13 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tm := time.Unix(notifications[0].post.CreateAt/1000, 0)
|
formattedTime := utils.GetFormattedPostTime(user, notifications[0].post, useMilitaryTime, translateFunc)
|
||||||
|
|
||||||
subject := translateFunc("api.email_batching.send_batched_email_notification.subject", len(notifications), map[string]any{
|
subject := translateFunc("api.email_batching.send_batched_email_notification.subject", len(notifications), map[string]any{
|
||||||
"SiteName": es.config().TeamSettings.SiteName,
|
"SiteName": es.config().TeamSettings.SiteName,
|
||||||
"Year": tm.Year(),
|
"Year": formattedTime.Year,
|
||||||
"Month": translateFunc(tm.Month().String()),
|
"Month": formattedTime.Month,
|
||||||
"Day": tm.Day(),
|
"Day": formattedTime.Day,
|
||||||
})
|
})
|
||||||
|
|
||||||
data := es.NewEmailTemplateData(user.Locale)
|
data := es.NewEmailTemplateData(user.Locale)
|
||||||
|
@ -9,9 +9,7 @@ import (
|
|||||||
"html"
|
"html"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
@ -148,7 +146,7 @@ func (a *App) sendNotificationEmail(c request.CTX, notification *PostNotificatio
|
|||||||
* Computes the subject line for direct notification email messages
|
* Computes the subject line for direct notification email messages
|
||||||
*/
|
*/
|
||||||
func getDirectMessageNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, senderName string, useMilitaryTime bool) string {
|
func getDirectMessageNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, senderName string, useMilitaryTime bool) string {
|
||||||
t := getFormattedPostTime(user, post, useMilitaryTime, translateFunc)
|
t := utils.GetFormattedPostTime(user, post, useMilitaryTime, translateFunc)
|
||||||
var subjectParameters = map[string]any{
|
var subjectParameters = map[string]any{
|
||||||
"SiteName": siteName,
|
"SiteName": siteName,
|
||||||
"SenderDisplayName": senderName,
|
"SenderDisplayName": senderName,
|
||||||
@ -163,7 +161,7 @@ func getDirectMessageNotificationEmailSubject(user *model.User, post *model.Post
|
|||||||
* Computes the subject line for group, public, and private email messages
|
* Computes the subject line for group, public, and private email messages
|
||||||
*/
|
*/
|
||||||
func getNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, teamName string, useMilitaryTime bool) string {
|
func getNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, teamName string, useMilitaryTime bool) string {
|
||||||
t := getFormattedPostTime(user, post, useMilitaryTime, translateFunc)
|
t := utils.GetFormattedPostTime(user, post, useMilitaryTime, translateFunc)
|
||||||
var subjectParameters = map[string]any{
|
var subjectParameters = map[string]any{
|
||||||
"SiteName": siteName,
|
"SiteName": siteName,
|
||||||
"TeamName": teamName,
|
"TeamName": teamName,
|
||||||
@ -178,7 +176,7 @@ func getNotificationEmailSubject(user *model.User, post *model.Post, translateFu
|
|||||||
* Computes the subject line for group email messages
|
* Computes the subject line for group email messages
|
||||||
*/
|
*/
|
||||||
func getGroupMessageNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, channelName string, emailNotificationContentsType string, useMilitaryTime bool) string {
|
func getGroupMessageNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, channelName string, emailNotificationContentsType string, useMilitaryTime bool) string {
|
||||||
t := getFormattedPostTime(user, post, useMilitaryTime, translateFunc)
|
t := utils.GetFormattedPostTime(user, post, useMilitaryTime, translateFunc)
|
||||||
var subjectParameters = map[string]any{
|
var subjectParameters = map[string]any{
|
||||||
"SiteName": siteName,
|
"SiteName": siteName,
|
||||||
"Month": t.Month,
|
"Month": t.Month,
|
||||||
@ -226,7 +224,7 @@ func (a *App) getNotificationEmailBody(c request.CTX, recipient *model.User, pos
|
|||||||
SenderPhoto: senderPhoto,
|
SenderPhoto: senderPhoto,
|
||||||
}
|
}
|
||||||
|
|
||||||
t := getFormattedPostTime(recipient, post, useMilitaryTime, translateFunc)
|
t := utils.GetFormattedPostTime(recipient, post, useMilitaryTime, translateFunc)
|
||||||
messageTime := map[string]any{
|
messageTime := map[string]any{
|
||||||
"Hour": t.Hour,
|
"Hour": t.Hour,
|
||||||
"Minute": t.Minute,
|
"Minute": t.Minute,
|
||||||
@ -311,48 +309,6 @@ func (a *App) getNotificationEmailBody(c request.CTX, recipient *model.User, pos
|
|||||||
return a.Srv().TemplatesContainer().RenderToString("messages_notification", data)
|
return a.Srv().TemplatesContainer().RenderToString("messages_notification", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
type formattedPostTime struct {
|
|
||||||
Time time.Time
|
|
||||||
Year string
|
|
||||||
Month string
|
|
||||||
Day string
|
|
||||||
Hour string
|
|
||||||
Minute string
|
|
||||||
TimeZone string
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFormattedPostTime(user *model.User, post *model.Post, useMilitaryTime bool, translateFunc i18n.TranslateFunc) formattedPostTime {
|
|
||||||
preferredTimezone := user.GetPreferredTimezone()
|
|
||||||
postTime := time.Unix(post.CreateAt/1000, 0)
|
|
||||||
zone, _ := postTime.Zone()
|
|
||||||
|
|
||||||
localTime := postTime
|
|
||||||
if preferredTimezone != "" {
|
|
||||||
loc, _ := time.LoadLocation(preferredTimezone)
|
|
||||||
if loc != nil {
|
|
||||||
localTime = postTime.In(loc)
|
|
||||||
zone, _ = localTime.Zone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hour := localTime.Format("15")
|
|
||||||
period := ""
|
|
||||||
if !useMilitaryTime {
|
|
||||||
hour = localTime.Format("3")
|
|
||||||
period = " " + localTime.Format("PM")
|
|
||||||
}
|
|
||||||
|
|
||||||
return formattedPostTime{
|
|
||||||
Time: localTime,
|
|
||||||
Year: strconv.Itoa(localTime.Year()),
|
|
||||||
Month: translateFunc(localTime.Month().String()),
|
|
||||||
Day: strconv.Itoa(localTime.Day()),
|
|
||||||
Hour: hour,
|
|
||||||
Minute: fmt.Sprintf("%02d"+period, localTime.Minute()),
|
|
||||||
TimeZone: zone,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) generateHyperlinkForChannels(c request.CTX, postMessage, teamName, teamURL string) (string, *model.AppError) {
|
func (a *App) generateHyperlinkForChannels(c request.CTX, postMessage, teamName, teamURL string) (string, *model.AppError) {
|
||||||
team, err := a.GetTeamByName(teamName)
|
team, err := a.GetTeamByName(teamName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
||||||
"github.com/mattermost/mattermost/server/public/shared/timezones"
|
"github.com/mattermost/mattermost/server/public/shared/timezones"
|
||||||
"github.com/mattermost/mattermost/server/v8/channels/store/storetest/mocks"
|
"github.com/mattermost/mattermost/server/v8/channels/store/storetest/mocks"
|
||||||
|
"github.com/mattermost/mattermost/server/v8/channels/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetDirectMessageNotificationEmailSubject(t *testing.T) {
|
func TestGetDirectMessageNotificationEmailSubject(t *testing.T) {
|
||||||
@ -255,7 +256,7 @@ func TestGetNotificationEmailBodyFullNotificationLocaleTimeNoTimezone(t *testing
|
|||||||
tm := time.Unix(post.CreateAt/1000, 0)
|
tm := time.Unix(post.CreateAt/1000, 0)
|
||||||
zone, _ := tm.Zone()
|
zone, _ := tm.Zone()
|
||||||
|
|
||||||
formattedTime := formattedPostTime{
|
formattedTime := utils.FormattedPostTime{
|
||||||
Hour: fmt.Sprintf("%02d", tm.Hour()),
|
Hour: fmt.Sprintf("%02d", tm.Hour()),
|
||||||
Minute: fmt.Sprintf("%02d", tm.Minute()),
|
Minute: fmt.Sprintf("%02d", tm.Minute()),
|
||||||
TimeZone: zone,
|
TimeZone: zone,
|
||||||
|
@ -4,7 +4,12 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
|
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MillisFromTime(t time.Time) int64 {
|
func MillisFromTime(t time.Time) int64 {
|
||||||
@ -28,3 +33,45 @@ func EndOfDay(t time.Time) time.Time {
|
|||||||
func Yesterday() time.Time {
|
func Yesterday() time.Time {
|
||||||
return time.Now().AddDate(0, 0, -1)
|
return time.Now().AddDate(0, 0, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FormattedPostTime struct {
|
||||||
|
Time time.Time
|
||||||
|
Year string
|
||||||
|
Month string
|
||||||
|
Day string
|
||||||
|
Hour string
|
||||||
|
Minute string
|
||||||
|
TimeZone string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFormattedPostTime(user *model.User, post *model.Post, useMilitaryTime bool, translateFunc i18n.TranslateFunc) FormattedPostTime {
|
||||||
|
preferredTimezone := user.GetPreferredTimezone()
|
||||||
|
postTime := time.Unix(post.CreateAt/1000, 0)
|
||||||
|
zone, _ := postTime.Zone()
|
||||||
|
|
||||||
|
localTime := postTime
|
||||||
|
if preferredTimezone != "" {
|
||||||
|
loc, _ := time.LoadLocation(preferredTimezone)
|
||||||
|
if loc != nil {
|
||||||
|
localTime = postTime.In(loc)
|
||||||
|
zone, _ = localTime.Zone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hour := localTime.Format("15")
|
||||||
|
period := ""
|
||||||
|
if !useMilitaryTime {
|
||||||
|
hour = localTime.Format("3")
|
||||||
|
period = " " + localTime.Format("PM")
|
||||||
|
}
|
||||||
|
|
||||||
|
return FormattedPostTime{
|
||||||
|
Time: localTime,
|
||||||
|
Year: strconv.Itoa(localTime.Year()),
|
||||||
|
Month: translateFunc(localTime.Month().String()),
|
||||||
|
Day: strconv.Itoa(localTime.Day()),
|
||||||
|
Hour: hour,
|
||||||
|
Minute: fmt.Sprintf("%02d"+period, localTime.Minute()),
|
||||||
|
TimeZone: zone,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user