1
0

feat(caldav): Add support for subtasks (i.e. RELATED-TO property) in CalDAV (#1634)

As I mentioned [here](https://kolaente.dev/vikunja/api/pulls/1442#issuecomment-55215), this is mainly a cleanup of @zewaren 's original [PR](https://kolaente.dev/vikunja/api/pulls/1442).

It adds support for the `RELATED-TO` property in CalDAV's `VTODO` and the `RELTYPE=PARENT` and `RELTYPE=CHILD` relationships. In other words, it allows for `ParentTask->SubTask` relations to be handled supported through CalDAV.

In addition to the included tests, this has been tested by both @zewaren & myself with DAVx5 & Tasks (Android) and it's been working great.

Resolves https://kolaente.dev/vikunja/api/issues/1345

Co-authored-by: Miguel A. Arroyo <miguel@codeheads.dev>
Co-authored-by: Erwan Martin <public@fzwte.net>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/1634
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Miguel Arroyo <mayanez@noreply.kolaente.de>
Co-committed-by: Miguel Arroyo <mayanez@noreply.kolaente.de>
This commit is contained in:
Miguel Arroyo
2023-11-10 22:44:03 +00:00
committed by konrad
parent 6169c2e12e
commit 225d65268d
15 changed files with 1351 additions and 74 deletions

View File

@ -38,21 +38,21 @@ type Todo struct {
UID string
// Optional
Summary string
Description string
Completed time.Time
Organizer *user.User
Priority int64 // 0-9, 1 is highest
RelatedToUID string
Color string
Categories []string
Start time.Time
End time.Time
DueDate time.Time
Duration time.Duration
RepeatAfter int64
RepeatMode models.TaskRepeatMode
Alarms []Alarm
Summary string
Description string
Completed time.Time
Organizer *user.User
Priority int64 // 0-9, 1 is highest
Relations []Relation
Color string
Categories []string
Start time.Time
End time.Time
DueDate time.Time
Duration time.Duration
RepeatAfter int64
RepeatMode models.TaskRepeatMode
Alarms []Alarm
Created time.Time
Updated time.Time // last-mod
@ -66,6 +66,11 @@ type Alarm struct {
Description string
}
type Relation struct {
Type models.RelationKind
UID string
}
// Config is the caldav calendar config
type Config struct {
Name string
@ -147,11 +152,6 @@ STATUS:COMPLETED`
ORGANIZER;CN=:` + t.Organizer.Username
}
if t.RelatedToUID != "" {
caldavtodos += `
RELATED-TO:` + t.RelatedToUID
}
if t.DueDate.Unix() > 0 {
caldavtodos += `
DUE:` + makeCalDavTimeFromTimeStamp(t.DueDate)
@ -185,6 +185,7 @@ CATEGORIES:` + strings.Join(t.Categories, ",")
caldavtodos += `
LAST-MODIFIED:` + makeCalDavTimeFromTimeStamp(t.Updated)
caldavtodos += ParseAlarms(t.Alarms, t.Summary)
caldavtodos += ParseRelations(t.Relations)
caldavtodos += `
END:VTODO`
}
@ -222,6 +223,47 @@ END:VALARM`
return caldavalarms
}
func ParseRelations(relations []Relation) (caldavrelatedtos string) {
for _, r := range relations {
switch r.Type {
case models.RelationKindParenttask:
caldavrelatedtos += `
RELATED-TO;RELTYPE=PARENT:`
case models.RelationKindSubtask:
caldavrelatedtos += `
RELATED-TO;RELTYPE=CHILD:`
case models.RelationKindUnknown:
continue
case models.RelationKindRelated:
continue
case models.RelationKindDuplicateOf:
continue
case models.RelationKindDuplicates:
continue
case models.RelationKindBlocking:
continue
case models.RelationKindBlocked:
continue
case models.RelationKindPreceeds:
continue
case models.RelationKindFollows:
continue
case models.RelationKindCopiedFrom:
continue
case models.RelationKindCopiedTo:
continue
default:
caldavrelatedtos += `
RELATED-TO:`
}
caldavrelatedtos += r.UID
}
return caldavrelatedtos
}
func makeCalDavTimeFromTimeStamp(ts time.Time) (caldavtime string) {
return ts.In(time.UTC).Format(DateFormat) + "Z"
}