mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-04-29 19:10:51 -05:00
fix(projects): (un-)archive child projects when archiving parent (#775)
This commit is contained in:
@@ -44,6 +44,7 @@ async function archiveProject() {
|
|||||||
})
|
})
|
||||||
useBaseStore().setCurrentProject(newProject)
|
useBaseStore().setCurrentProject(newProject)
|
||||||
success({message: t('project.archive.success')})
|
success({message: t('project.archive.success')})
|
||||||
|
await projectStore.loadAllProjects()
|
||||||
} finally {
|
} finally {
|
||||||
router.back()
|
router.back()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -944,6 +944,11 @@ func UpdateProject(s *xorm.Session, project *Project, auth web.Auth, updateProje
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = setArchiveStateForProjectDescendants(s, project.ID, project.IsArchived)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// We need to specify the cols we want to update here to be able to un-archive projects
|
// We need to specify the cols we want to update here to be able to un-archive projects
|
||||||
colsToUpdate := []string{
|
colsToUpdate := []string{
|
||||||
"title",
|
"title",
|
||||||
@@ -1286,3 +1291,40 @@ func SetProjectBackground(s *xorm.Session, projectID int64, background *files.Fi
|
|||||||
Update(l)
|
Update(l)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setArchiveStateForProjectDescendants uses a recursive CTE to find and set the archived status of all descendant projects.
|
||||||
|
func setArchiveStateForProjectDescendants(s *xorm.Session, parentProjectID int64, shouldBeArchived bool) error {
|
||||||
|
var descendantIDs []int64
|
||||||
|
err := s.SQL(
|
||||||
|
`
|
||||||
|
WITH RECURSIVE descendant_ids (id) AS (
|
||||||
|
SELECT id
|
||||||
|
FROM projects
|
||||||
|
WHERE parent_project_id = ?
|
||||||
|
UNION ALL
|
||||||
|
SELECT p.id
|
||||||
|
FROM projects p
|
||||||
|
INNER JOIN descendant_ids di ON p.parent_project_id = di.id
|
||||||
|
)
|
||||||
|
SELECT id FROM descendant_ids`,
|
||||||
|
parentProjectID,
|
||||||
|
).Find(&descendantIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error finding descendant projects for parent ID %d: %v", parentProjectID, err)
|
||||||
|
return fmt.Errorf("failed to find descendant projects for parent ID %d: %w", parentProjectID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(descendantIDs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.In("id", descendantIDs).
|
||||||
|
And("is_archived != ?", shouldBeArchived).
|
||||||
|
Cols("is_archived").
|
||||||
|
Update(&Project{IsArchived: shouldBeArchived})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error updating is_archived for descendant projects for parent ID %d to %t: %v", parentProjectID, shouldBeArchived, err)
|
||||||
|
return fmt.Errorf("failed to update is_archived for descendant projects for parent ID %d to %t: %w", parentProjectID, shouldBeArchived, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -305,6 +305,38 @@ func TestProject_CreateOrUpdate(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.True(t, IsErrCannotArchiveDefaultProject(err))
|
assert.True(t, IsErrCannotArchiveDefaultProject(err))
|
||||||
})
|
})
|
||||||
|
t.Run("archive parent archives child", func(t *testing.T) {
|
||||||
|
db.LoadAndAssertFixtures(t)
|
||||||
|
s := db.NewSession()
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
actingUser := &user.User{ID: 6}
|
||||||
|
|
||||||
|
projectToArchive := Project{
|
||||||
|
ID: 27,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to load the project first to have its fields populated for the update
|
||||||
|
can, err := projectToArchive.CanUpdate(s, actingUser)
|
||||||
|
require.NoError(t, err, "Failed to read project 27 before archiving")
|
||||||
|
assert.True(t, can)
|
||||||
|
projectToArchive.IsArchived = true // Ensure IsArchived is set after reading
|
||||||
|
|
||||||
|
err = projectToArchive.Update(s, actingUser)
|
||||||
|
require.NoError(t, err, "Failed to archive project")
|
||||||
|
err = s.Commit()
|
||||||
|
require.NoError(t, err, "Failed to commit session after archiving project")
|
||||||
|
|
||||||
|
db.AssertExists(t, "projects", map[string]interface{}{
|
||||||
|
"id": 27,
|
||||||
|
"is_archived": true,
|
||||||
|
}, false)
|
||||||
|
// Assert child project (ID 12) is also archived
|
||||||
|
db.AssertExists(t, "projects", map[string]interface{}{
|
||||||
|
"id": 12,
|
||||||
|
"is_archived": true,
|
||||||
|
}, false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user