aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLauris BH <lauris@nix.lv>2022-10-11 02:12:03 +0300
committerGitHub <noreply@github.com>2022-10-11 00:12:03 +0100
commitb59b0cad0a550223f74add109ff13c0d2f4309f3 (patch)
tree4c4d0482ca8740390b5939c3979d1fef35cb9047
parent3ccebf7f4044b85eef975e4544785893da763bd2 (diff)
downloadgitea-b59b0cad0a550223f74add109ff13c0d2f4309f3.tar.gz
gitea-b59b0cad0a550223f74add109ff13c0d2f4309f3.zip
Add user/organization code search (#19977)
Fixes #19925 Screenshots: ![attels](https://user-images.githubusercontent.com/165205/173864718-fe789429-55bc-4cad-808c-9f02f335cddf.png)
-rw-r--r--models/repo/repo_list.go30
-rw-r--r--modules/context/org.go1
-rw-r--r--options/locale/locale_en-US.ini8
-rw-r--r--routers/web/explore/code.go125
-rw-r--r--routers/web/repo/search.go22
-rw-r--r--routers/web/user/code.go114
-rw-r--r--routers/web/user/package.go4
-rw-r--r--routers/web/user/profile.go1
-rw-r--r--routers/web/web.go1
-rw-r--r--templates/code/searchform.tmpl14
-rw-r--r--templates/code/searchresults.tmpl43
-rw-r--r--templates/explore/code.tmpl61
-rw-r--r--templates/explore/repo_search.tmpl2
-rw-r--r--templates/explore/search.tmpl2
-rw-r--r--templates/org/menu.tmpl13
-rw-r--r--templates/repo/search.tmpl6
-rw-r--r--templates/user/code.tmpl25
-rw-r--r--templates/user/overview/header.tmpl7
-rw-r--r--templates/user/profile.tmpl7
19 files changed, 341 insertions, 145 deletions
diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go
index ee72dc6ee7..cc524a417e 100644
--- a/models/repo/repo_list.go
+++ b/models/repo/repo_list.go
@@ -593,6 +593,16 @@ func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c
return sess, count, nil
}
+// SearchRepositoryIDsByCondition search repository IDs by given condition.
+func SearchRepositoryIDsByCondition(ctx context.Context, cond builder.Cond) ([]int64, error) {
+ repoIDs := make([]int64, 0, 10)
+ return repoIDs, db.GetEngine(ctx).
+ Table("repository").
+ Cols("id").
+ Where(cond).
+ Find(&repoIDs)
+}
+
// AccessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible
func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) builder.Cond {
cond := builder.NewCond()
@@ -680,16 +690,16 @@ func AccessibleRepoIDsQuery(user *user_model.User) *builder.Builder {
}
// FindUserCodeAccessibleRepoIDs finds all at Code level accessible repositories' ID by the user's id
-func FindUserCodeAccessibleRepoIDs(user *user_model.User) ([]int64, error) {
- repoIDs := make([]int64, 0, 10)
- if err := db.GetEngine(db.DefaultContext).
- Table("repository").
- Cols("id").
- Where(AccessibleRepositoryCondition(user, unit.TypeCode)).
- Find(&repoIDs); err != nil {
- return nil, fmt.Errorf("FindUserCodeAccesibleRepoIDs: %v", err)
- }
- return repoIDs, nil
+func FindUserCodeAccessibleRepoIDs(ctx context.Context, user *user_model.User) ([]int64, error) {
+ return SearchRepositoryIDsByCondition(ctx, AccessibleRepositoryCondition(user, unit.TypeCode))
+}
+
+// FindUserCodeAccessibleOwnerRepoIDs finds all repository IDs for the given owner whose code the user can see.
+func FindUserCodeAccessibleOwnerRepoIDs(ctx context.Context, ownerID int64, user *user_model.User) ([]int64, error) {
+ return SearchRepositoryIDsByCondition(ctx, builder.NewCond().And(
+ builder.Eq{"owner_id": ownerID},
+ AccessibleRepositoryCondition(user, unit.TypeCode),
+ ))
}
// GetUserRepositories returns a list of repositories of given user.
diff --git a/modules/context/org.go b/modules/context/org.go
index d020befa40..89260b8654 100644
--- a/modules/context/org.go
+++ b/modules/context/org.go
@@ -130,6 +130,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["IsPublicMember"] = func(uid int64) bool {
is, _ := organization.IsPublicMembership(ctx.Org.Organization.ID, uid)
return is
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 1dba1d71d8..fbf9b70643 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -268,8 +268,11 @@ users = Users
organizations = Organizations
search = Search
code = Code
+search.type.tooltip = Search type
search.fuzzy = Fuzzy
+search.fuzzy.tooltip = Include results that also matches the search term closely
search.match = Match
+search.match.tooltip = Include only results that matches the exact search term
code_search_unavailable = Currently code search is not available. Please contact your site administrator.
repo_no_results = No matching repositories found.
user_no_results = No matching users found.
@@ -507,6 +510,7 @@ activity = Public Activity
followers = Followers
starred = Starred Repositories
watched = Watched Repositories
+code = Code
projects = Projects
following = Following
follow = Follow
@@ -1763,8 +1767,11 @@ activity.git_stats_deletion_n = %d deletions
search = Search
search.search_repo = Search repository
+search.type.tooltip = Search type
search.fuzzy = Fuzzy
+search.fuzzy.tooltip = Include results that also matches the search term closely
search.match = Match
+search.match.tooltip = Include only results that matches the exact search term
search.results = Search results for "%s" in <a href="%s">%s</a>
search.code_no_results = No source code matching your search term found.
search.code_search_unavailable = Currently code search is not available. Please contact your site administrator.
@@ -2310,6 +2317,7 @@ create_org = Create Organization
repo_updated = Updated
people = People
teams = Teams
+code = Code
lower_members = members
lower_repositories = repositories
create_new_team = New Team
diff --git a/routers/web/explore/code.go b/routers/web/explore/code.go
index 3afb2110d9..2357b34fd0 100644
--- a/routers/web/explore/code.go
+++ b/routers/web/explore/code.go
@@ -34,86 +34,91 @@ func Code(ctx *context.Context) {
language := ctx.FormTrim("l")
keyword := ctx.FormTrim("q")
+
+ queryType := ctx.FormTrim("t")
+ isMatch := queryType == "match"
+
+ ctx.Data["Keyword"] = keyword
+ ctx.Data["Language"] = language
+ ctx.Data["queryType"] = queryType
+ ctx.Data["PageIsViewCode"] = true
+
+ if keyword == "" {
+ ctx.HTML(http.StatusOK, tplExploreCode)
+ return
+ }
+
page := ctx.FormInt("page")
if page <= 0 {
page = 1
}
- queryType := ctx.FormTrim("t")
- isMatch := queryType == "match"
+ var (
+ repoIDs []int64
+ err error
+ isAdmin bool
+ )
+ if ctx.Doer != nil {
+ isAdmin = ctx.Doer.IsAdmin
+ }
- if keyword != "" {
- var (
- repoIDs []int64
- err error
- isAdmin bool
- )
- if ctx.Doer != nil {
- isAdmin = ctx.Doer.IsAdmin
+ // guest user or non-admin user
+ if ctx.Doer == nil || !isAdmin {
+ repoIDs, err = repo_model.FindUserCodeAccessibleRepoIDs(ctx, ctx.Doer)
+ if err != nil {
+ ctx.ServerError("FindUserCodeAccessibleRepoIDs", err)
+ return
}
+ }
- // guest user or non-admin user
- if ctx.Doer == nil || !isAdmin {
- repoIDs, err = repo_model.FindUserCodeAccessibleRepoIDs(ctx.Doer)
- if err != nil {
+ var (
+ total int
+ searchResults []*code_indexer.Result
+ searchResultLanguages []*code_indexer.SearchResultLanguages
+ )
+
+ if (len(repoIDs) > 0) || isAdmin {
+ total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
+ if err != nil {
+ if code_indexer.IsAvailable() {
ctx.ServerError("SearchResults", err)
return
}
+ ctx.Data["CodeIndexerUnavailable"] = true
+ } else {
+ ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
}
- var (
- total int
- searchResults []*code_indexer.Result
- searchResultLanguages []*code_indexer.SearchResultLanguages
- )
-
- if (len(repoIDs) > 0) || isAdmin {
- total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
- if err != nil {
- if code_indexer.IsAvailable() {
- ctx.ServerError("SearchResults", err)
- return
+ loadRepoIDs := make([]int64, 0, len(searchResults))
+ for _, result := range searchResults {
+ var find bool
+ for _, id := range loadRepoIDs {
+ if id == result.RepoID {
+ find = true
+ break
}
- ctx.Data["CodeIndexerUnavailable"] = true
- } else {
- ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
}
-
- loadRepoIDs := make([]int64, 0, len(searchResults))
- for _, result := range searchResults {
- var find bool
- for _, id := range loadRepoIDs {
- if id == result.RepoID {
- find = true
- break
- }
- }
- if !find {
- loadRepoIDs = append(loadRepoIDs, result.RepoID)
- }
- }
-
- repoMaps, err := repo_model.GetRepositoriesMapByIDs(loadRepoIDs)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
+ if !find {
+ loadRepoIDs = append(loadRepoIDs, result.RepoID)
}
+ }
- ctx.Data["RepoMaps"] = repoMaps
+ repoMaps, err := repo_model.GetRepositoriesMapByIDs(loadRepoIDs)
+ if err != nil {
+ ctx.ServerError("GetRepositoriesMapByIDs", err)
+ return
}
- ctx.Data["Keyword"] = keyword
- ctx.Data["Language"] = language
- ctx.Data["queryType"] = queryType
- ctx.Data["SearchResults"] = searchResults
- ctx.Data["SearchResultLanguages"] = searchResultLanguages
- ctx.Data["PageIsViewCode"] = true
-
- pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
- pager.SetDefaultParams(ctx)
- pager.AddParam(ctx, "l", "Language")
- ctx.Data["Page"] = pager
+ ctx.Data["RepoMaps"] = repoMaps
}
+ ctx.Data["SearchResults"] = searchResults
+ ctx.Data["SearchResultLanguages"] = searchResultLanguages
+
+ pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
+ pager.SetDefaultParams(ctx)
+ pager.AddParam(ctx, "l", "Language")
+ ctx.Data["Page"] = pager
+
ctx.HTML(http.StatusOK, tplExploreCode)
}
diff --git a/routers/web/repo/search.go b/routers/web/repo/search.go
index 8f141cb149..3d1835c7c3 100644
--- a/routers/web/repo/search.go
+++ b/routers/web/repo/search.go
@@ -21,14 +21,27 @@ func Search(ctx *context.Context) {
ctx.Redirect(ctx.Repo.RepoLink)
return
}
+
language := ctx.FormTrim("l")
keyword := ctx.FormTrim("q")
+
+ queryType := ctx.FormTrim("t")
+ isMatch := queryType == "match"
+
+ ctx.Data["Keyword"] = keyword
+ ctx.Data["Language"] = language
+ ctx.Data["queryType"] = queryType
+ ctx.Data["PageIsViewCode"] = true
+
+ if keyword == "" {
+ ctx.HTML(http.StatusOK, tplSearch)
+ return
+ }
+
page := ctx.FormInt("page")
if page <= 0 {
page = 1
}
- queryType := ctx.FormTrim("t")
- isMatch := queryType == "match"
total, searchResults, searchResultLanguages, err := code_indexer.PerformSearch(ctx, []int64{ctx.Repo.Repository.ID},
language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
@@ -41,13 +54,10 @@ func Search(ctx *context.Context) {
} else {
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
}
- ctx.Data["Keyword"] = keyword
- ctx.Data["Language"] = language
- ctx.Data["queryType"] = queryType
+
ctx.Data["SourcePath"] = ctx.Repo.Repository.HTMLURL()
ctx.Data["SearchResults"] = searchResults
ctx.Data["SearchResultLanguages"] = searchResultLanguages
- ctx.Data["PageIsViewCode"] = true
pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
pager.SetDefaultParams(ctx)
diff --git a/routers/web/user/code.go b/routers/web/user/code.go
new file mode 100644
index 0000000000..89bd23588b
--- /dev/null
+++ b/routers/web/user/code.go
@@ -0,0 +1,114 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package user
+
+import (
+ "net/http"
+
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ code_indexer "code.gitea.io/gitea/modules/indexer/code"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+const (
+ tplUserCode base.TplName = "user/code"
+)
+
+// CodeSearch render user/organization code search page
+func CodeSearch(ctx *context.Context) {
+ if !setting.Indexer.RepoIndexerEnabled {
+ ctx.Redirect(ctx.ContextUser.HomeLink())
+ return
+ }
+
+ ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+ ctx.Data["Title"] = ctx.Tr("code.title")
+ ctx.Data["ContextUser"] = ctx.ContextUser
+
+ language := ctx.FormTrim("l")
+ keyword := ctx.FormTrim("q")
+
+ queryType := ctx.FormTrim("t")
+ isMatch := queryType == "match"
+
+ ctx.Data["Keyword"] = keyword
+ ctx.Data["Language"] = language
+ ctx.Data["queryType"] = queryType
+ ctx.Data["IsCodePage"] = true
+
+ if keyword == "" {
+ ctx.HTML(http.StatusOK, tplUserCode)
+ return
+ }
+
+ var (
+ repoIDs []int64
+ err error
+ )
+
+ page := ctx.FormInt("page")
+ if page <= 0 {
+ page = 1
+ }
+
+ repoIDs, err = repo_model.FindUserCodeAccessibleOwnerRepoIDs(ctx, ctx.ContextUser.ID, ctx.Doer)
+ if err != nil {
+ ctx.ServerError("FindUserCodeAccessibleOwnerRepoIDs", err)
+ return
+ }
+
+ var (
+ total int
+ searchResults []*code_indexer.Result
+ searchResultLanguages []*code_indexer.SearchResultLanguages
+ )
+
+ if len(repoIDs) > 0 {
+ total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
+ if err != nil {
+ if code_indexer.IsAvailable() {
+ ctx.ServerError("SearchResults", err)
+ return
+ }
+ ctx.Data["CodeIndexerUnavailable"] = true
+ } else {
+ ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
+ }
+
+ loadRepoIDs := make([]int64, 0, len(searchResults))
+ for _, result := range searchResults {
+ var find bool
+ for _, id := range loadRepoIDs {
+ if id == result.RepoID {
+ find = true
+ break
+ }
+ }
+ if !find {
+ loadRepoIDs = append(loadRepoIDs, result.RepoID)
+ }
+ }
+
+ repoMaps, err := repo_model.GetRepositoriesMapByIDs(loadRepoIDs)
+ if err != nil {
+ ctx.ServerError("GetRepositoriesMapByIDs", err)
+ return
+ }
+
+ ctx.Data["RepoMaps"] = repoMaps
+ }
+ ctx.Data["SearchResults"] = searchResults
+ ctx.Data["SearchResultLanguages"] = searchResultLanguages
+
+ pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
+ pager.SetDefaultParams(ctx)
+ pager.AddParam(ctx, "l", "Language")
+ ctx.Data["Page"] = pager
+
+ ctx.HTML(http.StatusOK, tplUserCode)
+}
diff --git a/routers/web/user/package.go b/routers/web/user/package.go
index 20d8e32d29..c72592e728 100644
--- a/routers/web/user/package.go
+++ b/routers/web/user/package.go
@@ -86,6 +86,7 @@ func ListPackages(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("packages.title")
ctx.Data["IsPackagesPage"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ContextUser"] = ctx.ContextUser
ctx.Data["Query"] = query
ctx.Data["PackageType"] = packageType
@@ -157,6 +158,7 @@ func ViewPackageVersion(ctx *context.Context) {
ctx.Data["Title"] = pd.Package.Name
ctx.Data["IsPackagesPage"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ContextUser"] = ctx.ContextUser
ctx.Data["PackageDescriptor"] = pd
@@ -234,6 +236,7 @@ func ListPackageVersions(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("packages.title")
ctx.Data["IsPackagesPage"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ContextUser"] = ctx.ContextUser
ctx.Data["PackageDescriptor"] = &packages_model.PackageDescriptor{
Package: p,
@@ -305,6 +308,7 @@ func PackageSettings(ctx *context.Context) {
ctx.Data["Title"] = pd.Package.Name
ctx.Data["IsPackagesPage"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ContextUser"] = ctx.ContextUser
ctx.Data["PackageDescriptor"] = pd
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index a3452fd692..6e16b377db 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -290,6 +290,7 @@ func Profile(ctx *context.Context) {
}
ctx.Data["Page"] = pager
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ShowUserEmail"] = len(ctx.ContextUser.Email) > 0 && ctx.IsSigned && (!ctx.ContextUser.KeepEmailPrivate || ctx.ContextUser.ID == ctx.Doer.ID)
diff --git a/routers/web/web.go b/routers/web/web.go
index 656cd52b54..c74343c8cf 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -754,6 +754,7 @@ func RegisterRoutes(m *web.Route) {
})
}, ignSignIn, context.PackageAssignment(), reqPackageAccess(perm.AccessModeRead))
}
+ m.Get("/code", user.CodeSearch)
}, context_service.UserAssignmentWeb())
// ***** Release Attachment Download without Signin
diff --git a/templates/code/searchform.tmpl b/templates/code/searchform.tmpl
new file mode 100644
index 0000000000..26611cf4b2
--- /dev/null
+++ b/templates/code/searchform.tmpl
@@ -0,0 +1,14 @@
+<form class="ui form ignore-dirty" style="max-width: 100%">
+ <div class="ui fluid action input">
+ <input name="q" value="{{.Keyword}}"{{if .CodeIndexerUnavailable }} disabled{{end}} placeholder="{{.locale.Tr "explore.search"}}…" autofocus>
+ <div class="ui dropdown selection tooltip{{if .CodeIndexerUnavailable }} disabled{{end}}" data-content="{{.locale.Tr "explore.search.type.tooltip"}}">
+ <input name="t" type="hidden" value="{{.queryType}}"{{if .CodeIndexerUnavailable }} disabled{{end}}>{{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="text">{{.locale.Tr (printf "explore.search.%s" (or .queryType "fuzzy"))}}</div>
+ <div class="menu transition hidden" tabindex="-1" style="display: block !important;">
+ <div class="item tooltip" data-value="" data-content="{{.locale.Tr "explore.search.fuzzy.tooltip"}}">{{.locale.Tr "explore.search.fuzzy"}}</div>
+ <div class="item tooltip" data-value="match" data-content="{{.locale.Tr "explore.search.match.tooltip"}}">{{.locale.Tr "explore.search.match"}}</div>
+ </div>
+ </div>
+ <button class="ui primary button"{{if .CodeIndexerUnavailable }} disabled{{end}}>{{.locale.Tr "explore.search"}}</button>
+ </div>
+</form>
diff --git a/templates/code/searchresults.tmpl b/templates/code/searchresults.tmpl
new file mode 100644
index 0000000000..e21a50e1f1
--- /dev/null
+++ b/templates/code/searchresults.tmpl
@@ -0,0 +1,43 @@
+<div class="df ac fw">
+ {{range $term := .SearchResultLanguages}}
+ <a class="ui text-label df ac mr-1 my-1 {{if eq $.Language $term.Language}}primary {{end}}basic label" href="{{AppSubUrl}}{{if $.ContextUser}}/{{$.ContextUser.Name}}/-/code{{else}}/explore/code{{end}}?q={{$.Keyword}}{{if ne $.Language $term.Language}}&l={{$term.Language}}{{end}}{{if ne $.queryType ""}}&t={{$.queryType}}{{end}}">
+ <i class="color-icon mr-3" style="background-color: {{$term.Color}}"></i>
+ {{$term.Language}}
+ <div class="detail">{{$term.Count}}</div>
+ </a>
+ {{end}}
+</div>
+<div class="repository search">
+ {{range $result := .SearchResults}}
+ {{$repo := (index $.RepoMaps .RepoID)}}
+ <div class="diff-file-box diff-box file-content non-diff-file-content repo-search-result">
+ <h4 class="ui top attached normal header">
+ <span class="file">
+ <a rel="nofollow" href="{{$repo.HTMLURL}}">{{$repo.FullName}}</a>
+ {{if $repo.IsArchived}}
+ <span class="ui basic label">{{$.locale.Tr "repo.desc.archived"}}</span>
+ {{end}}
+ - {{.Filename}}
+ </span>
+ <a class="ui basic tiny button" rel="nofollow" href="{{$repo.HTMLURL}}/src/commit/{{$result.CommitID | PathEscape}}/{{.Filename | PathEscapeSegments}}">{{$.locale.Tr "repo.diff.view_file"}}</a>
+ </h4>
+ <div class="ui attached table segment">
+ <div class="file-body file-code code-view">
+ <table>
+ <tbody>
+ <tr>
+ <td class="lines-num">
+ {{range .LineNumbers}}
+ <a href="{{$repo.HTMLURL}}/src/commit/{{$result.CommitID | PathEscape}}/{{$result.Filename | PathEscapeSegments}}#L{{.}}"><span>{{.}}</span></a>
+ {{end}}
+ </td>
+ <td class="lines-code chroma"><code class="code-inner">{{.FormattedLines | Safe}}</code></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ {{template "shared/searchbottom" dict "root" $ "result" .}}
+ </div>
+ {{end}}
+</div>
diff --git a/templates/explore/code.tmpl b/templates/explore/code.tmpl
index b6429b1919..f4e46d1198 100644
--- a/templates/explore/code.tmpl
+++ b/templates/explore/code.tmpl
@@ -2,20 +2,7 @@
<div class="page-content explore users">
{{template "explore/navbar" .}}
<div class="ui container">
- <form class="ui form ignore-dirty" style="max-width: 100%">
- <div class="ui fluid action input">
- <input name="q" value="{{.Keyword}}"{{if .CodeIndexerUnavailable}} disabled{{end}} placeholder="{{.locale.Tr "explore.search"}}..." autofocus>
- <div class="ui dropdown selection{{if .CodeIndexerUnavailable}} disabled{{end}}">
- <input name="t" type="hidden" value="{{.queryType}}"{{if .CodeIndexerUnavailable}} disabled{{end}}>{{svg "octicon-triangle-down" 14 "dropdown icon"}}
- <div class="text">{{.locale.Tr (printf "explore.search.%s" (or .queryType "fuzzy"))}}</div>
- <div class="menu transition hidden" tabindex="-1" style="display: block !important;">
- <div class="item" data-value="">{{.locale.Tr "explore.search.fuzzy"}}</div>
- <div class="item" data-value="match">{{.locale.Tr "explore.search.match"}}</div>
- </div>
- </div>
- <button class="ui primary button"{{if .CodeIndexerUnavailable}} disabled{{end}}>{{.locale.Tr "explore.search"}}</button>
- </div>
- </form>
+ {{template "code/searchform" .}}
<div class="ui divider"></div>
<div class="ui user list">
{{if .CodeIndexerUnavailable}}
@@ -26,50 +13,8 @@
<h3>
{{.locale.Tr "explore.code_search_results" (.Keyword|Escape) | Str2html}}
</h3>
- <div class="df ac fw">
- {{range $term := .SearchResultLanguages}}
- <a class="ui text-label df ac mr-1 my-1 {{if eq $.Language $term.Language}}primary {{end}}basic label" href="{{AppSubUrl}}/explore/code?q={{$.Keyword}}{{if ne $.Language $term.Language}}&l={{$term.Language}}{{end}}{{if ne $.queryType ""}}&t={{$.queryType}}{{end}}">
- <i class="color-icon mr-3" style="background-color: {{$term.Color}}"></i>
- {{$term.Language}}
- <div class="detail">{{$term.Count}}</div>
- </a>
- {{end}}
- </div>
- <div class="repository search">
- {{range $result := .SearchResults}}
- {{$repo := (index $.RepoMaps .RepoID)}}
- <div class="diff-file-box diff-box file-content non-diff-file-content repo-search-result">
- <h4 class="ui top attached normal header">
- <span class="file">
- <a rel="nofollow" href="{{$repo.HTMLURL}}">{{$repo.FullName}}</a>
- {{if $repo.IsArchived}}
- <span class="ui basic label">{{$.locale.Tr "repo.desc.archived"}}</span>
- {{end}}
- - {{.Filename}}
- </span>
- <a class="ui basic tiny button" rel="nofollow" href="{{$repo.HTMLURL}}/src/commit/{{$result.CommitID | PathEscape}}/{{.Filename | PathEscapeSegments}}">{{$.locale.Tr "repo.diff.view_file"}}</a>
- </h4>
- <div class="ui attached table segment">
- <div class="file-body file-code code-view">
- <table>
- <tbody>
- <tr>
- <td class="lines-num">
- {{range .LineNumbers}}
- <a href="{{$repo.HTMLURL}}/src/commit/{{$result.CommitID | PathEscape}}/{{$result.Filename | PathEscapeSegments}}#L{{.}}"><span>{{.}}</span></a>
- {{end}}
- </td>
- <td class="lines-code chroma"><code class="code-inner">{{.FormattedLines | Safe}}</code></td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- {{template "shared/searchbottom" dict "root" $ "result" .}}
- </div>
- {{end}}
- </div>
- {{else}}
+ {{template "code/searchresults" .}}
+ {{else if .Keyword}}
<div>{{$.locale.Tr "explore.code_no_results"}}</div>
{{end}}
</div>
diff --git a/templates/explore/repo_search.tmpl b/templates/explore/repo_search.tmpl
index 1dabfede8c..b784722f50 100644
--- a/templates/explore/repo_search.tmpl
+++ b/templates/explore/repo_search.tmpl
@@ -25,7 +25,7 @@
<input type="hidden" name="sort" value="{{$.SortType}}">
<input type="hidden" name="language" value="{{$.Language}}">
<div class="ui fluid action input">
- <input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}..." autofocus>
+ <input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}…" autofocus>
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
</div>
</form>
diff --git a/templates/explore/search.tmpl b/templates/explore/search.tmpl
index 7e10412db8..123efa56dd 100644
--- a/templates/explore/search.tmpl
+++ b/templates/explore/search.tmpl
@@ -17,7 +17,7 @@
</div>
<form class="ui form ignore-dirty" style="max-width: 90%">
<div class="ui fluid action input">
- <input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}..." autofocus>
+ <input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}…" autofocus>
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
</div>
</form>
diff --git a/templates/org/menu.tmpl b/templates/org/menu.tmpl
index f86570d47b..87242b94d3 100644
--- a/templates/org/menu.tmpl
+++ b/templates/org/menu.tmpl
@@ -1,6 +1,6 @@
<div class="ui tabs container">
<div class="ui secondary stackable pointing menu">
- <a class="{{if .PageIsViewRepositories}}active{{end}} item" href="{{$.Org.HomeLink}}">
+ <a class="{{if .PageIsViewRepositories}}active {{end}}item" href="{{$.Org.HomeLink}}">
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
</a>
{{if .IsPackageEnabled}}
@@ -8,14 +8,19 @@
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
</a>
{{end}}
+ {{if .IsRepoIndexerEnabled}}
+ <a class="{{if $.PageIsOrgCode}}active {{end}}item" href="{{$.Org.HomeLink}}/-/code">
+ {{svg "octicon-code"}}&nbsp;{{$.locale.Tr "org.code"}}
+ </a>
+ {{end}}
{{if .IsOrganizationMember}}
- <a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members">
+ <a class="{{if $.PageIsOrgMembers}}active {{end}}item" href="{{$.OrgLink}}/members">
{{svg "octicon-organization"}}&nbsp;{{$.locale.Tr "org.people"}}
{{if .NumMembers}}
<div class="ui primary label">{{.NumMembers}}</div>
{{end}}
</a>
- <a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams">
+ <a class="{{if $.PageIsOrgTeams}}active {{end}}item" href="{{$.OrgLink}}/teams">
{{svg "octicon-people"}}&nbsp;{{$.locale.Tr "org.teams"}}
{{if .NumTeams}}
<div class="ui primary label">{{.NumTeams}}</div>
@@ -25,7 +30,7 @@
{{if .IsOrganizationOwner}}
<div class="right menu">
- <a class="{{if .PageIsOrgSettings}}active{{end}} item" href="{{.OrgLink}}/settings">
+ <a class="{{if .PageIsOrgSettings}}active {{end}}item" href="{{.OrgLink}}/settings">
{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}}
</a>
</div>
diff --git a/templates/repo/search.tmpl b/templates/repo/search.tmpl
index 9d8845443e..c68d20cdd2 100644
--- a/templates/repo/search.tmpl
+++ b/templates/repo/search.tmpl
@@ -6,12 +6,12 @@
<form class="ui form ignore-dirty" method="get">
<div class="ui fluid action input">
<input name="q" value="{{.Keyword}}"{{if .CodeIndexerUnavailable}} disabled{{end}} placeholder="{{.locale.Tr "repo.search.search_repo"}}">
- <div class="ui dropdown selection{{if .CodeIndexerUnavailable}} disabled{{end}}">
+ <div class="ui dropdown selection tooltip{{if .CodeIndexerUnavailable}} disabled{{end}}" data-content="{{.locale.Tr "repo.search.type.tooltip"}}">
<input name="t" type="hidden"{{if .CodeIndexerUnavailable}} disabled{{end}} value="{{.queryType}}">{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="text">{{.locale.Tr (printf "repo.search.%s" (or .queryType "fuzzy"))}}</div>
<div class="menu transition hidden" tabindex="-1" style="display: block !important;">
- <div class="item" data-value="">{{.locale.Tr "repo.search.fuzzy"}}</div>
- <div class="item" data-value="match">{{.locale.Tr "repo.search.match"}}</div>
+ <div class="item tooltip" data-value="" data-content="{{.locale.Tr "repo.search.fuzzy.tooltip"}}">{{.locale.Tr "repo.search.fuzzy"}}</div>
+ <div class="item tooltip" data-value="match" data-content="{{.locale.Tr "repo.search.match.tooltip"}}">{{.locale.Tr "repo.search.match"}}</div>
</div>
</div>
<button class="ui icon button"{{if .CodeIndexerUnavailable}} disabled{{end}} type="submit">{{svg "octicon-search" 16}}</button>
diff --git a/templates/user/code.tmpl b/templates/user/code.tmpl
new file mode 100644
index 0000000000..730d4dc9eb
--- /dev/null
+++ b/templates/user/code.tmpl
@@ -0,0 +1,25 @@
+{{template "base/head" .}}
+<div class="page-content repository code-search">
+ {{template "user/overview/header" .}}
+ <div class="ui container">
+ {{template "code/searchform" .}}
+ <div class="ui divider"></div>
+ <div class="ui user list">
+ {{if .CodeIndexerUnavailable }}
+ <div class="ui error message">
+ <p>{{$.locale.Tr "explore.code_search_unavailable"}}</p>
+ </div>
+ {{else if .SearchResults}}
+ <h3>
+ {{.locale.Tr "explore.code_search_results" (.Keyword|Escape) | Str2html }}
+ </h3>
+ {{template "code/searchresults" .}}
+ {{else if .Keyword}}
+ <div>{{$.locale.Tr "explore.code_no_results"}}</div>
+ {{end}}
+ </div>
+
+ {{template "base/paginate" .}}
+ </div>
+</div>
+{{template "base/footer" .}}
diff --git a/templates/user/overview/header.tmpl b/templates/user/overview/header.tmpl
index b61883b0c1..f007973607 100644
--- a/templates/user/overview/header.tmpl
+++ b/templates/user/overview/header.tmpl
@@ -23,10 +23,15 @@
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
</a>
{{if (not .UnitPackagesGlobalDisabled)}}
- <a href="{{.ContextUser.HTMLURL}}/-/packages" class="{{if .IsPackagesPage}}active{{end}} item">
+ <a href="{{.ContextUser.HomeLink}}/-/packages" class="{{if .IsPackagesPage}}active {{end}}item">
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
</a>
{{end}}
+ {{if .IsRepoIndexerEnabled}}
+ <a href="{{.ContextUser.HomeLink}}/-/code" class="{{if .IsCodePage}}active {{end}}item">
+ {{svg "octicon-code"}} {{.locale.Tr "user.code"}}
+ </a>
+ {{end}}
{{if .ContextUser.IsOrganization}}
{{if .IsOrganizationMember}}
diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl
index 7644872f09..a4ac65db6a 100644
--- a/templates/user/profile.tmpl
+++ b/templates/user/profile.tmpl
@@ -101,7 +101,7 @@
</div>
<div class="ui eleven wide column">
<div class="ui secondary stackable pointing tight menu">
- <a class='{{if and (ne .TabName "activity") (ne .TabName "following") (ne .TabName "followers") (ne .TabName "stars") (ne .TabName "watching") (ne .TabName "projects")}}active{{end}} item' href="{{.Owner.HomeLink}}">
+ <a class='{{if and (ne .TabName "activity") (ne .TabName "following") (ne .TabName "followers") (ne .TabName "stars") (ne .TabName "watching") (ne .TabName "projects") (ne .TabName "code")}}active{{end}} item' href="{{.Owner.HomeLink}}">
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
</a>
{{if .IsPackageEnabled}}
@@ -109,6 +109,11 @@
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
</a>
{{end}}
+ {{if .IsRepoIndexerEnabled}}
+ <a class='{{if eq .TabName "code"}}active{{end}} item' href="{{.Owner.HomeLink}}/-/code">
+ {{svg "octicon-code"}} {{.locale.Tr "user.code"}}
+ </a>
+ {{end}}
<a class='{{if eq .TabName "activity"}}active{{end}} item' href="{{.Owner.HomeLink}}?tab=activity">
{{svg "octicon-rss"}} {{.locale.Tr "user.activity"}}
</a>