feat(reminders): include project in reminder notification
This commit is contained in:
parent
b2b4b5423f
commit
66cf7ab50a
@ -32,17 +32,18 @@ import (
|
|||||||
|
|
||||||
// ReminderDueNotification represents a ReminderDueNotification notification
|
// ReminderDueNotification represents a ReminderDueNotification notification
|
||||||
type ReminderDueNotification struct {
|
type ReminderDueNotification struct {
|
||||||
User *user.User `json:"user"`
|
User *user.User `json:"user"`
|
||||||
Task *Task `json:"task"`
|
Task *Task `json:"task"`
|
||||||
|
Project *Project `json:"project"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToMail returns the mail notification for ReminderDueNotification
|
// ToMail returns the mail notification for ReminderDueNotification
|
||||||
func (n *ReminderDueNotification) ToMail() *notifications.Mail {
|
func (n *ReminderDueNotification) ToMail() *notifications.Mail {
|
||||||
return notifications.NewMail().
|
return notifications.NewMail().
|
||||||
To(n.User.Email).
|
To(n.User.Email).
|
||||||
Subject(`Reminder for "`+n.Task.Title+`"`).
|
Subject(`Reminder for "`+n.Task.Title+`" (`+n.Project.Title+`)`).
|
||||||
Greeting("Hi "+n.User.GetName()+",").
|
Greeting("Hi "+n.User.GetName()+",").
|
||||||
Line(`This is a friendly reminder of the task "`+n.Task.Title+`".`).
|
Line(`This is a friendly reminder of the task "`+n.Task.Title+`" (`+n.Project.Title+`).`).
|
||||||
Action("Open Task", config.ServiceFrontendurl.GetString()+"tasks/"+strconv.FormatInt(n.Task.ID, 10)).
|
Action("Open Task", config.ServiceFrontendurl.GetString()+"tasks/"+strconv.FormatInt(n.Task.ID, 10)).
|
||||||
Line("Have a nice day!")
|
Line("Have a nice day!")
|
||||||
}
|
}
|
||||||
@ -203,17 +204,18 @@ func (n *TeamMemberAddedNotification) Name() string {
|
|||||||
|
|
||||||
// UndoneTaskOverdueNotification represents a UndoneTaskOverdueNotification notification
|
// UndoneTaskOverdueNotification represents a UndoneTaskOverdueNotification notification
|
||||||
type UndoneTaskOverdueNotification struct {
|
type UndoneTaskOverdueNotification struct {
|
||||||
User *user.User
|
User *user.User
|
||||||
Task *Task
|
Task *Task
|
||||||
|
Project *Project
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToMail returns the mail notification for UndoneTaskOverdueNotification
|
// ToMail returns the mail notification for UndoneTaskOverdueNotification
|
||||||
func (n *UndoneTaskOverdueNotification) ToMail() *notifications.Mail {
|
func (n *UndoneTaskOverdueNotification) ToMail() *notifications.Mail {
|
||||||
until := time.Until(n.Task.DueDate).Round(1*time.Hour) * -1
|
until := time.Until(n.Task.DueDate).Round(1*time.Hour) * -1
|
||||||
return notifications.NewMail().
|
return notifications.NewMail().
|
||||||
Subject(`Task "`+n.Task.Title+`" is overdue`).
|
Subject(`Task "`+n.Task.Title+`" (`+n.Project.Title+`) is overdue`).
|
||||||
Greeting("Hi "+n.User.GetName()+",").
|
Greeting("Hi "+n.User.GetName()+",").
|
||||||
Line(`This is a friendly reminder of the task "`+n.Task.Title+`" which is overdue since `+utils.HumanizeDuration(until)+` and not yet done.`).
|
Line(`This is a friendly reminder of the task "`+n.Task.Title+`" (`+n.Project.Title+`) which is overdue since `+utils.HumanizeDuration(until)+` and not yet done.`).
|
||||||
Action("Open Task", config.ServiceFrontendurl.GetString()+"tasks/"+strconv.FormatInt(n.Task.ID, 10)).
|
Action("Open Task", config.ServiceFrontendurl.GetString()+"tasks/"+strconv.FormatInt(n.Task.ID, 10)).
|
||||||
Line("Have a nice day!")
|
Line("Have a nice day!")
|
||||||
}
|
}
|
||||||
@ -230,8 +232,9 @@ func (n *UndoneTaskOverdueNotification) Name() string {
|
|||||||
|
|
||||||
// UndoneTasksOverdueNotification represents a UndoneTasksOverdueNotification notification
|
// UndoneTasksOverdueNotification represents a UndoneTasksOverdueNotification notification
|
||||||
type UndoneTasksOverdueNotification struct {
|
type UndoneTasksOverdueNotification struct {
|
||||||
User *user.User
|
User *user.User
|
||||||
Tasks map[int64]*Task
|
Tasks map[int64]*Task
|
||||||
|
Projects map[int64]*Project
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToMail returns the mail notification for UndoneTasksOverdueNotification
|
// ToMail returns the mail notification for UndoneTasksOverdueNotification
|
||||||
@ -249,7 +252,7 @@ func (n *UndoneTasksOverdueNotification) ToMail() *notifications.Mail {
|
|||||||
overdueLine := ""
|
overdueLine := ""
|
||||||
for _, task := range sortedTasks {
|
for _, task := range sortedTasks {
|
||||||
until := time.Until(task.DueDate).Round(1*time.Hour) * -1
|
until := time.Until(task.DueDate).Round(1*time.Hour) * -1
|
||||||
overdueLine += `* [` + task.Title + `](` + config.ServiceFrontendurl.GetString() + "tasks/" + strconv.FormatInt(task.ID, 10) + `), overdue since ` + utils.HumanizeDuration(until) + "\n"
|
overdueLine += `* [` + task.Title + `](` + config.ServiceFrontendurl.GetString() + "tasks/" + strconv.FormatInt(task.ID, 10) + `) (` + n.Projects[task.ProjectID].Title + `), overdue since ` + utils.HumanizeDuration(until) + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
return notifications.NewMail().
|
return notifications.NewMail().
|
||||||
|
@ -314,6 +314,18 @@ func GetProjectSimplByTaskID(s *xorm.Session, taskID int64) (l *Project, err err
|
|||||||
return &project, nil
|
return &project, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProjectsSimplByTaskIDs gets a list of projects by a task ids
|
||||||
|
func GetProjectsSimplByTaskIDs(s *xorm.Session, taskIDs []int64) (ps map[int64]*Project, err error) {
|
||||||
|
ps = make(map[int64]*Project)
|
||||||
|
err = s.
|
||||||
|
Select("projects.*").
|
||||||
|
Table(Project{}).
|
||||||
|
Join("INNER", "tasks", "projects.id = tasks.project_id").
|
||||||
|
In("tasks.id", taskIDs).
|
||||||
|
Find(&ps)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GetProjectsByIDs returns a map of projects from a slice with project ids
|
// GetProjectsByIDs returns a map of projects from a slice with project ids
|
||||||
func GetProjectsByIDs(s *xorm.Session, projectIDs []int64) (projects map[int64]*Project, err error) {
|
func GetProjectsByIDs(s *xorm.Session, projectIDs []int64) (projects map[int64]*Project, err error) {
|
||||||
projects = make(map[int64]*Project, len(projectIDs))
|
projects = make(map[int64]*Project, len(projectIDs))
|
||||||
|
@ -132,10 +132,24 @@ func RegisterOverdueReminderCron() {
|
|||||||
|
|
||||||
log.Debugf("[Undone Overdue Tasks Reminder] Sending reminders to %d users", len(uts))
|
log.Debugf("[Undone Overdue Tasks Reminder] Sending reminders to %d users", len(uts))
|
||||||
|
|
||||||
|
taskIDs := []int64{}
|
||||||
|
for _, ut := range uts {
|
||||||
|
for _, t := range ut.tasks {
|
||||||
|
taskIDs = append(taskIDs, t.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
projects, err := GetProjectsSimplByTaskIDs(s, taskIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("[Undone Overdue Tasks Reminder] Could not get projects for tasks: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for _, ut := range uts {
|
for _, ut := range uts {
|
||||||
var n notifications.Notification = &UndoneTasksOverdueNotification{
|
var n notifications.Notification = &UndoneTasksOverdueNotification{
|
||||||
User: ut.user,
|
User: ut.user,
|
||||||
Tasks: ut.tasks,
|
Tasks: ut.tasks,
|
||||||
|
Projects: projects,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ut.tasks) == 1 {
|
if len(ut.tasks) == 1 {
|
||||||
@ -143,8 +157,9 @@ func RegisterOverdueReminderCron() {
|
|||||||
// first entry without knowing the key of it.
|
// first entry without knowing the key of it.
|
||||||
for _, t := range ut.tasks {
|
for _, t := range ut.tasks {
|
||||||
n = &UndoneTaskOverdueNotification{
|
n = &UndoneTaskOverdueNotification{
|
||||||
User: ut.user,
|
User: ut.user,
|
||||||
Task: t,
|
Task: t,
|
||||||
|
Project: projects[t.ProjectID],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,11 @@ func getTasksWithRemindersDueAndTheirUsers(s *xorm.Session, now time.Time) (remi
|
|||||||
|
|
||||||
seen := make(map[int64]map[int64]bool)
|
seen := make(map[int64]map[int64]bool)
|
||||||
|
|
||||||
|
projects, err := GetProjectsSimplByTaskIDs(s, taskIDs)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Time zone cache per time zone string to avoid parsing the same time zone over and over again
|
// Time zone cache per time zone string to avoid parsing the same time zone over and over again
|
||||||
tzs := make(map[string]*time.Location)
|
tzs := make(map[string]*time.Location)
|
||||||
// Figure out which reminders are actually due in the time zone of the users
|
// Figure out which reminders are actually due in the time zone of the users
|
||||||
@ -208,8 +213,9 @@ func getTasksWithRemindersDueAndTheirUsers(s *xorm.Session, now time.Time) (remi
|
|||||||
actualReminder := r.Reminder.In(tz)
|
actualReminder := r.Reminder.In(tz)
|
||||||
if (actualReminder.After(now) && actualReminder.Before(now.Add(time.Minute))) || actualReminder.Equal(now) {
|
if (actualReminder.After(now) && actualReminder.Before(now.Add(time.Minute))) || actualReminder.Equal(now) {
|
||||||
reminderNotifications = append(reminderNotifications, &ReminderDueNotification{
|
reminderNotifications = append(reminderNotifications, &ReminderDueNotification{
|
||||||
User: u.User,
|
User: u.User,
|
||||||
Task: u.Task,
|
Task: u.Task,
|
||||||
|
Project: projects[u.Task.ProjectID],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user