2
0

feat: improve org overview - stats layout, repo icons, recent activity

- Rename Activity to Stats in sidebar with better flex layout
- Add repo avatars/icons to pinned repos (Featured Projects)
- Add Recent Activity section showing 10 most recently updated repos
- Show repo description, language, and time since update

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-11 02:51:34 +00:00
parent 6f39dc6651
commit 9bbdc44c2a
3 changed files with 89 additions and 23 deletions

View File

@@ -3815,5 +3815,7 @@
"user.pinned_repos_empty_desc": "Pin repositories to showcase your best work. Visit a repository and use the Pin dropdown.",
"settings.show_heatmap_on_profile": "Show activity heatmap on profile",
"settings.show_heatmap_on_profile_popup": "Display your contribution heatmap on your profile overview page",
"user.activity_heatmap": "Activity Heatmap"
"user.activity_heatmap": "Activity Heatmap",
"org.stats": "Stats",
"org.recent_activity": "Recent Activity"
}

View File

@@ -105,6 +105,23 @@ func home(ctx *context.Context, viewRepositories bool) {
ctx.Data["ShowMemberAndTeamTab"] = ctx.Org.IsMember || len(members) > 0
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
// Load recently updated repositories for activity section
recentRepos, _, err := repo_model.SearchRepository(ctx, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
PageSize: 10,
Page: 1,
},
OwnerID: org.ID,
OrderBy: db.SearchOrderByRecentUpdated,
Private: ctx.IsSigned,
Actor: ctx.Doer,
})
if err != nil {
log.Error("SearchRepository for recent repos: %v", err)
} else {
ctx.Data["RecentRepos"] = recentRepos
}
prepareResult, err := shared_user.RenderUserOrgHeader(ctx)
if err != nil {
ctx.ServerError("RenderUserOrgHeader", err)

View File

@@ -31,12 +31,16 @@
{{if .Repo}}
<a class="ui card" href="{{.Repo.Link}}">
<div class="content">
<div class="header text truncate">
{{if .Repo.IsPrivate}}{{svg "octicon-lock" 16}}{{else if .Repo.IsFork}}{{svg "octicon-repo-forked" 16}}{{else if .Repo.IsMirror}}{{svg "octicon-mirror" 16}}{{else}}{{svg "octicon-repo" 16}}{{end}}
{{.Repo.Name}}
<div class="header tw-flex tw-items-center tw-gap-2">
{{if .Repo.Avatar}}
<img class="tw-w-6 tw-h-6 tw-rounded" src="{{.Repo.RelAvatarLink}}" alt="">
{{else}}
{{if .Repo.IsPrivate}}{{svg "octicon-lock" 16}}{{else if .Repo.IsFork}}{{svg "octicon-repo-forked" 16}}{{else if .Repo.IsMirror}}{{svg "octicon-mirror" 16}}{{else}}{{svg "octicon-repo" 16}}{{end}}
{{end}}
<span class="text truncate">{{.Repo.Name}}</span>
</div>
{{if .Repo.Description}}
<div class="description text truncate">{{.Repo.Description}}</div>
<div class="description text truncate tw-mt-2">{{.Repo.Description}}</div>
{{end}}
</div>
<div class="extra content">
@@ -72,12 +76,16 @@
{{if .Repo}}
<a class="ui card" href="{{.Repo.Link}}">
<div class="content">
<div class="header text truncate">
{{if .Repo.IsPrivate}}{{svg "octicon-lock" 16}}{{else if .Repo.IsFork}}{{svg "octicon-repo-forked" 16}}{{else if .Repo.IsMirror}}{{svg "octicon-mirror" 16}}{{else}}{{svg "octicon-repo" 16}}{{end}}
{{.Repo.Name}}
<div class="header tw-flex tw-items-center tw-gap-2">
{{if .Repo.Avatar}}
<img class="tw-w-6 tw-h-6 tw-rounded" src="{{.Repo.RelAvatarLink}}" alt="">
{{else}}
{{if .Repo.IsPrivate}}{{svg "octicon-lock" 16}}{{else if .Repo.IsFork}}{{svg "octicon-repo-forked" 16}}{{else if .Repo.IsMirror}}{{svg "octicon-mirror" 16}}{{else}}{{svg "octicon-repo" 16}}{{end}}
{{end}}
<span class="text truncate">{{.Repo.Name}}</span>
</div>
{{if .Repo.Description}}
<div class="description text truncate">{{.Repo.Description}}</div>
<div class="description text truncate tw-mt-2">{{.Repo.Description}}</div>
{{end}}
</div>
<div class="extra content">
@@ -145,6 +153,45 @@
</div>
</div>
{{end}}
{{/* Recent Activity Section */}}
{{if .RecentRepos}}
<div class="ui segment tw-mt-4">
<h4 class="ui header tw-flex tw-items-center">
{{svg "octicon-pulse" 16}} {{ctx.Locale.Tr "org.recent_activity"}}
</h4>
<div class="ui relaxed divided list">
{{range .RecentRepos}}
<div class="item">
<div class="tw-flex tw-items-center tw-gap-3">
{{if .Avatar}}
<img class="tw-w-8 tw-h-8 tw-rounded" src="{{.RelAvatarLink}}" alt="">
{{else}}
<div class="tw-w-8 tw-h-8 tw-flex tw-items-center tw-justify-center">
{{if .IsPrivate}}{{svg "octicon-lock" 20}}{{else if .IsFork}}{{svg "octicon-repo-forked" 20}}{{else if .IsMirror}}{{svg "octicon-mirror" 20}}{{else}}{{svg "octicon-repo" 20}}{{end}}
</div>
{{end}}
<div class="tw-flex-1 tw-min-w-0">
<a href="{{.Link}}" class="tw-font-semibold">{{.Name}}</a>
{{if .Description}}
<p class="text grey tw-text-sm tw-truncate tw-mb-0">{{.Description}}</p>
{{end}}
</div>
<div class="tw-text-right tw-text-sm text grey tw-flex-shrink-0">
{{if .PrimaryLanguage}}
<span class="tw-mr-2">
<span class="repo-language-color" style="background-color: {{.PrimaryLanguage.Color}}"></span>
{{.PrimaryLanguage.Language}}
</span>
{{end}}
<span title="{{DateTime "full" .UpdatedUnix}}">{{TimeSince .UpdatedUnix ctx.Locale}}</span>
</div>
</div>
</div>
{{end}}
</div>
</div>
{{end}}
{{end}}
{{/* Repositories Tab Content */}}
@@ -190,25 +237,25 @@
{{/* Organization Stats - Sidebar Card */}}
{{if .OrgStats}}
<div class="ui top attached header tw-flex">
<strong class="tw-flex-1">{{svg "octicon-graph" 16}} {{ctx.Locale.Tr "org.activity"}}</strong>
<strong class="tw-flex-1">{{svg "octicon-graph" 16}} {{ctx.Locale.Tr "org.stats"}}</strong>
</div>
<div class="ui attached segment">
<div class="tw-grid tw-grid-cols-2 tw-gap-4 tw-text-center">
<div>
<div class="tw-text-2xl tw-font-bold">{{.OrgStats.TotalRepos}}</div>
<div class="text grey tw-text-sm">{{ctx.Locale.Tr "org.repositories"}}</div>
<div class="tw-flex tw-flex-wrap tw-justify-around tw-text-center">
<div class="tw-p-2">
<div class="tw-text-xl tw-font-bold">{{.OrgStats.TotalRepos}}</div>
<div class="text grey tw-text-xs">{{ctx.Locale.Tr "org.repositories"}}</div>
</div>
<div>
<div class="tw-text-2xl tw-font-bold">{{.OrgStats.TotalMembers}}</div>
<div class="text grey tw-text-sm">{{ctx.Locale.Tr "org.members"}}</div>
<div class="tw-p-2">
<div class="tw-text-xl tw-font-bold">{{.OrgStats.TotalMembers}}</div>
<div class="text grey tw-text-xs">{{ctx.Locale.Tr "org.members"}}</div>
</div>
<div>
<div class="tw-text-2xl tw-font-bold">{{.OrgStats.TotalTeams}}</div>
<div class="text grey tw-text-sm">{{ctx.Locale.Tr "org.teams"}}</div>
<div class="tw-p-2">
<div class="tw-text-xl tw-font-bold">{{.OrgStats.TotalTeams}}</div>
<div class="text grey tw-text-xs">{{ctx.Locale.Tr "org.teams"}}</div>
</div>
<div>
<div class="tw-text-2xl tw-font-bold">{{.OrgStats.TotalStars}}</div>
<div class="text grey tw-text-sm">{{ctx.Locale.Tr "repo.stars"}}</div>
<div class="tw-p-2">
<div class="tw-text-xl tw-font-bold">{{.OrgStats.TotalStars}}</div>
<div class="text grey tw-text-xs">{{ctx.Locale.Tr "repo.stars"}}</div>
</div>
</div>
</div>