feat(caldav): add support for repeating tasks
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
Resolves https://github.com/go-vikunja/api/issues/57#issuecomment-1364373103
This commit is contained in:
parent
ea1d06bda6
commit
c5327845ee
@ -57,10 +57,12 @@ type Todo struct {
|
||||
RelatedToUID string
|
||||
Color string
|
||||
|
||||
Start time.Time
|
||||
End time.Time
|
||||
DueDate time.Time
|
||||
Duration time.Duration
|
||||
Start time.Time
|
||||
End time.Time
|
||||
DueDate time.Time
|
||||
Duration time.Duration
|
||||
RepeatAfter int64
|
||||
RepeatMode string
|
||||
|
||||
Created time.Time
|
||||
Updated time.Time // last-mod
|
||||
@ -225,6 +227,16 @@ CREATED:` + makeCalDavTimeFromTimeStamp(t.Created)
|
||||
PRIORITY:` + strconv.Itoa(mapPriorityToCaldav(t.Priority))
|
||||
}
|
||||
|
||||
if t.RepeatAfter > 0 || t.RepeatMode == "MONTHLY" {
|
||||
if t.RepeatMode == "MONTHLY" {
|
||||
caldavtodos += `
|
||||
RRULE:FREQ=MONTHLY;BYMONTHDAY=` + t.DueDate.Format("02") // Day of the month
|
||||
} else {
|
||||
caldavtodos += `
|
||||
RRULE:FREQ=SECONDLY;INTERVAL=` + strconv.FormatInt(t.RepeatAfter, 10)
|
||||
}
|
||||
}
|
||||
|
||||
caldavtodos += `
|
||||
LAST-MODIFIED:` + makeCalDavTimeFromTimeStamp(t.Updated)
|
||||
|
||||
|
@ -408,6 +408,77 @@ DESCRIPTION:Lorem Ipsum
|
||||
PRIORITY:9
|
||||
LAST-MODIFIED:00010101T000000Z
|
||||
END:VTODO
|
||||
END:VCALENDAR`,
|
||||
},
|
||||
{
|
||||
name: "with repeating monthly",
|
||||
args: args{
|
||||
config: &Config{
|
||||
Name: "test",
|
||||
ProdID: "RandomProdID which is not random",
|
||||
},
|
||||
todos: []*Todo{
|
||||
{
|
||||
Summary: "Todo #1",
|
||||
Description: "Lorem Ipsum",
|
||||
UID: "randommduid",
|
||||
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
|
||||
RepeatMode: "MONTHLY",
|
||||
DueDate: time.Unix(1543626724, 0).In(config.GetTimeZone()),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCaldavtasks: `BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
METHOD:PUBLISH
|
||||
X-PUBLISHED-TTL:PT4H
|
||||
X-WR-CALNAME:test
|
||||
PRODID:-//RandomProdID which is not random//EN
|
||||
BEGIN:VTODO
|
||||
UID:randommduid
|
||||
DTSTAMP:20181201T011204Z
|
||||
SUMMARY:Todo #1
|
||||
DESCRIPTION:Lorem Ipsum
|
||||
DUE:20181201T011204Z
|
||||
RRULE:FREQ=MONTHLY;BYMONTHDAY=01
|
||||
LAST-MODIFIED:00010101T000000Z
|
||||
END:VTODO
|
||||
END:VCALENDAR`,
|
||||
},
|
||||
{
|
||||
name: "with repeat mode default",
|
||||
args: args{
|
||||
config: &Config{
|
||||
Name: "test",
|
||||
ProdID: "RandomProdID which is not random",
|
||||
},
|
||||
todos: []*Todo{
|
||||
{
|
||||
Summary: "Todo #1",
|
||||
Description: "Lorem Ipsum",
|
||||
UID: "randommduid",
|
||||
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
|
||||
RepeatMode: "DEFAULT",
|
||||
DueDate: time.Unix(1543626724, 0).In(config.GetTimeZone()),
|
||||
RepeatAfter: 435,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCaldavtasks: `BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
METHOD:PUBLISH
|
||||
X-PUBLISHED-TTL:PT4H
|
||||
X-WR-CALNAME:test
|
||||
PRODID:-//RandomProdID which is not random//EN
|
||||
BEGIN:VTODO
|
||||
UID:randommduid
|
||||
DTSTAMP:20181201T011204Z
|
||||
SUMMARY:Todo #1
|
||||
DESCRIPTION:Lorem Ipsum
|
||||
DUE:20181201T011204Z
|
||||
RRULE:FREQ=SECONDLY;INTERVAL=435
|
||||
LAST-MODIFIED:00010101T000000Z
|
||||
END:VTODO
|
||||
END:VCALENDAR`,
|
||||
},
|
||||
}
|
||||
|
@ -35,6 +35,11 @@ func GetCaldavTodosForTasks(list *models.ListWithTasksAndBuckets, listTasks []*m
|
||||
|
||||
duration := t.EndDate.Sub(t.StartDate)
|
||||
|
||||
repeatMode := "DEFAULT"
|
||||
if t.RepeatMode == models.TaskRepeatModeMonth {
|
||||
repeatMode = "MONTHLY"
|
||||
}
|
||||
|
||||
caldavtodos = append(caldavtodos, &Todo{
|
||||
Timestamp: t.Updated,
|
||||
UID: t.UID,
|
||||
@ -42,13 +47,15 @@ func GetCaldavTodosForTasks(list *models.ListWithTasksAndBuckets, listTasks []*m
|
||||
Description: t.Description,
|
||||
Completed: t.DoneAt,
|
||||
// Organizer: &t.CreatedBy, // Disabled until we figure out how this works
|
||||
Priority: t.Priority,
|
||||
Start: t.StartDate,
|
||||
End: t.EndDate,
|
||||
Created: t.Created,
|
||||
Updated: t.Updated,
|
||||
DueDate: t.DueDate,
|
||||
Duration: duration,
|
||||
Priority: t.Priority,
|
||||
Start: t.StartDate,
|
||||
End: t.EndDate,
|
||||
Created: t.Created,
|
||||
Updated: t.Updated,
|
||||
DueDate: t.DueDate,
|
||||
Duration: duration,
|
||||
RepeatAfter: t.RepeatAfter,
|
||||
RepeatMode: repeatMode,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1369,7 +1369,7 @@ func setTaskDatesFromCurrentDateRepeat(oldTask, newTask *Task) {
|
||||
|
||||
// This helper function updates the reminders, doneAt, start and end dates of the *old* task
|
||||
// and saves the new values in the newTask object.
|
||||
// We make a few assumtions here:
|
||||
// We make a few assumptions here:
|
||||
// 1. Everything in oldTask is the truth - we figure out if we update anything at all if oldTask.RepeatAfter has a value > 0
|
||||
// 2. Because of 1., this functions should not be used to update values other than Done in the same go
|
||||
func updateDone(oldTask *Task, newTask *Task) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user