Put reminders in an extra table (#75)
This commit is contained in:
8
pkg/models/fixtures/task_reminders.yml
Normal file
8
pkg/models/fixtures/task_reminders.yml
Normal file
@ -0,0 +1,8 @@
|
||||
- id: 1
|
||||
task_id: 27
|
||||
reminder_unix: 1543626724
|
||||
created: 1543626724
|
||||
- id: 2
|
||||
task_id: 27
|
||||
reminder_unix: 1543626824
|
||||
created: 1543626724
|
@ -167,7 +167,6 @@
|
||||
- id: 27
|
||||
text: 'task #27 with reminders'
|
||||
created_by_id: 1
|
||||
reminders_unix: '[1543626724,1543626824]'
|
||||
list_id: 1
|
||||
created: 1543626724
|
||||
updated: 1543626724
|
||||
|
@ -8,6 +8,7 @@ package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/web"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -66,7 +67,7 @@ func (t *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, er
|
||||
}
|
||||
|
||||
//GetTasksByUser returns all tasks for a user
|
||||
func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate time.Time, endDate time.Time) (tasks []*ListTask, err error) {
|
||||
func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate time.Time, endDate time.Time) ([]*ListTask, error) {
|
||||
// Get all lists
|
||||
lists, err := getRawListsForUser("", u, page)
|
||||
if err != nil {
|
||||
@ -91,6 +92,8 @@ func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate t
|
||||
orderby = "due_date_unix asc"
|
||||
}
|
||||
|
||||
taskMap := make(map[int64]*ListTask)
|
||||
|
||||
// Then return all tasks for that lists
|
||||
if startDate.Unix() != 0 || endDate.Unix() != 0 {
|
||||
|
||||
@ -111,7 +114,7 @@ func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate t
|
||||
"(end_date_unix BETWEEN ? and ?))", startDateUnix, endDateUnix, startDateUnix, endDateUnix, startDateUnix, endDateUnix).
|
||||
And("(parent_task_id = 0 OR parent_task_id IS NULL)").
|
||||
OrderBy(orderby).
|
||||
Find(&tasks); err != nil {
|
||||
Find(&taskMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
@ -119,10 +122,39 @@ func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate t
|
||||
Where("text LIKE ?", "%"+search+"%").
|
||||
And("(parent_task_id = 0 OR parent_task_id IS NULL)").
|
||||
OrderBy(orderby).
|
||||
Find(&tasks); err != nil {
|
||||
Find(&taskMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
tasks, err := addMoreInfoToTasks(taskMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Because the list is sorted by id which we don't want (since we're dealing with maps)
|
||||
// we have to manually sort the tasks again here.
|
||||
sortTasks(tasks, sortby)
|
||||
|
||||
return tasks, err
|
||||
}
|
||||
|
||||
func sortTasks(tasks []*ListTask, by SortBy) {
|
||||
switch by {
|
||||
case SortTasksByPriorityDesc:
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].Priority > tasks[j].Priority
|
||||
})
|
||||
case SortTasksByPriorityAsc:
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].Priority < tasks[j].Priority
|
||||
})
|
||||
case SortTasksByDueDateDesc:
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].DueDateUnix > tasks[j].DueDateUnix
|
||||
})
|
||||
case SortTasksByDueDateAsc:
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].DueDateUnix < tasks[j].DueDateUnix
|
||||
})
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,7 +36,7 @@ type ListTask struct {
|
||||
// A unix timestamp when the task is due.
|
||||
DueDateUnix int64 `xorm:"int(11) INDEX null" json:"dueDate"`
|
||||
// An array of unix timestamps when the user wants to be reminded of the task.
|
||||
RemindersUnix []int64 `xorm:"JSON TEXT null" json:"reminderDates"`
|
||||
RemindersUnix []int64 `xorm:"-" json:"reminderDates"`
|
||||
CreatedByID int64 `xorm:"int(11) not null" json:"-"` // ID of the user who put that task on the list
|
||||
// The list this task belongs to.
|
||||
ListID int64 `xorm:"int(11) INDEX not null" json:"listID" param:"list"`
|
||||
@ -84,6 +84,19 @@ func (ListTask) TableName() string {
|
||||
return "tasks"
|
||||
}
|
||||
|
||||
// TaskReminder holds a reminder on a task
|
||||
type TaskReminder struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk"`
|
||||
TaskID int64 `xorm:"int(11) not null INDEX"`
|
||||
ReminderUnix int64 `xorm:"int(11) not null INDEX"`
|
||||
Created int64 `xorm:"created not null"`
|
||||
}
|
||||
|
||||
// TableName returns a pretty table name
|
||||
func (TaskReminder) TableName() string {
|
||||
return "task_reminders"
|
||||
}
|
||||
|
||||
// GetTasksByListID gets all todotasks for a list
|
||||
func GetTasksByListID(listID int64) (tasks []*ListTask, err error) {
|
||||
// make a map so we can put in a lot of other stuff more easily
|
||||
@ -236,12 +249,27 @@ func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err err
|
||||
return
|
||||
}
|
||||
|
||||
// Get all reminders and put them in a map to have it easier later
|
||||
reminders := []*TaskReminder{}
|
||||
err = x.Table("task_reminders").In("task_id", taskIDs).Find(&reminders)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
taskRemindersUnix := make(map[int64][]int64)
|
||||
for _, r := range reminders {
|
||||
taskRemindersUnix[r.TaskID] = append(taskRemindersUnix[r.TaskID], r.ReminderUnix)
|
||||
}
|
||||
|
||||
// Add all user objects to the appropriate tasks
|
||||
for _, task := range taskMap {
|
||||
|
||||
// Make created by user objects
|
||||
taskMap[task.ID].CreatedBy = *users[task.CreatedByID]
|
||||
|
||||
// Add the reminders
|
||||
taskMap[task.ID].RemindersUnix = taskRemindersUnix[task.ID]
|
||||
|
||||
// Reorder all subtasks
|
||||
if task.ParentTaskID != 0 {
|
||||
taskMap[task.ParentTaskID].Subtasks = append(taskMap[task.ParentTaskID].Subtasks, task)
|
||||
|
@ -78,6 +78,11 @@ func (t *ListTask) Create(a web.Auth) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the reminders
|
||||
if err := t.updateReminders(t.RemindersUnix); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
metrics.UpdateCount(1, metrics.TaskCountKey)
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
@ -118,6 +123,11 @@ func (t *ListTask) Update() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the reminders
|
||||
if err := ot.updateReminders(t.RemindersUnix); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the labels
|
||||
//
|
||||
// Maybe FIXME:
|
||||
@ -162,10 +172,6 @@ func (t *ListTask) Update() (err error) {
|
||||
if t.DueDateUnix == 0 {
|
||||
ot.DueDateUnix = 0
|
||||
}
|
||||
// Reminders
|
||||
if len(t.RemindersUnix) == 0 {
|
||||
ot.RemindersUnix = nil
|
||||
}
|
||||
// Repeat after
|
||||
if t.RepeatAfter == 0 {
|
||||
ot.RepeatAfter = 0
|
||||
@ -192,7 +198,6 @@ func (t *ListTask) Update() (err error) {
|
||||
"description",
|
||||
"done",
|
||||
"due_date_unix",
|
||||
"reminders_unix",
|
||||
"repeat_after",
|
||||
"parent_task_id",
|
||||
"priority",
|
||||
@ -232,3 +237,79 @@ func updateDone(oldTask *ListTask, newTask *ListTask) {
|
||||
oldTask.DoneAtUnix = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Creates or deletes all necessary remindes without unneded db operations.
|
||||
// The parameter is a slice with unix dates which holds the new reminders.
|
||||
func (t *ListTask) updateReminders(reminders []int64) (err error) {
|
||||
|
||||
// If we're removing everything, delete all reminders right away
|
||||
if len(reminders) == 0 && len(t.RemindersUnix) > 0 {
|
||||
_, err = x.Where("task_id = ?", t.ID).
|
||||
Delete(TaskReminder{})
|
||||
t.RemindersUnix = nil
|
||||
return err
|
||||
}
|
||||
|
||||
// If we didn't change anything (from 0 to zero) don't do anything.
|
||||
if len(reminders) == 0 && len(t.RemindersUnix) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Make a hashmap of the new reminders for easier comparison
|
||||
newReminders := make(map[int64]*TaskReminder, len(reminders))
|
||||
for _, newReminder := range reminders {
|
||||
newReminders[newReminder] = &TaskReminder{ReminderUnix: newReminder}
|
||||
}
|
||||
|
||||
// Get old reminders to delete
|
||||
var found bool
|
||||
var remindersToDelete []int64
|
||||
oldReminders := make(map[int64]*TaskReminder, len(t.RemindersUnix))
|
||||
for _, oldReminder := range t.RemindersUnix {
|
||||
found = false
|
||||
// If a new reminder is already in the list with old reminders
|
||||
if newReminders[oldReminder] != nil {
|
||||
found = true
|
||||
}
|
||||
|
||||
// Put all reminders which are only on the old list to the trash
|
||||
if !found {
|
||||
remindersToDelete = append(remindersToDelete, oldReminder)
|
||||
}
|
||||
|
||||
oldReminders[oldReminder] = &TaskReminder{ReminderUnix: oldReminder}
|
||||
}
|
||||
|
||||
// Delete all reminders not passed
|
||||
if len(remindersToDelete) > 0 {
|
||||
_, err = x.In("reminder_unix", remindersToDelete).
|
||||
And("task_id = ?", t.ID).
|
||||
Delete(ListTaskAssginee{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through our users and add them
|
||||
for _, r := range reminders {
|
||||
// Check if the reminder already exists and only inserts it if not
|
||||
if oldReminders[r] != nil {
|
||||
// continue outer loop
|
||||
continue
|
||||
}
|
||||
|
||||
// Add the new reminder
|
||||
_, err = x.Insert(TaskReminder{TaskID: t.ID, ReminderUnix: r})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
t.RemindersUnix = reminders
|
||||
if len(reminders) == 0 {
|
||||
t.RemindersUnix = nil
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
return
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ func GetTables() []interface{} {
|
||||
&ListTaskAssginee{},
|
||||
&Label{},
|
||||
&LabelTask{},
|
||||
&TaskReminder{},
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user