mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-30 22:11:07 +00: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
					
				
			
		
					 9 changed files with 79 additions and 34 deletions
				
			
		|  | @ -163,8 +163,8 @@ search = Search... | |||
| type_tooltip = Search type | ||||
| fuzzy = Fuzzy | ||||
| fuzzy_tooltip = Include results that also match the search term closely | ||||
| match = Match | ||||
| match_tooltip = Include only results that match the exact search term | ||||
| exact = Exact | ||||
| exact_tooltip = Include only results that match the exact search term | ||||
| repo_kind = Search repos... | ||||
| user_kind = Search users... | ||||
| org_kind = Search orgs... | ||||
|  | @ -178,6 +178,8 @@ branch_kind = Search branches... | |||
| commit_kind = Search commits... | ||||
| runner_kind = Search runners... | ||||
| 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. | ||||
| 
 | ||||
| [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 = "" | ||||
| 	} | ||||
| 
 | ||||
| 	isFuzzy := ctx.FormBool("fuzzy") | ||||
| 
 | ||||
| 	var mileIDs []int64 | ||||
| 	if milestoneID > 0 || milestoneID == db.NoConditionID { // -1 to get those issues which have no any milestone assigned | ||||
| 		mileIDs = []int64{milestoneID} | ||||
|  | @ -221,7 +223,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt | |||
| 		IssueIDs:          nil, | ||||
| 	} | ||||
| 	if keyword != "" { | ||||
| 		allIssueIDs, err := issueIDsFromSearch(ctx, keyword, statsOpts) | ||||
| 		allIssueIDs, err := issueIDsFromSearch(ctx, keyword, isFuzzy, statsOpts) | ||||
| 		if err != nil { | ||||
| 			if issue_indexer.IsAvailable(ctx) { | ||||
| 				ctx.ServerError("issueIDsFromSearch", err) | ||||
|  | @ -289,7 +291,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt | |||
| 
 | ||||
| 	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{ | ||||
| 				Page:     pager.Paginater.Current(), | ||||
| 				PageSize: setting.UI.IssuePagingNum, | ||||
|  | @ -465,6 +467,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt | |||
| 	ctx.Data["ProjectID"] = projectID | ||||
| 	ctx.Data["AssigneeID"] = assigneeID | ||||
| 	ctx.Data["PosterID"] = posterID | ||||
| 	ctx.Data["IsFuzzy"] = isFuzzy | ||||
| 	ctx.Data["Keyword"] = keyword | ||||
| 	switch { | ||||
| 	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, "poster", "PosterID") | ||||
| 	pager.AddParam(ctx, "archived", "ShowArchivedLabels") | ||||
| 	pager.AddParam(ctx, "fuzzy", "IsFuzzy") | ||||
| 
 | ||||
| 	ctx.Data["Page"] = pager | ||||
| } | ||||
| 
 | ||||
| func issueIDsFromSearch(ctx *context.Context, keyword string, opts *issues_model.IssuesOptions) ([]int64, error) { | ||||
| 	ids, _, err := issue_indexer.SearchIssues(ctx, issue_indexer.ToSearchOptions(keyword, opts)) | ||||
| 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).Copy( | ||||
| 		func(o *issue_indexer.SearchOptions) { | ||||
| 			o.IsFuzzyKeyword = fuzzy | ||||
| 		}, | ||||
| 	)) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("SearchIssues: %w", err) | ||||
| 	} | ||||
|  |  | |||
|  | @ -447,6 +447,8 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { | |||
| 		User:       ctx.Doer, | ||||
| 	} | ||||
| 
 | ||||
| 	isFuzzy := ctx.FormBool("fuzzy") | ||||
| 
 | ||||
| 	// Search all repositories which | ||||
| 	// | ||||
| 	// As user: | ||||
|  | @ -576,7 +578,9 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { | |||
| 	// USING FINAL STATE OF opts FOR A QUERY. | ||||
| 	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 { | ||||
| 			ctx.ServerError("issueIDsFromSearch", err) | ||||
| 			return | ||||
|  | @ -597,7 +601,9 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { | |||
| 	// ------------------------------- | ||||
| 	// 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 { | ||||
| 		ctx.ServerError("getUserIssueStats", err) | ||||
| 		return | ||||
|  | @ -652,6 +658,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { | |||
| 	ctx.Data["IsShowClosed"] = isShowClosed | ||||
| 	ctx.Data["SelectLabels"] = selectedLabels | ||||
| 	ctx.Data["PageIsOrgIssues"] = org != nil | ||||
| 	ctx.Data["IsFuzzy"] = isFuzzy | ||||
| 
 | ||||
| 	if isShowClosed { | ||||
| 		ctx.Data["State"] = "closed" | ||||
|  | @ -667,6 +674,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { | |||
| 	pager.AddParam(ctx, "labels", "SelectLabels") | ||||
| 	pager.AddParam(ctx, "milestone", "MilestoneID") | ||||
| 	pager.AddParam(ctx, "assignee", "AssigneeID") | ||||
| 	pager.AddParam(ctx, "fuzzy", "IsFuzzy") | ||||
| 	ctx.Data["Page"] = pager | ||||
| 
 | ||||
| 	ctx.HTML(http.StatusOK, tplIssues) | ||||
|  |  | |||
|  | @ -9,10 +9,10 @@ | |||
| 			<input type="hidden" name="assignee" value="{{$.AssigneeID}}"> | ||||
| 			<input type="hidden" name="poster" value="{{$.PosterID}}"> | ||||
| 		{{end}} | ||||
| 		{{template "shared/search/input" dict "Value" .Keyword}} | ||||
| 		{{if .PageIsIssueList}} | ||||
| 			<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> | ||||
| 		{{if .PageIsPullList}} | ||||
| 			{{template "shared/search/combo_fuzzy" dict "Value" .Keyword "IsFuzzy" .IsFuzzy "Placeholder" (ctx.Locale.Tr "search.pull_kind") "Tooltip" (ctx.Locale.Tr "explore.go_to")}} | ||||
| 		{{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}} | ||||
| 		{{template "shared/search/button"}} | ||||
| 	</div> | ||||
| </form> | ||||
|  |  | |||
|  | @ -2,9 +2,9 @@ | |||
| {{/* 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"}}"> | ||||
| 	<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="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> | ||||
|  |  | |||
|  | @ -5,11 +5,11 @@ | |||
| 		{{template "base/alert" .}} | ||||
| 		<div class="list-header"> | ||||
| 			<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"}} | ||||
| 					{{ctx.Locale.PrettyNumber .IssueStats.OpenCount}} {{ctx.Locale.Tr "repo.issues.open_title"}} | ||||
| 				</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"}} | ||||
| 					{{ctx.Locale.PrettyNumber .IssueStats.ClosedCount}} {{ctx.Locale.Tr "repo.issues.closed_title"}} | ||||
| 				</a> | ||||
|  | @ -19,9 +19,11 @@ | |||
| 					<input type="hidden" name="type" value="{{$.ViewType}}"> | ||||
| 					<input type="hidden" name="sort" value="{{$.SortType}}"> | ||||
| 					<input type="hidden" name="state" value="{{$.State}}"> | ||||
| 					{{template "shared/search/input" dict "Value" $.Keyword}} | ||||
| 					<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/button"}} | ||||
| 					{{if .PageIsPulls}} | ||||
| 						{{template "shared/search/combo_fuzzy" dict "Value" $.Keyword "IsFuzzy" $.IsFuzzy "Placeholder" (ctx.Locale.Tr "search.pull_kind") "Tooltip" (ctx.Locale.Tr "explore.go_to")}} | ||||
| 					{{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> | ||||
| 			</form> | ||||
| 			<div class="ui secondary menu tw-mt-0"> | ||||
|  | @ -36,29 +38,29 @@ | |||
| 						{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||
| 					</span> | ||||
| 					<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> | ||||
| 							{{ctx.Locale.Tr "home.issues.in_your_repos"}} | ||||
| 						</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> | ||||
| 							{{ctx.Locale.Tr "repo.issues.filter_type.assigned_to_you"}} | ||||
| 						</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> | ||||
| 							{{ctx.Locale.Tr "repo.issues.filter_type.created_by_you"}} | ||||
| 						</a> | ||||
| 						{{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> | ||||
| 								{{ctx.Locale.Tr "repo.issues.filter_type.review_requested"}} | ||||
| 							</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> | ||||
| 								{{ctx.Locale.Tr "repo.issues.filter_type.reviewed_by_you"}} | ||||
| 							</a> | ||||
| 						{{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> | ||||
| 							{{ctx.Locale.Tr "repo.issues.filter_type.mentioning_you"}} | ||||
| 						</a> | ||||
|  | @ -71,14 +73,14 @@ | |||
| 						{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||
| 					</span> | ||||
| 					<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 "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 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 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 "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 "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 "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 "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 "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}}&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}}&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}}&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}}&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}}&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}}&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}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
|  |  | |||
|  | @ -107,6 +107,7 @@ func TestViewIssuesKeyword(t *testing.T) { | |||
| 	}) | ||||
| 	issues.UpdateIssueIndexer(context.Background(), issue.ID) | ||||
| 	time.Sleep(time.Second * 1) | ||||
| 
 | ||||
| 	const keyword = "first" | ||||
| 	req := NewRequestf(t, "GET", "%s/issues?q=%s", repo.Link(), keyword) | ||||
| 	resp := MakeRequest(t, req, http.StatusOK) | ||||
|  | @ -120,6 +121,27 @@ func TestViewIssuesKeyword(t *testing.T) { | |||
| 		assert.False(t, issue.IsPull) | ||||
| 		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) { | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ textarea, | |||
| 
 | ||||
| /* fix fomantic small dropdown having inconsistent padding with input */ | ||||
| .ui.small.selection.dropdown { | ||||
|   padding: .67857143em 3.2em .67857143em 1em; | ||||
|   padding: .67857143em 1.6em .67857143em 1em; | ||||
| } | ||||
| 
 | ||||
| input:hover, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue