1
0

User Data Export and import (#967)

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/967
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
This commit is contained in:
konrad
2021-09-04 19:26:31 +00:00
parent fc51a3e76f
commit 90146aea5b
46 changed files with 2395 additions and 582 deletions

View File

@ -252,28 +252,30 @@ func parseDate(dateString string) (date time.Time, err error) {
return date, err
}
func convertTodoistToVikunja(sync *sync, doneItems map[int64]*doneItem) (fullVikunjaHierachie []*models.NamespaceWithLists, err error) {
func convertTodoistToVikunja(sync *sync, doneItems map[int64]*doneItem) (fullVikunjaHierachie []*models.NamespaceWithListsAndTasks, err error) {
newNamespace := &models.NamespaceWithLists{
newNamespace := &models.NamespaceWithListsAndTasks{
Namespace: models.Namespace{
Title: "Migrated from todoist",
},
}
// A map for all vikunja lists with the project id they're coming from as key
lists := make(map[int64]*models.List, len(sync.Projects))
lists := make(map[int64]*models.ListWithTasksAndBuckets, len(sync.Projects))
// A map for all vikunja tasks with the todoist task id as key to find them easily and add more data
tasks := make(map[int64]*models.Task, len(sync.Items))
tasks := make(map[int64]*models.TaskWithComments, len(sync.Items))
// A map for all vikunja labels with the todoist id as key to find them easier
labels := make(map[int64]*models.Label, len(sync.Labels))
for _, p := range sync.Projects {
list := &models.List{
Title: p.Name,
HexColor: todoistColors[p.Color],
IsArchived: p.IsArchived == 1,
list := &models.ListWithTasksAndBuckets{
List: models.List{
Title: p.Name,
HexColor: todoistColors[p.Color],
IsArchived: p.IsArchived == 1,
},
}
lists[p.ID] = list
@ -305,11 +307,13 @@ func convertTodoistToVikunja(sync *sync, doneItems map[int64]*doneItem) (fullVik
}
for _, i := range sync.Items {
task := &models.Task{
Title: i.Content,
Created: i.DateAdded.In(config.GetTimeZone()),
Done: i.Checked == 1,
BucketID: i.SectionID,
task := &models.TaskWithComments{
Task: models.Task{
Title: i.Content,
Created: i.DateAdded.In(config.GetTimeZone()),
Done: i.Checked == 1,
BucketID: i.SectionID,
},
}
// Only try to parse the task done at date if the task is actually done
@ -365,7 +369,7 @@ func convertTodoistToVikunja(sync *sync, doneItems map[int64]*doneItem) (fullVik
tasks[i.ParentID].RelatedTasks = make(models.RelatedTaskMap)
}
tasks[i.ParentID].RelatedTasks[models.RelationKindSubtask] = append(tasks[i.ParentID].RelatedTasks[models.RelationKindSubtask], tasks[i.ID])
tasks[i.ParentID].RelatedTasks[models.RelationKindSubtask] = append(tasks[i.ParentID].RelatedTasks[models.RelationKindSubtask], &tasks[i.ID].Task)
// Remove the task from the top level structure, otherwise it is added twice
outer:
@ -449,7 +453,7 @@ func convertTodoistToVikunja(sync *sync, doneItems map[int64]*doneItem) (fullVik
tasks[r.ItemID].Reminders = append(tasks[r.ItemID].Reminders, date.In(config.GetTimeZone()))
}
return []*models.NamespaceWithLists{
return []*models.NamespaceWithListsAndTasks{
newNamespace,
}, err
}

View File

@ -375,210 +375,258 @@ func TestConvertTodoistToVikunja(t *testing.T) {
},
}
expectedHierachie := []*models.NamespaceWithLists{
expectedHierachie := []*models.NamespaceWithListsAndTasks{
{
Namespace: models.Namespace{
Title: "Migrated from todoist",
},
Lists: []*models.List{
Lists: []*models.ListWithTasksAndBuckets{
{
Title: "Project1",
Description: "Lorem Ipsum dolor sit amet\nLorem Ipsum dolor sit amet 2\nLorem Ipsum dolor sit amet 3",
HexColor: todoistColors[30],
List: models.List{
Title: "Project1",
Description: "Lorem Ipsum dolor sit amet\nLorem Ipsum dolor sit amet 2\nLorem Ipsum dolor sit amet 3",
HexColor: todoistColors[30],
},
Buckets: []*models.Bucket{
{
ID: 1234,
Title: "Some Bucket",
},
},
Tasks: []*models.Task{
Tasks: []*models.TaskWithComments{
{
Title: "Task400000000",
Description: "Lorem Ipsum dolor sit amet",
Done: false,
Created: time1,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 0, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
time.Date(2020, time.June, 16, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
Task: models.Task{
Title: "Task400000000",
Description: "Lorem Ipsum dolor sit amet",
Done: false,
Created: time1,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 0, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
time.Date(2020, time.June, 16, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
},
},
},
{
Title: "Task400000001",
Description: "Lorem Ipsum dolor sit amet",
Done: false,
Created: time1,
},
{
Title: "Task400000002",
Done: false,
Created: time1,
Reminders: []time.Time{
time.Date(2020, time.July, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
Task: models.Task{
Title: "Task400000001",
Description: "Lorem Ipsum dolor sit amet",
Done: false,
Created: time1,
},
},
{
Title: "Task400000003",
Description: "Lorem Ipsum dolor sit amet",
Done: true,
DueDate: dueTime,
Created: time1,
DoneAt: time3,
Labels: vikunjaLabels,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
Task: models.Task{
Title: "Task400000002",
Done: false,
Created: time1,
Reminders: []time.Time{
time.Date(2020, time.July, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
},
},
},
{
Title: "Task400000004",
Done: false,
Created: time1,
Labels: vikunjaLabels,
},
{
Title: "Task400000005",
Done: true,
DueDate: dueTime,
Created: time1,
DoneAt: time3,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
Task: models.Task{
Title: "Task400000003",
Description: "Lorem Ipsum dolor sit amet",
Done: true,
DueDate: dueTime,
Created: time1,
DoneAt: time3,
Labels: vikunjaLabels,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
},
},
},
{
Title: "Task400000006",
Done: true,
DueDate: dueTime,
Created: time1,
DoneAt: time3,
RelatedTasks: map[models.RelationKind][]*models.Task{
models.RelationKindSubtask: {
Task: models.Task{
Title: "Task400000004",
Done: false,
Created: time1,
Labels: vikunjaLabels,
},
},
{
Task: models.Task{
Title: "Task400000005",
Done: true,
DueDate: dueTime,
Created: time1,
DoneAt: time3,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
},
},
},
{
Task: models.Task{
Title: "Task400000006",
Done: true,
DueDate: dueTime,
Created: time1,
DoneAt: time3,
RelatedTasks: map[models.RelationKind][]*models.Task{
models.RelationKindSubtask: {
{
Title: "Task with parent",
Done: false,
Priority: 2,
Created: time1,
DoneAt: nilTime,
},
},
},
},
},
{
Task: models.Task{
Title: "Task400000106",
Done: true,
DueDate: dueTimeWithTime,
Created: time1,
DoneAt: time3,
Labels: vikunjaLabels,
},
},
{
Task: models.Task{
Title: "Task400000107",
Done: true,
Created: time1,
DoneAt: time3,
},
},
{
Task: models.Task{
Title: "Task400000108",
Done: true,
Created: time1,
DoneAt: time3,
},
},
{
Task: models.Task{
Title: "Task400000109",
Done: true,
Created: time1,
DoneAt: time3,
BucketID: 1234,
},
},
},
},
{
List: models.List{
Title: "Project2",
Description: "Lorem Ipsum dolor sit amet 4\nLorem Ipsum dolor sit amet 5",
HexColor: todoistColors[37],
},
Tasks: []*models.TaskWithComments{
{
Task: models.Task{
Title: "Task400000007",
Done: false,
DueDate: dueTime,
Created: time1,
},
},
{
Task: models.Task{
Title: "Task400000008",
Done: false,
DueDate: dueTime,
Created: time1,
},
},
{
Task: models.Task{
Title: "Task400000009",
Done: false,
Created: time1,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
},
},
},
{
Task: models.Task{
Title: "Task400000010",
Description: "Lorem Ipsum dolor sit amet",
Done: true,
Created: time1,
DoneAt: time3,
},
},
{
Task: models.Task{
Title: "Task400000101",
Description: "Lorem Ipsum dolor sit amet",
Done: false,
Created: time1,
Attachments: []*models.TaskAttachment{
{
Title: "Task with parent",
Done: false,
Priority: 2,
Created: time1,
DoneAt: nilTime,
File: &files.File{
Name: "file.md",
Mime: "text/plain",
Size: 12345,
Created: time1,
FileContent: exampleFile,
},
Created: time1,
},
},
},
},
{
Title: "Task400000106",
Done: true,
DueDate: dueTimeWithTime,
Created: time1,
DoneAt: time3,
Labels: vikunjaLabels,
Task: models.Task{
Title: "Task400000102",
Done: false,
DueDate: dueTime,
Created: time1,
Labels: vikunjaLabels,
},
},
{
Title: "Task400000107",
Done: true,
Created: time1,
DoneAt: time3,
Task: models.Task{
Title: "Task400000103",
Done: false,
Created: time1,
Labels: vikunjaLabels,
},
},
{
Title: "Task400000108",
Done: true,
Created: time1,
DoneAt: time3,
Task: models.Task{
Title: "Task400000104",
Done: false,
Created: time1,
Labels: vikunjaLabels,
},
},
{
Title: "Task400000109",
Done: true,
Created: time1,
DoneAt: time3,
BucketID: 1234,
Task: models.Task{
Title: "Task400000105",
Done: false,
DueDate: dueTime,
Created: time1,
Labels: vikunjaLabels,
},
},
},
},
{
Title: "Project2",
Description: "Lorem Ipsum dolor sit amet 4\nLorem Ipsum dolor sit amet 5",
HexColor: todoistColors[37],
Tasks: []*models.Task{
{
Title: "Task400000007",
Done: false,
DueDate: dueTime,
Created: time1,
},
{
Title: "Task400000008",
Done: false,
DueDate: dueTime,
Created: time1,
},
{
Title: "Task400000009",
Done: false,
Created: time1,
Reminders: []time.Time{
time.Date(2020, time.June, 15, 7, 0, 0, 0, time.UTC).In(config.GetTimeZone()),
},
},
{
Title: "Task400000010",
Description: "Lorem Ipsum dolor sit amet",
Done: true,
Created: time1,
DoneAt: time3,
},
{
Title: "Task400000101",
Description: "Lorem Ipsum dolor sit amet",
Done: false,
Created: time1,
Attachments: []*models.TaskAttachment{
{
File: &files.File{
Name: "file.md",
Mime: "text/plain",
Size: 12345,
Created: time1,
FileContent: exampleFile,
},
Created: time1,
},
},
},
{
Title: "Task400000102",
Done: false,
DueDate: dueTime,
Created: time1,
Labels: vikunjaLabels,
},
{
Title: "Task400000103",
Done: false,
Created: time1,
Labels: vikunjaLabels,
},
{
Title: "Task400000104",
Done: false,
Created: time1,
Labels: vikunjaLabels,
},
{
Title: "Task400000105",
Done: false,
DueDate: dueTime,
Created: time1,
Labels: vikunjaLabels,
},
List: models.List{
Title: "Project3 - Archived",
HexColor: todoistColors[37],
IsArchived: true,
},
},
{
Title: "Project3 - Archived",
HexColor: todoistColors[37],
IsArchived: true,
Tasks: []*models.Task{
Tasks: []*models.TaskWithComments{
{
Title: "Task400000111",
Done: true,
Created: time1,
DoneAt: time3,
Task: models.Task{
Title: "Task400000111",
Done: true,
Created: time1,
DoneAt: time3,
},
},
},
},