feat(caldav): Import Labels from caldav categories
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
cernst 2023-02-28 16:17:46 +01:00
parent fdb0169f13
commit ce47ef1270
6 changed files with 93 additions and 31 deletions

View File

@ -10,9 +10,9 @@ menu:
# Caldav
> **Warning:** The caldav integration is in an early alpha stage and has bugs.
> **Warning:** The caldav integration is in an early alpha stage and has bugs.
> It works well with some clients while having issues with others.
> If you encounter issues, please [report them](https://code.vikunja.io/api/issues/new?body=[caldav])
> If you encounter issues, please [report them](https://code.vikunja.io/api/issues/new?body=[caldav])
Vikunja supports managing tasks via the [caldav VTODO](https://tools.ietf.org/html/rfc5545#section-3.6.2) extension.
@ -37,6 +37,7 @@ Vikunja currently supports the following properties:
* `SUMMARY`
* `DESCRIPTION`
* `PRIORITY`
* `CATEGORIES`
* `COMPLETED`
* `DUE`
* `DTSTART`
@ -50,7 +51,6 @@ Vikunja currently supports the following properties:
Vikunja **currently does not** support these properties:
* `ATTACH`
* `CATEGORIES`
* `CLASS`
* `COMMENT`
* `GEO`

View File

@ -96,12 +96,15 @@ func ParseTaskFromVTODO(content string) (vTask *models.Task, err error) {
description := strings.ReplaceAll(task["DESCRIPTION"], "\\,", ",")
description = strings.ReplaceAll(description, "\\n", "\n")
categories := strings.Split(task["CATEGORIES"], ",")
labels := make([]*models.Label, 0, len(categories))
for _, category := range categories {
labels = append(labels, &models.Label{
Title: category,
})
var labels []*models.Label
if val, ok := task["CATEGORIES"]; ok {
categories := strings.Split(val, ",")
labels = make([]*models.Label, 0, len(categories))
for _, category := range categories {
labels = append(labels, &models.Label{
Title: category,
})
}
}
vTask = &models.Task{

View File

@ -176,15 +176,15 @@ func (l *Label) ReadAll(s *xorm.Session, a web.Auth, search string, page int, pe
// @Failure 500 {object} models.Message "Internal error"
// @Router /labels/{id} [get]
func (l *Label) ReadOne(s *xorm.Session, a web.Auth) (err error) {
label, err := getLabelByIDSimple(s, l.ID)
label, err := getLabelByExampleSimple(s, l)
if err != nil {
return err
return
}
*l = *label
u, err := user.GetUserByID(s, l.CreatedByID)
if err != nil {
return err
return
}
l.CreatedBy = u
@ -192,14 +192,16 @@ func (l *Label) ReadOne(s *xorm.Session, a web.Auth) (err error) {
}
func getLabelByIDSimple(s *xorm.Session, labelID int64) (*Label, error) {
label := Label{}
exists, err := s.ID(labelID).Get(&label)
if err != nil {
return &label, err
}
if !exists {
return &Label{}, ErrLabelDoesNotExist{labelID}
}
return &label, err
return getLabelByExampleSimple(s, &Label{ID: labelID})
}
func getLabelByExampleSimple(s *xorm.Session, l *Label) (*Label, error) {
exists, err := s.Get(l)
if err != nil {
return l, err
}
if !exists {
return &Label{}, ErrLabelDoesNotExist{l.ID}
}
return l, err
}

View File

@ -264,7 +264,7 @@ func getLabelsByTaskIDs(s *xorm.Session, opts *LabelByTaskIDsOptions) (ls []*lab
}
// Create or update a bunch of task labels
func (t *Task) updateTaskLabels(s *xorm.Session, creator web.Auth, labels []*Label) (err error) {
func (t *Task) UpdateTaskLabels(s *xorm.Session, creator web.Auth, labels []*Label) (err error) {
// If we don't have any new labels, delete everything right away. Saves us some hassle.
if len(labels) == 0 && len(t.Labels) > 0 {
@ -390,5 +390,5 @@ func (ltb *LabelTaskBulk) Create(s *xorm.Session, a web.Auth) (err error) {
for _, l := range labels {
task.Labels = append(task.Labels, &l.Label)
}
return task.updateTaskLabels(s, a, ltb.Labels)
return task.UpdateTaskLabels(s, a, ltb.Labels)
}

View File

@ -198,6 +198,21 @@ func TestLabel_ReadOne(t *testing.T) {
},
auth: &user.User{ID: 1},
},
{
name: "Get label by Title",
fields: fields{
Title: "Label #2",
},
want: &Label{
ID: 2,
Title: "Label #2",
CreatedByID: 1,
CreatedBy: user1,
Created: testCreatedTime,
Updated: testUpdatedTime,
},
auth: &user.User{ID: 1},
},
{
name: "Get nonexistant label",
fields: fields{
@ -259,9 +274,11 @@ func TestLabel_ReadOne(t *testing.T) {
s := db.NewSession()
allowed, _, _ := l.CanRead(s, tt.auth)
if !allowed && !tt.wantForbidden {
t.Errorf("Label.CanRead() forbidden, want %v", tt.wantForbidden)
if l.ID != 0 {
allowed, _, _ := l.CanRead(s, tt.auth)
if !allowed && !tt.wantForbidden {
t.Errorf("Label.CanRead() forbidden, want %v", tt.wantForbidden)
}
}
err := l.ReadOne(s, tt.auth)
if (err != nil) != tt.wantErr {

View File

@ -273,8 +273,28 @@ func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*da
return nil, errs.ForbiddenError
}
// Find or create Labels by title
// Insert label_task
for _, label := range vTask.Labels {
// Find or create Labels by title
err = label.ReadOne(s, vcls.user)
if err != nil {
err = label.Create(s, vcls.user)
if err != nil {
_ = s.Rollback()
return nil, err
}
err = label.ReadOne(s, vcls.user)
if err != nil {
_ = s.Rollback()
return nil, err
}
}
}
// Insert LabelTask relation
err = vcls.task.UpdateTaskLabels(s, vcls.user, vTask.Labels)
if err != nil {
_ = s.Rollback()
return nil, err
}
// Create the task
err = vTask.Create(s, vcls.user)
@ -321,8 +341,28 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da
return nil, errs.ForbiddenError
}
// Find or create Labels by title
// Update label_task
for _, label := range vTask.Labels {
// Find or create Labels by title
err = label.ReadOne(s, vcls.user)
if err != nil {
err = label.Create(s, vcls.user)
if err != nil {
_ = s.Rollback()
return nil, err
}
err = label.ReadOne(s, vcls.user)
if err != nil {
_ = s.Rollback()
return nil, err
}
}
}
// Update LabelTask relation
err = vcls.task.UpdateTaskLabels(s, vcls.user, vTask.Labels)
if err != nil {
_ = s.Rollback()
return nil, err
}
// Update the task
err = vTask.Update(s, vcls.user)