Added multi-project feature

This commit is contained in:
Tyrone Yeh
2025-05-07 09:02:35 +08:00
parent 6bd8fe5353
commit d48061bb19
19 changed files with 185 additions and 131 deletions
+1 -1
View File
@@ -30,7 +30,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"`
ProjectColumnID int64 `json:"project_board_id"` // the key should be kept as project_board_id to keep compatible
PosterID int64 `json:"poster_id"`
AssigneeID int64 `json:"assignee_id"`
+10 -6
View File
@@ -302,7 +302,7 @@ var cases = []*testIndexerCase{
},
},
{
Name: "ProjectID",
Name: "ProjectIDs",
SearchOptions: &internal.SearchOptions{
Paginator: &db.ListOptions{
PageSize: 5,
@@ -312,10 +312,10 @@ var cases = []*testIndexerCase{
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
assert.Len(t, result.Hits, 5)
for _, v := range result.Hits {
assert.Equal(t, int64(1), data[v.ID].ProjectID)
assert.Equal(t, int64(1), data[v.ID].ProjectIDs[0])
}
assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool {
return v.ProjectID == 1
return v.ProjectIDs[0] == 1
}), result.Total)
},
},
@@ -330,10 +330,10 @@ var cases = []*testIndexerCase{
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
assert.Len(t, result.Hits, 5)
for _, v := range result.Hits {
assert.Equal(t, int64(0), data[v.ID].ProjectID)
assert.Equal(t, int64(0), data[v.ID].ProjectIDs[0])
}
assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool {
return v.ProjectID == 0
return v.ProjectIDs[0] == 0
}), result.Total)
},
},
@@ -691,6 +691,10 @@ func generateDefaultIndexerData() []*internal.IndexerData {
for i := range labelIDs {
labelIDs[i] = int64(i) + 1 // LabelID should not be 0
}
projectIDs := make([]int64, id%5)
for i := range projectIDs {
projectIDs[i] = int64(i) + 1 // projectIDs should not be 0
}
mentionIDs := make([]int64, id%6)
for i := range mentionIDs {
mentionIDs[i] = int64(i) + 1 // MentionID should not be 0
@@ -720,7 +724,7 @@ func generateDefaultIndexerData() []*internal.IndexerData {
LabelIDs: labelIDs,
NoLabel: len(labelIDs) == 0,
MilestoneID: issueIndex % 4,
ProjectID: issueIndex % 5,
ProjectIDs: projectIDs,
ProjectColumnID: issueIndex % 6,
PosterID: id%10 + 1, // PosterID should not be 0
AssigneeID: issueIndex % 10,
+4 -4
View File
@@ -87,9 +87,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
projectIDs := make([]int64, 0, len(issue.Projects))
for _, project := range issue.Projects {
projectIDs = append(projectIDs, project.ID)
}
projectColumnID, err := issue.ProjectColumnID(ctx)
@@ -110,7 +110,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
LabelIDs: labels,
NoLabel: len(labels) == 0,
MilestoneID: issue.MilestoneID,
ProjectID: projectID,
ProjectIDs: projectIDs,
ProjectColumnID: projectColumnID,
PosterID: issue.PosterID,
AssigneeID: issue.AssigneeID,
+24
View File
@@ -253,3 +253,27 @@ func ReserveLineBreakForTextarea(input string) string {
// Other than this, we should respect the original content, even leading or trailing spaces.
return strings.ReplaceAll(input, "\r\n", "\n")
}
func DiffSlice[T comparable](oldSlice, newSlice []T) (added, removed []T) {
oldSet := make(map[T]struct{}, len(oldSlice))
newSet := make(map[T]struct{}, len(newSlice))
for _, v := range oldSlice {
oldSet[v] = struct{}{}
}
for _, v := range newSlice {
newSet[v] = struct{}{}
}
for v := range newSet {
if _, found := oldSet[v]; !found {
added = append(added, v)
}
}
for v := range oldSet {
if _, found := newSet[v]; !found {
removed = append(removed, v)
}
}
return added, removed
}