feat(migration): use new structure for migration

This commit is contained in:
kolaente 2022-12-29 18:11:15 +01:00
parent 92f0a50996
commit e8e2e205f4
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
8 changed files with 44 additions and 44 deletions

View File

@ -85,6 +85,8 @@ type Project struct {
type ProjectWithTasksAndBuckets struct {
Project
ChildProjects []*ProjectWithTasksAndBuckets `xorm:"-" json:"child_projects"`
// An array of tasks which belong to the project.
Tasks []*TaskWithComments `xorm:"-" json:"tasks"`
// Only used for migration.

View File

@ -127,7 +127,7 @@ func getProjectsToDelete(s *xorm.Session, u *user.User) (projectsToDelete []*Pro
return
}
// DeleteUser completely removes a user and all their associated projects, namespaces and tasks.
// DeleteUser completely removes a user and all their associated projects and tasks.
// This action is irrevocable.
// Public to allow deletion from the CLI.
func DeleteUser(s *xorm.Session, u *user.User) (err error) {

View File

@ -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.NamespaceWithProjectsAndTasks, user *user.User) (err error) {
func InsertFromStructure(str []*models.ProjectWithTasksAndBuckets, user *user.User) (err error) {
s := db.NewSession()
defer s.Close()
@ -45,7 +45,7 @@ func InsertFromStructure(str []*models.NamespaceWithProjectsAndTasks, user *user
return s.Commit()
}
func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithProjectsAndTasks, user *user.User) (err error) {
func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBuckets, user *user.User) (err error) {
log.Debugf("[creating structure] Creating %d namespaces", len(str))
@ -55,30 +55,30 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithProjectsAnd
archivedNamespaces := []int64{}
// Create all namespaces
for _, n := range str {
n.ID = 0
for _, p := range str {
p.ID = 0
// Saving the archived status to archive the namespace again after creating it
var wasArchived bool
if n.IsArchived {
n.IsArchived = false
if p.IsArchived {
p.IsArchived = false
wasArchived = true
}
err = n.Create(s, user)
err = p.Create(s, user)
if err != nil {
return
}
if wasArchived {
archivedNamespaces = append(archivedNamespaces, n.ID)
archivedNamespaces = append(archivedNamespaces, p.ID)
}
log.Debugf("[creating structure] Created namespace %d", n.ID)
log.Debugf("[creating structure] Creating %d projects", len(n.Projects))
log.Debugf("[creating structure] Created project %d", p.ID)
log.Debugf("[creating structure] Creating %d projects", len(p.ChildProjects))
// Create all projects
for _, l := range n.Projects {
for _, l := range p.ChildProjects {
// 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
@ -93,7 +93,7 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithProjectsAnd
l.IsArchived = false
}
l.NamespaceID = n.ID
l.ParentProjectID = p.ID
l.ID = 0
err = l.Create(s, user)
if err != nil {
@ -291,7 +291,7 @@ func insertFromStructure(s *xorm.Session, str []*models.NamespaceWithProjectsAnd
_, err = s.
Cols("is_archived").
In("id", archivedNamespaces).
Update(&models.Namespace{IsArchived: true})
Update(&models.Project{IsArchived: true})
if err != nil {
return err
}

View File

@ -259,15 +259,15 @@ func getMicrosoftTodoData(token string) (microsoftTodoData []*project, err error
return
}
func convertMicrosoftTodoData(todoData []*project) (vikunjsStructure []*models.NamespaceWithProjectsAndTasks, err error) {
func convertMicrosoftTodoData(todoData []*project) (vikunjsStructure []*models.ProjectWithTasksAndBuckets, err error) {
// One namespace with all projects
vikunjsStructure = []*models.NamespaceWithProjectsAndTasks{
vikunjsStructure = []*models.ProjectWithTasksAndBuckets{
{
Namespace: models.Namespace{
Project: models.Project{
Title: "Migrated from Microsoft Todo",
},
Projects: []*models.ProjectWithTasksAndBuckets{},
ChildProjects: []*models.ProjectWithTasksAndBuckets{},
},
}
@ -362,7 +362,7 @@ func convertMicrosoftTodoData(todoData []*project) (vikunjsStructure []*models.N
log.Debugf("[Microsoft Todo Migration] Done converted %d tasks", len(l.Tasks))
}
vikunjsStructure[0].Projects = append(vikunjsStructure[0].Projects, project)
vikunjsStructure[0].ChildProjects = append(vikunjsStructure[0].ChildProjects, project)
log.Debugf("[Microsoft Todo Migration] Done converting project %s", l.ID)
}

View File

@ -88,12 +88,12 @@ func parseDurationPart(value string, unit time.Duration) time.Duration {
return 0
}
func convertTickTickToVikunja(tasks []*tickTickTask) (result []*models.NamespaceWithProjectsAndTasks) {
namespace := &models.NamespaceWithProjectsAndTasks{
Namespace: models.Namespace{
func convertTickTickToVikunja(tasks []*tickTickTask) (result []*models.ProjectWithTasksAndBuckets) {
parent := &models.ProjectWithTasksAndBuckets{
Project: models.Project{
Title: "Migrated from TickTick",
},
Projects: []*models.ProjectWithTasksAndBuckets{},
ChildProjects: []*models.ProjectWithTasksAndBuckets{},
}
projects := make(map[string]*models.ProjectWithTasksAndBuckets)
@ -142,14 +142,14 @@ func convertTickTickToVikunja(tasks []*tickTickTask) (result []*models.Namespace
}
for _, l := range projects {
namespace.Projects = append(namespace.Projects, l)
parent.ChildProjects = append(parent.ChildProjects, l)
}
sort.Slice(namespace.Projects, func(i, j int) bool {
return namespace.Projects[i].Title < namespace.Projects[j].Title
sort.Slice(parent.ChildProjects, func(i, j int) bool {
return parent.ChildProjects[i].Title < parent.ChildProjects[j].Title
})
return []*models.NamespaceWithProjectsAndTasks{namespace}
return []*models.ProjectWithTasksAndBuckets{parent}
}
// Name is used to get the name of the ticktick migration - we're using the docs here to annotate the status route.

View File

@ -251,10 +251,10 @@ func parseDate(dateString string) (date time.Time, err error) {
return date, err
}
func convertTodoistToVikunja(sync *sync, doneItems map[string]*doneItem) (fullVikunjaHierachie []*models.NamespaceWithProjectsAndTasks, err error) {
func convertTodoistToVikunja(sync *sync, doneItems map[string]*doneItem) (fullVikunjaHierachie []*models.ProjectWithTasksAndBuckets, err error) {
newNamespace := &models.NamespaceWithProjectsAndTasks{
Namespace: models.Namespace{
parent := &models.ProjectWithTasksAndBuckets{
Project: models.Project{
Title: "Migrated from todoist",
},
}
@ -281,7 +281,7 @@ func convertTodoistToVikunja(sync *sync, doneItems map[string]*doneItem) (fullVi
lists[p.ID] = project
newNamespace.Projects = append(newNamespace.Projects, project)
parent.ChildProjects = append(parent.ChildProjects, project)
}
sort.Slice(sync.Sections, func(i, j int) bool {
@ -463,9 +463,7 @@ func convertTodoistToVikunja(sync *sync, doneItems map[string]*doneItem) (fullVi
tasks[r.ItemID].Reminders = append(tasks[r.ItemID].Reminders, date.In(config.GetTimeZone()))
}
return []*models.NamespaceWithProjectsAndTasks{
newNamespace,
}, err
return []*models.ProjectWithTasksAndBuckets{parent}, err
}
func getAccessTokenFromAuthToken(authToken string) (accessToken string, err error) {

View File

@ -144,16 +144,16 @@ 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 projects and cards respectively.
func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullVikunjaHierachie []*models.NamespaceWithProjectsAndTasks, err error) {
func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullVikunjaHierachie []*models.ProjectWithTasksAndBuckets, err error) {
log.Debugf("[Trello Migration] ")
fullVikunjaHierachie = []*models.NamespaceWithProjectsAndTasks{
fullVikunjaHierachie = []*models.ProjectWithTasksAndBuckets{
{
Namespace: models.Namespace{
Project: models.Project{
Title: "Imported from Trello",
},
Projects: []*models.ProjectWithTasksAndBuckets{},
ChildProjects: []*models.ProjectWithTasksAndBuckets{},
},
}
@ -282,7 +282,7 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullV
log.Debugf("[Trello Migration] Converted all cards to tasks for board %s", board.ID)
fullVikunjaHierachie[0].Projects = append(fullVikunjaHierachie[0].Projects, project)
fullVikunjaHierachie[0].ChildProjects = append(fullVikunjaHierachie[0].ChildProjects, project)
}
return

View File

@ -113,13 +113,13 @@ 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.NamespaceWithProjectsAndTasks{}
if err := json.Unmarshal(bufData.Bytes(), &namespaces); err != nil {
parent := []*models.ProjectWithTasksAndBuckets{}
if err := json.Unmarshal(bufData.Bytes(), &parent); err != nil {
return fmt.Errorf("could not read data: %w", err)
}
for _, n := range namespaces {
for _, l := range n.Projects {
for _, n := range parent {
for _, l := range n.ChildProjects {
if b, exists := storedFiles[l.BackgroundFileID]; exists {
bf, err := b.Open()
if err != nil {
@ -158,7 +158,7 @@ func (v *FileMigrator) Migrate(user *user.User, file io.ReaderAt, size int64) er
}
}
err = migration.InsertFromStructure(namespaces, user)
err = migration.InsertFromStructure(parent, user)
if err != nil {
return fmt.Errorf("could not insert data: %w", err)
}