mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Only show relevant repositories on explore page (#19361)
Adds a new option to only show relevant repo's on the explore page, for bigger Gitea instances like Codeberg this is a nice option to enable to make the explore page more populated with unique and "high" quality repo's. A note is shown that the results are filtered and have the possibility to see the unfiltered results. Co-authored-by: vednoc <vednoc@protonmail.com> Co-authored-by: delvh <dev.lh@web.de> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
		| @@ -1164,6 +1164,10 @@ ROUTER = console | ||||
| ;; | ||||
| ;; Whether to enable a Service Worker to cache frontend assets | ||||
| ;USE_SERVICE_WORKER = false | ||||
| ;; | ||||
| ;; Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used. | ||||
| ;; A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic). | ||||
| ;ONLY_SHOW_RELEVANT_REPOS = false | ||||
|  | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
|   | ||||
| @@ -194,6 +194,8 @@ The following configuration set `Content-Type: application/vnd.android.package-a | ||||
| - `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used. | ||||
| - `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page. | ||||
| - `USE_SERVICE_WORKER`: **false**: Whether to enable a Service Worker to cache frontend assets. | ||||
| - `ONLY_SHOW_RELEVANT_REPOS`: **false** Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used. | ||||
|     A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic). | ||||
|  | ||||
| ### UI - Admin (`ui.admin`) | ||||
|  | ||||
|   | ||||
| @@ -163,6 +163,10 @@ type SearchRepoOptions struct { | ||||
| 	HasMilestones util.OptionalBool | ||||
| 	// LowerNames represents valid lower names to restrict to | ||||
| 	LowerNames []string | ||||
| 	// When specified true, apply some filters over the conditions: | ||||
| 	// - Don't show forks, when opts.Fork is OptionalBoolNone. | ||||
| 	// - Do not display repositories that don't have a description, an icon and topics. | ||||
| 	OnlyShowRelevant bool | ||||
| } | ||||
|  | ||||
| // SearchOrderBy is used to sort the result | ||||
| @@ -463,9 +467,13 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | ||||
| 			Where(builder.Eq{"language": opts.Language}).And(builder.Eq{"is_primary": true}))) | ||||
| 	} | ||||
|  | ||||
| 	if opts.Fork != util.OptionalBoolNone { | ||||
| 	if opts.Fork != util.OptionalBoolNone || opts.OnlyShowRelevant { | ||||
| 		if opts.OnlyShowRelevant && opts.Fork == util.OptionalBoolNone { | ||||
| 			cond = cond.And(builder.Eq{"is_fork": false}) | ||||
| 		} else { | ||||
| 			cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue}) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if opts.Mirror != util.OptionalBoolNone { | ||||
| 		cond = cond.And(builder.Eq{"is_mirror": opts.Mirror == util.OptionalBoolTrue}) | ||||
| @@ -486,6 +494,25 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | ||||
| 		cond = cond.And(builder.Eq{"num_milestones": 0}.Or(builder.IsNull{"num_milestones"})) | ||||
| 	} | ||||
|  | ||||
| 	if opts.OnlyShowRelevant { | ||||
| 		// Only show a repo that either has a topic or description. | ||||
| 		subQueryCond := builder.NewCond() | ||||
|  | ||||
| 		// Topic checking. Topics is non-null. | ||||
| 		subQueryCond = subQueryCond.Or(builder.And(builder.Neq{"topics": "null"}, builder.Neq{"topics": "[]"})) | ||||
|  | ||||
| 		// Description checking. Description not empty. | ||||
| 		subQueryCond = subQueryCond.Or(builder.Neq{"description": ""}) | ||||
|  | ||||
| 		// Repo has a avatar. | ||||
| 		subQueryCond = subQueryCond.Or(builder.Neq{"avatar": ""}) | ||||
|  | ||||
| 		// Always hide repo's that are empty. | ||||
| 		subQueryCond = subQueryCond.And(builder.Eq{"is_empty": false}) | ||||
|  | ||||
| 		cond = cond.And(subQueryCond) | ||||
| 	} | ||||
|  | ||||
| 	return cond | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -240,6 +240,7 @@ var ( | ||||
| 		CustomEmojisMap       map[string]string `ini:"-"` | ||||
| 		SearchRepoDescription bool | ||||
| 		UseServiceWorker      bool | ||||
| 		OnlyShowRelevantRepos bool | ||||
|  | ||||
| 		Notification struct { | ||||
| 			MinTimeout            time.Duration | ||||
| @@ -1087,6 +1088,7 @@ func loadFromConf(allowEmpty bool, extraConfig string) { | ||||
| 	UI.DefaultShowFullName = Cfg.Section("ui").Key("DEFAULT_SHOW_FULL_NAME").MustBool(false) | ||||
| 	UI.SearchRepoDescription = Cfg.Section("ui").Key("SEARCH_REPO_DESCRIPTION").MustBool(true) | ||||
| 	UI.UseServiceWorker = Cfg.Section("ui").Key("USE_SERVICE_WORKER").MustBool(false) | ||||
| 	UI.OnlyShowRelevantRepos = Cfg.Section("ui").Key("ONLY_SHOW_RELEVANT_REPOS").MustBool(false) | ||||
|  | ||||
| 	HasRobotsTxt, err = util.IsFile(path.Join(CustomPath, "robots.txt")) | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -277,6 +277,9 @@ org_no_results = No matching organizations found. | ||||
| code_no_results = No source code matching your search term found. | ||||
| code_search_results = Search results for '%s' | ||||
| code_last_indexed_at = Last indexed %s | ||||
| relevant_repositories_tooltip = Repositories that are forks or that have no topic, no icon, and no description are hidden. | ||||
| relevant_repositories = Only relevant repositories are being shown, <a href="%s">show unfiltered results</a>. | ||||
|  | ||||
|  | ||||
| [auth] | ||||
| create_new_account = Register Account | ||||
|   | ||||
| @@ -52,6 +52,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | ||||
| 		count            int64 | ||||
| 		err              error | ||||
| 		orderBy          db.SearchOrderBy | ||||
| 		onlyShowRelevant bool | ||||
| 	) | ||||
|  | ||||
| 	ctx.Data["SortType"] = ctx.FormString("sort") | ||||
| @@ -60,8 +61,6 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | ||||
| 		orderBy = db.SearchOrderByNewest | ||||
| 	case "oldest": | ||||
| 		orderBy = db.SearchOrderByOldest | ||||
| 	case "recentupdate": | ||||
| 		orderBy = db.SearchOrderByRecentUpdated | ||||
| 	case "leastupdate": | ||||
| 		orderBy = db.SearchOrderByLeastUpdated | ||||
| 	case "reversealphabetically": | ||||
| @@ -83,9 +82,16 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | ||||
| 	default: | ||||
| 		ctx.Data["SortType"] = "recentupdate" | ||||
| 		orderBy = db.SearchOrderByRecentUpdated | ||||
| 		onlyShowRelevant = setting.UI.OnlyShowRelevantRepos && !ctx.FormBool("no_filter") | ||||
| 	} | ||||
|  | ||||
| 	keyword := ctx.FormTrim("q") | ||||
| 	if keyword != "" { | ||||
| 		onlyShowRelevant = false | ||||
| 	} | ||||
|  | ||||
| 	ctx.Data["OnlyShowRelevant"] = onlyShowRelevant | ||||
|  | ||||
| 	topicOnly := ctx.FormBool("topic") | ||||
| 	ctx.Data["TopicOnly"] = topicOnly | ||||
|  | ||||
| @@ -107,6 +113,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | ||||
| 		TopicOnly:          topicOnly, | ||||
| 		Language:           language, | ||||
| 		IncludeDescription: setting.UI.SearchRepoDescription, | ||||
| 		OnlyShowRelevant:   onlyShowRelevant, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("SearchRepository", err) | ||||
| @@ -133,6 +140,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | ||||
| 	pager.SetDefaultParams(ctx) | ||||
| 	pager.AddParam(ctx, "topic", "TopicOnly") | ||||
| 	pager.AddParam(ctx, "language", "Language") | ||||
| 	pager.AddParamString("no_filter", ctx.FormString("no_filter")) | ||||
| 	ctx.Data["Page"] = pager | ||||
|  | ||||
| 	ctx.HTML(http.StatusOK, opts.TplName) | ||||
|   | ||||
| @@ -29,4 +29,9 @@ | ||||
| 		<button class="ui primary button">{{.locale.Tr "explore.search"}}</button> | ||||
| 	</div> | ||||
| </form> | ||||
| {{if .OnlyShowRelevant}} | ||||
| 	<div class="ui blue attached message explore-relevancy-note"> | ||||
| 		<span class="ui tooltip" data-content="{{.locale.Tr "explore.relevant_repositories_tooltip"}}">{{.locale.Tr "explore.relevant_repositories" ((printf "%s%s" $.Link "?no_filter=1")|Escape) | Safe}}</span> | ||||
| 	</div> | ||||
| {{end}} | ||||
| <div class="ui divider"></div> | ||||
|   | ||||
| @@ -89,3 +89,9 @@ | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .ui.explore-relevancy-note { | ||||
|   border-top: 0; | ||||
|   margin-top: 0; | ||||
|   max-width: 90%; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user