refactor organization menu (#33928)

Fix missing items in organization menu.

**Menu**

<details>
<summary>Show</summary>

Before:

![](https://github.com/user-attachments/assets/bcbce97e-84de-44ea-9889-a664979433cd)

After:

![](https://github.com/user-attachments/assets/a169e00f-5212-4733-af9e-e8676ad74376)

</details>

**Packages**

<details>

 keep it consistent with the other pages.

<summary>Show</summary>

Before:

![](https://github.com/user-attachments/assets/170d7b3d-ecac-49b9-8296-44d0b0f2b191)

After:

![](https://github.com/user-attachments/assets/9c3c6915-870c-48cc-8a35-3d615a27d36d)

</details>

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Exploding Dragon 2025-04-11 03:12:55 +08:00 committed by GitHub
parent fa49cd719f
commit 4ddf94dee5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 304 additions and 302 deletions

View File

@ -20,6 +20,11 @@ func BlockedUsers(ctx *context.Context) {
ctx.Data["PageIsOrgSettings"] = true
ctx.Data["PageIsSettingsBlockedUsers"] = true
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
shared_user.BlockedUsers(ctx, ctx.ContextUser)
if ctx.Written() {
return
@ -29,6 +34,11 @@ func BlockedUsers(ctx *context.Context) {
}
func BlockedUsersPost(ctx *context.Context) {
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
shared_user.BlockedUsersPost(ctx, ctx.ContextUser)
if ctx.Written() {
return

View File

@ -86,12 +86,6 @@ func home(ctx *context.Context, viewRepositories bool) {
private := ctx.FormOptionalBool("private")
ctx.Data["IsPrivate"] = private
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
opts := &organization.FindOrgMembersOpts{
Doer: ctx.Doer,
OrgID: org.ID,
@ -109,9 +103,9 @@ func home(ctx *context.Context, viewRepositories bool) {
ctx.Data["DisableNewPullMirrors"] = setting.Mirror.DisableNewPull
ctx.Data["ShowMemberAndTeamTab"] = ctx.Org.IsMember || len(members) > 0
prepareResult, err := shared_user.PrepareOrgHeader(ctx)
prepareResult, err := shared_user.RenderUserOrgHeader(ctx)
if err != nil {
ctx.ServerError("PrepareOrgHeader", err)
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -154,7 +148,7 @@ func home(ctx *context.Context, viewRepositories bool) {
ctx.HTML(http.StatusOK, tplOrgHome)
}
func prepareOrgProfileReadme(ctx *context.Context, prepareResult *shared_user.PrepareOrgHeaderResult) bool {
func prepareOrgProfileReadme(ctx *context.Context, prepareResult *shared_user.PrepareOwnerHeaderResult) bool {
viewAs := ctx.FormString("view_as", util.Iif(ctx.Org.IsMember, "member", "public"))
viewAsMember := viewAs == "member"

View File

@ -54,9 +54,8 @@ func Members(ctx *context.Context) {
return
}
_, err = shared_user.PrepareOrgHeader(ctx)
if err != nil {
ctx.ServerError("PrepareOrgHeader", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}

View File

@ -43,7 +43,10 @@ func MustEnableProjects(ctx *context.Context) {
// Projects renders the home page of projects
func Projects(ctx *context.Context) {
shared_user.PrepareContextForProfileBigAvatar(ctx)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.Data["Title"] = ctx.Tr("repo.projects")
sortType := ctx.FormTrim("sort")
@ -101,7 +104,6 @@ func Projects(ctx *context.Context) {
}
ctx.Data["Projects"] = projects
shared_user.RenderUserHeader(ctx)
if isShowClosed {
ctx.Data["State"] = "closed"
@ -113,12 +115,6 @@ func Projects(ctx *context.Context) {
project.RenderedContent = renderUtils.MarkdownToHtml(project.Description)
}
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
numPages := 0
if total > 0 {
numPages = (int(total) - 1/setting.UI.IssuePagingNum)
@ -152,11 +148,8 @@ func RenderNewProject(ctx *context.Context) {
ctx.Data["PageIsViewProjects"] = true
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
ctx.Data["CancelLink"] = ctx.ContextUser.HomeLink() + "/-/projects"
shared_user.RenderUserHeader(ctx)
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -167,7 +160,10 @@ func RenderNewProject(ctx *context.Context) {
func NewProjectPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.CreateProjectForm)
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
shared_user.RenderUserHeader(ctx)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
if ctx.HasError() {
RenderNewProject(ctx)
@ -248,7 +244,10 @@ func RenderEditProject(ctx *context.Context) {
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["CardTypes"] = project_model.GetCardConfig()
shared_user.RenderUserHeader(ctx)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
p, err := project_model.GetProjectByID(ctx, ctx.PathParamInt64("id"))
if err != nil {
@ -282,11 +281,8 @@ func EditProjectPost(ctx *context.Context) {
ctx.Data["CardTypes"] = project_model.GetCardConfig()
ctx.Data["CancelLink"] = project_model.ProjectLinkForOrg(ctx.ContextUser, projectID)
shared_user.RenderUserHeader(ctx)
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -443,11 +439,9 @@ func ViewProject(ctx *context.Context) {
ctx.Data["Project"] = project
ctx.Data["IssuesMap"] = issuesMap
ctx.Data["Columns"] = columns
shared_user.RenderUserHeader(ctx)
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}

View File

@ -48,9 +48,8 @@ func Settings(ctx *context.Context) {
ctx.Data["RepoAdminChangeTeamAccess"] = ctx.Org.Organization.RepoAdminChangeTeamAccess
ctx.Data["ContextUser"] = ctx.ContextUser
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -194,9 +193,8 @@ func SettingsDelete(ctx *context.Context) {
return
}
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -218,9 +216,8 @@ func Webhooks(ctx *context.Context) {
return
}
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -246,9 +243,8 @@ func Labels(ctx *context.Context) {
ctx.Data["PageIsOrgSettingsLabels"] = true
ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}

View File

@ -45,9 +45,8 @@ func Applications(ctx *context.Context) {
}
ctx.Data["Applications"] = apps
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}

View File

@ -25,9 +25,8 @@ func Packages(ctx *context.Context) {
ctx.Data["PageIsOrgSettings"] = true
ctx.Data["PageIsSettingsPackages"] = true
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -41,9 +40,8 @@ func PackagesRuleAdd(ctx *context.Context) {
ctx.Data["PageIsOrgSettings"] = true
ctx.Data["PageIsSettingsPackages"] = true
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -57,9 +55,8 @@ func PackagesRuleEdit(ctx *context.Context) {
ctx.Data["PageIsOrgSettings"] = true
ctx.Data["PageIsSettingsPackages"] = true
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -99,9 +96,8 @@ func PackagesRulePreview(ctx *context.Context) {
ctx.Data["PageIsOrgSettings"] = true
ctx.Data["PageIsSettingsPackages"] = true
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}

View File

@ -46,6 +46,10 @@ const (
// Teams render teams list page
func Teams(ctx *context.Context) {
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
org := ctx.Org.Organization
ctx.Data["Title"] = org.FullName
ctx.Data["PageIsOrgTeams"] = true
@ -58,12 +62,6 @@ func Teams(ctx *context.Context) {
}
ctx.Data["Teams"] = ctx.Org.Teams
_, err := shared_user.PrepareOrgHeader(ctx)
if err != nil {
ctx.ServerError("PrepareOrgHeader", err)
return
}
ctx.HTML(http.StatusOK, tplTeams)
}
@ -272,15 +270,15 @@ func TeamsRepoAction(ctx *context.Context) {
// NewTeam render create new team page
func NewTeam(ctx *context.Context) {
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.Data["Title"] = ctx.Org.Organization.FullName
ctx.Data["PageIsOrgTeams"] = true
ctx.Data["PageIsOrgTeamsNew"] = true
ctx.Data["Team"] = &org_model.Team{}
ctx.Data["Units"] = unit_model.Units
if err := shared_user.LoadHeaderCount(ctx); err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
ctx.HTML(http.StatusOK, tplTeamNew)
}
@ -370,15 +368,15 @@ func NewTeamPost(ctx *context.Context) {
// TeamMembers render team members page
func TeamMembers(ctx *context.Context) {
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.Data["Title"] = ctx.Org.Team.Name
ctx.Data["PageIsOrgTeams"] = true
ctx.Data["PageIsOrgTeamMembers"] = true
if err := shared_user.LoadHeaderCount(ctx); err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
if err := ctx.Org.Team.LoadMembers(ctx); err != nil {
ctx.ServerError("GetMembers", err)
return
@ -398,15 +396,15 @@ func TeamMembers(ctx *context.Context) {
// TeamRepositories show the repositories of team
func TeamRepositories(ctx *context.Context) {
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.Data["Title"] = ctx.Org.Team.Name
ctx.Data["PageIsOrgTeams"] = true
ctx.Data["PageIsOrgTeamRepos"] = true
if err := shared_user.LoadHeaderCount(ctx); err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
TeamID: ctx.Org.Team.ID,
})
@ -463,16 +461,16 @@ func SearchTeam(ctx *context.Context) {
// EditTeam render team edit page
func EditTeam(ctx *context.Context) {
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.Data["Title"] = ctx.Org.Organization.FullName
ctx.Data["PageIsOrgTeams"] = true
if err := ctx.Org.Team.LoadUnits(ctx); err != nil {
ctx.ServerError("LoadUnits", err)
return
}
if err := shared_user.LoadHeaderCount(ctx); err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
ctx.Data["Team"] = ctx.Org.Team
ctx.Data["Units"] = unit_model.Units
ctx.HTML(http.StatusOK, tplTeamNew)

View File

@ -9,6 +9,7 @@ import (
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/modules/templates"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
)
@ -70,6 +71,12 @@ func Worktime(ctx *context.Context) {
ctx.ServerError("GetWorktime", err)
return
}
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.Data["WorktimeSumResult"] = worktimeSumResult
ctx.HTML(http.StatusOK, tplByRepos)
}

View File

@ -44,9 +44,8 @@ func getSecretsCtx(ctx *context.Context) (*secretsCtx, error) {
}
if ctx.Data["PageIsOrgSettings"] == true {
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return nil, nil
}
return &secretsCtx{

View File

@ -57,9 +57,8 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
}
if ctx.Data["PageIsOrgSettings"] == true {
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return nil, nil
}
return &runnersCtx{

View File

@ -49,9 +49,8 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
}
if ctx.Data["PageIsOrgSettings"] == true {
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return nil, nil
}
return &variablesCtx{

View File

@ -24,19 +24,8 @@ import (
"code.gitea.io/gitea/services/context"
)
// 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["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)
// prepareContextForProfileBigAvatar set the context for big avatar view on the profile page
func prepareContextForProfileBigAvatar(ctx *context.Context) {
ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
if setting.Service.UserLocationMapURL != "" {
@ -138,16 +127,44 @@ func FindOwnerProfileReadme(ctx *context.Context, doer *user_model.User, optProf
return profileDbRepo, profileReadmeBlob
}
func RenderUserHeader(ctx *context.Context) {
prepareContextForCommonProfile(ctx)
_, profileReadmeBlob := FindOwnerProfileReadme(ctx, ctx.Doer)
ctx.Data["HasUserProfileReadme"] = profileReadmeBlob != nil
type PrepareOwnerHeaderResult struct {
ProfilePublicRepo *repo_model.Repository
ProfilePublicReadmeBlob *git.Blob
ProfilePrivateRepo *repo_model.Repository
ProfilePrivateReadmeBlob *git.Blob
HasOrgProfileReadme bool
}
func LoadHeaderCount(ctx *context.Context) error {
prepareContextForCommonProfile(ctx)
const (
RepoNameProfilePrivate = ".profile-private"
RepoNameProfile = ".profile"
)
func RenderUserOrgHeader(ctx *context.Context) (result *PrepareOwnerHeaderResult, err error) {
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink()
if err := loadHeaderCount(ctx); err != nil {
return nil, err
}
result = &PrepareOwnerHeaderResult{}
if ctx.ContextUser.IsOrganization() {
result.ProfilePublicRepo, result.ProfilePublicReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer)
result.ProfilePrivateRepo, result.ProfilePrivateReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer, RepoNameProfilePrivate)
result.HasOrgProfileReadme = result.ProfilePublicReadmeBlob != nil || result.ProfilePrivateReadmeBlob != nil
ctx.Data["HasOrgProfileReadme"] = result.HasOrgProfileReadme // many pages need it to show the "overview" tab
} else {
_, profileReadmeBlob := FindOwnerProfileReadme(ctx, ctx.Doer)
ctx.Data["HasUserProfileReadme"] = profileReadmeBlob != nil
prepareContextForProfileBigAvatar(ctx)
}
return result, nil
}
func loadHeaderCount(ctx *context.Context) error {
repoCount, err := repo_model.CountRepository(ctx, &repo_model.SearchRepoOptions{
Actor: ctx.Doer,
OwnerID: ctx.ContextUser.ID,
@ -178,29 +195,3 @@ func LoadHeaderCount(ctx *context.Context) error {
return nil
}
const (
RepoNameProfilePrivate = ".profile-private"
RepoNameProfile = ".profile"
)
type PrepareOrgHeaderResult struct {
ProfilePublicRepo *repo_model.Repository
ProfilePublicReadmeBlob *git.Blob
ProfilePrivateRepo *repo_model.Repository
ProfilePrivateReadmeBlob *git.Blob
HasOrgProfileReadme bool
}
func PrepareOrgHeader(ctx *context.Context) (result *PrepareOrgHeaderResult, err error) {
if err = LoadHeaderCount(ctx); err != nil {
return nil, err
}
result = &PrepareOrgHeaderResult{}
result.ProfilePublicRepo, result.ProfilePublicReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer)
result.ProfilePrivateRepo, result.ProfilePrivateReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer, RepoNameProfilePrivate)
result.HasOrgProfileReadme = result.ProfilePublicReadmeBlob != nil || result.ProfilePrivateReadmeBlob != nil
ctx.Data["HasOrgProfileReadme"] = result.HasOrgProfileReadme // many pages need it to show the "overview" tab
return result, nil
}

View File

@ -26,11 +26,8 @@ func CodeSearch(ctx *context.Context) {
ctx.Redirect(ctx.ContextUser.HomeLink())
return
}
shared_user.PrepareContextForProfileBigAvatar(ctx)
shared_user.RenderUserHeader(ctx)
if err := shared_user.LoadHeaderCount(ctx); err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}

View File

@ -42,7 +42,10 @@ const (
// ListPackages displays a list of all packages of the context user
func ListPackages(ctx *context.Context) {
shared_user.PrepareContextForProfileBigAvatar(ctx)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
page := ctx.FormInt("page")
if page <= 1 {
page = 1
@ -94,8 +97,6 @@ func ListPackages(ctx *context.Context) {
return
}
shared_user.RenderUserHeader(ctx)
ctx.Data["Title"] = ctx.Tr("packages.title")
ctx.Data["IsPackagesPage"] = true
ctx.Data["Query"] = query
@ -106,9 +107,8 @@ func ListPackages(ctx *context.Context) {
ctx.Data["Total"] = total
ctx.Data["RepositoryAccessMap"] = repositoryAccessMap
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -126,11 +126,9 @@ func ListPackages(ctx *context.Context) {
ctx.Data["IsOrganizationOwner"] = false
}
}
pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
pager.AddParamFromRequest(ctx.Req)
ctx.Data["Page"] = pager
ctx.HTML(http.StatusOK, tplPackagesList)
}
@ -164,16 +162,17 @@ func RedirectToLastVersion(ctx *context.Context) {
ctx.ServerError("GetPackageDescriptor", err)
return
}
ctx.Redirect(pd.VersionWebLink())
}
// ViewPackageVersion displays a single package version
func ViewPackageVersion(ctx *context.Context) {
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
pd := ctx.Package.Descriptor
shared_user.RenderUserHeader(ctx)
ctx.Data["Title"] = pd.Package.Name
ctx.Data["IsPackagesPage"] = true
ctx.Data["PackageDescriptor"] = pd
@ -301,19 +300,16 @@ func ViewPackageVersion(ctx *context.Context) {
hasRepositoryAccess = permission.HasAnyUnitAccess()
}
ctx.Data["HasRepositoryAccess"] = hasRepositoryAccess
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
ctx.HTML(http.StatusOK, tplPackagesView)
}
// ListPackageVersions lists all versions of a package
func ListPackageVersions(ctx *context.Context) {
shared_user.PrepareContextForProfileBigAvatar(ctx)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
p, err := packages_model.GetPackageByName(ctx, ctx.Package.Owner.ID, packages_model.Type(ctx.PathParam("type")), ctx.PathParam("name"))
if err != nil {
if err == packages_model.ErrPackageNotExist {
@ -336,8 +332,6 @@ func ListPackageVersions(ctx *context.Context) {
query := ctx.FormTrim("q")
sort := ctx.FormTrim("sort")
shared_user.RenderUserHeader(ctx)
ctx.Data["Title"] = ctx.Tr("packages.title")
ctx.Data["IsPackagesPage"] = true
ctx.Data["PackageDescriptor"] = &packages_model.PackageDescriptor{
@ -393,12 +387,6 @@ func ListPackageVersions(ctx *context.Context) {
ctx.Data["Total"] = total
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
pager.AddParamFromRequest(ctx.Req)
ctx.Data["Page"] = pager
@ -410,7 +398,10 @@ func ListPackageVersions(ctx *context.Context) {
func PackageSettings(ctx *context.Context) {
pd := ctx.Package.Descriptor
shared_user.RenderUserHeader(ctx)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.Data["Title"] = pd.Package.Name
ctx.Data["IsPackagesPage"] = true
@ -423,12 +414,6 @@ func PackageSettings(ctx *context.Context) {
ctx.Data["Repos"] = repos
ctx.Data["CanWritePackages"] = ctx.Package.AccessMode >= perm.AccessModeWrite || ctx.IsUserSiteAdmin()
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
ctx.HTML(http.StatusOK, tplPackagesSettings)
}

View File

@ -78,8 +78,15 @@ func userProfile(ctx *context.Context) {
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
prepareUserProfileTabData(ctx, showPrivate, profileDbRepo, profileReadmeBlob)
// call PrepareContextForProfileBigAvatar later to avoid re-querying the NumFollowers & NumFollowing
shared_user.PrepareContextForProfileBigAvatar(ctx)
// prepare the user nav header data after "prepareUserProfileTabData" to avoid re-querying the NumFollowers & NumFollowing
// because ctx.Data["NumFollowers"] and "NumFollowing" logic duplicates in both of them
// and the "profile readme" related logic also duplicates in both of FindOwnerProfileReadme and RenderUserOrgHeader
// TODO: it is a bad design and should be refactored later,
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
ctx.HTML(http.StatusOK, tplProfile)
}
@ -302,9 +309,8 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb
ctx.Data["Repos"] = repos
ctx.Data["Total"] = total
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
@ -328,9 +334,11 @@ func ActionUserFollow(ctx *context.Context) {
ctx.HTTPError(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action")))
return
}
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
if ctx.ContextUser.IsIndividual() {
shared_user.PrepareContextForProfileBigAvatar(ctx)
ctx.HTML(http.StatusOK, tplProfileBigAvatar)
return
} else if ctx.ContextUser.IsOrganization() {

View File

@ -28,8 +28,8 @@ func (oa *OAuth2CommonHandlers) renderEditPage(ctx *context.Context) {
ctx.Data["FormActionPath"] = fmt.Sprintf("%s/%d", oa.BasePathEditPrefix, app.ID)
if ctx.ContextUser != nil && ctx.ContextUser.IsOrganization() {
if err := shared_user.LoadHeaderCount(ctx); err != nil {
ctx.ServerError("LoadHeaderCount", err)
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
ctx.ServerError("RenderUserOrgHeader", err)
return
}
}

View File

@ -44,7 +44,7 @@
{{end}}
</a>
{{end}}
{{if .IsOrganizationOwner}}
{{if and EnableTimetracking .IsOrganizationOwner}}
<a class="{{if $.PageIsOrgTimes}}active{{end}} item" href="{{$.OrgLink}}/worktime">
{{svg "octicon-clock"}} {{ctx.Locale.Tr "org.worktime"}}
</a>

View File

@ -1,9 +1,24 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content organization projects edit-project new">
{{template "shared/user/org_profile_avatar" .}}
{{if .ContextUser.IsOrganization}}
<div role="main" aria-label="{{.Title}}" class="page-content organization projects">
{{template "org/header" .}}
<div class="ui container">
{{template "user/overview/header" .}}
{{template "projects/new" .}}
{{template "projects/new" .}}
</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 tw-mb-4">
{{template "user/overview/header" .}}
{{template "projects/new" .}}
</div>
</div>
</div>
</div>
{{end}}
{{template "base/footer" .}}

View File

@ -0,0 +1,106 @@
<div class="issue-title-header">
<h1>{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</h1>
<div>
{{$timeStr := DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}
{{if .HasRepositoryAccess}}
{{ctx.Locale.Tr "packages.published_by_in" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName .PackageDescriptor.Repository.Link .PackageDescriptor.Repository.FullName}}
{{else}}
{{ctx.Locale.Tr "packages.published_by" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName}}
{{end}}
</div>
</div>
<div class="issue-content">
<div class="issue-content-left">
{{template "package/content/alpine" .}}
{{template "package/content/arch" .}}
{{template "package/content/cargo" .}}
{{template "package/content/chef" .}}
{{template "package/content/composer" .}}
{{template "package/content/conan" .}}
{{template "package/content/conda" .}}
{{template "package/content/container" .}}
{{template "package/content/cran" .}}
{{template "package/content/debian" .}}
{{template "package/content/generic" .}}
{{template "package/content/go" .}}
{{template "package/content/helm" .}}
{{template "package/content/maven" .}}
{{template "package/content/npm" .}}
{{template "package/content/nuget" .}}
{{template "package/content/pub" .}}
{{template "package/content/pypi" .}}
{{template "package/content/rpm" .}}
{{template "package/content/rubygems" .}}
{{template "package/content/swift" .}}
{{template "package/content/vagrant" .}}
</div>
<div class="issue-content-right ui segment">
<strong>{{ctx.Locale.Tr "packages.details"}}</strong>
<div class="ui relaxed list flex-items-block">
<div class="item">{{svg .PackageDescriptor.Package.Type.SVGName}} {{.PackageDescriptor.Package.Type.Name}}</div>
{{if .HasRepositoryAccess}}
<div class="item">{{svg "octicon-repo"}} <a href="{{.PackageDescriptor.Repository.Link}}">{{.PackageDescriptor.Repository.FullName}}</a></div>
{{end}}
<div class="item">{{svg "octicon-calendar"}} {{DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}</div>
<div class="item">{{svg "octicon-download"}} {{.PackageDescriptor.Version.DownloadCount}}</div>
{{template "package/metadata/alpine" .}}
{{template "package/metadata/arch" .}}
{{template "package/metadata/cargo" .}}
{{template "package/metadata/chef" .}}
{{template "package/metadata/composer" .}}
{{template "package/metadata/conan" .}}
{{template "package/metadata/conda" .}}
{{template "package/metadata/container" .}}
{{template "package/metadata/cran" .}}
{{template "package/metadata/debian" .}}
{{template "package/metadata/generic" .}}
{{template "package/metadata/helm" .}}
{{template "package/metadata/maven" .}}
{{template "package/metadata/npm" .}}
{{template "package/metadata/nuget" .}}
{{template "package/metadata/pub" .}}
{{template "package/metadata/pypi" .}}
{{template "package/metadata/rpm" .}}
{{template "package/metadata/rubygems" .}}
{{template "package/metadata/swift" .}}
{{template "package/metadata/vagrant" .}}
{{if not (and (eq .PackageDescriptor.Package.Type "container") .PackageDescriptor.Metadata.Manifests)}}
<div class="item">{{svg "octicon-database"}} {{FileSize .PackageDescriptor.CalculateBlobSize}}</div>
{{end}}
</div>
{{if not (eq .PackageDescriptor.Package.Type "container")}}
<div class="divider"></div>
<strong>{{ctx.Locale.Tr "packages.assets"}} ({{len .PackageDescriptor.Files}})</strong>
<div class="ui relaxed list">
{{range .PackageDescriptor.Files}}
<div class="item">
<a href="{{$.Link}}/files/{{.File.ID}}">{{.File.Name}}</a>
<span class="text small file-size">{{FileSize .Blob.Size}}</span>
</div>
{{end}}
</div>
{{end}}
<div class="divider"></div>
<strong>{{ctx.Locale.Tr "packages.versions"}} ({{.TotalVersionCount}})</strong>
<a class="tw-float-right" href="{{$.PackageDescriptor.PackageWebLink}}/versions">{{ctx.Locale.Tr "packages.versions.view_all"}}</a>
<div class="ui relaxed list">
{{range .LatestVersions}}
<div class="item tw-flex">
<a class="tw-flex-1 gt-ellipsis" title="{{.Version}}" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
<span class="text small">{{DateUtils.AbsoluteShort .CreatedUnix}}</span>
</div>
{{end}}
</div>
{{if or .CanWritePackages .HasRepositoryAccess}}
<div class="divider"></div>
<div class="ui relaxed list flex-items-block">
{{if .HasRepositoryAccess}}
<div class="item">{{svg "octicon-issue-opened"}} <a href="{{.PackageDescriptor.Repository.Link}}/issues">{{ctx.Locale.Tr "repo.issues"}}</a></div>
{{end}}
{{if .CanWritePackages}}
<div class="item">{{svg "octicon-tools"}} <a href="{{.Link}}/settings">{{ctx.Locale.Tr "repo.settings"}}</a></div>
{{end}}
</div>
{{end}}
</div>
</div>

View File

@ -1,114 +1,24 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content repository packages">
{{template "shared/user/org_profile_avatar" .}}
{{if .ContextUser.IsOrganization}}
<div role="main" aria-label="{{.Title}}" class="page-content organization packages">
{{template "org/header" .}}
<div class="ui container">
{{template "user/overview/header" .}}
<div class="issue-title-header">
<h1>{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</h1>
<div>
{{$timeStr := DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}
{{if .HasRepositoryAccess}}
{{ctx.Locale.Tr "packages.published_by_in" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName .PackageDescriptor.Repository.Link .PackageDescriptor.Repository.FullName}}
{{else}}
{{ctx.Locale.Tr "packages.published_by" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName}}
{{end}}
{{template "package/shared/view" .}}
</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>
<div class="issue-content">
<div class="issue-content-left">
{{template "package/content/alpine" .}}
{{template "package/content/arch" .}}
{{template "package/content/cargo" .}}
{{template "package/content/chef" .}}
{{template "package/content/composer" .}}
{{template "package/content/conan" .}}
{{template "package/content/conda" .}}
{{template "package/content/container" .}}
{{template "package/content/cran" .}}
{{template "package/content/debian" .}}
{{template "package/content/generic" .}}
{{template "package/content/go" .}}
{{template "package/content/helm" .}}
{{template "package/content/maven" .}}
{{template "package/content/npm" .}}
{{template "package/content/nuget" .}}
{{template "package/content/pub" .}}
{{template "package/content/pypi" .}}
{{template "package/content/rpm" .}}
{{template "package/content/rubygems" .}}
{{template "package/content/swift" .}}
{{template "package/content/vagrant" .}}
</div>
<div class="issue-content-right ui segment">
<strong>{{ctx.Locale.Tr "packages.details"}}</strong>
<div class="ui relaxed list flex-items-block">
<div class="item">{{svg .PackageDescriptor.Package.Type.SVGName}} {{.PackageDescriptor.Package.Type.Name}}</div>
{{if .HasRepositoryAccess}}
<div class="item">{{svg "octicon-repo"}} <a href="{{.PackageDescriptor.Repository.Link}}">{{.PackageDescriptor.Repository.FullName}}</a></div>
{{end}}
<div class="item">{{svg "octicon-calendar"}} {{DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}</div>
<div class="item">{{svg "octicon-download"}} {{.PackageDescriptor.Version.DownloadCount}}</div>
{{template "package/metadata/alpine" .}}
{{template "package/metadata/arch" .}}
{{template "package/metadata/cargo" .}}
{{template "package/metadata/chef" .}}
{{template "package/metadata/composer" .}}
{{template "package/metadata/conan" .}}
{{template "package/metadata/conda" .}}
{{template "package/metadata/container" .}}
{{template "package/metadata/cran" .}}
{{template "package/metadata/debian" .}}
{{template "package/metadata/generic" .}}
{{template "package/metadata/helm" .}}
{{template "package/metadata/maven" .}}
{{template "package/metadata/npm" .}}
{{template "package/metadata/nuget" .}}
{{template "package/metadata/pub" .}}
{{template "package/metadata/pypi" .}}
{{template "package/metadata/rpm" .}}
{{template "package/metadata/rubygems" .}}
{{template "package/metadata/swift" .}}
{{template "package/metadata/vagrant" .}}
{{if not (and (eq .PackageDescriptor.Package.Type "container") .PackageDescriptor.Metadata.Manifests)}}
<div class="item">{{svg "octicon-database"}} {{FileSize .PackageDescriptor.CalculateBlobSize}}</div>
{{end}}
</div>
{{if not (eq .PackageDescriptor.Package.Type "container")}}
<div class="divider"></div>
<strong>{{ctx.Locale.Tr "packages.assets"}} ({{len .PackageDescriptor.Files}})</strong>
<div class="ui relaxed list">
{{range .PackageDescriptor.Files}}
<div class="item">
<a href="{{$.Link}}/files/{{.File.ID}}">{{.File.Name}}</a>
<span class="text small file-size">{{FileSize .Blob.Size}}</span>
</div>
{{end}}
</div>
{{end}}
<div class="divider"></div>
<strong>{{ctx.Locale.Tr "packages.versions"}} ({{.TotalVersionCount}})</strong>
<a class="tw-float-right" href="{{$.PackageDescriptor.PackageWebLink}}/versions">{{ctx.Locale.Tr "packages.versions.view_all"}}</a>
<div class="ui relaxed list">
{{range .LatestVersions}}
<div class="item tw-flex">
<a class="tw-flex-1 gt-ellipsis" title="{{.Version}}" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
<span class="text small">{{DateUtils.AbsoluteShort .CreatedUnix}}</span>
</div>
{{end}}
</div>
{{if or .CanWritePackages .HasRepositoryAccess}}
<div class="divider"></div>
<div class="ui relaxed list flex-items-block">
{{if .HasRepositoryAccess}}
<div class="item">{{svg "octicon-issue-opened"}} <a href="{{.PackageDescriptor.Repository.Link}}/issues">{{ctx.Locale.Tr "repo.issues"}}</a></div>
{{end}}
{{if .CanWritePackages}}
<div class="item">{{svg "octicon-tools"}} <a href="{{.Link}}/settings">{{ctx.Locale.Tr "repo.settings"}}</a></div>
{{end}}
</div>
{{end}}
<div class="ui twelve wide column tw-mb-4">
{{template "user/overview/header" .}}
{{template "package/shared/view" .}}
</div>
</div>
</div>
</div>
{{end}}
{{template "base/footer" .}}