summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGusted <gusted@noreply.codeberg.org>2024-11-02 23:33:30 +0100
committerGusted <gusted@noreply.codeberg.org>2024-11-02 23:33:30 +0100
commitd5426b0626f415875ac184d8c1a72a5b2cf113c1 (patch)
tree9a78ebff5d840f92d6dcb5b0e9d7d0dad5a3280e
parentMerge pull request 'Update module github.com/yuin/goldmark to v1.7.8 (forgejo... (diff)
parentfeat: Add Search to Releases Page (diff)
downloadforgejo-d5426b0626f415875ac184d8c1a72a5b2cf113c1.tar.xz
forgejo-d5426b0626f415875ac184d8c1a72a5b2cf113c1.zip
Merge pull request 'feat: Add Search to Releases Page' (#5777) from JakobDev/forgejo:releasesearch into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5777 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: Shiny Nematoda <snematoda@noreply.codeberg.org>
-rw-r--r--models/repo/release.go10
-rw-r--r--routers/api/v1/repo/release.go5
-rw-r--r--routers/web/repo/release.go10
-rw-r--r--templates/repo/release_tag_header.tmpl11
-rw-r--r--templates/swagger/v1_json.tmpl6
-rw-r--r--tests/integration/api_releases_test.go1
-rw-r--r--tests/integration/release_test.go29
7 files changed, 69 insertions, 3 deletions
diff --git a/models/repo/release.go b/models/repo/release.go
index e2cd7d7ed3..d96eac0d19 100644
--- a/models/repo/release.go
+++ b/models/repo/release.go
@@ -249,6 +249,7 @@ type FindReleasesOptions struct {
IsDraft optional.Option[bool]
TagNames []string
HasSha1 optional.Option[bool] // useful to find draft releases which are created with existing tags
+ Keyword string
}
func (opts FindReleasesOptions) ToConds() builder.Cond {
@@ -276,6 +277,15 @@ func (opts FindReleasesOptions) ToConds() builder.Cond {
cond = cond.And(builder.Eq{"sha1": ""})
}
}
+
+ if opts.Keyword != "" {
+ keywordCond := builder.NewCond()
+ keywordCond = keywordCond.Or(builder.Like{"lower_tag_name", strings.ToLower(opts.Keyword)})
+ keywordCond = keywordCond.Or(db.BuildCaseInsensitiveLike("title", opts.Keyword))
+ keywordCond = keywordCond.Or(db.BuildCaseInsensitiveLike("note", opts.Keyword))
+ cond = cond.And(keywordCond)
+ }
+
return cond
}
diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go
index 5ea4dc8cfc..2fc5f095cb 100644
--- a/routers/api/v1/repo/release.go
+++ b/routers/api/v1/repo/release.go
@@ -136,6 +136,10 @@ func ListReleases(ctx *context.APIContext) {
// in: query
// description: filter (exclude / include) pre-releases
// type: boolean
+ // - name: q
+ // in: query
+ // description: Search string
+ // type: string
// - name: page
// in: query
// description: page number of results to return (1-based)
@@ -158,6 +162,7 @@ func ListReleases(ctx *context.APIContext) {
IsDraft: ctx.FormOptionalBool("draft"),
IsPreRelease: ctx.FormOptionalBool("pre-release"),
RepoID: ctx.Repo.Repository.ID,
+ Keyword: ctx.FormTrim("q"),
}
releases, err := db.Find[repo_model.Release](ctx, opts)
diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go
index 2266debd6e..65d526d2f2 100644
--- a/routers/web/repo/release.go
+++ b/routers/web/repo/release.go
@@ -168,6 +168,10 @@ func Releases(ctx *context.Context) {
// Disable the showCreateNewBranch form in the dropdown on this page.
ctx.Data["CanCreateBranch"] = false
ctx.Data["HideBranchesInDropdown"] = true
+ ctx.Data["ShowReleaseSearch"] = true
+
+ keyword := ctx.FormTrim("q")
+ ctx.Data["Keyword"] = keyword
listOptions := db.ListOptions{
Page: ctx.FormInt("page"),
@@ -188,6 +192,7 @@ func Releases(ctx *context.Context) {
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
IncludeDrafts: writeAccess,
RepoID: ctx.Repo.Repository.ID,
+ Keyword: keyword,
})
if err != nil {
ctx.ServerError("getReleaseInfos", err)
@@ -258,6 +263,10 @@ func TagsList(ctx *context.Context) {
ctx.Data["CanCreateBranch"] = false
ctx.Data["HideBranchesInDropdown"] = true
ctx.Data["CanCreateRelease"] = ctx.Repo.CanWrite(unit.TypeReleases) && !ctx.Repo.Repository.IsArchived
+ ctx.Data["ShowReleaseSearch"] = true
+
+ keyword := ctx.FormTrim("q")
+ ctx.Data["Keyword"] = keyword
listOptions := db.ListOptions{
Page: ctx.FormInt("page"),
@@ -278,6 +287,7 @@ func TagsList(ctx *context.Context) {
IncludeTags: true,
HasSha1: optional.Some(true),
RepoID: ctx.Repo.Repository.ID,
+ Keyword: keyword,
}
releases, err := db.Find[repo_model.Release](ctx, opts)
diff --git a/templates/repo/release_tag_header.tmpl b/templates/repo/release_tag_header.tmpl
index dafe9f2fa6..63d0689c50 100644
--- a/templates/repo/release_tag_header.tmpl
+++ b/templates/repo/release_tag_header.tmpl
@@ -5,15 +5,20 @@
<div class="tw-flex">
<div class="tw-flex-1 tw-flex tw-items-center">
<h2 class="ui compact small menu small-menu-items">
- <a class="{{if and .PageIsReleaseList (not .PageIsSingleTag)}}active {{end}}item" href="{{.RepoLink}}/releases">{{ctx.Locale.TrN .NumReleases "repo.n_release_one" "repo.n_release_few" (ctx.Locale.PrettyNumber .NumReleases)}}</a>
+ <a class="{{if and .PageIsReleaseList (not .PageIsSingleTag)}}active {{end}}item" href="{{.RepoLink}}/releases{{if .Keyword}}?q={{.Keyword}}{{end}}">{{ctx.Locale.TrN .NumReleases "repo.n_release_one" "repo.n_release_few" (ctx.Locale.PrettyNumber .NumReleases)}}</a>
{{if $canReadCode}}
- <a class="{{if or .PageIsTagList .PageIsSingleTag}}active {{end}}item" href="{{.RepoLink}}/tags">{{ctx.Locale.TrN .NumTags "repo.n_tag_one" "repo.n_tag_few" (ctx.Locale.PrettyNumber .NumTags)}}</a>
+ <a class="{{if or .PageIsTagList .PageIsSingleTag}}active {{end}}item" href="{{.RepoLink}}/tags{{if .Keyword}}?q={{.Keyword}}{{end}}">{{ctx.Locale.TrN .NumTags "repo.n_tag_one" "repo.n_tag_few" (ctx.Locale.PrettyNumber .NumTags)}}</a>
{{end}}
</h2>
</div>
+ {{if .ShowReleaseSearch}}
+ <form class="ignore-dirty tw-w-1/5 tw-mr-3" method="get">
+ {{template "shared/search/combo" dict "Value" .Keyword}}
+ </form>
+ {{end}}
<div class="button-row">
{{if .EnableFeed}}
- <a class="ui small button" href="{{.RepoLink}}/{{if .PageIsTagList}}tags{{else}}releases{{end}}.rss">
+ <a class="ui small button tw-h-full" href="{{.RepoLink}}/{{if .PageIsTagList}}tags{{else}}releases{{end}}.rss">
{{svg "octicon-rss" 16}} {{ctx.Locale.Tr "rss_feed"}}
</a>
{{end}}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index dcf505cc7d..8e64c68f89 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -14164,6 +14164,12 @@
"in": "query"
},
{
+ "type": "string",
+ "description": "Search string",
+ "name": "q",
+ "in": "query"
+ },
+ {
"type": "integer",
"description": "page number of results to return (1-based)",
"name": "page",
diff --git a/tests/integration/api_releases_test.go b/tests/integration/api_releases_test.go
index 1bd8a643ad..1327daf57e 100644
--- a/tests/integration/api_releases_test.go
+++ b/tests/integration/api_releases_test.go
@@ -76,6 +76,7 @@ func TestAPIListReleases(t *testing.T) {
testFilterByLen(true, url.Values{"draft": {"false"}, "pre-release": {"false"}}, 1, "exclude drafts and pre-releases")
testFilterByLen(true, url.Values{"pre-release": {"true"}}, 1, "only get pre-release")
testFilterByLen(true, url.Values{"draft": {"true"}, "pre-release": {"true"}}, 0, "there is no pre-release draft")
+ testFilterByLen(true, url.Values{"q": {"release"}}, 3, "keyword")
}
func createNewReleaseUsingAPI(t *testing.T, token string, owner *user_model.User, repo *repo_model.Repository, name, target, title, desc string) *api.Release {
diff --git a/tests/integration/release_test.go b/tests/integration/release_test.go
index 48c2b37c91..c535c6c93d 100644
--- a/tests/integration/release_test.go
+++ b/tests/integration/release_test.go
@@ -272,6 +272,35 @@ func TestViewReleaseListLogin(t *testing.T) {
}, links)
}
+func TestViewReleaseListKeyword(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+
+ link := repo.Link() + "/releases?q=testing"
+
+ session := loginUser(t, "user1")
+ req := NewRequest(t, "GET", link)
+ rsp := session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, rsp.Body)
+ releases := htmlDoc.Find("#release-list li.ui.grid")
+ assert.Equal(t, 1, releases.Length())
+
+ links := make([]string, 0, 5)
+ releases.Each(func(i int, s *goquery.Selection) {
+ link, exist := s.Find(".release-list-title a").Attr("href")
+ if !exist {
+ return
+ }
+ links = append(links, link)
+ })
+
+ assert.EqualValues(t, []string{
+ "/user2/repo1/releases/tag/v1.1",
+ }, links)
+}
+
func TestReleaseOnCommit(t *testing.T) {
defer tests.PrepareTestEnv(t)()