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:
@@ -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"
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user