mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-25 14:35:40 +00: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:
parent
dc0253b063
commit
27ac65a124
|
@ -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,8 +467,12 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
|
|||
Where(builder.Eq{"language": opts.Language}).And(builder.Eq{"is_primary": true})))
|
||||
}
|
||||
|
||||
if opts.Fork != util.OptionalBoolNone {
|
||||
cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue})
|
||||
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 {
|
||||
|
@ -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
|
||||
|
|
|
@ -48,10 +48,11 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
|
|||
}
|
||||
|
||||
var (
|
||||
repos []*repo_model.Repository
|
||||
count int64
|
||||
err error
|
||||
orderBy db.SearchOrderBy
|
||||
repos []*repo_model.Repository
|
||||
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%;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue