mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-29 13:16:10 +01:00
[FEAT] expose fuzzy search for issues/repo (#4160)
Ports fuzzy search for `/issues` and `/pulls` from gitea. Adds fuzzy search for `/user/repo/issues` and `/user/repo/pulls`. --- ## Notes ### Port: [`gitea#be5be0ac81`](be5be0ac81
) - CONFLICT (content): Merge conflict in routers/web/user/home.go Conflict resolved by 1. keeping both `PageIsOrgIssues` and the newly introduced `IsFuzzy` 2. using `pager.AddParam(ctx, "fuzzy", "IsFuzzy")` rather than `pager.AddParamString("fuzzy", fmt.Sprintf("%v", isFuzzy))` - CONFLICT (content): Merge conflict in templates/user/dashboard/issues.tmpl Conflict resolved by keeping the changes from #4096, and picking the `&fuzzy=${{.IsFuzzy}}` inclusion to all urls and `{{if .PageIsPulls}}...` ### Port: [`gitea#fede3cbada`](fede3cbada
) - CONFLICT (content): Merge conflict in templates/user/dashboard/issues.tmpl Conflict resolved by keeping previous changes and picking the replacement of `{{if .PageIsPulls}}...` with `{{template "shared/search/combo_fuzzy"...` which contains the replacement of `explorer.go` to `explorer.go_to` ### Fixup commit replaces `Iif` with `if` which was introduced in gitea#fede3cbada ### Feature commit adds in support for /user/repo/(issues|pulls) + test Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Kerwin Bryant <kerwin612@qq.com> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/4160 Reviewed-by: twenty-panda <twenty-panda@noreply.codeberg.org> Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com> Co-committed-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
This commit is contained in:
parent
bd23b8c75f
commit
b5d96e7db7
|
@ -163,8 +163,8 @@ search = Search...
|
||||||
type_tooltip = Search type
|
type_tooltip = Search type
|
||||||
fuzzy = Fuzzy
|
fuzzy = Fuzzy
|
||||||
fuzzy_tooltip = Include results that also match the search term closely
|
fuzzy_tooltip = Include results that also match the search term closely
|
||||||
match = Match
|
exact = Exact
|
||||||
match_tooltip = Include only results that match the exact search term
|
exact_tooltip = Include only results that match the exact search term
|
||||||
repo_kind = Search repos...
|
repo_kind = Search repos...
|
||||||
user_kind = Search users...
|
user_kind = Search users...
|
||||||
org_kind = Search orgs...
|
org_kind = Search orgs...
|
||||||
|
@ -178,6 +178,8 @@ branch_kind = Search branches...
|
||||||
commit_kind = Search commits...
|
commit_kind = Search commits...
|
||||||
runner_kind = Search runners...
|
runner_kind = Search runners...
|
||||||
no_results = No matching results found.
|
no_results = No matching results found.
|
||||||
|
issue_kind = Search issues...
|
||||||
|
pull_kind = Search pulls...
|
||||||
keyword_search_unavailable = Searching by keyword is currently not available. Please contact the site administrator.
|
keyword_search_unavailable = Searching by keyword is currently not available. Please contact the site administrator.
|
||||||
|
|
||||||
[aria]
|
[aria]
|
||||||
|
|
3
release-notes/8.0.0/feat/4160.md
Normal file
3
release-notes/8.0.0/feat/4160.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Added support for fuzzy searching issues and pulls
|
||||||
|
- support for `/issues` and `/pulls` were ported from [`gitea#be5be0ac81`](https://github.com/go-gitea/gitea/commit/be5be0ac81ce50ad5adb079af6ca4e8c396aaece)
|
||||||
|
- support for `/user/repo/issues` and `/user/repo/pulls` were added
|
|
@ -201,6 +201,8 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||||
keyword = ""
|
keyword = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isFuzzy := ctx.FormBool("fuzzy")
|
||||||
|
|
||||||
var mileIDs []int64
|
var mileIDs []int64
|
||||||
if milestoneID > 0 || milestoneID == db.NoConditionID { // -1 to get those issues which have no any milestone assigned
|
if milestoneID > 0 || milestoneID == db.NoConditionID { // -1 to get those issues which have no any milestone assigned
|
||||||
mileIDs = []int64{milestoneID}
|
mileIDs = []int64{milestoneID}
|
||||||
|
@ -221,7 +223,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||||
IssueIDs: nil,
|
IssueIDs: nil,
|
||||||
}
|
}
|
||||||
if keyword != "" {
|
if keyword != "" {
|
||||||
allIssueIDs, err := issueIDsFromSearch(ctx, keyword, statsOpts)
|
allIssueIDs, err := issueIDsFromSearch(ctx, keyword, isFuzzy, statsOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if issue_indexer.IsAvailable(ctx) {
|
if issue_indexer.IsAvailable(ctx) {
|
||||||
ctx.ServerError("issueIDsFromSearch", err)
|
ctx.ServerError("issueIDsFromSearch", err)
|
||||||
|
@ -289,7 +291,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||||
|
|
||||||
var issues issues_model.IssueList
|
var issues issues_model.IssueList
|
||||||
{
|
{
|
||||||
ids, err := issueIDsFromSearch(ctx, keyword, &issues_model.IssuesOptions{
|
ids, err := issueIDsFromSearch(ctx, keyword, isFuzzy, &issues_model.IssuesOptions{
|
||||||
Paginator: &db.ListOptions{
|
Paginator: &db.ListOptions{
|
||||||
Page: pager.Paginater.Current(),
|
Page: pager.Paginater.Current(),
|
||||||
PageSize: setting.UI.IssuePagingNum,
|
PageSize: setting.UI.IssuePagingNum,
|
||||||
|
@ -465,6 +467,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||||
ctx.Data["ProjectID"] = projectID
|
ctx.Data["ProjectID"] = projectID
|
||||||
ctx.Data["AssigneeID"] = assigneeID
|
ctx.Data["AssigneeID"] = assigneeID
|
||||||
ctx.Data["PosterID"] = posterID
|
ctx.Data["PosterID"] = posterID
|
||||||
|
ctx.Data["IsFuzzy"] = isFuzzy
|
||||||
ctx.Data["Keyword"] = keyword
|
ctx.Data["Keyword"] = keyword
|
||||||
switch {
|
switch {
|
||||||
case isShowClosed.Value():
|
case isShowClosed.Value():
|
||||||
|
@ -486,12 +489,17 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||||
pager.AddParam(ctx, "assignee", "AssigneeID")
|
pager.AddParam(ctx, "assignee", "AssigneeID")
|
||||||
pager.AddParam(ctx, "poster", "PosterID")
|
pager.AddParam(ctx, "poster", "PosterID")
|
||||||
pager.AddParam(ctx, "archived", "ShowArchivedLabels")
|
pager.AddParam(ctx, "archived", "ShowArchivedLabels")
|
||||||
|
pager.AddParam(ctx, "fuzzy", "IsFuzzy")
|
||||||
|
|
||||||
ctx.Data["Page"] = pager
|
ctx.Data["Page"] = pager
|
||||||
}
|
}
|
||||||
|
|
||||||
func issueIDsFromSearch(ctx *context.Context, keyword string, opts *issues_model.IssuesOptions) ([]int64, error) {
|
func issueIDsFromSearch(ctx *context.Context, keyword string, fuzzy bool, opts *issues_model.IssuesOptions) ([]int64, error) {
|
||||||
ids, _, err := issue_indexer.SearchIssues(ctx, issue_indexer.ToSearchOptions(keyword, opts))
|
ids, _, err := issue_indexer.SearchIssues(ctx, issue_indexer.ToSearchOptions(keyword, opts).Copy(
|
||||||
|
func(o *issue_indexer.SearchOptions) {
|
||||||
|
o.IsFuzzyKeyword = fuzzy
|
||||||
|
},
|
||||||
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("SearchIssues: %w", err)
|
return nil, fmt.Errorf("SearchIssues: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,6 +447,8 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
|
||||||
User: ctx.Doer,
|
User: ctx.Doer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isFuzzy := ctx.FormBool("fuzzy")
|
||||||
|
|
||||||
// Search all repositories which
|
// Search all repositories which
|
||||||
//
|
//
|
||||||
// As user:
|
// As user:
|
||||||
|
@ -576,7 +578,9 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
|
||||||
// USING FINAL STATE OF opts FOR A QUERY.
|
// USING FINAL STATE OF opts FOR A QUERY.
|
||||||
var issues issues_model.IssueList
|
var issues issues_model.IssueList
|
||||||
{
|
{
|
||||||
issueIDs, _, err := issue_indexer.SearchIssues(ctx, issue_indexer.ToSearchOptions(keyword, opts))
|
issueIDs, _, err := issue_indexer.SearchIssues(ctx, issue_indexer.ToSearchOptions(keyword, opts).Copy(
|
||||||
|
func(o *issue_indexer.SearchOptions) { o.IsFuzzyKeyword = isFuzzy },
|
||||||
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("issueIDsFromSearch", err)
|
ctx.ServerError("issueIDsFromSearch", err)
|
||||||
return
|
return
|
||||||
|
@ -597,7 +601,9 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Fill stats to post to ctx.Data.
|
// Fill stats to post to ctx.Data.
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
issueStats, err := getUserIssueStats(ctx, ctxUser, filterMode, issue_indexer.ToSearchOptions(keyword, opts))
|
issueStats, err := getUserIssueStats(ctx, ctxUser, filterMode, issue_indexer.ToSearchOptions(keyword, opts).Copy(
|
||||||
|
func(o *issue_indexer.SearchOptions) { o.IsFuzzyKeyword = isFuzzy },
|
||||||
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("getUserIssueStats", err)
|
ctx.ServerError("getUserIssueStats", err)
|
||||||
return
|
return
|
||||||
|
@ -652,6 +658,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
|
||||||
ctx.Data["IsShowClosed"] = isShowClosed
|
ctx.Data["IsShowClosed"] = isShowClosed
|
||||||
ctx.Data["SelectLabels"] = selectedLabels
|
ctx.Data["SelectLabels"] = selectedLabels
|
||||||
ctx.Data["PageIsOrgIssues"] = org != nil
|
ctx.Data["PageIsOrgIssues"] = org != nil
|
||||||
|
ctx.Data["IsFuzzy"] = isFuzzy
|
||||||
|
|
||||||
if isShowClosed {
|
if isShowClosed {
|
||||||
ctx.Data["State"] = "closed"
|
ctx.Data["State"] = "closed"
|
||||||
|
@ -667,6 +674,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
|
||||||
pager.AddParam(ctx, "labels", "SelectLabels")
|
pager.AddParam(ctx, "labels", "SelectLabels")
|
||||||
pager.AddParam(ctx, "milestone", "MilestoneID")
|
pager.AddParam(ctx, "milestone", "MilestoneID")
|
||||||
pager.AddParam(ctx, "assignee", "AssigneeID")
|
pager.AddParam(ctx, "assignee", "AssigneeID")
|
||||||
|
pager.AddParam(ctx, "fuzzy", "IsFuzzy")
|
||||||
ctx.Data["Page"] = pager
|
ctx.Data["Page"] = pager
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplIssues)
|
ctx.HTML(http.StatusOK, tplIssues)
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
<input type="hidden" name="assignee" value="{{$.AssigneeID}}">
|
<input type="hidden" name="assignee" value="{{$.AssigneeID}}">
|
||||||
<input type="hidden" name="poster" value="{{$.PosterID}}">
|
<input type="hidden" name="poster" value="{{$.PosterID}}">
|
||||||
{{end}}
|
{{end}}
|
||||||
{{template "shared/search/input" dict "Value" .Keyword}}
|
{{if .PageIsPullList}}
|
||||||
{{if .PageIsIssueList}}
|
{{template "shared/search/combo_fuzzy" dict "Value" .Keyword "IsFuzzy" .IsFuzzy "Placeholder" (ctx.Locale.Tr "search.pull_kind") "Tooltip" (ctx.Locale.Tr "explore.go_to")}}
|
||||||
<button id="issue-list-quick-goto" class="ui small icon button tw-hidden" data-tooltip-content="{{ctx.Locale.Tr "explore.go_to"}}" data-repo-link="{{.RepoLink}}">{{svg "octicon-hash"}}</button>
|
{{else}}
|
||||||
|
{{template "shared/search/combo_fuzzy" dict "Value" .Keyword "IsFuzzy" .IsFuzzy "Placeholder" (ctx.Locale.Tr "search.issue_kind") "Tooltip" (ctx.Locale.Tr "explore.go_to")}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{template "shared/search/button"}}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
{{/* IsFuzzy - state of the fuzzy search toggle */}}
|
{{/* IsFuzzy - state of the fuzzy search toggle */}}
|
||||||
<div class="ui small dropdown selection {{if .Disabled}} disabled{{end}}" data-tooltip-content="{{ctx.Locale.Tr "search.type_tooltip"}}">
|
<div class="ui small dropdown selection {{if .Disabled}} disabled{{end}}" data-tooltip-content="{{ctx.Locale.Tr "search.type_tooltip"}}">
|
||||||
<input name="fuzzy" type="hidden"{{if .Disabled}} disabled{{end}} value="{{.IsFuzzy}}">{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
<input name="fuzzy" type="hidden"{{if .Disabled}} disabled{{end}} value="{{.IsFuzzy}}">{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
<div class="text">{{if .IsFuzzy}}{{ctx.Locale.Tr "search.fuzzy"}}{{else}}{{ctx.Locale.Tr "search.match"}}{{end}}</div>
|
<div class="text">{{if .IsFuzzy}}{{ctx.Locale.Tr "search.fuzzy"}}{{else}}{{ctx.Locale.Tr "search.exact"}}{{end}}</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="item" data-value="true" data-tooltip-content="{{ctx.Locale.Tr "search.fuzzy_tooltip"}}">{{ctx.Locale.Tr "search.fuzzy"}}</div>
|
<div class="item" data-value="true" data-tooltip-content="{{ctx.Locale.Tr "search.fuzzy_tooltip"}}">{{ctx.Locale.Tr "search.fuzzy"}}</div>
|
||||||
<div class="item" data-value="false" data-tooltip-content="{{ctx.Locale.Tr "search.match_tooltip"}}">{{ctx.Locale.Tr "search.match"}}</div>
|
<div class="item" data-value="false" data-tooltip-content="{{ctx.Locale.Tr "search.exact_tooltip"}}">{{ctx.Locale.Tr "search.exact"}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<div class="list-header">
|
<div class="list-header">
|
||||||
<div class="small-menu-items ui compact tiny menu list-header-toggle">
|
<div class="small-menu-items ui compact tiny menu list-header-toggle">
|
||||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&q={{$.Keyword}}">
|
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
{{svg "octicon-issue-opened" 16 "tw-mr-2"}}
|
{{svg "octicon-issue-opened" 16 "tw-mr-2"}}
|
||||||
{{ctx.Locale.PrettyNumber .IssueStats.OpenCount}} {{ctx.Locale.Tr "repo.issues.open_title"}}
|
{{ctx.Locale.PrettyNumber .IssueStats.OpenCount}} {{ctx.Locale.Tr "repo.issues.open_title"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="item{{if .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&q={{$.Keyword}}">
|
<a class="item{{if .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
{{svg "octicon-issue-closed" 16 "tw-mr-2"}}
|
{{svg "octicon-issue-closed" 16 "tw-mr-2"}}
|
||||||
{{ctx.Locale.PrettyNumber .IssueStats.ClosedCount}} {{ctx.Locale.Tr "repo.issues.closed_title"}}
|
{{ctx.Locale.PrettyNumber .IssueStats.ClosedCount}} {{ctx.Locale.Tr "repo.issues.closed_title"}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -19,9 +19,11 @@
|
||||||
<input type="hidden" name="type" value="{{$.ViewType}}">
|
<input type="hidden" name="type" value="{{$.ViewType}}">
|
||||||
<input type="hidden" name="sort" value="{{$.SortType}}">
|
<input type="hidden" name="sort" value="{{$.SortType}}">
|
||||||
<input type="hidden" name="state" value="{{$.State}}">
|
<input type="hidden" name="state" value="{{$.State}}">
|
||||||
{{template "shared/search/input" dict "Value" $.Keyword}}
|
{{if .PageIsPulls}}
|
||||||
<button id="issue-list-quick-goto" class="ui small icon button tw-hidden" data-tooltip-content="{{ctx.Locale.Tr "explore.go_to"}}">{{svg "octicon-hash"}}</button>
|
{{template "shared/search/combo_fuzzy" dict "Value" $.Keyword "IsFuzzy" $.IsFuzzy "Placeholder" (ctx.Locale.Tr "search.pull_kind") "Tooltip" (ctx.Locale.Tr "explore.go_to")}}
|
||||||
{{template "shared/search/button"}}
|
{{else}}
|
||||||
|
{{template "shared/search/combo_fuzzy" dict "Value" $.Keyword "IsFuzzy" $.IsFuzzy "Placeholder" (ctx.Locale.Tr "search.issue_kind") "Tooltip" (ctx.Locale.Tr "explore.go_to")}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="ui secondary menu tw-mt-0">
|
<div class="ui secondary menu tw-mt-0">
|
||||||
|
@ -36,29 +38,29 @@
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
</span>
|
</span>
|
||||||
<div class="ui menu">
|
<div class="ui menu">
|
||||||
<a class="{{if eq .ViewType "your_repositories"}}active{{end}} item" href="?type=your_repositories&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}">
|
<a class="{{if eq .ViewType "your_repositories"}}active{{end}} item" href="?type=your_repositories&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.YourRepositoriesCount}}</div>
|
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.YourRepositoriesCount}}</div>
|
||||||
{{ctx.Locale.Tr "home.issues.in_your_repos"}}
|
{{ctx.Locale.Tr "home.issues.in_your_repos"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if eq .ViewType "assigned"}}active{{end}} item" href="?type=assigned&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}">
|
<a class="{{if eq .ViewType "assigned"}}active{{end}} item" href="?type=assigned&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.AssignCount}}</div>
|
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.AssignCount}}</div>
|
||||||
{{ctx.Locale.Tr "repo.issues.filter_type.assigned_to_you"}}
|
{{ctx.Locale.Tr "repo.issues.filter_type.assigned_to_you"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if eq .ViewType "created_by"}}active{{end}} item" href="?type=created_by&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}">
|
<a class="{{if eq .ViewType "created_by"}}active{{end}} item" href="?type=created_by&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.CreateCount}}</div>
|
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.CreateCount}}</div>
|
||||||
{{ctx.Locale.Tr "repo.issues.filter_type.created_by_you"}}
|
{{ctx.Locale.Tr "repo.issues.filter_type.created_by_you"}}
|
||||||
</a>
|
</a>
|
||||||
{{if .PageIsPulls}}
|
{{if .PageIsPulls}}
|
||||||
<a class="{{if eq .ViewType "review_requested"}}active{{end}} item" href="?type=review_requested&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}">
|
<a class="{{if eq .ViewType "review_requested"}}active{{end}} item" href="?type=review_requested&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.ReviewRequestedCount}}</div>
|
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.ReviewRequestedCount}}</div>
|
||||||
{{ctx.Locale.Tr "repo.issues.filter_type.review_requested"}}
|
{{ctx.Locale.Tr "repo.issues.filter_type.review_requested"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if eq .ViewType "reviewed_by"}}active{{end}} item" href="?type=reviewed_by&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}">
|
<a class="{{if eq .ViewType "reviewed_by"}}active{{end}} item" href="?type=reviewed_by&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.ReviewedCount}}</div>
|
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.ReviewedCount}}</div>
|
||||||
{{ctx.Locale.Tr "repo.issues.filter_type.reviewed_by_you"}}
|
{{ctx.Locale.Tr "repo.issues.filter_type.reviewed_by_you"}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<a class="{{if eq .ViewType "mentioned"}}active{{end}} item" href="?type=mentioned&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}">
|
<a class="{{if eq .ViewType "mentioned"}}active{{end}} item" href="?type=mentioned&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
|
||||||
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.MentionCount}}</div>
|
<div class="ui circular mini label tw-ml-0">{{CountFmt .IssueStats.MentionCount}}</div>
|
||||||
{{ctx.Locale.Tr "repo.issues.filter_type.mentioning_you"}}
|
{{ctx.Locale.Tr "repo.issues.filter_type.mentioning_you"}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -71,14 +73,14 @@
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
</span>
|
</span>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
|
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
|
||||||
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
|
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
|
||||||
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active {{end}}item" href="?type={{$.ViewType}}&sort=latest&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
|
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active {{end}}item" href="?type={{$.ViewType}}&sort=latest&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
|
||||||
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="?type={{$.ViewType}}&sort=oldest&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
|
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="?type={{$.ViewType}}&sort=oldest&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
|
||||||
<a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="?type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
|
<a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="?type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
|
||||||
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="?type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
|
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="?type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
|
||||||
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=nearduedate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
|
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=nearduedate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
|
||||||
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=farduedate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
|
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=farduedate&state={{$.State}}&labels={{.SelectLabels}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -107,6 +107,7 @@ func TestViewIssuesKeyword(t *testing.T) {
|
||||||
})
|
})
|
||||||
issues.UpdateIssueIndexer(context.Background(), issue.ID)
|
issues.UpdateIssueIndexer(context.Background(), issue.ID)
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
|
|
||||||
const keyword = "first"
|
const keyword = "first"
|
||||||
req := NewRequestf(t, "GET", "%s/issues?q=%s", repo.Link(), keyword)
|
req := NewRequestf(t, "GET", "%s/issues?q=%s", repo.Link(), keyword)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -120,6 +121,27 @@ func TestViewIssuesKeyword(t *testing.T) {
|
||||||
assert.False(t, issue.IsPull)
|
assert.False(t, issue.IsPull)
|
||||||
assertMatch(t, issue, keyword)
|
assertMatch(t, issue, keyword)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// keyword: 'firstt'
|
||||||
|
// should not match when fuzzy searching is disabled
|
||||||
|
req = NewRequestf(t, "GET", "%s/issues?q=%st&fuzzy=false", repo.Link(), keyword)
|
||||||
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc = NewHTMLParser(t, resp.Body)
|
||||||
|
issuesSelection = getIssuesSelection(t, htmlDoc)
|
||||||
|
assert.EqualValues(t, 0, issuesSelection.Length())
|
||||||
|
|
||||||
|
// should match as 'first' when fuzzy seaeching is enabled
|
||||||
|
req = NewRequestf(t, "GET", "%s/issues?q=%st&fuzzy=true", repo.Link(), keyword)
|
||||||
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc = NewHTMLParser(t, resp.Body)
|
||||||
|
issuesSelection = getIssuesSelection(t, htmlDoc)
|
||||||
|
assert.EqualValues(t, 1, issuesSelection.Length())
|
||||||
|
issuesSelection.Each(func(_ int, selection *goquery.Selection) {
|
||||||
|
issue := getIssue(t, repo.ID, selection)
|
||||||
|
assert.False(t, issue.IsClosed)
|
||||||
|
assert.False(t, issue.IsPull)
|
||||||
|
assertMatch(t, issue, keyword)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoLoginViewIssue(t *testing.T) {
|
func TestNoLoginViewIssue(t *testing.T) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ textarea,
|
||||||
|
|
||||||
/* fix fomantic small dropdown having inconsistent padding with input */
|
/* fix fomantic small dropdown having inconsistent padding with input */
|
||||||
.ui.small.selection.dropdown {
|
.ui.small.selection.dropdown {
|
||||||
padding: .67857143em 3.2em .67857143em 1em;
|
padding: .67857143em 1.6em .67857143em 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:hover,
|
input:hover,
|
||||||
|
|
Loading…
Reference in a new issue