fix(export): make export work with project views and new task positions
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kolaente 2024-04-13 21:07:06 +02:00
parent 9a16f6f817
commit ce1d7778c7
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
3 changed files with 152 additions and 12 deletions

View File

@ -155,6 +155,21 @@ func exportProjectsAndTasks(s *xorm.Session, u *user.User, wr *zip.Writer) (task
projectIDs = append(projectIDs, p.ID)
}
views := map[int64]*ProjectView{}
err = s.In("project_id", projectIDs).Find(&views)
if err != nil {
return
}
viewIDs := []int64{}
for _, v := range views {
if projectsMap[v.ProjectID].Views == nil {
projectsMap[v.ProjectID].Views = []*ProjectView{}
}
projectsMap[v.ProjectID].Views = append(projectsMap[v.ProjectID].Views, v)
viewIDs = append(viewIDs, v.ID)
}
tasks, _, _, err := getTasksForProjects(s, rawProjects, u, &taskSearchOptions{
page: 0,
perPage: -1,
@ -194,17 +209,75 @@ func exportProjectsAndTasks(s *xorm.Session, u *user.User, wr *zip.Writer) (task
}
buckets := []*Bucket{}
err = s.In("project_id", projectIDs).Find(&buckets)
err = s.In("project_view_id", viewIDs).Find(&buckets)
if err != nil {
return
}
bucketIDs := []int64{}
for _, b := range buckets {
if _, exists := projectsMap[b.ProjectID]; !exists {
log.Debugf("[User Data Export] Project %d does not exist for bucket %d, omitting", b.ProjectID, b.ID)
view, exists := views[b.ProjectViewID]
if !exists {
log.Debugf("[User Data Export] Project view %d does not exist for bucket %d, omitting", b.ProjectViewID, b.ID)
continue
}
projectsMap[b.ProjectID].Buckets = append(projectsMap[b.ProjectID].Buckets, b)
_, exists = projectsMap[view.ProjectID]
if !exists {
log.Debugf("[User Data Export] Project %d does not exist for bucket %d, omitting", view.ProjectID, b.ID)
continue
}
projectsMap[view.ProjectID].Buckets = append(projectsMap[view.ProjectID].Buckets, b)
bucketIDs = append(bucketIDs, b.ID)
}
taskBuckets := []*TaskBucket{}
err = s.In("bucket_id", bucketIDs).Find(&taskBuckets)
if err != nil {
return
}
for _, tb := range taskBuckets {
view, exists := views[tb.ProjectViewID]
if !exists {
log.Debugf("[User Data Export] Project view %d does not exist, omitting", tb.ProjectViewID)
continue
}
_, exists = projectsMap[view.ProjectID]
if !exists {
log.Debugf("[User Data Export] Project %d does not exist, omitting", view.ProjectID)
continue
}
if projectsMap[view.ProjectID].TaskBuckets == nil {
projectsMap[view.ProjectID].TaskBuckets = []*TaskBucket{}
}
projectsMap[view.ProjectID].TaskBuckets = append(projectsMap[view.ProjectID].TaskBuckets, tb)
}
taskPositions := []*TaskPosition{}
err = s.In("project_view_id", viewIDs).Find(&taskPositions)
if err != nil {
return
}
for _, p := range taskPositions {
view, exists := views[p.ProjectViewID]
if !exists {
log.Debugf("[User Data Export] Project view %d does not exist, omitting", p.ProjectViewID)
continue
}
_, exists = projectsMap[view.ProjectID]
if !exists {
log.Debugf("[User Data Export] Project %d does not exist, omitting", view.ProjectID)
continue
}
if projectsMap[view.ProjectID].Positions == nil {
projectsMap[view.ProjectID].Positions = []*TaskPosition{}
}
projectsMap[view.ProjectID].Positions = append(projectsMap[view.ProjectID].Positions, p)
}
data, err := json.Marshal(projects)

View File

@ -93,8 +93,10 @@ type ProjectWithTasksAndBuckets struct {
// An array of tasks which belong to the project.
Tasks []*TaskWithComments `xorm:"-" json:"tasks"`
// Only used for migration.
Buckets []*Bucket `xorm:"-" json:"buckets"`
BackgroundFileID int64 `xorm:"null" json:"background_file_id"`
Buckets []*Bucket `xorm:"-" json:"buckets"`
TaskBuckets []*TaskBucket `xorm:"-" json:"task_buckets"`
Positions []*TaskPosition `xorm:"-" json:"positions"`
BackgroundFileID int64 `xorm:"null" json:"background_file_id"`
}
// TableName returns a better name for the projects table

View File

@ -64,6 +64,11 @@ func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBucke
}
p.ID = 0
for _, view := range p.Views {
view.ProjectID = 0
}
err = createProject(s, p, &archivedProjects, labels, user)
if err != nil {
return err
@ -167,7 +172,7 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
}
// Create all buckets
buckets := make(map[int64]*models.Bucket) // old bucket id is the key
bucketsByOldID := make(map[int64]*models.Bucket) // old bucket id is the key
if len(project.Buckets) > 0 {
log.Debugf("[creating structure] Creating %d buckets", len(project.Buckets))
}
@ -179,40 +184,45 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
if err != nil {
return
}
buckets[oldID] = bucket
bucketsByOldID[oldID] = bucket
log.Debugf("[creating structure] Created bucket %d, old ID was %d", bucket.ID, oldID)
}
// Create all views, create default views if we don't have any
viewsByOldIDs := make(map[int64]*models.ProjectView, len(oldViews))
if len(oldViews) > 0 {
for _, view := range oldViews {
oldID := view.ID
view.ID = 0
if view.DefaultBucketID != 0 {
bucket, has := buckets[view.DefaultBucketID]
bucket, has := bucketsByOldID[view.DefaultBucketID]
if has {
view.DefaultBucketID = bucket.ID
}
}
if view.DoneBucketID != 0 {
bucket, has := buckets[view.DoneBucketID]
bucket, has := bucketsByOldID[view.DoneBucketID]
if has {
view.DoneBucketID = bucket.ID
}
}
view.ProjectID = project.ID
err = view.Create(s, user)
if err != nil {
return
}
viewsByOldIDs[oldID] = view
}
} else {
// Only using the default views
// Add all buckets to the default kanban view
for _, view := range project.Views {
if view.ViewKind == models.ProjectViewKindKanban {
for _, b := range buckets {
for _, b := range bucketsByOldID {
b.ProjectViewID = view.ID
err = b.Update(s, user)
if err != nil {
@ -227,7 +237,7 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
log.Debugf("[creating structure] Creating %d tasks", len(tasks))
setBucketOrDefault := func(task *models.Task) {
bucket, exists := buckets[task.BucketID]
bucket, exists := bucketsByOldID[task.BucketID]
if exists {
task.BucketID = bucket.ID
} else if task.BucketID > 0 {
@ -240,6 +250,7 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
}
tasksByOldID := make(map[int64]*models.TaskWithComments, len(tasks))
newTaskIDs := []int64{}
// Create all tasks
for i, t := range tasks {
setBucketOrDefault(&tasks[i].Task)
@ -251,6 +262,8 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
continue
}
newTaskIDs = append(newTaskIDs, t.ID)
if err != nil {
return
}
@ -401,6 +414,58 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
}
}
if len(viewsByOldIDs) > 0 {
newPositions := []*models.TaskPosition{}
for _, pos := range project.Positions {
_, hasTask := tasksByOldID[pos.TaskID]
_, hasView := viewsByOldIDs[pos.ProjectViewID]
if !hasTask || !hasView {
continue
}
newPositions = append(newPositions, &models.TaskPosition{
TaskID: tasksByOldID[pos.TaskID].ID,
ProjectViewID: viewsByOldIDs[pos.ProjectViewID].ID,
Position: pos.Position,
})
}
if len(newPositions) > 0 {
_, err = s.In("task_id", newTaskIDs).Delete(&models.TaskPosition{})
if err != nil {
return
}
_, err = s.Insert(newPositions)
if err != nil {
return
}
}
newTaskBuckets := make([]*models.TaskBucket, 0, len(project.TaskBuckets))
for _, tb := range project.TaskBuckets {
_, hasTask := tasksByOldID[tb.TaskID]
_, hasBucket := bucketsByOldID[tb.BucketID]
if !hasTask || !hasBucket {
continue
}
newTaskBuckets = append(newTaskBuckets, &models.TaskBucket{
TaskID: tasksByOldID[tb.TaskID].ID,
BucketID: bucketsByOldID[tb.BucketID].ID,
ProjectViewID: bucketsByOldID[tb.BucketID].ProjectViewID,
})
}
if len(newTaskBuckets) > 0 {
_, err = s.In("task_id", newTaskIDs).Delete(&models.TaskBucket{})
if err != nil {
return
}
_, err = s.Insert(newTaskBuckets)
if err != nil {
return
}
}
}
project.Tasks = tasks
project.Buckets = originalBuckets