-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multiple projects #27984
Support multiple projects #27984
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,27 +14,24 @@ import ( | |
|
||
// LoadProject load the project the issue was assigned to | ||
func (issue *Issue) LoadProject(ctx context.Context) (err error) { | ||
if issue.Project == nil { | ||
var p project_model.Project | ||
has, err := db.GetEngine(ctx).Table("project"). | ||
if issue.Projects == nil { | ||
err = db.GetEngine(ctx).Table("project"). | ||
Join("INNER", "project_issue", "project.id=project_issue.project_id"). | ||
Where("project_issue.issue_id = ?", issue.ID).Get(&p) | ||
if err != nil { | ||
return err | ||
} else if has { | ||
issue.Project = &p | ||
} | ||
Where("project_issue.issue_id = ?", issue.ID).OrderBy("title"). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why we need to order the result here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, this is just a holdover from @tyroneyeh 's original thing. All I did was try to resolve the conflicts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sorry. I was just reviewing this PR and didn't notice your comment above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sorting applies to the sidebar menu list order |
||
Find(&issue.Projects) | ||
} | ||
return err | ||
} | ||
|
||
func (issue *Issue) projectID(ctx context.Context) int64 { | ||
var ip project_model.ProjectIssue | ||
has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip) | ||
if err != nil || !has { | ||
return 0 | ||
|
||
func (issue *Issue) projectIDs(ctx context.Context) []int64 { | ||
var ips []int64 | ||
if err := db.GetEngine(ctx).Table("project_issue").Select("project_id"). | ||
Where("issue_id=?", issue.ID).Find(&ips); err != nil { | ||
return nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
return ip.ProjectID | ||
|
||
return ips | ||
} | ||
|
||
// ProjectBoardID return project board id if issue was assigned to one | ||
|
@@ -96,57 +93,101 @@ func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (m | |
} | ||
|
||
// ChangeProjectAssign changes the project associated with an issue | ||
func ChangeProjectAssign(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error { | ||
func ChangeProjectAssign(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64, action string) error { | ||
ctx, committer, err := db.TxContext(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
defer committer.Close() | ||
|
||
if err := addUpdateIssueProject(ctx, issue, doer, newProjectID); err != nil { | ||
if err := addUpdateIssueProject(ctx, issue, doer, newProjectID, action); err != nil { | ||
return err | ||
} | ||
|
||
return committer.Commit() | ||
} | ||
|
||
func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error { | ||
oldProjectID := issue.projectID(ctx) | ||
|
||
func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64, action string) error { | ||
if err := issue.LoadRepo(ctx); err != nil { | ||
return err | ||
} | ||
|
||
// Only check if we add a new project and not remove it. | ||
if newProjectID > 0 { | ||
newProject, err := project_model.GetProjectByID(ctx, newProjectID) | ||
if err != nil { | ||
return err | ||
oldProjectIDs := issue.projectIDs(ctx) | ||
|
||
if len(oldProjectIDs) > 0 { | ||
for _, i := range oldProjectIDs { | ||
// Only check if we add a new project and not remove it. | ||
if newProjectID > 0 { | ||
newProject, err := project_model.GetProjectByID(ctx, newProjectID) | ||
if err != nil { | ||
return err | ||
} | ||
if newProject.RepoID != issue.RepoID && newProject.OwnerID != issue.Repo.OwnerID { | ||
return fmt.Errorf("issue's repository is not the same as project's repository") | ||
} | ||
} | ||
|
||
if action == "attach" && newProjectID > 0 { | ||
if err := db.Insert(ctx, &project_model.ProjectIssue{ | ||
IssueID: issue.ID, | ||
ProjectID: newProjectID, | ||
}); err != nil { | ||
return err | ||
} | ||
i = 0 | ||
} else { | ||
if action == "clear" { | ||
if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&project_model.ProjectIssue{}); err != nil { | ||
return err | ||
} | ||
} else { | ||
i = newProjectID | ||
newProjectID = 0 | ||
if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=? AND project_issue.project_id=?", issue.ID, i).Delete(&project_model.ProjectIssue{}); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
if i > 0 || newProjectID > 0 { | ||
if _, err := CreateComment(ctx, &CreateCommentOptions{ | ||
Type: CommentTypeProject, | ||
Doer: doer, | ||
Repo: issue.Repo, | ||
Issue: issue, | ||
OldProjectID: i, | ||
ProjectID: newProjectID, | ||
}); err != nil { | ||
return err | ||
} | ||
} | ||
if action != "clear" && newProjectID == 0 || newProjectID > 0 { | ||
break | ||
} | ||
} | ||
if newProject.RepoID != issue.RepoID && newProject.OwnerID != issue.Repo.OwnerID { | ||
return fmt.Errorf("issue's repository is not the same as project's repository") | ||
} else { | ||
if action == "attach" || action == "" { | ||
if err := db.Insert(ctx, &project_model.ProjectIssue{ | ||
IssueID: issue.ID, | ||
ProjectID: newProjectID, | ||
}); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&project_model.ProjectIssue{}); err != nil { | ||
return err | ||
} | ||
|
||
if oldProjectID > 0 || newProjectID > 0 { | ||
if _, err := CreateComment(ctx, &CreateCommentOptions{ | ||
Type: CommentTypeProject, | ||
Doer: doer, | ||
Repo: issue.Repo, | ||
Issue: issue, | ||
OldProjectID: oldProjectID, | ||
ProjectID: newProjectID, | ||
}); err != nil { | ||
return err | ||
if newProjectID > 0 { | ||
if _, err := CreateComment(ctx, &CreateCommentOptions{ | ||
Type: CommentTypeProject, | ||
Doer: doer, | ||
Repo: issue.Repo, | ||
Issue: issue, | ||
OldProjectID: 0, | ||
ProjectID: newProjectID, | ||
}); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
return db.Insert(ctx, &project_model.ProjectIssue{ | ||
IssueID: issue.ID, | ||
ProjectID: newProjectID, | ||
}) | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -26,7 +26,7 @@ type IndexerData struct { | |||||
LabelIDs []int64 `json:"label_ids"` | ||||||
NoLabel bool `json:"no_label"` // True if LabelIDs is empty | ||||||
MilestoneID int64 `json:"milestone_id"` | ||||||
ProjectID int64 `json:"project_id"` | ||||||
ProjectIDs []int64 `json:"project_id"` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Other places also need to be modified. |
||||||
ProjectBoardID int64 `json:"project_board_id"` | ||||||
PosterID int64 `json:"poster_id"` | ||||||
AssigneeID int64 `json:"assignee_id"` | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,9 +89,9 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD | |
return nil, false, err | ||
} | ||
|
||
var projectID int64 | ||
if issue.Project != nil { | ||
projectID = issue.Project.ID | ||
var projectIDs []int64 | ||
for _, project := range issue.Projects { | ||
projectIDs = append(projectIDs, project.ID) | ||
} | ||
Comment on lines
+92
to
95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a function is better? Just a suggestion. Then we can use it in other places if necessary. |
||
|
||
return &internal.IndexerData{ | ||
|
@@ -106,7 +106,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD | |
LabelIDs: labels, | ||
NoLabel: len(labels) == 0, | ||
MilestoneID: issue.MilestoneID, | ||
ProjectID: projectID, | ||
ProjectIDs: projectIDs, | ||
ProjectBoardID: issue.ProjectBoardID(ctx), | ||
PosterID: issue.PosterID, | ||
AssigneeID: issue.AssigneeID, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need to check whether
projectIssue.Project
is already inissue.Projects
here.