diff options
author | Lauris BH <lauris@nix.lv> | 2022-10-11 02:12:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-11 00:12:03 +0100 |
commit | b59b0cad0a550223f74add109ff13c0d2f4309f3 (patch) | |
tree | 4c4d0482ca8740390b5939c3979d1fef35cb9047 | |
parent | 3ccebf7f4044b85eef975e4544785893da763bd2 (diff) | |
download | gitea-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.go | 30 | ||||
-rw-r--r-- | modules/context/org.go | 1 | ||||
-rw-r--r-- | options/locale/locale_en-US.ini | 8 | ||||
-rw-r--r-- | routers/web/explore/code.go | 125 | ||||
-rw-r--r-- | routers/web/repo/search.go | 22 | ||||
-rw-r--r-- | routers/web/user/code.go | 114 | ||||
-rw-r--r-- | routers/web/user/package.go | 4 | ||||
-rw-r--r-- | routers/web/user/profile.go | 1 | ||||
-rw-r--r-- | routers/web/web.go | 1 | ||||
-rw-r--r-- | templates/code/searchform.tmpl | 14 | ||||
-rw-r--r-- | templates/code/searchresults.tmpl | 43 | ||||
-rw-r--r-- | templates/explore/code.tmpl | 61 | ||||
-rw-r--r-- | templates/explore/repo_search.tmpl | 2 | ||||
-rw-r--r-- | templates/explore/search.tmpl | 2 | ||||
-rw-r--r-- | templates/org/menu.tmpl | 13 | ||||
-rw-r--r-- | templates/repo/search.tmpl | 6 | ||||
-rw-r--r-- | templates/user/code.tmpl | 25 | ||||
-rw-r--r-- | templates/user/overview/header.tmpl | 7 | ||||
-rw-r--r-- | templates/user/profile.tmpl | 7 |
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"}} {{$.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"}} {{$.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"}} {{$.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> |