From d07fbce201a1be1a19e65686b55e2e54c72bf55f Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Sat, 12 Jul 2025 20:28:10 +0900 Subject: [PATCH] appview: add issue search endpoint Change-Id: sqlmmyoulmsmmyvqqwlrtsktryoutywx Signed-off-by: Seongmin Lee --- appview/db/issues.go | 56 +++++++++++++++++++ appview/issues/issues.go | 35 +++++++++--- .../pages/templates/repo/issues/issues.html | 11 +++- 3 files changed, 93 insertions(+), 9 deletions(-) diff --git a/appview/db/issues.go b/appview/db/issues.go index f781de8b..6cab07bc 100644 --- a/appview/db/issues.go +++ b/appview/db/issues.go @@ -250,6 +250,62 @@ func GetIssues(e Execer, filters ...filter) ([]models.Issue, error) { return GetIssuesPaginated(e, pagination.Page{}, filters...) } +// GetIssueIDs gets list of all existing issue's IDs +func GetIssueIDs(e Execer, opts models.IssueSearchOptions) ([]int64, error) { + var ids []int64 + + var filters []filter + openValue := 0 + if opts.IsOpen { + openValue = 1 + } + filters = append(filters, FilterEq("open", openValue)) + if opts.RepoAt != "" { + filters = append(filters, FilterEq("repo_at", opts.RepoAt)) + } + + var conditions []string + var args []any + + for _, filter := range filters { + conditions = append(conditions, filter.Condition()) + args = append(args, filter.Arg()...) + } + + whereClause := "" + if conditions != nil { + whereClause = " where " + strings.Join(conditions, " and ") + } + query := fmt.Sprintf( + ` + select + id + from + issues + %s + limit ? offset ?`, + whereClause, + ) + args = append(args, opts.Page.Limit, opts.Page.Offset) + rows, err := e.Query(query, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var id int64 + err := rows.Scan(&id) + if err != nil { + return nil, err + } + + ids = append(ids, id) + } + + return ids, nil +} + func AddIssueComment(e Execer, c models.IssueComment) (int64, error) { result, err := e.Exec( `insert into issue_comments ( diff --git a/appview/issues/issues.go b/appview/issues/issues.go index 9ac8b326..d1c598b3 100644 --- a/appview/issues/issues.go +++ b/appview/issues/issues.go @@ -783,15 +783,35 @@ func (rp *Issues) RepoIssues(w http.ResponseWriter, r *http.Request) { return } - openVal := 0 - if isOpen { - openVal = 1 + keyword := params.Get("q") + + var ids []int64 + searchOpts := models.IssueSearchOptions{ + Keyword: keyword, + RepoAt: f.RepoAt().String(), + IsOpen: isOpen, + Page: page, + } + if keyword != "" { + res, err := rp.indexer.Search(r.Context(), searchOpts) + if err != nil { + l.Error("failed to search for issues", "err", err) + return + } + ids = res.Hits + l.Debug("searched issues with indexer", "count", len(ids)) + } else { + ids, err = db.GetIssueIDs(rp.db, searchOpts) + if err != nil { + l.Error("failed to search for issues", "err", err) + return + } + l.Debug("indexed all issues from the db", "count", len(ids)) } - issues, err := db.GetIssuesPaginated( + + issues, err := db.GetIssues( rp.db, - page, - db.FilterEq("repo_at", f.RepoAt()), - db.FilterEq("open", openVal), + db.FilterIn("id", ids), ) if err != nil { l.Error("failed to get issues", "err", err) @@ -821,6 +841,7 @@ func (rp *Issues) RepoIssues(w http.ResponseWriter, r *http.Request) { Issues: issues, LabelDefs: defs, FilteringByOpen: isOpen, + FilterQuery: keyword, Page: page, }) } diff --git a/appview/pages/templates/repo/issues/issues.html b/appview/pages/templates/repo/issues/issues.html index 5d073f0e..34f11abd 100644 --- a/appview/pages/templates/repo/issues/issues.html +++ b/appview/pages/templates/repo/issues/issues.html @@ -24,6 +24,13 @@ {{ i "ban" "w-4 h-4" }} {{ .RepoInfo.Stats.IssueCount.Closed }} closed +
+ + + +
{{ i "chevron-left" "w-4 h-4" }} previous @@ -69,7 +76,7 @@ next {{ i "chevron-right" "w-4 h-4" }} -- 2.43.0