aboutsummaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2024-12-11 14:33:24 +0800
committerGitHub <noreply@github.com>2024-12-11 06:33:24 +0000
commite619384098419569e570796a57ee6af4948067ae (patch)
tree9c5413be580d91ed9912878f80336eab89543670 /models
parent734ddf71180a9bf843d12dd9664eed28ba1a5748 (diff)
downloadgitea-e619384098419569e570796a57ee6af4948067ae.tar.gz
gitea-e619384098419569e570796a57ee6af4948067ae.zip
Add label/author/assignee filters to the user/org home issue list (#32779)
Replace #26661, fix #25979 Not perfect, but usable and much better than before. Since it is quite complex, I am not quite sure whether there would be any regression, if any, I will fix in first time. I have tested the related pages many times: issue list, milestone issue list, project view, user issue list, org issue list.
Diffstat (limited to 'models')
-rw-r--r--models/db/search.go12
-rw-r--r--models/issues/issue_search.go39
-rw-r--r--models/issues/issue_stats.go10
-rw-r--r--models/issues/issue_test.go3
4 files changed, 34 insertions, 30 deletions
diff --git a/models/db/search.go b/models/db/search.go
index 37565f45e1..e0a1b6bde9 100644
--- a/models/db/search.go
+++ b/models/db/search.go
@@ -26,8 +26,10 @@ const (
SearchOrderByForksReverse SearchOrderBy = "num_forks DESC"
)
-const (
- // Which means a condition to filter the records which don't match any id.
- // It's different from zero which means the condition could be ignored.
- NoConditionID = -1
-)
+// NoConditionID means a condition to filter the records which don't match any id.
+// eg: "milestone_id=-1" means "find the items without any milestone.
+const NoConditionID int64 = -1
+
+// NonExistingID means a condition to match no result (eg: a non-existing user)
+// It doesn't use -1 or -2 because they are used as builtin users.
+const NonExistingID int64 = -1000000
diff --git a/models/issues/issue_search.go b/models/issues/issue_search.go
index 5948a67d4e..f1cd125d49 100644
--- a/models/issues/issue_search.go
+++ b/models/issues/issue_search.go
@@ -27,8 +27,8 @@ type IssuesOptions struct { //nolint
RepoIDs []int64 // overwrites RepoCond if the length is not 0
AllPublic bool // include also all public repositories
RepoCond builder.Cond
- AssigneeID int64
- PosterID int64
+ AssigneeID optional.Option[int64]
+ PosterID optional.Option[int64]
MentionedID int64
ReviewRequestedID int64
ReviewedID int64
@@ -231,15 +231,8 @@ func applyConditions(sess *xorm.Session, opts *IssuesOptions) {
sess.And("issue.is_closed=?", opts.IsClosed.Value())
}
- if opts.AssigneeID > 0 {
- applyAssigneeCondition(sess, opts.AssigneeID)
- } else if opts.AssigneeID == db.NoConditionID {
- sess.Where("issue.id NOT IN (SELECT issue_id FROM issue_assignees)")
- }
-
- if opts.PosterID > 0 {
- applyPosterCondition(sess, opts.PosterID)
- }
+ applyAssigneeCondition(sess, opts.AssigneeID)
+ applyPosterCondition(sess, opts.PosterID)
if opts.MentionedID > 0 {
applyMentionedCondition(sess, opts.MentionedID)
@@ -359,13 +352,27 @@ func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *organizati
return cond
}
-func applyAssigneeCondition(sess *xorm.Session, assigneeID int64) {
- sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
- And("issue_assignees.assignee_id = ?", assigneeID)
+func applyAssigneeCondition(sess *xorm.Session, assigneeID optional.Option[int64]) {
+ // old logic: 0 is also treated as "not filtering assignee", because the "assignee" was read as FormInt64
+ if !assigneeID.Has() || assigneeID.Value() == 0 {
+ return
+ }
+ if assigneeID.Value() == db.NoConditionID {
+ sess.Where("issue.id NOT IN (SELECT issue_id FROM issue_assignees)")
+ } else {
+ sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
+ And("issue_assignees.assignee_id = ?", assigneeID.Value())
+ }
}
-func applyPosterCondition(sess *xorm.Session, posterID int64) {
- sess.And("issue.poster_id=?", posterID)
+func applyPosterCondition(sess *xorm.Session, posterID optional.Option[int64]) {
+ if !posterID.Has() {
+ return
+ }
+ // poster doesn't need to support db.NoConditionID(-1), so just use the value as-is
+ if posterID.Has() {
+ sess.And("issue.poster_id=?", posterID.Value())
+ }
}
func applyMentionedCondition(sess *xorm.Session, mentionedID int64) {
diff --git a/models/issues/issue_stats.go b/models/issues/issue_stats.go
index 39326616f8..9ef9347a16 100644
--- a/models/issues/issue_stats.go
+++ b/models/issues/issue_stats.go
@@ -151,15 +151,9 @@ func applyIssuesOptions(sess *xorm.Session, opts *IssuesOptions, issueIDs []int6
applyProjectCondition(sess, opts)
- if opts.AssigneeID > 0 {
- applyAssigneeCondition(sess, opts.AssigneeID)
- } else if opts.AssigneeID == db.NoConditionID {
- sess.Where("issue.id NOT IN (SELECT issue_id FROM issue_assignees)")
- }
+ applyAssigneeCondition(sess, opts.AssigneeID)
- if opts.PosterID > 0 {
- applyPosterCondition(sess, opts.PosterID)
- }
+ applyPosterCondition(sess, opts.PosterID)
if opts.MentionedID > 0 {
applyMentionedCondition(sess, opts.MentionedID)
diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go
index 1bbc0eee56..548f137f39 100644
--- a/models/issues/issue_test.go
+++ b/models/issues/issue_test.go
@@ -16,6 +16,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"github.com/stretchr/testify/assert"
@@ -155,7 +156,7 @@ func TestIssues(t *testing.T) {
}{
{
issues_model.IssuesOptions{
- AssigneeID: 1,
+ AssigneeID: optional.Some(int64(1)),
SortType: "oldest",
},
[]int64{1, 6},