feat: rename lists to projects
This commit is contained in:
@ -31,7 +31,7 @@ import (
|
||||
|
||||
// InsertFromStructure takes a fully nested Vikunja data structure and a user and then creates everything for this user
|
||||
// (Namespaces, tasks, etc. Even attachments and relations.)
|
||||
func InsertFromStructure(str []*models.NamespaceWithListsAndTasks, user *user.User) (err error) {
|
||||
func InsertFromStructure(str []*models.NamespaceWithProjectsAndTasks, user *user.User) (err error) {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
@ -45,13 +45,13 @@ func InsertFromStructure(str []*models.NamespaceWithListsAndTasks, user *user.Us
|
||||
return s.Commit()
|
||||
}
|
||||
|
||||
func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTasks, user *user.User) (err error) {
|
||||
func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithProjectsAndTasks, user *user.User) (err error) {
|
||||
|
||||
log.Debugf("[creating structure] Creating %d namespaces", len(str))
|
||||
|
||||
labels := make(map[string]*models.Label)
|
||||
|
||||
archivedLists := []int64{}
|
||||
archivedProjects := []int64{}
|
||||
archivedNamespaces := []int64{}
|
||||
|
||||
// Create all namespaces
|
||||
@ -75,18 +75,18 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
||||
}
|
||||
|
||||
log.Debugf("[creating structure] Created namespace %d", n.ID)
|
||||
log.Debugf("[creating structure] Creating %d lists", len(n.Lists))
|
||||
log.Debugf("[creating structure] Creating %d projects", len(n.Projects))
|
||||
|
||||
// Create all lists
|
||||
for _, l := range n.Lists {
|
||||
// The tasks and bucket slices are going to be reset during the creation of the list so we rescue it here
|
||||
// to be able to still loop over them aftere the list was created.
|
||||
// Create all projects
|
||||
for _, l := range n.Projects {
|
||||
// The tasks and bucket slices are going to be reset during the creation of the project so we rescue it here
|
||||
// to be able to still loop over them aftere the project was created.
|
||||
tasks := l.Tasks
|
||||
originalBuckets := l.Buckets
|
||||
originalBackgroundInformation := l.BackgroundInformation
|
||||
needsDefaultBucket := false
|
||||
|
||||
// Saving the archived status to archive the list again after creating it
|
||||
// Saving the archived status to archive the project again after creating it
|
||||
var wasArchived bool
|
||||
if l.IsArchived {
|
||||
wasArchived = true
|
||||
@ -101,24 +101,24 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
||||
}
|
||||
|
||||
if wasArchived {
|
||||
archivedLists = append(archivedLists, l.ID)
|
||||
archivedProjects = append(archivedProjects, l.ID)
|
||||
}
|
||||
|
||||
log.Debugf("[creating structure] Created list %d", l.ID)
|
||||
log.Debugf("[creating structure] Created project %d", l.ID)
|
||||
|
||||
bf, is := originalBackgroundInformation.(*bytes.Buffer)
|
||||
if is {
|
||||
|
||||
backgroundFile := bytes.NewReader(bf.Bytes())
|
||||
|
||||
log.Debugf("[creating structure] Creating a background file for list %d", l.ID)
|
||||
log.Debugf("[creating structure] Creating a background file for project %d", l.ID)
|
||||
|
||||
err = handler.SaveBackgroundFile(s, user, &l.List, backgroundFile, "", uint64(backgroundFile.Len()))
|
||||
err = handler.SaveBackgroundFile(s, user, &l.Project, backgroundFile, "", uint64(backgroundFile.Len()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("[creating structure] Created a background file for list %d", l.ID)
|
||||
log.Debugf("[creating structure] Created a background file for project %d", l.ID)
|
||||
}
|
||||
|
||||
// Create all buckets
|
||||
@ -129,7 +129,7 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
||||
for _, bucket := range originalBuckets {
|
||||
oldID := bucket.ID
|
||||
bucket.ID = 0 // We want a new id
|
||||
bucket.ListID = l.ID
|
||||
bucket.ProjectID = l.ID
|
||||
err = bucket.Create(s, user)
|
||||
if err != nil {
|
||||
return
|
||||
@ -157,7 +157,7 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
||||
for _, t := range tasks {
|
||||
setBucketOrDefault(&t.Task)
|
||||
|
||||
t.ListID = l.ID
|
||||
t.ProjectID = l.ID
|
||||
err = t.Create(s, user)
|
||||
if err != nil {
|
||||
return
|
||||
@ -179,7 +179,7 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
||||
// First create the related tasks if they do not exist
|
||||
if rt.ID == 0 {
|
||||
setBucketOrDefault(rt)
|
||||
rt.ListID = t.ListID
|
||||
rt.ProjectID = t.ProjectID
|
||||
err = rt.Create(s, user)
|
||||
if err != nil {
|
||||
return
|
||||
@ -263,7 +263,7 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
||||
|
||||
// All tasks brought their own bucket with them, therefore the newly created default bucket is just extra space
|
||||
if !needsDefaultBucket {
|
||||
b := &models.Bucket{ListID: l.ID}
|
||||
b := &models.Bucket{ProjectID: l.ID}
|
||||
bucketsIn, _, _, err := b.ReadAll(s, user, "", 1, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -280,11 +280,11 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithListsAndTas
|
||||
}
|
||||
}
|
||||
|
||||
if len(archivedLists) > 0 {
|
||||
if len(archivedProjects) > 0 {
|
||||
_, err = s.
|
||||
Cols("is_archived").
|
||||
In("id", archivedLists).
|
||||
Update(&models.List{IsArchived: true})
|
||||
In("id", archivedProjects).
|
||||
Update(&models.Project{IsArchived: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -32,16 +32,16 @@ func TestInsertFromStructure(t *testing.T) {
|
||||
}
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
testStructure := []*models.NamespaceWithListsAndTasks{
|
||||
testStructure := []*models.NamespaceWithProjectsAndTasks{
|
||||
{
|
||||
Namespace: models.Namespace{
|
||||
Title: "Test1",
|
||||
Description: "Lorem Ipsum",
|
||||
},
|
||||
Lists: []*models.ListWithTasksAndBuckets{
|
||||
Projects: []*models.ProjectWithTasksAndBuckets{
|
||||
{
|
||||
List: models.List{
|
||||
Title: "Testlist1",
|
||||
Project: models.Project{
|
||||
Title: "Testproject1",
|
||||
Description: "Something",
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
@ -133,19 +133,19 @@ func TestInsertFromStructure(t *testing.T) {
|
||||
"title": testStructure[0].Namespace.Title,
|
||||
"description": testStructure[0].Namespace.Description,
|
||||
}, false)
|
||||
db.AssertExists(t, "lists", map[string]interface{}{
|
||||
"title": testStructure[0].Lists[0].Title,
|
||||
"description": testStructure[0].Lists[0].Description,
|
||||
db.AssertExists(t, "projects", map[string]interface{}{
|
||||
"title": testStructure[0].Projects[0].Title,
|
||||
"description": testStructure[0].Projects[0].Description,
|
||||
}, false)
|
||||
db.AssertExists(t, "tasks", map[string]interface{}{
|
||||
"title": testStructure[0].Lists[0].Tasks[5].Title,
|
||||
"bucket_id": testStructure[0].Lists[0].Buckets[0].ID,
|
||||
"title": testStructure[0].Projects[0].Tasks[5].Title,
|
||||
"bucket_id": testStructure[0].Projects[0].Buckets[0].ID,
|
||||
}, false)
|
||||
db.AssertMissing(t, "tasks", map[string]interface{}{
|
||||
"title": testStructure[0].Lists[0].Tasks[6].Title,
|
||||
"title": testStructure[0].Projects[0].Tasks[6].Title,
|
||||
"bucket_id": 1111, // No task with that bucket should exist
|
||||
})
|
||||
assert.NotEqual(t, 0, testStructure[0].Lists[0].Tasks[0].BucketID) // Should get the default bucket
|
||||
assert.NotEqual(t, 0, testStructure[0].Lists[0].Tasks[6].BucketID) // Should get the default bucket
|
||||
assert.NotEqual(t, 0, testStructure[0].Projects[0].Tasks[0].BucketID) // Should get the default bucket
|
||||
assert.NotEqual(t, 0, testStructure[0].Projects[0].Tasks[6].BucketID) // Should get the default bucket
|
||||
})
|
||||
}
|
||||
|
@ -98,19 +98,19 @@ type tasksResponse struct {
|
||||
Value []*task `json:"value"`
|
||||
}
|
||||
|
||||
type list struct {
|
||||
ID string `json:"id"`
|
||||
OdataEtag string `json:"@odata.etag"`
|
||||
DisplayName string `json:"displayName"`
|
||||
IsOwner bool `json:"isOwner"`
|
||||
IsShared bool `json:"isShared"`
|
||||
WellknownListName string `json:"wellknownListName"`
|
||||
Tasks []*task `json:"-"` // This field does not exist in the api, we're just using it to return a structure with everything at once
|
||||
type project struct {
|
||||
ID string `json:"id"`
|
||||
OdataEtag string `json:"@odata.etag"`
|
||||
DisplayName string `json:"displayName"`
|
||||
IsOwner bool `json:"isOwner"`
|
||||
IsShared bool `json:"isShared"`
|
||||
WellknownProjectName string `json:"wellknownProjectName"`
|
||||
Tasks []*task `json:"-"` // This field does not exist in the api, we're just using it to return a structure with everything at once
|
||||
}
|
||||
|
||||
type listsResponse struct {
|
||||
OdataContext string `json:"@odata.context"`
|
||||
Value []*list `json:"value"`
|
||||
type projectsResponse struct {
|
||||
OdataContext string `json:"@odata.context"`
|
||||
Value []*project `json:"value"`
|
||||
}
|
||||
|
||||
func (dtt *dateTimeTimeZone) toTime() (t time.Time, err error) {
|
||||
@ -213,22 +213,22 @@ func makeAuthenticatedGetRequest(token, urlPart string, v interface{}) error {
|
||||
return json.Unmarshal(buf.Bytes(), v)
|
||||
}
|
||||
|
||||
func getMicrosoftTodoData(token string) (microsoftTodoData []*list, err error) {
|
||||
func getMicrosoftTodoData(token string) (microsoftTodoData []*project, err error) {
|
||||
|
||||
microsoftTodoData = []*list{}
|
||||
microsoftTodoData = []*project{}
|
||||
|
||||
lists := &listsResponse{}
|
||||
err = makeAuthenticatedGetRequest(token, "lists", lists)
|
||||
projects := &projectsResponse{}
|
||||
err = makeAuthenticatedGetRequest(token, "projects", projects)
|
||||
if err != nil {
|
||||
log.Errorf("[Microsoft Todo Migration] Could not get lists: %s", err)
|
||||
log.Errorf("[Microsoft Todo Migration] Could not get projects: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("[Microsoft Todo Migration] Got %d lists", len(lists.Value))
|
||||
log.Debugf("[Microsoft Todo Migration] Got %d projects", len(projects.Value))
|
||||
|
||||
for _, list := range lists.Value {
|
||||
link := "lists/" + list.ID + "/tasks"
|
||||
list.Tasks = []*task{}
|
||||
for _, project := range projects.Value {
|
||||
link := "projects/" + project.ID + "/tasks"
|
||||
project.Tasks = []*task{}
|
||||
|
||||
// Microsoft's Graph API has pagination, so we're going through all pages to get all tasks
|
||||
for {
|
||||
@ -236,13 +236,13 @@ func getMicrosoftTodoData(token string) (microsoftTodoData []*list, err error) {
|
||||
|
||||
err = makeAuthenticatedGetRequest(token, link, tr)
|
||||
if err != nil {
|
||||
log.Errorf("[Microsoft Todo Migration] Could not get tasks for list %s: %s", list.ID, err)
|
||||
log.Errorf("[Microsoft Todo Migration] Could not get tasks for project %s: %s", project.ID, err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("[Microsoft Todo Migration] Got %d tasks for list %s", len(tr.Value), list.ID)
|
||||
log.Debugf("[Microsoft Todo Migration] Got %d tasks for project %s", len(tr.Value), project.ID)
|
||||
|
||||
list.Tasks = append(list.Tasks, tr.Value...)
|
||||
project.Tasks = append(project.Tasks, tr.Value...)
|
||||
|
||||
if tr.Nextlink == "" {
|
||||
break
|
||||
@ -251,35 +251,35 @@ func getMicrosoftTodoData(token string) (microsoftTodoData []*list, err error) {
|
||||
link = strings.ReplaceAll(tr.Nextlink, apiPrefix, "")
|
||||
}
|
||||
|
||||
microsoftTodoData = append(microsoftTodoData, list)
|
||||
microsoftTodoData = append(microsoftTodoData, project)
|
||||
}
|
||||
|
||||
log.Debugf("[Microsoft Todo Migration] Got all tasks for %d lists", len(lists.Value))
|
||||
log.Debugf("[Microsoft Todo Migration] Got all tasks for %d projects", len(projects.Value))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func convertMicrosoftTodoData(todoData []*list) (vikunjsStructure []*models.NamespaceWithListsAndTasks, err error) {
|
||||
func convertMicrosoftTodoData(todoData []*project) (vikunjsStructure []*models.NamespaceWithProjectsAndTasks, err error) {
|
||||
|
||||
// One namespace with all lists
|
||||
vikunjsStructure = []*models.NamespaceWithListsAndTasks{
|
||||
// One namespace with all projects
|
||||
vikunjsStructure = []*models.NamespaceWithProjectsAndTasks{
|
||||
{
|
||||
Namespace: models.Namespace{
|
||||
Title: "Migrated from Microsoft Todo",
|
||||
},
|
||||
Lists: []*models.ListWithTasksAndBuckets{},
|
||||
Projects: []*models.ProjectWithTasksAndBuckets{},
|
||||
},
|
||||
}
|
||||
|
||||
log.Debugf("[Microsoft Todo Migration] Converting %d lists", len(todoData))
|
||||
log.Debugf("[Microsoft Todo Migration] Converting %d projects", len(todoData))
|
||||
|
||||
for _, l := range todoData {
|
||||
|
||||
log.Debugf("[Microsoft Todo Migration] Converting list %s", l.ID)
|
||||
log.Debugf("[Microsoft Todo Migration] Converting project %s", l.ID)
|
||||
|
||||
// Lists only with title
|
||||
list := &models.ListWithTasksAndBuckets{
|
||||
List: models.List{
|
||||
// Projects only with title
|
||||
project := &models.ProjectWithTasksAndBuckets{
|
||||
Project: models.Project{
|
||||
Title: l.DisplayName,
|
||||
},
|
||||
}
|
||||
@ -358,19 +358,19 @@ func convertMicrosoftTodoData(todoData []*list) (vikunjsStructure []*models.Name
|
||||
}
|
||||
}
|
||||
|
||||
list.Tasks = append(list.Tasks, &models.TaskWithComments{Task: *task})
|
||||
project.Tasks = append(project.Tasks, &models.TaskWithComments{Task: *task})
|
||||
log.Debugf("[Microsoft Todo Migration] Done converted %d tasks", len(l.Tasks))
|
||||
}
|
||||
|
||||
vikunjsStructure[0].Lists = append(vikunjsStructure[0].Lists, list)
|
||||
log.Debugf("[Microsoft Todo Migration] Done converting list %s", l.ID)
|
||||
vikunjsStructure[0].Projects = append(vikunjsStructure[0].Projects, project)
|
||||
log.Debugf("[Microsoft Todo Migration] Done converting project %s", l.ID)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Migrate gets all tasks from Microsoft Todo for a user and puts them into vikunja
|
||||
// @Summary Migrate all lists, tasks etc. from Microsoft Todo
|
||||
// @Summary Migrate all projects, tasks etc. from Microsoft Todo
|
||||
// @Description Migrates all tasklinsts, tasks, notes and reminders from Microsoft Todo to Vikunja.
|
||||
// @tags migration
|
||||
// @Accept json
|
||||
|
@ -35,9 +35,9 @@ func TestConverting(t *testing.T) {
|
||||
testtimeTime, err := time.Parse(time.RFC3339Nano, "2020-12-18T03:00:00.4770000Z")
|
||||
assert.NoError(t, err)
|
||||
|
||||
microsoftTodoData := []*list{
|
||||
microsoftTodoData := []*project{
|
||||
{
|
||||
DisplayName: "List 1",
|
||||
DisplayName: "Project 1",
|
||||
Tasks: []*task{
|
||||
{
|
||||
Title: "Task 1",
|
||||
@ -88,7 +88,7 @@ func TestConverting(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
DisplayName: "List 2",
|
||||
DisplayName: "Project 2",
|
||||
Tasks: []*task{
|
||||
{
|
||||
Title: "Task 1",
|
||||
@ -102,15 +102,15 @@ func TestConverting(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
expectedHierachie := []*models.NamespaceWithListsAndTasks{
|
||||
expectedHierachie := []*models.NamespaceWithProjectsAndTasks{
|
||||
{
|
||||
Namespace: models.Namespace{
|
||||
Title: "Migrated from Microsoft Todo",
|
||||
},
|
||||
Lists: []*models.ListWithTasksAndBuckets{
|
||||
Projects: []*models.ProjectWithTasksAndBuckets{
|
||||
{
|
||||
List: models.List{
|
||||
Title: "List 1",
|
||||
Project: models.Project{
|
||||
Title: "Project 1",
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
@ -162,8 +162,8 @@ func TestConverting(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
List: models.List{
|
||||
Title: "List 2",
|
||||
Project: models.Project{
|
||||
Title: "Project 2",
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ type Migrator interface {
|
||||
// FileMigrator handles importing Vikunja data from a file. The implementation of it determines the format.
|
||||
type FileMigrator interface {
|
||||
MigratorName
|
||||
// Migrate is the interface used to migrate a user's tasks, list and other things from a file to vikunja.
|
||||
// Migrate is the interface used to migrate a user's tasks, project and other things from a file to vikunja.
|
||||
// The user object is the user who's tasks will be migrated.
|
||||
Migrate(user *user.User, file io.ReaderAt, size int64) error
|
||||
}
|
||||
|
@ -105,21 +105,21 @@ func parseDurationPart(value string, unit time.Duration) time.Duration {
|
||||
return 0
|
||||
}
|
||||
|
||||
func convertTickTickToVikunja(tasks []*tickTickTask) (result []*models.NamespaceWithListsAndTasks) {
|
||||
namespace := &models.NamespaceWithListsAndTasks{
|
||||
func convertTickTickToVikunja(tasks []*tickTickTask) (result []*models.NamespaceWithProjectsAndTasks) {
|
||||
namespace := &models.NamespaceWithProjectsAndTasks{
|
||||
Namespace: models.Namespace{
|
||||
Title: "Migrated from TickTick",
|
||||
},
|
||||
Lists: []*models.ListWithTasksAndBuckets{},
|
||||
Projects: []*models.ProjectWithTasksAndBuckets{},
|
||||
}
|
||||
|
||||
lists := make(map[string]*models.ListWithTasksAndBuckets)
|
||||
projects := make(map[string]*models.ProjectWithTasksAndBuckets)
|
||||
for _, t := range tasks {
|
||||
_, has := lists[t.ListName]
|
||||
_, has := projects[t.ProjectName]
|
||||
if !has {
|
||||
lists[t.ListName] = &models.ListWithTasksAndBuckets{
|
||||
List: models.List{
|
||||
Title: t.ListName,
|
||||
projects[t.ProjectName] = &models.ProjectWithTasksAndBuckets{
|
||||
Project: models.Project{
|
||||
Title: t.ProjectName,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -158,18 +158,18 @@ func convertTickTickToVikunja(tasks []*tickTickTask) (result []*models.Namespace
|
||||
}
|
||||
}
|
||||
|
||||
lists[t.ListName].Tasks = append(lists[t.ListName].Tasks, task)
|
||||
projects[t.ProjectName].Tasks = append(projects[t.ProjectName].Tasks, task)
|
||||
}
|
||||
|
||||
for _, l := range lists {
|
||||
namespace.Lists = append(namespace.Lists, l)
|
||||
for _, l := range projects {
|
||||
namespace.Projects = append(namespace.Projects, l)
|
||||
}
|
||||
|
||||
sort.Slice(namespace.Lists, func(i, j int) bool {
|
||||
return namespace.Lists[i].Title < namespace.Lists[j].Title
|
||||
sort.Slice(namespace.Projects, func(i, j int) bool {
|
||||
return namespace.Projects[i].Title < namespace.Projects[j].Title
|
||||
})
|
||||
|
||||
return []*models.NamespaceWithListsAndTasks{namespace}
|
||||
return []*models.NamespaceWithProjectsAndTasks{namespace}
|
||||
}
|
||||
|
||||
// Name is used to get the name of the ticktick migration - we're using the docs here to annotate the status route.
|
||||
@ -202,7 +202,7 @@ func newLineSkipDecoder(r io.Reader, linesToSkip int) gocsv.SimpleDecoder {
|
||||
}
|
||||
|
||||
// Migrate takes a ticktick export, parses it and imports everything in it into Vikunja.
|
||||
// @Summary Import all lists, tasks etc. from a TickTick backup export
|
||||
// @Summary Import all projects, tasks etc. from a TickTick backup export
|
||||
// @Description Imports all projects, tasks, notes, reminders, subtasks and files from a TickTick backup export into Vikunja.
|
||||
// @tags migration
|
||||
// @Accept json
|
||||
|
@ -40,76 +40,76 @@ func TestConvertTicktickTasksToVikunja(t *testing.T) {
|
||||
|
||||
tickTickTasks := []*tickTickTask{
|
||||
{
|
||||
TaskID: 1,
|
||||
ParentID: 0,
|
||||
ListName: "List 1",
|
||||
Title: "Test task 1",
|
||||
Tags: []string{"label1", "label2"},
|
||||
Content: "Lorem Ipsum Dolor sit amet",
|
||||
StartDate: time1,
|
||||
DueDate: time2,
|
||||
Reminder: duration,
|
||||
Repeat: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20190117T210000Z",
|
||||
Status: "0",
|
||||
Order: -1099511627776,
|
||||
TaskID: 1,
|
||||
ParentID: 0,
|
||||
ProjectName: "Project 1",
|
||||
Title: "Test task 1",
|
||||
Tags: []string{"label1", "label2"},
|
||||
Content: "Lorem Ipsum Dolor sit amet",
|
||||
StartDate: time1,
|
||||
DueDate: time2,
|
||||
Reminder: duration,
|
||||
Repeat: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20190117T210000Z",
|
||||
Status: "0",
|
||||
Order: -1099511627776,
|
||||
},
|
||||
{
|
||||
TaskID: 2,
|
||||
ParentID: 1,
|
||||
ListName: "List 1",
|
||||
ProjectName: "Project 1",
|
||||
Title: "Test task 2",
|
||||
Status: "1",
|
||||
CompletedTime: time3,
|
||||
Order: -1099511626,
|
||||
},
|
||||
{
|
||||
TaskID: 3,
|
||||
ParentID: 0,
|
||||
ListName: "List 1",
|
||||
Title: "Test task 3",
|
||||
Tags: []string{"label1", "label2", "other label"},
|
||||
StartDate: time1,
|
||||
DueDate: time2,
|
||||
Reminder: duration,
|
||||
Status: "0",
|
||||
Order: -109951627776,
|
||||
TaskID: 3,
|
||||
ParentID: 0,
|
||||
ProjectName: "Project 1",
|
||||
Title: "Test task 3",
|
||||
Tags: []string{"label1", "label2", "other label"},
|
||||
StartDate: time1,
|
||||
DueDate: time2,
|
||||
Reminder: duration,
|
||||
Status: "0",
|
||||
Order: -109951627776,
|
||||
},
|
||||
{
|
||||
TaskID: 4,
|
||||
ParentID: 0,
|
||||
ListName: "List 2",
|
||||
Title: "Test task 4",
|
||||
Status: "0",
|
||||
Order: -109951627777,
|
||||
TaskID: 4,
|
||||
ParentID: 0,
|
||||
ProjectName: "Project 2",
|
||||
Title: "Test task 4",
|
||||
Status: "0",
|
||||
Order: -109951627777,
|
||||
},
|
||||
}
|
||||
|
||||
vikunjaTasks := convertTickTickToVikunja(tickTickTasks)
|
||||
|
||||
assert.Len(t, vikunjaTasks, 1)
|
||||
assert.Len(t, vikunjaTasks[0].Lists, 2)
|
||||
assert.Len(t, vikunjaTasks[0].Projects, 2)
|
||||
|
||||
assert.Len(t, vikunjaTasks[0].Lists[0].Tasks, 3)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Title, tickTickTasks[0].ListName)
|
||||
assert.Len(t, vikunjaTasks[0].Projects[0].Tasks, 3)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Title, tickTickTasks[0].ProjectName)
|
||||
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].Title, tickTickTasks[0].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].Description, tickTickTasks[0].Content)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].StartDate, tickTickTasks[0].StartDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].EndDate, tickTickTasks[0].DueDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].DueDate, tickTickTasks[0].DueDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].Labels, []*models.Label{
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].Title, tickTickTasks[0].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].Description, tickTickTasks[0].Content)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].StartDate, tickTickTasks[0].StartDate)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].EndDate, tickTickTasks[0].DueDate)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].DueDate, tickTickTasks[0].DueDate)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].Labels, []*models.Label{
|
||||
{Title: "label1"},
|
||||
{Title: "label2"},
|
||||
})
|
||||
//assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].Reminders, tickTickTasks[0].) // TODO
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].Position, tickTickTasks[0].Order)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].Done, false)
|
||||
//assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].Reminders, tickTickTasks[0].) // TODO
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].Position, tickTickTasks[0].Order)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].Done, false)
|
||||
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[1].Title, tickTickTasks[1].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[1].Position, tickTickTasks[1].Order)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[1].Done, true)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[1].DoneAt, tickTickTasks[1].CompletedTime.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[1].RelatedTasks, models.RelatedTaskMap{
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[1].Title, tickTickTasks[1].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[1].Position, tickTickTasks[1].Order)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[1].Done, true)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[1].DoneAt, tickTickTasks[1].CompletedTime.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[1].RelatedTasks, models.RelatedTaskMap{
|
||||
models.RelationKindParenttask: []*models.Task{
|
||||
{
|
||||
ID: tickTickTasks[1].ParentID,
|
||||
@ -117,23 +117,23 @@ func TestConvertTicktickTasksToVikunja(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].Title, tickTickTasks[2].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].Description, tickTickTasks[2].Content)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].StartDate, tickTickTasks[2].StartDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].EndDate, tickTickTasks[2].DueDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].DueDate, tickTickTasks[2].DueDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].Labels, []*models.Label{
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].Title, tickTickTasks[2].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].Description, tickTickTasks[2].Content)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].StartDate, tickTickTasks[2].StartDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].EndDate, tickTickTasks[2].DueDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].DueDate, tickTickTasks[2].DueDate.Time)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].Labels, []*models.Label{
|
||||
{Title: "label1"},
|
||||
{Title: "label2"},
|
||||
{Title: "other label"},
|
||||
})
|
||||
//assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[0].Reminders, tickTickTasks[0].) // TODO
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].Position, tickTickTasks[2].Order)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[0].Tasks[2].Done, false)
|
||||
//assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[0].Reminders, tickTickTasks[0].) // TODO
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].Position, tickTickTasks[2].Order)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[0].Tasks[2].Done, false)
|
||||
|
||||
assert.Len(t, vikunjaTasks[0].Lists[1].Tasks, 1)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[1].Title, tickTickTasks[3].ListName)
|
||||
assert.Len(t, vikunjaTasks[0].Projects[1].Tasks, 1)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[1].Title, tickTickTasks[3].ProjectName)
|
||||
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[1].Tasks[0].Title, tickTickTasks[3].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Lists[1].Tasks[0].Position, tickTickTasks[3].Order)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[1].Tasks[0].Title, tickTickTasks[3].Title)
|
||||
assert.Equal(t, vikunjaTasks[0].Projects[1].Tasks[0].Position, tickTickTasks[3].Order)
|
||||
}
|
||||
|
@ -363,14 +363,14 @@ func TestConvertTodoistToVikunja(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
expectedHierachie := []*models.NamespaceWithListsAndTasks{
|
||||
expectedHierachie := []*models.NamespaceWithProjectsAndTasks{
|
||||
{
|
||||
Namespace: models.Namespace{
|
||||
Title: "Migrated from todoist",
|
||||
},
|
||||
Lists: []*models.ListWithTasksAndBuckets{
|
||||
Projects: []*models.ProjectWithTasksAndBuckets{
|
||||
{
|
||||
List: models.List{
|
||||
Project: models.Project{
|
||||
Title: "Project1",
|
||||
Description: "Lorem Ipsum dolor sit amet\nLorem Ipsum dolor sit amet 2\nLorem Ipsum dolor sit amet 3",
|
||||
HexColor: todoistColors["berry_red"],
|
||||
@ -504,7 +504,7 @@ func TestConvertTodoistToVikunja(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
List: models.List{
|
||||
Project: models.Project{
|
||||
Title: "Project2",
|
||||
Description: "Lorem Ipsum dolor sit amet 4\nLorem Ipsum dolor sit amet 5",
|
||||
HexColor: todoistColors["mint_green"],
|
||||
@ -602,7 +602,7 @@ func TestConvertTodoistToVikunja(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
List: models.List{
|
||||
Project: models.Project{
|
||||
Title: "Project3 - Archived",
|
||||
HexColor: todoistColors["mint_green"],
|
||||
IsArchived: true,
|
||||
|
@ -99,14 +99,14 @@ func getTrelloData(token string) (trelloData []*trello.Board, err error) {
|
||||
log.Debugf("[Trello Migration] Got %d trello boards", len(trelloData))
|
||||
|
||||
for _, board := range trelloData {
|
||||
log.Debugf("[Trello Migration] Getting lists for board %s", board.ID)
|
||||
log.Debugf("[Trello Migration] Getting projects for board %s", board.ID)
|
||||
|
||||
board.Lists, err = board.GetLists(trello.Defaults())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got %d lists for board %s", len(board.Lists), board.ID)
|
||||
log.Debugf("[Trello Migration] Got %d projects for board %s", len(board.Lists), board.ID)
|
||||
|
||||
listMap := make(map[string]*trello.List, len(board.Lists))
|
||||
for _, list := range board.Lists {
|
||||
@ -161,27 +161,27 @@ func getTrelloData(token string) (trelloData []*trello.Board, err error) {
|
||||
}
|
||||
|
||||
// Converts all previously obtained data from trello into the vikunja format.
|
||||
// `trelloData` should contain all boards with their lists and cards respectively.
|
||||
func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullVikunjaHierachie []*models.NamespaceWithListsAndTasks, err error) {
|
||||
// `trelloData` should contain all boards with their projects and cards respectively.
|
||||
func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullVikunjaHierachie []*models.NamespaceWithProjectsAndTasks, err error) {
|
||||
|
||||
log.Debugf("[Trello Migration] ")
|
||||
|
||||
fullVikunjaHierachie = []*models.NamespaceWithListsAndTasks{
|
||||
fullVikunjaHierachie = []*models.NamespaceWithProjectsAndTasks{
|
||||
{
|
||||
Namespace: models.Namespace{
|
||||
Title: "Imported from Trello",
|
||||
},
|
||||
Lists: []*models.ListWithTasksAndBuckets{},
|
||||
Projects: []*models.ProjectWithTasksAndBuckets{},
|
||||
},
|
||||
}
|
||||
|
||||
var bucketID int64 = 1
|
||||
|
||||
log.Debugf("[Trello Migration] Converting %d boards to vikunja lists", len(trelloData))
|
||||
log.Debugf("[Trello Migration] Converting %d boards to vikunja projects", len(trelloData))
|
||||
|
||||
for _, board := range trelloData {
|
||||
list := &models.ListWithTasksAndBuckets{
|
||||
List: models.List{
|
||||
project := &models.ProjectWithTasksAndBuckets{
|
||||
Project: models.Project{
|
||||
Title: board.Name,
|
||||
Description: board.Desc,
|
||||
IsArchived: board.Closed,
|
||||
@ -189,7 +189,7 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullV
|
||||
}
|
||||
|
||||
// Background
|
||||
// We're pretty much abusing the backgroundinformation field here - not sure if this is really better than adding a new property to the list
|
||||
// We're pretty much abusing the backgroundinformation field here - not sure if this is really better than adding a new property to the project
|
||||
if board.Prefs.BackgroundImage != "" {
|
||||
log.Debugf("[Trello Migration] Downloading background %s for board %s", board.Prefs.BackgroundImage, board.ID)
|
||||
buf, err := migration.DownloadFile(board.Prefs.BackgroundImage)
|
||||
@ -197,7 +197,7 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullV
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("[Trello Migration] Downloaded background %s for board %s", board.Prefs.BackgroundImage, board.ID)
|
||||
list.BackgroundInformation = buf
|
||||
project.BackgroundInformation = buf
|
||||
} else {
|
||||
log.Debugf("[Trello Migration] Board %s does not have a background image, not copying...", board.ID)
|
||||
}
|
||||
@ -291,23 +291,23 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullV
|
||||
log.Debugf("[Trello Migration] Downloaded card attachment %s", attachment.ID)
|
||||
}
|
||||
|
||||
list.Tasks = append(list.Tasks, &models.TaskWithComments{Task: *task})
|
||||
project.Tasks = append(project.Tasks, &models.TaskWithComments{Task: *task})
|
||||
}
|
||||
|
||||
list.Buckets = append(list.Buckets, bucket)
|
||||
project.Buckets = append(project.Buckets, bucket)
|
||||
bucketID++
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Converted all cards to tasks for board %s", board.ID)
|
||||
|
||||
fullVikunjaHierachie[0].Lists = append(fullVikunjaHierachie[0].Lists, list)
|
||||
fullVikunjaHierachie[0].Projects = append(fullVikunjaHierachie[0].Projects, project)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Migrate gets all tasks from trello for a user and puts them into vikunja
|
||||
// @Summary Migrate all lists, tasks etc. from trello
|
||||
// @Summary Migrate all projects, tasks etc. from trello
|
||||
// @Description Migrates all projects, tasks, notes, reminders, subtasks and files from trello to vikunja.
|
||||
// @tags migration
|
||||
// @Accept json
|
||||
|
@ -44,9 +44,9 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
Name: "TestBoard",
|
||||
Desc: "This is a description",
|
||||
Closed: false,
|
||||
Lists: []*trello.List{
|
||||
Projects: []*trello.Project{
|
||||
{
|
||||
Name: "Test List 1",
|
||||
Name: "Test Project 1",
|
||||
Cards: []*trello.Card{
|
||||
{
|
||||
Name: "Test Card 1",
|
||||
@ -77,9 +77,9 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
{
|
||||
Name: "Test Card 2",
|
||||
Pos: 124,
|
||||
Checklists: []*trello.Checklist{
|
||||
Checkprojects: []*trello.Checkproject{
|
||||
{
|
||||
Name: "Checklist 1",
|
||||
Name: "Checkproject 1",
|
||||
CheckItems: []trello.CheckItem{
|
||||
{
|
||||
State: "pending",
|
||||
@ -92,7 +92,7 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Checklist 2",
|
||||
Name: "Checkproject 2",
|
||||
CheckItems: []trello.CheckItem{
|
||||
{
|
||||
State: "pending",
|
||||
@ -124,7 +124,7 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Test List 2",
|
||||
Name: "Test Project 2",
|
||||
Cards: []*trello.Card{
|
||||
{
|
||||
Name: "Test Card 5",
|
||||
@ -157,9 +157,9 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
{
|
||||
Name: "TestBoard 2",
|
||||
Closed: false,
|
||||
Lists: []*trello.List{
|
||||
Projects: []*trello.Project{
|
||||
{
|
||||
Name: "Test List 4",
|
||||
Name: "Test Project 4",
|
||||
Cards: []*trello.Card{
|
||||
{
|
||||
Name: "Test Card 634",
|
||||
@ -172,9 +172,9 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
{
|
||||
Name: "TestBoard Archived",
|
||||
Closed: true,
|
||||
Lists: []*trello.List{
|
||||
Projects: []*trello.Project{
|
||||
{
|
||||
Name: "Test List 5",
|
||||
Name: "Test Project 5",
|
||||
Cards: []*trello.Card{
|
||||
{
|
||||
Name: "Test Card 63423",
|
||||
@ -187,14 +187,14 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
}
|
||||
trelloData[0].Prefs.BackgroundImage = "https://vikunja.io/testimage.jpg" // Using an image which we are hosting, so it'll still be up
|
||||
|
||||
expectedHierachie := []*models.NamespaceWithListsAndTasks{
|
||||
expectedHierachie := []*models.NamespaceWithProjectsAndTasks{
|
||||
{
|
||||
Namespace: models.Namespace{
|
||||
Title: "Imported from Trello",
|
||||
},
|
||||
Lists: []*models.ListWithTasksAndBuckets{
|
||||
Projects: []*models.ProjectWithTasksAndBuckets{
|
||||
{
|
||||
List: models.List{
|
||||
Project: models.Project{
|
||||
Title: "TestBoard",
|
||||
Description: "This is a description",
|
||||
BackgroundInformation: bytes.NewBuffer(exampleFile),
|
||||
@ -202,11 +202,11 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 1,
|
||||
Title: "Test List 1",
|
||||
Title: "Test Project 1",
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Title: "Test List 2",
|
||||
Title: "Test Project 2",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
@ -244,12 +244,12 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
Title: "Test Card 2",
|
||||
Description: `
|
||||
|
||||
## Checklist 1
|
||||
## Checkproject 1
|
||||
|
||||
* [ ] Pending Task
|
||||
* [x] Completed Task
|
||||
|
||||
## Checklist 2
|
||||
## Checkproject 2
|
||||
|
||||
* [ ] Pending Task
|
||||
* [ ] Another Pending Task`,
|
||||
@ -315,13 +315,13 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
List: models.List{
|
||||
Project: models.Project{
|
||||
Title: "TestBoard 2",
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 3,
|
||||
Title: "Test List 4",
|
||||
Title: "Test Project 4",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
@ -335,14 +335,14 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
List: models.List{
|
||||
Project: models.Project{
|
||||
Title: "TestBoard Archived",
|
||||
IsArchived: true,
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 4,
|
||||
Title: "Test List 5",
|
||||
Title: "Test Project 5",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
|
@ -51,7 +51,7 @@ func (v *FileMigrator) Name() string {
|
||||
}
|
||||
|
||||
// Migrate takes a vikunja file export, parses it and imports everything in it into Vikunja.
|
||||
// @Summary Import all lists, tasks etc. from a Vikunja data export
|
||||
// @Summary Import all projects, tasks etc. from a Vikunja data export
|
||||
// @Description Imports all projects, tasks, notes, reminders, subtasks and files from a Vikunjda data export into Vikunja.
|
||||
// @tags migration
|
||||
// @Accept json
|
||||
@ -113,21 +113,21 @@ func (v *FileMigrator) Migrate(user *user.User, file io.ReaderAt, size int64) er
|
||||
return fmt.Errorf("could not read data file: %w", err)
|
||||
}
|
||||
|
||||
namespaces := []*models.NamespaceWithListsAndTasks{}
|
||||
namespaces := []*models.NamespaceWithProjectsAndTasks{}
|
||||
if err := json.Unmarshal(bufData.Bytes(), &namespaces); err != nil {
|
||||
return fmt.Errorf("could not read data: %w", err)
|
||||
}
|
||||
|
||||
for _, n := range namespaces {
|
||||
for _, l := range n.Lists {
|
||||
for _, l := range n.Projects {
|
||||
if b, exists := storedFiles[l.BackgroundFileID]; exists {
|
||||
bf, err := b.Open()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not open list background file %d for reading: %w", l.BackgroundFileID, err)
|
||||
return fmt.Errorf("could not open project background file %d for reading: %w", l.BackgroundFileID, err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if _, err := buf.ReadFrom(bf); err != nil {
|
||||
return fmt.Errorf("could not read list background file %d: %w", l.BackgroundFileID, err)
|
||||
return fmt.Errorf("could not read project background file %d: %w", l.BackgroundFileID, err)
|
||||
}
|
||||
|
||||
l.BackgroundInformation = &buf
|
||||
|
@ -48,12 +48,12 @@ func TestVikunjaFileMigrator_Migrate(t *testing.T) {
|
||||
"title": "test",
|
||||
"owner_id": u.ID,
|
||||
}, false)
|
||||
db.AssertExists(t, "lists", map[string]interface{}{
|
||||
"title": "Test list",
|
||||
db.AssertExists(t, "projects", map[string]interface{}{
|
||||
"title": "Test project",
|
||||
"owner_id": u.ID,
|
||||
}, false)
|
||||
db.AssertExists(t, "lists", map[string]interface{}{
|
||||
"title": "A list with a background",
|
||||
db.AssertExists(t, "projects", map[string]interface{}{
|
||||
"title": "A project with a background",
|
||||
"owner_id": u.ID,
|
||||
}, false)
|
||||
db.AssertExists(t, "tasks", map[string]interface{}{
|
||||
|
Reference in New Issue
Block a user