1
0

Put reminders in an extra table (#75)

This commit is contained in:
konrad
2019-05-25 07:33:57 +00:00
committed by Gitea
parent 802a13cffd
commit 24ce940885
11 changed files with 320 additions and 742 deletions

View 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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
}

View File

@ -47,6 +47,7 @@ func GetTables() []interface{} {
&ListTaskAssginee{},
&Label{},
&LabelTask{},
&TaskReminder{},
}
}