aboutsummaryrefslogtreecommitdiffstats
path: root/routers/web
diff options
context:
space:
mode:
Diffstat (limited to 'routers/web')
-rw-r--r--routers/web/org/projects.go1
-rw-r--r--routers/web/shared/user/header.go106
-rw-r--r--routers/web/user/code.go4
-rw-r--r--routers/web/user/home.go2
-rw-r--r--routers/web/user/package.go2
-rw-r--r--routers/web/user/profile.go148
6 files changed, 135 insertions, 128 deletions
diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go
index 4b33d943b3..21cb23000d 100644
--- a/routers/web/org/projects.go
+++ b/routers/web/org/projects.go
@@ -41,6 +41,7 @@ func MustEnableProjects(ctx *context.Context) {
// Projects renders the home page of projects
func Projects(ctx *context.Context) {
+ shared_user.PrepareContextForProfileBigAvatar(ctx)
ctx.Data["Title"] = ctx.Tr("repo.project_board")
sortType := ctx.FormTrim("sort")
diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go
index 9594e6975a..516c853b02 100644
--- a/routers/web/shared/user/header.go
+++ b/routers/web/shared/user/header.go
@@ -4,35 +4,109 @@
package user
import (
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
+ user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
)
-func RenderUserHeader(ctx *context.Context) {
- ctx.Data["IsProjectEnabled"] = true
+// prepareContextForCommonProfile store some common data into context data for user's profile related pages (including the nav menu)
+// It is designed to be fast and safe to be called multiple times in one request
+func prepareContextForCommonProfile(ctx *context.Context) {
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ContextUser"] = ctx.ContextUser
- tab := ctx.FormString("tab")
- ctx.Data["TabName"] = tab
- repo, err := repo_model.GetRepositoryByName(ctx.ContextUser.ID, ".profile")
- if err == nil && !repo.IsEmpty {
- gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
+ ctx.Data["EnableFeed"] = setting.Other.EnableFeed
+ ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink()
+}
+
+// PrepareContextForProfileBigAvatar set the context for big avatar view on the profile page
+func PrepareContextForProfileBigAvatar(ctx *context.Context) {
+ prepareContextForCommonProfile(ctx)
+
+ ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx.Doer.ID, ctx.ContextUser.ID)
+ ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
+
+ // Show OpenID URIs
+ openIDs, err := user_model.GetUserOpenIDs(ctx.ContextUser.ID)
+ if err != nil {
+ ctx.ServerError("GetUserOpenIDs", err)
+ return
+ }
+ ctx.Data["OpenIDs"] = openIDs
+
+ if len(ctx.ContextUser.Description) != 0 {
+ content, err := markdown.RenderString(&markup.RenderContext{
+ URLPrefix: ctx.Repo.RepoLink,
+ Metas: map[string]string{"mode": "document"},
+ GitRepo: ctx.Repo.GitRepo,
+ Ctx: ctx,
+ }, ctx.ContextUser.Description)
if err != nil {
- ctx.ServerError("OpenRepository", err)
+ ctx.ServerError("RenderString", err)
return
}
- defer gitRepo.Close()
- commit, err := gitRepo.GetBranchCommit(repo.DefaultBranch)
- if err != nil {
- ctx.ServerError("GetBranchCommit", err)
- return
+ ctx.Data["RenderedDescription"] = content
+ }
+
+ showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
+ orgs, err := organization.FindOrgs(organization.FindOrgOptions{
+ UserID: ctx.ContextUser.ID,
+ IncludePrivate: showPrivate,
+ })
+ if err != nil {
+ ctx.ServerError("FindOrgs", err)
+ return
+ }
+ ctx.Data["Orgs"] = orgs
+ ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(orgs, ctx.Doer)
+
+ badges, _, err := user_model.GetUserBadges(ctx, ctx.ContextUser)
+ if err != nil {
+ ctx.ServerError("GetUserBadges", err)
+ return
+ }
+ ctx.Data["Badges"] = badges
+
+ // in case the numbers are already provided by other functions, no need to query again (which is slow)
+ if _, ok := ctx.Data["NumFollowers"]; !ok {
+ _, ctx.Data["NumFollowers"], _ = user_model.GetUserFollowers(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{PageSize: 1, Page: 1})
+ }
+ if _, ok := ctx.Data["NumFollowing"]; !ok {
+ _, ctx.Data["NumFollowing"], _ = user_model.GetUserFollowing(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{PageSize: 1, Page: 1})
+ }
+}
+
+func FindUserProfileReadme(ctx *context.Context) (profileGitRepo *git.Repository, profileReadmeBlob *git.Blob, profileClose func()) {
+ profileDbRepo, err := repo_model.GetRepositoryByName(ctx.ContextUser.ID, ".profile")
+ if err == nil && !profileDbRepo.IsEmpty {
+ if profileGitRepo, err = git.OpenRepository(ctx, profileDbRepo.RepoPath()); err != nil {
+ log.Error("FindUserProfileReadme failed to OpenRepository: %v", err)
+ } else {
+ if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil {
+ log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err)
+ } else {
+ profileReadmeBlob, _ = commit.GetBlobByPath("README.md")
+ }
}
- blob, err := commit.GetBlobByPath("README.md")
- if err == nil && blob != nil {
- ctx.Data["ProfileReadme"] = true
+ }
+ return profileGitRepo, profileReadmeBlob, func() {
+ if profileGitRepo != nil {
+ _ = profileGitRepo.Close()
}
}
}
+
+func RenderUserHeader(ctx *context.Context) {
+ prepareContextForCommonProfile(ctx)
+
+ _, profileReadmeBlob, profileClose := FindUserProfileReadme(ctx)
+ defer profileClose()
+ ctx.Data["HasProfileReadme"] = profileReadmeBlob != nil
+}
diff --git a/routers/web/user/code.go b/routers/web/user/code.go
index 15524de7d6..033f65c9c0 100644
--- a/routers/web/user/code.go
+++ b/routers/web/user/code.go
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/modules/context"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/setting"
+ shared_user "code.gitea.io/gitea/routers/web/shared/user"
)
const (
@@ -23,8 +24,9 @@ func CodeSearch(ctx *context.Context) {
ctx.Redirect(ctx.ContextUser.HomeLink())
return
}
+ shared_user.PrepareContextForProfileBigAvatar(ctx)
+ shared_user.RenderUserHeader(ctx)
- ctx.Data["IsProjectEnabled"] = true
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["Title"] = ctx.Tr("explore.code")
diff --git a/routers/web/user/home.go b/routers/web/user/home.go
index 1b0f651b07..6a89c507a9 100644
--- a/routers/web/user/home.go
+++ b/routers/web/user/home.go
@@ -857,7 +857,7 @@ func UsernameSubRoute(ctx *context.Context) {
context_service.UserAssignmentWeb()(ctx)
if !ctx.Written() {
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
- Profile(ctx)
+ OwnerProfile(ctx)
}
}
}
diff --git a/routers/web/user/package.go b/routers/web/user/package.go
index 551e7f54c8..2e2c2a6e1f 100644
--- a/routers/web/user/package.go
+++ b/routers/web/user/package.go
@@ -37,6 +37,7 @@ const (
// ListPackages displays a list of all packages of the context user
func ListPackages(ctx *context.Context) {
+ shared_user.PrepareContextForProfileBigAvatar(ctx)
page := ctx.FormInt("page")
if page <= 1 {
page = 1
@@ -259,6 +260,7 @@ func ViewPackageVersion(ctx *context.Context) {
// ListPackageVersions lists all versions of a package
func ListPackageVersions(ctx *context.Context) {
+ shared_user.PrepareContextForProfileBigAvatar(ctx)
p, err := packages_model.GetPackageByName(ctx, ctx.Package.Owner.ID, packages_model.Type(ctx.Params("type")), ctx.Params("name"))
if err != nil {
if err == packages_model.ErrPackageNotExist {
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 6f9f84d60d..442fd0433a 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -11,22 +11,22 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/models/organization"
- project_model "code.gitea.io/gitea/models/project"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
"code.gitea.io/gitea/routers/web/org"
+ shared_user "code.gitea.io/gitea/routers/web/shared/user"
)
-// Profile render user's profile page
-func Profile(ctx *context.Context) {
+// OwnerProfile render profile page for a user or a organization (aka, repo owner)
+func OwnerProfile(ctx *context.Context) {
if strings.Contains(ctx.Req.Header.Get("Accept"), "application/rss+xml") {
feed.ShowUserFeedRSS(ctx)
return
@@ -38,36 +38,22 @@ func Profile(ctx *context.Context) {
if ctx.ContextUser.IsOrganization() {
org.Home(ctx)
- return
+ } else {
+ userProfile(ctx)
}
+}
+func userProfile(ctx *context.Context) {
// check view permissions
if !user_model.IsUserVisibleToViewer(ctx, ctx.ContextUser, ctx.Doer) {
ctx.NotFound("user", fmt.Errorf(ctx.ContextUser.Name))
return
}
- // advertise feed via meta tag
- ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink()
-
- // Show OpenID URIs
- openIDs, err := user_model.GetUserOpenIDs(ctx.ContextUser.ID)
- if err != nil {
- ctx.ServerError("GetUserOpenIDs", err)
- return
- }
-
- var isFollowing bool
- if ctx.Doer != nil {
- isFollowing = user_model.IsFollowing(ctx.Doer.ID, ctx.ContextUser.ID)
- }
-
ctx.Data["Title"] = ctx.ContextUser.DisplayName()
ctx.Data["PageIsUserProfile"] = true
- ctx.Data["ContextUser"] = ctx.ContextUser
- ctx.Data["OpenIDs"] = openIDs
- ctx.Data["IsFollowing"] = isFollowing
+ // prepare heatmap data
if setting.Service.EnableUserHeatmap {
data, err := activities_model.GetUserHeatmapDataByUser(ctx.ContextUser, ctx.Doer)
if err != nil {
@@ -78,75 +64,28 @@ func Profile(ctx *context.Context) {
ctx.Data["HeatmapTotalContributions"] = activities_model.GetTotalContributionsInHeatmap(data)
}
- if len(ctx.ContextUser.Description) != 0 {
- content, err := markdown.RenderString(&markup.RenderContext{
- URLPrefix: ctx.Repo.RepoLink,
- Metas: map[string]string{"mode": "document"},
- GitRepo: ctx.Repo.GitRepo,
- Ctx: ctx,
- }, ctx.ContextUser.Description)
- if err != nil {
- ctx.ServerError("RenderString", err)
- return
- }
- ctx.Data["RenderedDescription"] = content
- }
-
- repo, err := repo_model.GetRepositoryByName(ctx.ContextUser.ID, ".profile")
- if err == nil && !repo.IsEmpty {
- gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
- if err != nil {
- ctx.ServerError("OpenRepository", err)
- return
- }
- defer gitRepo.Close()
- commit, err := gitRepo.GetBranchCommit(repo.DefaultBranch)
- if err != nil {
- ctx.ServerError("GetBranchCommit", err)
- return
- }
- blob, err := commit.GetBlobByPath("README.md")
- if err == nil {
- bytes, err := blob.GetBlobContent(setting.UI.MaxDisplayFileSize)
- if err != nil {
- ctx.ServerError("GetBlobContent", err)
- return
- }
- profileContent, err := markdown.RenderString(&markup.RenderContext{
- Ctx: ctx,
- GitRepo: gitRepo,
- }, bytes)
- if err != nil {
- ctx.ServerError("RenderString", err)
- return
- }
- ctx.Data["ProfileReadme"] = profileContent
- }
- }
+ profileGitRepo, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx)
+ defer profileClose()
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
+ prepareUserProfileTabData(ctx, showPrivate, profileGitRepo, profileReadmeBlob)
+ // call PrepareContextForProfileBigAvatar later to avoid re-querying the NumFollowers & NumFollowing
+ shared_user.PrepareContextForProfileBigAvatar(ctx)
+ ctx.HTML(http.StatusOK, tplProfile)
+}
- orgs, err := organization.FindOrgs(organization.FindOrgOptions{
- UserID: ctx.ContextUser.ID,
- IncludePrivate: showPrivate,
- })
- if err != nil {
- ctx.ServerError("FindOrgs", err)
- return
- }
-
- ctx.Data["Orgs"] = orgs
- ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(orgs, ctx.Doer)
-
- badges, _, err := user_model.GetUserBadges(ctx, ctx.ContextUser)
- if err != nil {
- ctx.ServerError("GetUserBadges", err)
- return
- }
- ctx.Data["Badges"] = badges
-
+func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileGitRepo *git.Repository, profileReadme *git.Blob) {
+ // if there is a profile readme, default to "overview" page, otherwise, default to "repositories" page
tab := ctx.FormString("tab")
+ if tab == "" {
+ if profileReadme != nil {
+ tab = "overview"
+ } else {
+ tab = "repositories"
+ }
+ }
ctx.Data["TabName"] = tab
+ ctx.Data["HasProfileReadme"] = profileReadme != nil
page := ctx.FormInt("page")
if page <= 0 {
@@ -154,12 +93,7 @@ func Profile(ctx *context.Context) {
}
pagingNum := setting.UI.User.RepoPagingNum
- if tab == "activity" {
- pagingNum = setting.UI.FeedPagingNum
- }
-
topicOnly := ctx.FormBool("topic")
-
var (
repos []*repo_model.Repository
count int64
@@ -228,6 +162,7 @@ func Profile(ctx *context.Context) {
total = int(count)
case "activity":
date := ctx.FormString("date")
+ pagingNum = setting.UI.FeedPagingNum
items, count, err := activities_model.GetFeeds(ctx, activities_model.GetFeedsOptions{
RequestedUser: ctx.ContextUser,
Actor: ctx.Doer,
@@ -271,16 +206,6 @@ func Profile(ctx *context.Context) {
}
total = int(count)
- case "projects":
- ctx.Data["OpenProjects"], _, err = project_model.FindProjects(ctx, project_model.SearchOptions{
- Page: -1,
- IsClosed: util.OptionalBoolFalse,
- Type: project_model.TypeIndividual,
- })
- if err != nil {
- ctx.ServerError("GetProjects", err)
- return
- }
case "watching":
repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
@@ -303,7 +228,17 @@ func Profile(ctx *context.Context) {
}
total = int(count)
- default:
+ case "overview":
+ if bytes, err := profileReadme.GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil {
+ log.Error("failed to GetBlobContent: %v", err)
+ } else {
+ if profileContent, err := markdown.RenderString(&markup.RenderContext{Ctx: ctx, GitRepo: profileGitRepo}, bytes); err != nil {
+ log.Error("failed to RenderString: %v", err)
+ } else {
+ ctx.Data["ProfileReadme"] = profileContent
+ }
+ }
+ default: // default to "repositories"
repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
PageSize: pagingNum,
@@ -339,13 +274,6 @@ func Profile(ctx *context.Context) {
pager.AddParam(ctx, "date", "Date")
}
ctx.Data["Page"] = pager
- ctx.Data["IsProjectEnabled"] = true
- ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
-
- ctx.HTML(http.StatusOK, tplProfile)
}
// Action response for follow/unfollow user request