mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Fix inconsistent user profile layout across tabs (#25625)
Fix ::User Profile Page Project Tab Have Inconsistent Layout and Style Added the big_avator for consistency in the all header_items tabs. Fixes: #24871 > ### Description > in the user profile page the `Packages` and `Projects` tab have small icons for user but other tabs have bigger profile picture with user info: > > ### Screenshots > ### **For Packages And Projects:** >  > > ### **For Other Tabs:** >  > ## Before  ## After changes Project View <img width="1394" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/95d181d7-8e61-496d-9899-7b825c91ad56"> Packages View <img width="1378" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/7f5fd60f-6b18-4fa8-8c56-7b0d45d1a610"> ## Org view for projects page <img width="1385" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/6400dc89-a5ae-4f0a-831b-5b6efa020d89"> ## Org view for packages page <img width="1387" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/4e1e9ffe-1e4b-4334-8657-de11b5fd31d0"> --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
		| @@ -336,7 +336,7 @@ func GetUserFollowers(ctx context.Context, u, viewer *User, listOptions db.ListO | ||||
|  | ||||
| // GetUserFollowing returns range of user's following. | ||||
| func GetUserFollowing(ctx context.Context, u, viewer *User, listOptions db.ListOptions) ([]*User, int64, error) { | ||||
| 	sess := db.GetEngine(db.DefaultContext). | ||||
| 	sess := db.GetEngine(ctx). | ||||
| 		Select("`user`.*"). | ||||
| 		Join("LEFT", "follow", "`user`.id=follow.follow_id"). | ||||
| 		Where("follow.user_id=?", u.ID). | ||||
|   | ||||
| @@ -161,7 +161,6 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { | ||||
| 	} | ||||
| 	ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner | ||||
| 	ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember | ||||
| 	ctx.Data["IsProjectEnabled"] = true | ||||
| 	ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled | ||||
| 	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ||||
| 	ctx.Data["IsPublicMember"] = func(uid int64) bool { | ||||
|   | ||||
| @@ -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") | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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") | ||||
|   | ||||
| @@ -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) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										17
									
								
								templates/code/searchcombo.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								templates/code/searchcombo.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| {{template "code/searchform" .}} | ||||
| <div class="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" .}} | ||||
| @@ -2,24 +2,7 @@ | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content explore users"> | ||||
| 	{{template "explore/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "code/searchform" .}} | ||||
| 		<div class="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" .}} | ||||
| 		{{template "code/searchcombo" .}} | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <div class="ui tabs container"> | ||||
| <div class="ui container"> | ||||
| 	<div class="ui secondary stackable pointing menu"> | ||||
| 		<a class="{{if .PageIsViewRepositories}}active {{end}}item" href="{{$.Org.HomeLink}}"> | ||||
| 			{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}} | ||||
| @@ -6,7 +6,7 @@ | ||||
| 				<div class="ui small label">{{.ContextUser.NumRepos}}</div> | ||||
| 			{{end}} | ||||
| 		</a> | ||||
| 		{{if and .IsProjectEnabled .CanReadProjects}} | ||||
| 		{{if .CanReadProjects}} | ||||
| 		<a class="{{if .PageIsViewProjects}}active {{end}}item" href="{{$.Org.HomeLink}}/-/projects"> | ||||
| 			{{svg "octicon-project-symlink"}} {{.locale.Tr "user.projects"}} | ||||
| 		</a> | ||||
|   | ||||
| @@ -1,6 +1,27 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	{{template "projects/list" .}} | ||||
| </div> | ||||
| {{if .ContextUser.IsOrganization}} | ||||
| 	<div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 		{{template "shared/user/org_profile_avatar" .}} | ||||
| 		<div class="ui container"> | ||||
| 		{{template "user/overview/header" .}} | ||||
| 		{{template "projects/list" .}} | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{else}} | ||||
| 	<div role="main" aria-label="{{.Title}}" class="page-content user profile"> | ||||
| 		<div class="ui container"> | ||||
| 			<div class="ui stackable grid"> | ||||
| 				<div class="ui four wide column"> | ||||
| 					{{template "shared/user/profile_big_avatar" .}} | ||||
| 				</div> | ||||
| 				<div class="ui twelve wide column"> | ||||
| 				<div class="gt-mb-4"> | ||||
| 					{{template "user/overview/header" .}} | ||||
| 				</div> | ||||
| 				{{template "projects/list" .}} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{end}} | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content organization projects edit-project new"> | ||||
| 	{{template "shared/user/org_profile_avatar" .}} | ||||
| 	<div class="ui container"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	{{template "projects/new" .}} | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 	{{template "shared/user/org_profile_avatar" .}} | ||||
| 	<div class="ui container"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	{{template "projects/view" .}} | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository settings options"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	{{template "shared/user/org_profile_avatar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "user/overview/header" .}} | ||||
| 		{{template "base/alert" .}} | ||||
| 		<p><a href="{{.PackageDescriptor.FullWebLink}}">{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</a> / <strong>{{.locale.Tr "repo.settings"}}</strong></p> | ||||
| 		<h4 class="ui top attached header"> | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| <div class="ui container"> | ||||
| 	{{template "base/alert" .}} | ||||
| 	<form class="ui form ignore-dirty"> | ||||
| 		<div class="ui fluid action input"> | ||||
| @@ -37,7 +36,7 @@ | ||||
| 			</li> | ||||
| 		{{else}} | ||||
| 			{{if not .HasPackages}} | ||||
| 				<div class="empty center"> | ||||
| 				<div class="gt-pt-5 empty center"> | ||||
| 					{{svg "octicon-package" 48}} | ||||
| 					<h2>{{.locale.Tr "packages.empty"}}</h2> | ||||
| 					{{if and .Repository .CanWritePackages}} | ||||
| @@ -52,4 +51,3 @@ | ||||
| 		{{end}} | ||||
| 		{{template "base/paginate" .}} | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| <div class="ui container"> | ||||
| 	<p><a href="{{.PackageDescriptor.PackageWebLink}}">{{.PackageDescriptor.Package.Name}}</a> / <strong>{{.locale.Tr "packages.versions"}}</strong></p> | ||||
| 	<form class="ui form ignore-dirty"> | ||||
| 		<div class="ui fluid action input"> | ||||
| @@ -36,4 +35,3 @@ | ||||
| 		{{end}} | ||||
| 		{{template "base/paginate" .}} | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository view issue packages"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	{{template "shared/user/org_profile_avatar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "user/overview/header" .}} | ||||
| 		<div class="issue-title-header"> | ||||
| 			<div class="issue-title"> | ||||
| 				<h1>{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</h1> | ||||
|   | ||||
| @@ -1,10 +1,6 @@ | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository projects"> | ||||
| 	<div class="ui container"> | ||||
| 		{{if .CanWriteProjects}} | ||||
| 			<div class="navbar"> | ||||
| 				<div class="ui right"> | ||||
| 					<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a> | ||||
| 				</div> | ||||
| 			<div class="gt-tr"> | ||||
| 				<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a> | ||||
| 			</div> | ||||
| 			<div class="divider"></div> | ||||
| 		{{end}} | ||||
| @@ -75,8 +71,6 @@ | ||||
|  | ||||
| 			{{template "base/paginate" .}} | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| {{if $.CanWriteProjects}} | ||||
| <div class="ui g-modal-confirm delete modal"> | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| <div class="ui container"> | ||||
| 	<h2 class="ui dividing header"> | ||||
| 		{{if .PageIsEditProjects}} | ||||
| 		{{.locale.Tr "repo.projects.edit"}} | ||||
| @@ -55,7 +54,6 @@ | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="ui container"> | ||||
| 			<div class="divider"></div> | ||||
| 			<div class="ui left"> | ||||
| 				<a class="ui cancel button" href="{{$.CancelLink}}"> | ||||
| @@ -65,6 +63,4 @@ | ||||
| 					{{if .PageIsEditProjects}}{{.locale.Tr "repo.projects.modify"}}{{else}}{{.locale.Tr "repo.projects.create"}}{{end}} | ||||
| 				</button> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</form> | ||||
| </div> | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 	{{template "repo/header" .}} | ||||
| 	<div class="ui container"> | ||||
| 	{{template "package/shared/list" .}} | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository projects edit-project new milestone"> | ||||
| 	{{template "repo/header" .}} | ||||
| 	<div class="ui container"> | ||||
| 	{{template "projects/new" .}} | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
							
								
								
									
										16
									
								
								templates/shared/user/org_profile_avatar.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								templates/shared/user/org_profile_avatar.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| {{with .ContextUser}} | ||||
| 	<div class="ui container"> | ||||
| 		<div class="ui vertically grid head"> | ||||
| 			<div class="column"> | ||||
| 				<div class="ui header"> | ||||
| 					{{avatar $.Context . 100}} | ||||
| 					<span class="text thin grey"><a href="{{.HomeLink}}">{{.DisplayName}}</a></span> | ||||
| 					<span class="org-visibility"> | ||||
| 						{{if .Visibility.IsLimited}}<div class="ui medium basic horizontal label">{{$.locale.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}} | ||||
| 						{{if .Visibility.IsPrivate}}<div class="ui medium basic horizontal label">{{$.locale.Tr "org.settings.visibility.private_shortname"}}</div>{{end}} | ||||
| 					</span> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{end}} | ||||
							
								
								
									
										116
									
								
								templates/shared/user/profile_big_avatar.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								templates/shared/user/profile_big_avatar.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| <div class="ui card"> | ||||
| 	<div id="profile-avatar" class="content gt-df"> | ||||
| 	{{if eq .SignedUserID .ContextUser.ID}} | ||||
| 		<a class="image" href="{{AppSubUrl}}/user/settings" data-tooltip-content="{{.locale.Tr "user.change_avatar"}}"> | ||||
| 			{{/* the size doesn't take affect (and no need to take affect), image size(width) should be controlled by the parent container since this is not a flex layout*/}} | ||||
| 			{{avatar $.Context .ContextUser 256}} | ||||
| 		</a> | ||||
| 	{{else}} | ||||
| 		<span class="image"> | ||||
| 			{{avatar $.Context .ContextUser 256}} | ||||
| 		</span> | ||||
| 	{{end}} | ||||
| 	</div> | ||||
| 	<div class="content gt-word-break profile-avatar-name"> | ||||
| 		{{if .ContextUser.FullName}}<span class="header text center">{{.ContextUser.FullName}}</span>{{end}} | ||||
| 		<span class="username text center">{{.ContextUser.Name}}</span> | ||||
| 		{{if .EnableFeed}} | ||||
| 			<a href="{{.ContextUser.HomeLink}}.rss"><i class="ui text grey gt-ml-3" data-tooltip-content="{{.locale.Tr "rss_feed"}}">{{svg "octicon-rss" 18}}</i></a> | ||||
| 		{{end}} | ||||
| 		<div class="gt-mt-3"> | ||||
| 			<a class="muted" href="{{.ContextUser.HomeLink}}?tab=followers">{{svg "octicon-person" 18 "gt-mr-2"}}{{.NumFollowers}} {{.locale.Tr "user.followers"}}</a> · <a class="muted" href="{{.ContextUser.HomeLink}}?tab=following">{{.NumFollowing}} {{.locale.Tr "user.following"}}</a> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="extra content gt-word-break"> | ||||
| 		<ul> | ||||
| 			{{if .ContextUser.Location}} | ||||
| 				<li>{{svg "octicon-location"}} {{.ContextUser.Location}}</li> | ||||
| 			{{end}} | ||||
| 			{{if (eq .SignedUserID .ContextUser.ID)}} | ||||
| 				<li> | ||||
| 					{{svg "octicon-mail"}} | ||||
| 					<a href="mailto:{{.ContextUser.Email}}" rel="nofollow">{{.ContextUser.Email}}</a> | ||||
| 					<a href="{{AppSubUrl}}/user/settings#keep-email-private"> | ||||
| 						{{if .ShowUserEmail}} | ||||
| 							<i class="ui right" data-tooltip-content="{{.locale.Tr "user.email_visibility.limited"}}"> | ||||
| 								{{svg "octicon-unlock"}} | ||||
| 							</i> | ||||
| 						{{else}} | ||||
| 							<i class="ui right" data-tooltip-content="{{.locale.Tr "user.email_visibility.private"}}"> | ||||
| 								{{svg "octicon-lock"}} | ||||
| 							</i> | ||||
| 						{{end}} | ||||
| 					</a> | ||||
| 				</li> | ||||
| 			{{else}} | ||||
| 				{{if .ShowUserEmail}} | ||||
| 					<li> | ||||
| 						{{svg "octicon-mail"}} | ||||
| 						<a href="mailto:{{.ContextUser.Email}}" rel="nofollow">{{.ContextUser.Email}}</a> | ||||
| 					</li> | ||||
| 				{{end}} | ||||
| 			{{end}} | ||||
| 			{{if .ContextUser.Website}} | ||||
| 				<li> | ||||
| 					{{svg "octicon-link"}} | ||||
| 					<a target="_blank" rel="noopener noreferrer me" href="{{.ContextUser.Website}}">{{.ContextUser.Website}}</a> | ||||
| 				</li> | ||||
| 			{{end}} | ||||
| 			{{if $.RenderedDescription}} | ||||
| 				<li> | ||||
| 					<div class="render-content markup">{{$.RenderedDescription|Str2html}}</div> | ||||
| 				</li> | ||||
| 			{{end}} | ||||
| 			{{range .OpenIDs}} | ||||
| 				{{if .Show}} | ||||
| 					<li> | ||||
| 						{{svg "fontawesome-openid"}} | ||||
| 						<a target="_blank" rel="noopener noreferrer" href="{{.URI}}">{{.URI}}</a> | ||||
| 					</li> | ||||
| 				{{end}} | ||||
| 			{{end}} | ||||
| 			<li>{{svg "octicon-clock"}} {{.locale.Tr "user.joined_on" (DateTime "short" .ContextUser.CreatedUnix) | Safe}}</li> | ||||
| 			{{if and .Orgs .HasOrgsVisible}} | ||||
| 			<li> | ||||
| 				<ul class="user-orgs"> | ||||
| 				{{range .Orgs}} | ||||
| 					{{if (or .Visibility.IsPublic (and ($.SignedUser) (or .Visibility.IsLimited (and (.HasMemberWithUserID $.SignedUserID) .Visibility.IsPrivate) ($.IsAdmin))))}} | ||||
| 					<li> | ||||
| 						<a href="{{.HomeLink}}" data-tooltip-content="{{.Name}}"> | ||||
| 							{{avatar $.Context .}} | ||||
| 						</a> | ||||
| 					</li> | ||||
| 					{{end}} | ||||
| 				{{end}} | ||||
| 				</ul> | ||||
| 			</li> | ||||
| 			{{end}} | ||||
| 			{{if .Badges}} | ||||
| 			<li> | ||||
| 				<ul class="user-badges"> | ||||
| 				{{range .Badges}} | ||||
| 					<li> | ||||
| 						<img width="64" height="64" src="{{.ImageURL}}" alt="{{.Description}}" data-tooltip-content="{{.Description}}"> | ||||
| 					</li> | ||||
| 				{{end}} | ||||
| 				</ul> | ||||
| 			</li> | ||||
| 			{{end}} | ||||
| 			{{if and .IsSigned (ne .SignedUserID .ContextUser.ID)}} | ||||
| 			<li class="follow"> | ||||
| 				{{if $.IsFollowing}} | ||||
| 					<form method="post" action="{{.Link}}?action=unfollow&redirect_to={{$.Link}}"> | ||||
| 						{{$.CsrfTokenHtml}} | ||||
| 						<button type="submit" class="ui basic red button">{{svg "octicon-person"}} {{.locale.Tr "user.unfollow"}}</button> | ||||
| 					</form> | ||||
| 				{{else}} | ||||
| 					<form method="post" action="{{.Link}}?action=follow&redirect_to={{$.Link}}"> | ||||
| 						{{$.CsrfTokenHtml}} | ||||
| 						<button type="submit" class="ui basic green button">{{svg "octicon-person"}} {{.locale.Tr "user.follow"}}</button> | ||||
| 					</form> | ||||
| 				{{end}} | ||||
| 			</li> | ||||
| 			{{end}} | ||||
| 		</ul> | ||||
| 	</div> | ||||
| </div> | ||||
| @@ -1,25 +1,25 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository code-search"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "code/searchform" .}} | ||||
| 		<div class="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}} | ||||
| {{if .ContextUser.IsOrganization}} | ||||
| 	<div role="main" aria-label="{{.Title}}" class="page-content repository"> | ||||
| 		{{template "shared/user/org_profile_avatar" .}} | ||||
| 		<div class="ui container"> | ||||
| 			{{template "user/overview/header" .}} | ||||
| 			{{template "code/searchcombo" .}} | ||||
| 		</div> | ||||
|  | ||||
| 		{{template "base/paginate" .}} | ||||
| 	</div> | ||||
| </div> | ||||
| {{else}} | ||||
| 	<div role="main" aria-label="{{.Title}}" class="page-content user profile"> | ||||
| 		<div class="ui container"> | ||||
| 			<div class="ui stackable grid"> | ||||
| 				<div class="ui four wide column"> | ||||
| 					{{template "shared/user/profile_big_avatar" .}} | ||||
| 				</div> | ||||
| 				<div class="ui twelve wide column"> | ||||
| 					{{template "user/overview/header" .}} | ||||
| 					{{template "code/searchcombo" .}} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{end}} | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,92 +1,69 @@ | ||||
| <!-- TODO: make template org and user can share --> | ||||
| {{if or (.IsPackagesPage) (.PageIsViewProjects)}} | ||||
| 	{{with .ContextUser}} | ||||
| 		<div class="ui container"> | ||||
| 		<div class="ui vertically grid head"> | ||||
| 			<div class="column"> | ||||
| 				<div class="ui header"> | ||||
| 					{{avatar $.Context . 100}} | ||||
| 					<span class="text thin grey"><a href="{{.HomeLink}}">{{.DisplayName}}</a></span> | ||||
| 					<span class="org-visibility"> | ||||
| 						{{if .Visibility.IsLimited}}<div class="ui medium basic horizontal label">{{$.locale.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}} | ||||
| 						{{if .Visibility.IsPrivate}}<div class="ui medium basic horizontal label">{{$.locale.Tr "org.settings.visibility.private_shortname"}}</div>{{end}} | ||||
| 					</span> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| <div class="ui secondary stackable pointing menu"> | ||||
| 	{{if .HasProfileReadme}} | ||||
| 	<a class='{{if eq .TabName "overview"}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=overview"> | ||||
| 		{{svg "octicon-info"}} {{.locale.Tr "user.overview"}} | ||||
| 	</a> | ||||
| 	{{end}} | ||||
| 	<a class="{{if eq .TabName "repositories"}}active {{end}} item" href="{{.ContextUser.HomeLink}}?tab=repositories"> | ||||
| 		{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}} | ||||
| 		{{if .ContextUser.NumRepos}} | ||||
| 			<div class="ui small label">{{.ContextUser.NumRepos}}</div> | ||||
| 		{{end}} | ||||
| 	</a> | ||||
| 	{{if or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadProjects)}} | ||||
| 	<a href="{{.ContextUser.HomeLink}}/-/projects" class="{{if .PageIsViewProjects}}active {{end}}item"> | ||||
| 		{{svg "octicon-project-symlink"}} {{.locale.Tr "user.projects"}} | ||||
| 	</a> | ||||
| 	{{end}} | ||||
| 	{{if and .IsPackageEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadPackages))}} | ||||
| 		<a href="{{.ContextUser.HomeLink}}/-/packages" class="{{if .IsPackagesPage}}active {{end}}item"> | ||||
| 			{{svg "octicon-package"}} {{.locale.Tr "packages.title"}} | ||||
| 		</a> | ||||
| 	{{end}} | ||||
| 	{{if and .IsRepoIndexerEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadCode))}} | ||||
| 		<a href="{{.ContextUser.HomeLink}}/-/code" class="{{if .IsCodePage}}active {{end}}item"> | ||||
| 			{{svg "octicon-code"}} {{.locale.Tr "user.code"}} | ||||
| 		</a> | ||||
| 	{{end}} | ||||
| {{end}} | ||||
|  | ||||
| <div class="ui tabs container"> | ||||
| 	<div class="ui secondary stackable pointing menu"> | ||||
| 		{{if .ProfileReadme}} | ||||
| 		<a class='{{if or (eq .TabName "overview") (and (eq .TabName "") (not .IsPackagesPage) (not .PageIsViewProjects))}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=overview"> | ||||
| 							{{svg "octicon-info"}} {{.locale.Tr "user.overview"}} | ||||
| 						</a> | ||||
| 		{{end}} | ||||
| 		<a class="{{if or (eq .TabName "repositories") (and (eq .TabName "") (not .IsPackagesPage) (not .PageIsViewProjects) (not .ProfileReadme))}}active {{end}} item" href="{{.ContextUser.HomeLink}}?tab=repositories"> | ||||
| 			{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}} | ||||
| 			{{if .ContextUser.NumRepos}} | ||||
| 				<div class="ui small label">{{.ContextUser.NumRepos}}</div> | ||||
| 			{{end}} | ||||
| 		</a> | ||||
| 		{{if and .IsProjectEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadProjects))}} | ||||
| 		<a href="{{.ContextUser.HomeLink}}/-/projects" class="{{if .PageIsViewProjects}}active {{end}}item"> | ||||
| 			{{svg "octicon-project-symlink"}} {{.locale.Tr "user.projects"}} | ||||
| 		</a> | ||||
| 		{{end}} | ||||
| 		{{if and .IsPackageEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadPackages))}} | ||||
| 			<a href="{{.ContextUser.HomeLink}}/-/packages" class="{{if .IsPackagesPage}}active {{end}}item"> | ||||
| 				{{svg "octicon-package"}} {{.locale.Tr "packages.title"}} | ||||
| 	{{if .ContextUser.IsOrganization}} | ||||
| 		{{if .IsOrganizationMember}} | ||||
| 			<a class="item" href="{{$.OrgLink}}/members"> | ||||
| 				{{svg "octicon-person"}} {{$.locale.Tr "org.members"}} | ||||
| 				{{if .NumMembers}} | ||||
| 					<div class="ui small label">{{.NumMembers}}</div> | ||||
| 				{{end}} | ||||
| 			</a> | ||||
| 		{{end}} | ||||
| 		{{if and .IsRepoIndexerEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadCode))}} | ||||
| 			<a href="{{.ContextUser.HomeLink}}/-/code" class="{{if .IsCodePage}}active {{end}}item"> | ||||
| 				{{svg "octicon-code"}} {{.locale.Tr "user.code"}} | ||||
| 			<a class="item" href="{{$.OrgLink}}/teams"> | ||||
| 				{{svg "octicon-people"}} {{$.locale.Tr "org.teams"}} | ||||
| 				{{if .NumTeams}} | ||||
| 					<div class="ui small label">{{.NumTeams}}</div> | ||||
| 				{{end}} | ||||
| 			</a> | ||||
| 		{{end}} | ||||
|  | ||||
| 		{{if .ContextUser.IsOrganization}} | ||||
| 			{{if .IsOrganizationMember}} | ||||
| 				<a class="item" href="{{$.OrgLink}}/members"> | ||||
| 					{{svg "octicon-person"}} {{$.locale.Tr "org.members"}} | ||||
| 					{{if .NumMembers}} | ||||
| 						<div class="ui small label">{{.NumMembers}}</div> | ||||
| 					{{end}} | ||||
| 		{{if .IsOrganizationOwner}} | ||||
| 			<div class="right menu"> | ||||
| 				<a class="item" href="{{.OrgLink}}/settings"> | ||||
| 				{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}} | ||||
| 				</a> | ||||
| 				<a class="item" href="{{$.OrgLink}}/teams"> | ||||
| 					{{svg "octicon-people"}} {{$.locale.Tr "org.teams"}} | ||||
| 					{{if .NumTeams}} | ||||
| 						<div class="ui small label">{{.NumTeams}}</div> | ||||
| 					{{end}} | ||||
| 				</a> | ||||
| 			{{end}} | ||||
|  | ||||
| 			{{if .IsOrganizationOwner}} | ||||
| 				<div class="right menu"> | ||||
| 					<a class="item" href="{{.OrgLink}}/settings"> | ||||
| 					{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}} | ||||
| 					</a> | ||||
| 				</div> | ||||
| 			{{end}} | ||||
| 			</div> | ||||
| 		{{end}} | ||||
| 	{{else}} | ||||
| 		<a class='{{if eq .TabName "activity"}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=activity"> | ||||
| 			{{svg "octicon-rss"}} {{.locale.Tr "user.activity"}} | ||||
| 		</a> | ||||
| 		{{if not .DisableStars}} | ||||
| 			<a class='{{if eq .TabName "stars"}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=stars"> | ||||
| 				{{svg "octicon-star"}} {{.locale.Tr "user.starred"}} | ||||
| 				{{if .ContextUser.NumStars}} | ||||
| 					<div class="ui small label">{{.ContextUser.NumStars}}</div> | ||||
| 				{{end}} | ||||
| 			</a> | ||||
| 		{{else}} | ||||
| 			<a class='{{if eq .TabName "activity"}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=activity"> | ||||
| 				{{svg "octicon-rss"}} {{.locale.Tr "user.activity"}} | ||||
| 			<a class='{{if eq .TabName "watching"}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=watching"> | ||||
| 				{{svg "octicon-eye"}} {{.locale.Tr "user.watched"}} | ||||
| 			</a> | ||||
| 			{{if not .DisableStars}} | ||||
| 				<a class='{{if eq .TabName "stars"}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=stars"> | ||||
| 					{{svg "octicon-star"}} {{.locale.Tr "user.starred"}} | ||||
| 					{{if .ContextUser.NumStars}} | ||||
| 						<div class="ui small label">{{.ContextUser.NumStars}}</div> | ||||
| 					{{end}} | ||||
| 				</a> | ||||
| 			{{else}} | ||||
| 				<a class='{{if eq .TabName "watching"}}active {{end}}item' href="{{.ContextUser.HomeLink}}?tab=watching"> | ||||
| 					{{svg "octicon-eye"}} {{.locale.Tr "user.watched"}} | ||||
| 				</a> | ||||
| 			{{end}} | ||||
| 		{{end}} | ||||
|  | ||||
| 	</div> | ||||
| 	{{end}} | ||||
| </div> | ||||
|   | ||||
| @@ -1,6 +1,27 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	{{template "package/shared/versionlist" .}} | ||||
| {{if .ContextUser.IsOrganization}} | ||||
| 	<div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 		{{template "shared/user/org_profile_avatar" .}} | ||||
| 		<div class="ui container"> | ||||
| 		{{template "user/overview/header" .}} | ||||
| 		{{template "package/shared/versionlist" .}} | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{else}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content user profile packages"> | ||||
| 	<div class="ui container"> | ||||
| 		<div class="ui stackable grid"> | ||||
| 			<div class="ui four wide column"> | ||||
| 				{{template "shared/user/profile_big_avatar" .}} | ||||
| 			</div> | ||||
| 			<div class="ui twelve wide column"> | ||||
| 				<div class="gt-mb-4"> | ||||
| 					{{template "user/overview/header" .}} | ||||
| 				</div> | ||||
| 				{{template "package/shared/versionlist" .}} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {{end}} | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,6 +1,27 @@ | ||||
| {{template "base/head" .}} | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 	{{template "user/overview/header" .}} | ||||
| 	{{template "package/shared/list" .}} | ||||
| </div> | ||||
| {{if .ContextUser.IsOrganization}} | ||||
| 	<div role="main" aria-label="{{.Title}}" class="page-content repository packages"> | ||||
| 		{{template "shared/user/org_profile_avatar" .}} | ||||
| 		<div class="ui container"> | ||||
| 		{{template "user/overview/header" .}} | ||||
| 		{{template "package/shared/list" .}} | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{else}} | ||||
| 	<div role="main" aria-label="{{.Title}}" class="page-content user profile packages"> | ||||
| 		<div class="ui container"> | ||||
| 			<div class="ui stackable grid"> | ||||
| 				<div class="ui four wide column"> | ||||
| 					{{template "shared/user/profile_big_avatar" .}} | ||||
| 				</div> | ||||
| 				<div class="ui twelve wide column"> | ||||
| 					<div class="gt-mb-4"> | ||||
| 						{{template "user/overview/header" .}} | ||||
| 					</div> | ||||
| 					{{template "package/shared/list" .}} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{end}} | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -3,125 +3,10 @@ | ||||
| 	<div class="ui container"> | ||||
| 		<div class="ui stackable grid"> | ||||
| 			<div class="ui four wide column"> | ||||
| 				<div class="ui card"> | ||||
| 					<div id="profile-avatar" class="content gt-df"> | ||||
| 					{{if eq .SignedUserID .ContextUser.ID}} | ||||
| 						<a class="image" href="{{AppSubUrl}}/user/settings" data-tooltip-content="{{.locale.Tr "user.change_avatar"}}"> | ||||
| 							{{/* the size doesn't take affect (and no need to take affect), image size(width) should be controlled by the parent container since this is not a flex layout*/}} | ||||
| 							{{avatar $.Context .ContextUser 256}} | ||||
| 						</a> | ||||
| 					{{else}} | ||||
| 						<span class="image"> | ||||
| 							{{avatar $.Context .ContextUser 256}} | ||||
| 						</span> | ||||
| 					{{end}} | ||||
| 					</div> | ||||
| 					<div class="content gt-word-break profile-avatar-name"> | ||||
| 						{{if .ContextUser.FullName}}<span class="header text center">{{.ContextUser.FullName}}</span>{{end}} | ||||
| 						<span class="username text center">{{.ContextUser.Name}}</span> | ||||
| 						{{if .EnableFeed}} | ||||
| 							<a href="{{.ContextUser.HomeLink}}.rss"><i class="ui text grey gt-ml-3" data-tooltip-content="{{.locale.Tr "rss_feed"}}">{{svg "octicon-rss" 18}}</i></a> | ||||
| 						{{end}} | ||||
| 						<div class="gt-mt-3"> | ||||
| 							<a class="muted" href="{{.ContextUser.HomeLink}}?tab=followers">{{svg "octicon-person" 18 "gt-mr-2"}}{{.NumFollowers}} {{.locale.Tr "user.followers"}}</a> · <a class="muted" href="{{.ContextUser.HomeLink}}?tab=following">{{.NumFollowing}} {{.locale.Tr "user.following"}}</a> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 					<div class="extra content gt-word-break"> | ||||
| 						<ul> | ||||
| 							{{if .ContextUser.Location}} | ||||
| 								<li>{{svg "octicon-location"}} {{.ContextUser.Location}}</li> | ||||
| 							{{end}} | ||||
| 							{{if (eq .SignedUserID .ContextUser.ID)}} | ||||
| 								<li> | ||||
| 									{{svg "octicon-mail"}} | ||||
| 									<a href="mailto:{{.ContextUser.Email}}" rel="nofollow">{{.ContextUser.Email}}</a> | ||||
| 									<a href="{{AppSubUrl}}/user/settings#privacy-user-settings"> | ||||
| 										{{if .ShowUserEmail}} | ||||
| 											<i class="ui right" data-tooltip-content="{{.locale.Tr "user.email_visibility.limited"}}"> | ||||
| 												{{svg "octicon-unlock"}} | ||||
| 											</i> | ||||
| 										{{else}} | ||||
| 											<i class="ui right" data-tooltip-content="{{.locale.Tr "user.email_visibility.private"}}"> | ||||
| 												{{svg "octicon-lock"}} | ||||
| 											</i> | ||||
| 										{{end}} | ||||
| 									</a> | ||||
| 								</li> | ||||
| 							{{else}} | ||||
| 								{{if .ShowUserEmail}} | ||||
| 									<li> | ||||
| 										{{svg "octicon-mail"}} | ||||
| 										<a href="mailto:{{.ContextUser.Email}}" rel="nofollow">{{.ContextUser.Email}}</a> | ||||
| 									</li> | ||||
| 								{{end}} | ||||
| 							{{end}} | ||||
| 							{{if .ContextUser.Website}} | ||||
| 								<li> | ||||
| 									{{svg "octicon-link"}} | ||||
| 									<a target="_blank" rel="noopener noreferrer me" href="{{.ContextUser.Website}}">{{.ContextUser.Website}}</a> | ||||
| 								</li> | ||||
| 							{{end}} | ||||
| 							{{if $.RenderedDescription}} | ||||
| 								<li> | ||||
| 									<div class="render-content markup">{{$.RenderedDescription|Str2html}}</div> | ||||
| 								</li> | ||||
| 							{{end}} | ||||
| 							{{range .OpenIDs}} | ||||
| 								{{if .Show}} | ||||
| 									<li> | ||||
| 										{{svg "fontawesome-openid"}} | ||||
| 										<a target="_blank" rel="noopener noreferrer" href="{{.URI}}">{{.URI}}</a> | ||||
| 									</li> | ||||
| 								{{end}} | ||||
| 							{{end}} | ||||
| 							<li>{{svg "octicon-clock"}} {{.locale.Tr "user.joined_on" (DateTime "short" .ContextUser.CreatedUnix) | Safe}}</li> | ||||
| 							{{if and .Orgs .HasOrgsVisible}} | ||||
| 							<li> | ||||
| 								<ul class="user-orgs"> | ||||
| 								{{range .Orgs}} | ||||
| 									{{if (or .Visibility.IsPublic (and ($.SignedUser) (or .Visibility.IsLimited (and (.HasMemberWithUserID $.SignedUserID) .Visibility.IsPrivate) ($.IsAdmin))))}} | ||||
| 									<li> | ||||
| 										<a href="{{.HomeLink}}" data-tooltip-content="{{.Name}}"> | ||||
| 											{{avatar $.Context .}} | ||||
| 										</a> | ||||
| 									</li> | ||||
| 									{{end}} | ||||
| 								{{end}} | ||||
| 								</ul> | ||||
| 							</li> | ||||
| 							{{end}} | ||||
| 							{{if .Badges}} | ||||
| 							<li> | ||||
| 								<ul class="user-badges"> | ||||
| 								{{range .Badges}} | ||||
| 									<li> | ||||
| 										<img width="64" height="64" src="{{.ImageURL}}" alt="{{.Description}}" data-tooltip-content="{{.Description}}"> | ||||
| 									</li> | ||||
| 								{{end}} | ||||
| 								</ul> | ||||
| 							</li> | ||||
| 							{{end}} | ||||
| 							{{if and .IsSigned (ne .SignedUserID .ContextUser.ID)}} | ||||
| 							<li class="follow"> | ||||
| 								{{if $.IsFollowing}} | ||||
| 									<form method="post" action="{{.Link}}?action=unfollow&redirect_to={{$.Link}}"> | ||||
| 										{{$.CsrfTokenHtml}} | ||||
| 										<button type="submit" class="ui basic red button">{{svg "octicon-person"}} {{.locale.Tr "user.unfollow"}}</button> | ||||
| 									</form> | ||||
| 								{{else}} | ||||
| 									<form method="post" action="{{.Link}}?action=follow&redirect_to={{$.Link}}"> | ||||
| 										{{$.CsrfTokenHtml}} | ||||
| 										<button type="submit" class="ui basic green button">{{svg "octicon-person"}} {{.locale.Tr "user.follow"}}</button> | ||||
| 									</form> | ||||
| 								{{end}} | ||||
| 							</li> | ||||
| 							{{end}} | ||||
| 						</ul> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				{{template "shared/user/profile_big_avatar" .}} | ||||
| 			</div> | ||||
| 			<div class="ui twelve wide column"> | ||||
| 				<div class="gt-mb-4 gt-df"> | ||||
| 				<div class="gt-mb-4"> | ||||
| 					{{template "user/overview/header" .}} | ||||
| 				</div> | ||||
|  | ||||
| @@ -145,12 +30,12 @@ | ||||
| 					{{template "repo/user_cards" .}} | ||||
| 				{{else if eq .TabName "followers"}} | ||||
| 					{{template "repo/user_cards" .}} | ||||
| 				{{else if or (eq .TabName "repositories") (not .ProfileReadme)}} | ||||
| 				{{else if eq .TabName "overview"}} | ||||
| 					<div id="readme_profile" class="markup">{{.ProfileReadme | Str2html}}</div> | ||||
| 				{{else}} | ||||
| 					{{template "explore/repo_search" .}} | ||||
| 					{{template "explore/repo_list" .}} | ||||
| 					{{template "base/paginate" .}} | ||||
| 				{{else if .ProfileReadme}} | ||||
| 					<div id="readme_profile" class="render-content markup"> {{$.ProfileReadme|Str2html}} </div> | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 		</div> | ||||
|   | ||||
| @@ -11,6 +11,7 @@ Gitea's private styles use `g-` prefix. | ||||
| .gt-ab { align-items: baseline !important; } | ||||
| .gt-tc { text-align: center !important; } | ||||
| .gt-tl { text-align: left !important; } | ||||
| .gt-tr { text-align: right !important; } /* TODO: rename these to "gt-text-right", etc. there are only a few */ | ||||
| .gt-jc { justify-content: center !important; } | ||||
| .gt-js { justify-content: flex-start !important; } | ||||
| .gt-je { justify-content: flex-end !important; } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user