mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-01 20:59:24 +00:00
Why? You are working on a ticket, it's ready to be moved to the QA column in your project. Currently you have to go to the project, find the issue card, then move it. With this change you can move the issue's column on the issue page. When an issue or pull request belongs to a project board, a dropdown appears in the sidebar to move it between columns without opening the board view. Read-only users see the current column name instead. * Fix #13520 * Replace #30617 This was written using Claude Code and Opus. Closed: <img width="1346" height="507" alt="image" src="https://github.com/user-attachments/assets/7c1ea7ee-b71c-40af-bb14-aeb1d2beff73" /> Open: <img width="1315" height="577" alt="image" src="https://github.com/user-attachments/assets/4d64b065-44c2-42c7-8d20-84b5caea589a" /> --------- Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Nicolas <bircni@icloud.com> Co-authored-by: Cursor <cursor@cursor.com>
90 lines
2.6 KiB
Go
90 lines
2.6 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package project
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
"code.gitea.io/gitea/modules/util"
|
|
)
|
|
|
|
// ProjectIssue saves relation from issue to a project
|
|
type ProjectIssue struct { //revive:disable-line:exported
|
|
ID int64 `xorm:"pk autoincr"`
|
|
IssueID int64 `xorm:"INDEX"`
|
|
ProjectID int64 `xorm:"INDEX"`
|
|
|
|
// ProjectColumnID should not be zero since 1.22. If it's zero, the issue will not be displayed on UI and it might result in errors.
|
|
ProjectColumnID int64 `xorm:"'project_board_id' INDEX"`
|
|
|
|
// the sorting order on the column
|
|
Sorting int64 `xorm:"NOT NULL DEFAULT 0"`
|
|
}
|
|
|
|
func init() {
|
|
db.RegisterModel(new(ProjectIssue))
|
|
}
|
|
|
|
func deleteProjectIssuesByProjectID(ctx context.Context, projectID int64) error {
|
|
_, err := db.GetEngine(ctx).Where("project_id=?", projectID).Delete(&ProjectIssue{})
|
|
return err
|
|
}
|
|
|
|
// GetColumnIssueNextSorting returns the sorting value to append an issue at the end of the column.
|
|
func GetColumnIssueNextSorting(ctx context.Context, projectID, columnID int64) (int64, error) {
|
|
res := struct {
|
|
MaxSorting int64
|
|
IssueCount int64
|
|
}{}
|
|
if _, err := db.GetEngine(ctx).Select("max(sorting) AS max_sorting, count(*) AS issue_count").
|
|
Table("project_issue").
|
|
Where("project_id=?", projectID).
|
|
And("project_board_id=?", columnID).
|
|
Get(&res); err != nil {
|
|
return 0, err
|
|
}
|
|
return util.Iif(res.IssueCount > 0, res.MaxSorting+1, 0), nil
|
|
}
|
|
|
|
func moveIssuesToAnotherColumn(ctx context.Context, oldColumn, newColumn *Column) error {
|
|
if oldColumn.ProjectID != newColumn.ProjectID {
|
|
return errors.New("columns have to be in the same project")
|
|
}
|
|
|
|
if oldColumn.ID == newColumn.ID {
|
|
return nil
|
|
}
|
|
|
|
movedIssues, err := oldColumn.GetIssues(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(movedIssues) == 0 {
|
|
return nil
|
|
}
|
|
|
|
nextSorting, err := GetColumnIssueNextSorting(ctx, newColumn.ProjectID, newColumn.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return db.WithTx(ctx, func(ctx context.Context) error {
|
|
for i, issue := range movedIssues {
|
|
issue.ProjectColumnID = newColumn.ID
|
|
issue.Sorting = nextSorting + int64(i)
|
|
if _, err := db.GetEngine(ctx).ID(issue.ID).Cols("project_board_id", "sorting").Update(issue); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// DeleteAllProjectIssueByIssueIDsAndProjectIDs delete all project's issues by issue's and project's ids
|
|
func DeleteAllProjectIssueByIssueIDsAndProjectIDs(ctx context.Context, issueIDs, projectIDs []int64) error {
|
|
_, err := db.GetEngine(ctx).In("project_id", projectIDs).In("issue_id", issueIDs).Delete(&ProjectIssue{})
|
|
return err
|
|
}
|