From cbbf9282b5dc47218caa4a2545a06a6eae069ebc Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Fri, 5 Nov 2021 10:01:32 +0800 Subject: [PATCH 01/27] add contributors route --- routers/repo/view.go | 120 +++++++++++++++++++++++++++------------ routers/routes/routes.go | 1 + templates/repo/contributors.tmpl | 6 ++ 3 files changed, 92 insertions(+), 35 deletions(-) mode change 100644 => 100755 routers/repo/view.go create mode 100755 templates/repo/contributors.tmpl diff --git a/routers/repo/view.go b/routers/repo/view.go old mode 100644 new mode 100755 index 9477b27dd..a8b2f239d --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -12,6 +12,7 @@ import ( "fmt" gotemplate "html/template" "io/ioutil" + "net/http" "net/url" "path" "strings" @@ -31,11 +32,12 @@ import ( ) const ( - tplRepoEMPTY base.TplName = "repo/empty" - tplRepoHome base.TplName = "repo/home" - tplWatchers base.TplName = "repo/watchers" - tplForks base.TplName = "repo/forks" - tplMigrating base.TplName = "repo/migrating" + tplRepoEMPTY base.TplName = "repo/empty" + tplRepoHome base.TplName = "repo/home" + tplWatchers base.TplName = "repo/watchers" + tplForks base.TplName = "repo/forks" + tplMigrating base.TplName = "repo/migrating" + tplContributors base.TplName = "repo/contributors" ) type namedBlob struct { @@ -570,19 +572,20 @@ func safeURL(address string) string { } type ContributorInfo struct { - UserInfo *models.User // nil for contributor who is not a registered user - Email string + UserInfo *models.User // nil for contributor who is not a registered user + Email string CommitCnt int } -func getContributorInfo(contributorInfos []*ContributorInfo, email string) *ContributorInfo{ +func getContributorInfo(contributorInfos []*ContributorInfo, email string) *ContributorInfo { for _, c := range contributorInfos { - if strings.Compare(c.Email,email) == 0 { + if strings.Compare(c.Email, email) == 0 { return c } } return nil } + // Home render repository home page func Home(ctx *context.Context) { if len(ctx.Repo.Units) > 0 { @@ -591,34 +594,34 @@ func Home(ctx *context.Context) { if err == nil && contributors != nil { startTime := time.Now() var contributorInfos []*ContributorInfo - contributorInfoHash:= make(map[string]*ContributorInfo) + contributorInfoHash := make(map[string]*ContributorInfo) for _, c := range contributors { - if strings.Compare(c.Email,"") == 0 { + if strings.Compare(c.Email, "") == 0 { continue } // get user info from committer email user, err := models.GetUserByActivateEmail(c.Email) if err == nil { // committer is system user, get info through user's primary email - if existedContributorInfo,ok:=contributorInfoHash[user.Email];ok { + if existedContributorInfo, ok := contributorInfoHash[user.Email]; ok { // existed: same primary email, different committer name existedContributorInfo.CommitCnt += c.CommitCnt - }else{ + } else { // new committer info var newContributor = &ContributorInfo{ - user, user.Email,c.CommitCnt, + user, user.Email, c.CommitCnt, } - contributorInfos = append(contributorInfos, newContributor ) + contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[user.Email] = newContributor } } else { // committer is not system user - if existedContributorInfo,ok:=contributorInfoHash[c.Email];ok { + if existedContributorInfo, ok := contributorInfoHash[c.Email]; ok { // existed: same primary email, different committer name existedContributorInfo.CommitCnt += c.CommitCnt - }else{ + } else { var newContributor = &ContributorInfo{ - user, c.Email,c.CommitCnt, + user, c.Email, c.CommitCnt, } contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[c.Email] = newContributor @@ -627,7 +630,7 @@ func Home(ctx *context.Context) { } ctx.Data["ContributorInfo"] = contributorInfos var duration = time.Since(startTime) - log.Info("getContributorInfo cost: %v seconds",duration.Seconds()) + log.Info("getContributorInfo cost: %v seconds", duration.Seconds()) } if ctx.Repo.Repository.IsBeingCreated() { task, err := models.GetMigratingTask(ctx.Repo.Repository.ID) @@ -694,13 +697,13 @@ func renderLicense(ctx *context.Context) { log.Error("failed to get license content: %v, err:%v", f, err) continue } - if bytes.Compare(buf,license) == 0 { - log.Info("got matched license:%v",f) + if bytes.Compare(buf, license) == 0 { + log.Info("got matched license:%v", f) ctx.Data["LICENSE"] = f return } } - log.Info("not found matched license,repo:%v",ctx.Repo.Repository.Name) + log.Info("not found matched license,repo:%v", ctx.Repo.Repository.Name) } func renderLanguageStats(ctx *context.Context) { @@ -801,31 +804,31 @@ func renderCode(ctx *context.Context) { baseGitRepo, err := git.OpenRepository(ctx.Repo.Repository.BaseRepo.RepoPath()) defer baseGitRepo.Close() if err != nil { - log.Error("error open baseRepo:%s",ctx.Repo.Repository.BaseRepo.RepoPath()) + log.Error("error open baseRepo:%s", ctx.Repo.Repository.BaseRepo.RepoPath()) ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error - }else{ - if _,error:= baseGitRepo.GetBranch(ctx.Repo.BranchName);error==nil{ + } else { + if _, error := baseGitRepo.GetBranch(ctx.Repo.BranchName); error == nil { //base repo has the same branch, then compare between current repo branch and base repo's branch - compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.BranchName - ctx.SetParams("*",compareUrl) + compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.BranchName + ctx.SetParams("*", compareUrl) ctx.Data["UpstreamSameBranchName"] = true - }else{ + } else { //else, compare between current repo branch and base repo's default branch - compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.Repository.BaseRepo.DefaultBranch - ctx.SetParams("*",compareUrl) + compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.Repository.BaseRepo.DefaultBranch + ctx.SetParams("*", compareUrl) ctx.Data["UpstreamSameBranchName"] = false } _, _, headGitRepo, compareInfo, _, _ := ParseCompareInfo(ctx) defer headGitRepo.Close() - if compareInfo!= nil { - if compareInfo.Commits!=nil { - log.Info("compareInfoCommits数量:%d",compareInfo.Commits.Len()) + if compareInfo != nil { + if compareInfo.Commits != nil { + log.Info("compareInfoCommits数量:%d", compareInfo.Commits.Len()) ctx.Data["FetchUpstreamCnt"] = compareInfo.Commits.Len() - }else{ + } else { log.Info("compareInfo nothing different") ctx.Data["FetchUpstreamCnt"] = 0 } - }else{ + } else { ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error } } @@ -893,3 +896,50 @@ func Forks(ctx *context.Context) { ctx.HTML(200, tplForks) } + +func Contributors(ctx *context.Context) { + //get repo contributors info + contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) + if err == nil && contributors != nil { + startTime := time.Now() + var contributorInfos []*ContributorInfo + contributorInfoHash := make(map[string]*ContributorInfo) + for _, c := range contributors { + if strings.Compare(c.Email, "") == 0 { + continue + } + // get user info from committer email + user, err := models.GetUserByActivateEmail(c.Email) + if err == nil { + // committer is system user, get info through user's primary email + if existedContributorInfo, ok := contributorInfoHash[user.Email]; ok { + // existed: same primary email, different committer name + existedContributorInfo.CommitCnt += c.CommitCnt + } else { + // new committer info + var newContributor = &ContributorInfo{ + user, user.Email, c.CommitCnt, + } + contributorInfos = append(contributorInfos, newContributor) + contributorInfoHash[user.Email] = newContributor + } + } else { + // committer is not system user + if existedContributorInfo, ok := contributorInfoHash[c.Email]; ok { + // existed: same primary email, different committer name + existedContributorInfo.CommitCnt += c.CommitCnt + } else { + var newContributor = &ContributorInfo{ + user, c.Email, c.CommitCnt, + } + contributorInfos = append(contributorInfos, newContributor) + contributorInfoHash[c.Email] = newContributor + } + } + } + ctx.Data["ContributorInfo"] = contributorInfos + var duration= time.Since(startTime) + log.Info("getContributorInfo cost: %v seconds", duration.Seconds()) + } + ctx.HTML(http.StatusOK, tplContributors) +} diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 7e7d0642a..c8dad85a2 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -789,6 +789,7 @@ func RegisterRoutes(m *macaron.Macaron) { // Grouping for those endpoints not requiring authentication m.Group("/:username/:reponame", func() { + m.Get("/contributors", repo.Contributors) m.Group("/milestone", func() { m.Get("/:id", repo.MilestoneIssuesAndPulls) }, reqRepoIssuesOrPullsReader, context.RepoRef()) diff --git a/templates/repo/contributors.tmpl b/templates/repo/contributors.tmpl new file mode 100755 index 000000000..235ebf23b --- /dev/null +++ b/templates/repo/contributors.tmpl @@ -0,0 +1,6 @@ +{{template "base/head" .}} +
+ {{template "repo/header" .}} + {{template "repo/user_cards" .}} +
+{{template "base/footer" .}} From c571409ecfdc50d50356706ffd68669353a6425f Mon Sep 17 00:00:00 2001 From: zhoupzh Date: Fri, 5 Nov 2021 16:37:00 +0800 Subject: [PATCH 02/27] fix issue --- options/locale/locale_en-US.ini | 1 + options/locale/locale_zh-CN.ini | 2 + templates/repo/contributors.tmpl | 97 ++++++++++++++++++++++++++++++++++++- templates/repo/home.tmpl | 12 ++--- web_src/js/features/letteravatar.js | 74 ++++++++++++++++++++++++++++ web_src/js/index.js | 2 +- 6 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 web_src/js/features/letteravatar.js diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 7fa8c7a4f..759583242 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -218,6 +218,7 @@ show_only_private = Showing only private show_only_public = Showing only public issues.in_your_repos = In your repositories +contributors = Contributors [explore] repos = Repositories diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 81b4a8459..b01626b2b 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -220,6 +220,8 @@ show_only_public=只显示公开的 issues.in_your_repos=属于该用户项目的 +contributors=贡献者 + [explore] repos=项目 users=用户 diff --git a/templates/repo/contributors.tmpl b/templates/repo/contributors.tmpl index 235ebf23b..4412c1942 100755 --- a/templates/repo/contributors.tmpl +++ b/templates/repo/contributors.tmpl @@ -1,6 +1,101 @@ {{template "base/head" .}} +
{{template "repo/header" .}} - {{template "repo/user_cards" .}} +
+ +
+

+ {{.i18n.Tr "home.contributors"}} ({{len .ContributorInfo}}) +

+
+ {{range .ContributorInfo}} +
+ {{if .UserInfo}} + + {{else if .Email}} + + {{end}} + +
+
+ {{if .UserInfo}} + {{.UserInfo.Name}} + {{else if .Email}} + {{.Email}} + {{end}} +
+ Commits: {{.CommitCnt}} +
+ +
+ + {{end}} + +
+ + {{template "base/paginate" .}} + +
+ + + +
{{template "base/footer" .}} diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl index 8648b8b59..cbba6f3ee 100644 --- a/templates/repo/home.tmpl +++ b/templates/repo/home.tmpl @@ -331,7 +331,7 @@

贡献者 ({{len .ContributorInfo}})

@@ -353,10 +353,10 @@
{{template "base/footer" .}} diff --git a/web_src/js/features/letteravatar.js b/web_src/js/features/letteravatar.js new file mode 100644 index 000000000..9ec12b60f --- /dev/null +++ b/web_src/js/features/letteravatar.js @@ -0,0 +1,74 @@ +/** + * LetterAvatar + * + * Artur Heinze + * Create Letter avatar based on Initials + * based on https://gist.github.com/leecrossley/6027780 + */ +(function(w, d){ + function LetterAvatar (name, size, color) { + name = name || ''; + size = size || 60; + var colours = [ + "#1abc9c", "#2ecc71", "#3498db", "#9b59b6", "#34495e", "#16a085", "#27ae60", "#2980b9", "#8e44ad", "#2c3e50", + "#f1c40f", "#e67e22", "#e74c3c", "#00bcd4", "#95a5a6", "#f39c12", "#d35400", "#c0392b", "#bdc3c7", "#7f8c8d" + ], + nameSplit = String(name).split(' '), + initials, charIndex, colourIndex, canvas, context, dataURI; + if (nameSplit.length == 1) { + initials = nameSplit[0] ? nameSplit[0].charAt(0):'?'; + } else { + initials = nameSplit[0].charAt(0) + nameSplit[1].charAt(0); + } + if (w.devicePixelRatio) { + size = (size * w.devicePixelRatio); + } + + charIndex = (initials == '?' ? 72 : initials.charCodeAt(0)) - 64; + colourIndex = charIndex % 20; + canvas = d.createElement('canvas'); + canvas.width = size; + canvas.height = size; + context = canvas.getContext("2d"); + + context.fillStyle = color ? color : colours[colourIndex - 1]; + context.fillRect (0, 0, canvas.width, canvas.height); + context.font = Math.round(canvas.width/2)+"px 'Microsoft Yahei'"; + context.textAlign = "center"; + context.fillStyle = "#FFF"; + context.fillText(initials, size / 2, size / 1.5); + dataURI = canvas.toDataURL(); + canvas = null; + return dataURI; + } + LetterAvatar.transform = function() { + Array.prototype.forEach.call(d.querySelectorAll('img[avatar]'), function(img, name, color) { + name = img.getAttribute('avatar'); + color = img.getAttribute('color'); + img.src = LetterAvatar(name, img.getAttribute('width'), color); + img.removeAttribute('avatar'); + img.setAttribute('alt', name); + }); + }; + // AMD support + if (typeof define === 'function' && define.amd) { + + define(function () { return LetterAvatar; }); + + // CommonJS and Node.js module support. + } else if (typeof exports !== 'undefined') { + + // Support Node.js specific `module.exports` (which can be a function) + if (typeof module != 'undefined' && module.exports) { + exports = module.exports = LetterAvatar; + } + // But always support CommonJS module 1.1.1 spec (`exports` cannot be a function) + exports.LetterAvatar = LetterAvatar; + } else { + + window.LetterAvatar = LetterAvatar; + d.addEventListener('DOMContentLoaded', function(event) { + LetterAvatar.transform(); + }); + } +})(window, document); \ No newline at end of file diff --git a/web_src/js/index.js b/web_src/js/index.js index 5c6ff188a..a117ee73d 100755 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -4,7 +4,7 @@ import './publicpath.js'; import './polyfills.js'; - +import './features/letteravatar.js' import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; From 3c4a436f310c3881af6b2a9dbc231356eb5cc20e Mon Sep 17 00:00:00 2001 From: zhoupzh Date: Fri, 5 Nov 2021 16:44:51 +0800 Subject: [PATCH 03/27] fix issue --- templates/repo/contributors.tmpl | 54 ---------------------------------------- web_src/less/openi.less | 42 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 54 deletions(-) diff --git a/templates/repo/contributors.tmpl b/templates/repo/contributors.tmpl index 4412c1942..a31ebb3d4 100755 --- a/templates/repo/contributors.tmpl +++ b/templates/repo/contributors.tmpl @@ -1,59 +1,5 @@ {{template "base/head" .}}
diff --git a/web_src/less/openi.less b/web_src/less/openi.less index 56234586e..9f59e678d 100644 --- a/web_src/less/openi.less +++ b/web_src/less/openi.less @@ -243,4 +243,46 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;} display: inline-block; width: 100%; } +.git-user-content{ + margin-bottom: 16px; + word-break: break-all; +} +.row.git-user-content .ui.avatar.s16.image { + width: 50px !important; + height: 50px !important; + vertical-align: middle; + border-radius: 500rem;} +.user-list-item { + padding: 0.3em 0px !important; + margin: 15px 0 !important; + width: 220px !important; +} +.row.git-user-content .content { + margin-left: 6px; + display: inline-block; + vertical-align: top !important; + overflow: hidden; +} +.row.git-user-content .content .header { + font-weight: bold; +} +.item.user-list-item .header { + line-height: 23px !important; + font-size: 16px !important; + text-overflow: ellipsis; + overflow: hidden; + width: 145px; + + white-space:nowrap; + +} +.item.user-list-item .header a { + color: #587284 !important; +} +.row.git-user-content .content .commit-btn { + margin-top: 6px; + float: left; + font-size: 11px; + color: #40485b !important; +} From 232bddf24e3d41c78ed86ba7e1bdb3418d447e89 Mon Sep 17 00:00:00 2001 From: zhoupzh Date: Fri, 5 Nov 2021 17:17:03 +0800 Subject: [PATCH 04/27] fix issue --- templates/repo/contributors.tmpl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/templates/repo/contributors.tmpl b/templates/repo/contributors.tmpl index a31ebb3d4..71b706331 100755 --- a/templates/repo/contributors.tmpl +++ b/templates/repo/contributors.tmpl @@ -8,7 +8,12 @@

- {{.i18n.Tr "home.contributors"}} ({{len .ContributorInfo}}) + +

{{range .ContributorInfo}} @@ -39,9 +44,6 @@ {{template "base/paginate" .}}
- - -
{{template "base/footer" .}} From 350b1d5229cc26e191d0bb04df95e2c338ee5a6b Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Mon, 8 Nov 2021 15:30:51 +0800 Subject: [PATCH 05/27] add contributors --- modules/setting/setting.go | 28 +++++++++++++++------------- routers/repo/view.go | 21 ++++++++++++++++++++- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/modules/setting/setting.go b/modules/setting/setting.go index abe406de8..2d469b638 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -163,6 +163,7 @@ var ( // UI settings UI = struct { ExplorePagingNum int + ContributorPagingNum int IssuePagingNum int RepoSearchPagingNum int MembersPagingNum int @@ -203,19 +204,20 @@ var ( Keywords string } `ini:"ui.meta"` }{ - ExplorePagingNum: 20, - IssuePagingNum: 10, - RepoSearchPagingNum: 10, - MembersPagingNum: 20, - FeedMaxCommitNum: 5, - GraphMaxCommitNum: 100, - CodeCommentLines: 4, - ReactionMaxUserNum: 10, - ThemeColorMetaTag: `#6cc644`, - MaxDisplayFileSize: 8388608, - DefaultTheme: `gitea`, - Themes: []string{`gitea`, `arc-green`}, - Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`}, + ExplorePagingNum: 20, + ContributorPagingNum: 50, + IssuePagingNum: 10, + RepoSearchPagingNum: 10, + MembersPagingNum: 20, + FeedMaxCommitNum: 5, + GraphMaxCommitNum: 100, + CodeCommentLines: 4, + ReactionMaxUserNum: 10, + ThemeColorMetaTag: `#6cc644`, + MaxDisplayFileSize: 8388608, + DefaultTheme: `gitea`, + Themes: []string{`gitea`, `arc-green`}, + Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`}, Notification: struct { MinTimeout time.Duration TimeoutStep time.Duration diff --git a/routers/repo/view.go b/routers/repo/view.go index a8b2f239d..cc33302e9 100755 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -898,13 +898,24 @@ func Forks(ctx *context.Context) { } func Contributors(ctx *context.Context) { + page := ctx.QueryInt("page") + if page <= 0 { + page = 1 + } + pageSize := setting.UI.ContributorPagingNum + start := (page-1) * pageSize + end := page * pageSize + count := 0 //get repo contributors info contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) if err == nil && contributors != nil { startTime := time.Now() var contributorInfos []*ContributorInfo contributorInfoHash := make(map[string]*ContributorInfo) - for _, c := range contributors { + for i, c := range contributors { + if i < start || i >= end { + continue + } if strings.Compare(c.Email, "") == 0 { continue } @@ -937,9 +948,17 @@ func Contributors(ctx *context.Context) { } } } + count ++ ctx.Data["ContributorInfo"] = contributorInfos var duration= time.Since(startTime) log.Info("getContributorInfo cost: %v seconds", duration.Seconds()) + } else { + ctx.ServerError("GetContributors failed", err) + return } + + pager := context.NewPagination(count, pageSize, page, 5) + ctx.Data["Page"] = pager + ctx.Data["Total"] = count ctx.HTML(http.StatusOK, tplContributors) } From b452434a782f161f91dc220f432fb84eb634123c Mon Sep 17 00:00:00 2001 From: zhoupzh Date: Mon, 8 Nov 2021 17:21:50 +0800 Subject: [PATCH 06/27] change show contributors nums --- templates/repo/home.tmpl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl index cbba6f3ee..34c3a3121 100644 --- a/templates/repo/home.tmpl +++ b/templates/repo/home.tmpl @@ -4,7 +4,7 @@ font-size: 1.0em; margin-bottom: 1.0rem; } -#contributorInfo > a:nth-child(n+25){ +#contributorInfo > a:nth-child(n+26){ display:none; } #contributorInfo > a{ @@ -329,7 +329,13 @@

+ {{$lenCon := len .ContributorInfo}} + {{if lt $lenCon 25 }} 贡献者 ({{len .ContributorInfo}}) + {{else}} + 贡献者 ({{len .ContributorInfo}}+) + {{end}} + From f277c5c8a8a11dbd6b5190ece11ff99842e49b32 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Mon, 8 Nov 2021 18:04:18 +0800 Subject: [PATCH 07/27] show --- routers/repo/view.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/routers/repo/view.go b/routers/repo/view.go index cc33302e9..e0439f6d9 100755 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -595,7 +595,11 @@ func Home(ctx *context.Context) { startTime := time.Now() var contributorInfos []*ContributorInfo contributorInfoHash := make(map[string]*ContributorInfo) + count := 0 for _, c := range contributors { + if count >= 25 { + continue + } if strings.Compare(c.Email, "") == 0 { continue } @@ -611,6 +615,7 @@ func Home(ctx *context.Context) { var newContributor = &ContributorInfo{ user, user.Email, c.CommitCnt, } + count++ contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[user.Email] = newContributor } @@ -623,6 +628,7 @@ func Home(ctx *context.Context) { var newContributor = &ContributorInfo{ user, c.Email, c.CommitCnt, } + count++ contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[c.Email] = newContributor } @@ -931,6 +937,7 @@ func Contributors(ctx *context.Context) { var newContributor = &ContributorInfo{ user, user.Email, c.CommitCnt, } + count ++ contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[user.Email] = newContributor } @@ -943,12 +950,12 @@ func Contributors(ctx *context.Context) { var newContributor = &ContributorInfo{ user, c.Email, c.CommitCnt, } + count ++ contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[c.Email] = newContributor } } } - count ++ ctx.Data["ContributorInfo"] = contributorInfos var duration= time.Since(startTime) log.Info("getContributorInfo cost: %v seconds", duration.Seconds()) From 7e5688866bb347dba13fe6feb470831ccc543dde Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Tue, 9 Nov 2021 10:55:17 +0800 Subject: [PATCH 08/27] fix bug --- modules/storage/obs.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/storage/obs.go b/modules/storage/obs.go index bd73281d0..8dbf37b76 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -178,6 +178,7 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { input := &obs.ListObjectsInput{} input.Bucket = setting.Bucket input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir), "/") + strPrefix := strings.Split(input.Prefix, "/") output, err := ObsCli.ListObjects(input) fileInfos := make([]FileInfo, 0) if err == nil { @@ -193,6 +194,10 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { continue } } else { + //files in next level dir + if len(str1) - len(strPrefix) > 1 { + continue + } fileName = str1[len(str1)-1] isDir = false } From 537c02ebacce89148906896d57afa911bc1989b7 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Tue, 9 Nov 2021 11:54:08 +0800 Subject: [PATCH 09/27] dirs --- modules/storage/obs.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/storage/obs.go b/modules/storage/obs.go index 8dbf37b76..8e72c03c4 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -187,10 +187,19 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { var isDir bool var fileName,nextParentDir string if strings.HasSuffix(val.Key, "/") { + //dirs in next level dir + if len(str1) - len(strPrefix) > 2 { + continue + } fileName = str1[len(str1)-2] isDir = true - nextParentDir = fileName - if fileName == parentDir || (fileName + "/") == setting.OutPutPath { + if parentDir == "" { + nextParentDir = fileName + } else { + nextParentDir = parentDir + "/" + fileName + } + + if fileName == strPrefix[len(strPrefix)-1] || (fileName + "/") == setting.OutPutPath { continue } } else { @@ -200,6 +209,7 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { } fileName = str1[len(str1)-1] isDir = false + nextParentDir = parentDir } fileInfo := FileInfo{ From 91145c8e049e99c227202fe42a654441fc029571 Mon Sep 17 00:00:00 2001 From: ychao_1983 Date: Tue, 9 Nov 2021 14:08:10 +0800 Subject: [PATCH 10/27] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E9=9D=9E=E5=8D=8F?= =?UTF-8?q?=E4=BD=9C=E8=80=85=E7=9A=84=E8=B4=A1=E7=8C=AE=E8=80=85=E6=9D=83?= =?UTF-8?q?=E9=99=90=E8=8E=B7=E5=8F=96=E4=B8=8D=E5=AF=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- models/repo_activity_custom.go | 5 ++++- routers/api/v1/repo/repo_dashbord.go | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/models/repo_activity_custom.go b/models/repo_activity_custom.go index 698436e2a..7cfed2359 100644 --- a/models/repo_activity_custom.go +++ b/models/repo_activity_custom.go @@ -11,7 +11,8 @@ import ( type ContributorWithUserId struct { git.Contributor - UserId int64 + UserId int64 + IsAdmin bool } func GetRepoKPIStats(repo *Repository) (*git.RepoKPIStats, error) { @@ -144,6 +145,7 @@ func GetTop10Contributor(repoPath string) ([]ContributorWithUserId, error) { contributorDistinctDict[user.Email] = ContributorWithUserId{ contributor, user.ID, + user.IsAdmin, } } else { @@ -156,6 +158,7 @@ func GetTop10Contributor(repoPath string) ([]ContributorWithUserId, error) { contributorDistinctDict[contributor.Email] = ContributorWithUserId{ contributor, -1, + false, } } else { value.CommitCnt += contributor.CommitCnt diff --git a/routers/api/v1/repo/repo_dashbord.go b/routers/api/v1/repo/repo_dashbord.go index d9be6d5a7..6759470fb 100644 --- a/routers/api/v1/repo/repo_dashbord.go +++ b/routers/api/v1/repo/repo_dashbord.go @@ -151,6 +151,15 @@ func GetProjectLatestStatistics(ctx *context.Context) { for _, contributor := range contributors { mode := repository.GetCollaboratorMode(contributor.UserId) + if mode == -1 { + if contributor.IsAdmin { + mode = int(models.AccessModeAdmin) + } + if contributor.UserId == repository.OwnerID { + mode = int(models.AccessModeOwner) + } + } + pr := models.GetPullCountByUserAndRepoId(repoIdInt, contributor.UserId) userInfo := UserInfo{ User: contributor.Committer, From fc4a173f1f611c8014f5148f78179b96add8d874 Mon Sep 17 00:00:00 2001 From: OpenIhu Date: Tue, 9 Nov 2021 15:41:35 +0800 Subject: [PATCH 11/27] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=8D=95=E7=8B=AC?= =?UTF-8?q?=E7=99=BE=E5=BA=A6=E7=BB=9F=E8=AE=A1=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/base/head.tmpl | 4 ++-- templates/base/head_home.tmpl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 24389d122..110200894 100755 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -180,8 +180,8 @@ var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); - hm.src = "https://hm.baidu.com/hm.js?7c4ef0a24be6109ab22e63c832ab21cf"; - var s = document.getElementsByTagName("script")[0]; + hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba"; + var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); diff --git a/templates/base/head_home.tmpl b/templates/base/head_home.tmpl index 69bf23f51..d1b2934ea 100644 --- a/templates/base/head_home.tmpl +++ b/templates/base/head_home.tmpl @@ -181,8 +181,8 @@ var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); - hm.src = "https://hm.baidu.com/hm.js?7c4ef0a24be6109ab22e63c832ab21cf"; - var s = document.getElementsByTagName("script")[0]; + hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba"; + var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); From f5a036274e555c69b1758e0a3a87ac5a783cc098 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Tue, 9 Nov 2021 19:49:18 +0800 Subject: [PATCH 12/27] contributor api --- routers/repo/view.go | 60 +++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/routers/repo/view.go b/routers/repo/view.go index 46665f860..cee9a1740 100755 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -578,8 +578,16 @@ func safeURL(address string) string { type ContributorInfo struct { UserInfo *models.User // nil for contributor who is not a registered user - Email string - CommitCnt int + UserName string `json:"user_name"` + Email string `json:"email"` + CommitCnt int `json:"commit_cnt"` +} + +type GetContributorsInfo struct { + ErrorCode int `json:"error_code"` + ErrorMsg string `json:"error_msg"` + Count int `json:"count"` + ContributorInfo []*ContributorInfo `json:"contributor_info"` } func getContributorInfo(contributorInfos []*ContributorInfo, email string) *ContributorInfo { @@ -618,7 +626,7 @@ func Home(ctx *context.Context) { } else { // new committer info var newContributor = &ContributorInfo{ - user, user.Email, c.CommitCnt, + user, user.Name, user.Email, c.CommitCnt, } count++ contributorInfos = append(contributorInfos, newContributor) @@ -631,7 +639,7 @@ func Home(ctx *context.Context) { existedContributorInfo.CommitCnt += c.CommitCnt } else { var newContributor = &ContributorInfo{ - user, c.Email, c.CommitCnt, + user, "", c.Email, c.CommitCnt, } count++ contributorInfos = append(contributorInfos, newContributor) @@ -909,24 +917,14 @@ func Forks(ctx *context.Context) { } func Contributors(ctx *context.Context) { - page := ctx.QueryInt("page") - if page <= 0 { - page = 1 - } - pageSize := setting.UI.ContributorPagingNum - start := (page-1) * pageSize - end := page * pageSize count := 0 - //get repo contributors info + errorCode := 0 + errorMsg := "" contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) + var contributorInfos []*ContributorInfo if err == nil && contributors != nil { - startTime := time.Now() - var contributorInfos []*ContributorInfo contributorInfoHash := make(map[string]*ContributorInfo) - for i, c := range contributors { - if i < start || i >= end { - continue - } + for _, c := range contributors { if strings.Compare(c.Email, "") == 0 { continue } @@ -940,9 +938,9 @@ func Contributors(ctx *context.Context) { } else { // new committer info var newContributor = &ContributorInfo{ - user, user.Email, c.CommitCnt, + user, user.Name, user.Email, c.CommitCnt, } - count ++ + count++ contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[user.Email] = newContributor } @@ -953,24 +951,24 @@ func Contributors(ctx *context.Context) { existedContributorInfo.CommitCnt += c.CommitCnt } else { var newContributor = &ContributorInfo{ - user, c.Email, c.CommitCnt, + user, "", c.Email, c.CommitCnt, } - count ++ + count++ contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[c.Email] = newContributor } } } - ctx.Data["ContributorInfo"] = contributorInfos - var duration= time.Since(startTime) - log.Info("getContributorInfo cost: %v seconds", duration.Seconds()) } else { - ctx.ServerError("GetContributors failed", err) - return + log.Error("GetContributors failed: %v", err) + errorCode = -1 + errorMsg = err.Error() } - pager := context.NewPagination(count, pageSize, page, 5) - ctx.Data["Page"] = pager - ctx.Data["Total"] = count - ctx.HTML(http.StatusOK, tplContributors) + ctx.JSON(http.StatusOK, GetContributorsInfo{ + ErrorCode: errorCode, + ErrorMsg: errorMsg, + Count: count, + ContributorInfo: contributorInfos, + }) } From 4ea524bc0685dd92c99211bd7394de15db284931 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Wed, 10 Nov 2021 09:53:20 +0800 Subject: [PATCH 13/27] add route --- routers/repo/view.go | 4 ++++ routers/routes/routes.go | 1 + 2 files changed, 5 insertions(+) diff --git a/routers/repo/view.go b/routers/repo/view.go index cee9a1740..3d1a8fc23 100755 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -917,6 +917,10 @@ func Forks(ctx *context.Context) { } func Contributors(ctx *context.Context) { + ctx.HTML(http.StatusOK, tplContributors) +} + +func ContributorsAPI(ctx *context.Context) { count := 0 errorCode := 0 errorMsg := "" diff --git a/routers/routes/routes.go b/routers/routes/routes.go index e2df14b26..07207959c 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -795,6 +795,7 @@ func RegisterRoutes(m *macaron.Macaron) { // Grouping for those endpoints not requiring authentication m.Group("/:username/:reponame", func() { m.Get("/contributors", repo.Contributors) + m.Get("/contributors/", repo.ContributorsAPI) m.Group("/milestone", func() { m.Get("/:id", repo.MilestoneIssuesAndPulls) }, reqRepoIssuesOrPullsReader, context.RepoRef()) From 1fe68bf63fd72c83c7f0733473956bdf0f855c26 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Wed, 10 Nov 2021 09:55:15 +0800 Subject: [PATCH 14/27] add route --- routers/routes/routes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 07207959c..db5039571 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -795,7 +795,7 @@ func RegisterRoutes(m *macaron.Macaron) { // Grouping for those endpoints not requiring authentication m.Group("/:username/:reponame", func() { m.Get("/contributors", repo.Contributors) - m.Get("/contributors/", repo.ContributorsAPI) + m.Get("/contributors/list", repo.ContributorsAPI) m.Group("/milestone", func() { m.Get("/:id", repo.MilestoneIssuesAndPulls) }, reqRepoIssuesOrPullsReader, context.RepoRef()) From 0999c02bb89bb52097e03850c1b239ea21fbf5e6 Mon Sep 17 00:00:00 2001 From: ychao_1983 Date: Wed, 10 Nov 2021 09:57:57 +0800 Subject: [PATCH 15/27] =?UTF-8?q?fork=E6=8C=87=E6=A0=87=E6=A5=BC=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routers/repo/repo_statistic.go | 1 + 1 file changed, 1 insertion(+) diff --git a/routers/repo/repo_statistic.go b/routers/repo/repo_statistic.go index 6dbdc1ca2..c1edb0fed 100755 --- a/routers/repo/repo_statistic.go +++ b/routers/repo/repo_statistic.go @@ -93,6 +93,7 @@ func RepoStatisticDaily(date string) { IsPrivate: repo.IsPrivate, NumWatches: int64(repo.NumWatches), NumStars: int64(repo.NumStars), + NumForks: int64(repo.NumForks), NumDownloads: repo.CloneCnt, NumComments: numComments, NumVisits: int64(numVisits), From 43200e0e67263a537b7e56d4214ee9408006a418 Mon Sep 17 00:00:00 2001 From: ychao_1983 Date: Wed, 10 Nov 2021 14:57:38 +0800 Subject: [PATCH 16/27] =?UTF-8?q?=E6=8F=90=E4=BE=9B=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C=E5=8D=87=E7=BA=A7=E5=90=8E=E6=81=A2=E5=A4=8Dfork?= =?UTF-8?q?=E6=8C=87=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- models/repo_statistic.go | 7 +++++++ routers/api/v1/api.go | 2 ++ routers/api/v1/repo/repo_dashbord.go | 13 +++++++++++++ 3 files changed, 22 insertions(+) diff --git a/models/repo_statistic.go b/models/repo_statistic.go index 9184ab4ec..df065bb79 100755 --- a/models/repo_statistic.go +++ b/models/repo_statistic.go @@ -158,6 +158,13 @@ func InsertRepoStat(repoStat *RepoStatistic) (int64, error) { return xStatistic.Insert(repoStat) } +func RestoreRepoStatFork(numForks int64, repoId int64) error { + sql := "update repo_statistic set num_forks=? where repo_id=?" + + _, err := xStatistic.Exec(sql, numForks, repoId) + return err +} + func UpdateRepoStat(repoStat *RepoStatistic) error { sql := "update repo_statistic set impact=?,completeness=?,liveness=?,project_health=?,team_health=?,growth=?,radar_total=? where repo_id=? and date=?" diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index dd744e933..8b068d612 100755 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -527,6 +527,8 @@ func RegisterRoutes(m *macaron.Macaron) { //Project board m.Group("/projectboard", func() { + m.Get("/restoreFork", adminReq, repo.RestoreForkNumber) + m.Group("/project", func() { m.Get("", adminReq, repo.GetAllProjectsPeriodStatistics) m.Group("/:id", func() { diff --git a/routers/api/v1/repo/repo_dashbord.go b/routers/api/v1/repo/repo_dashbord.go index 6759470fb..e48bda50d 100644 --- a/routers/api/v1/repo/repo_dashbord.go +++ b/routers/api/v1/repo/repo_dashbord.go @@ -50,6 +50,19 @@ type ProjectLatestData struct { Top10 []UserInfo `json:"top10"` } +func RestoreForkNumber(ctx *context.Context) { + repos, err := models.GetAllRepositories() + if err != nil { + log.Error("GetAllRepositories failed: %v", err.Error()) + return + } + for _, repo := range repos { + models.RestoreRepoStatFork(int64(repo.NumForks), repo.ID) + } + + ctx.JSON(http.StatusOK, struct{}{}) +} + func GetAllProjectsPeriodStatistics(ctx *context.Context) { recordBeginTime, err := getRecordBeginTime() From 7dd86b5e245a81ef57da87d6e3ee791befab9864 Mon Sep 17 00:00:00 2001 From: ychao_1983 Date: Wed, 10 Nov 2021 15:00:30 +0800 Subject: [PATCH 17/27] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=9C=8B=E6=9D=BF?= =?UTF-8?q?=E8=B5=B7=E5=A7=8B=E6=97=B6=E9=97=B4=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/setting/setting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting/setting.go b/modules/setting/setting.go index abe406de8..738284c8e 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -1325,7 +1325,7 @@ func SetRadarMapConfig() { RadarMap.GrowthContributors = sec.Key("growth_contributors").MustFloat64(0.2) RadarMap.GrowthCommit = sec.Key("growth_commit").MustFloat64(0.2) RadarMap.GrowthComments = sec.Key("growth_comments").MustFloat64(0.2) - RadarMap.RecordBeginTime = sec.Key("record_beigin_time").MustString("2021-11-04") + RadarMap.RecordBeginTime = sec.Key("record_beigin_time").MustString("2021-11-05") } From dbb75c168ee65e755d6a057abe887ed90fc5cbcd Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Wed, 10 Nov 2021 15:52:13 +0800 Subject: [PATCH 18/27] add avatar --- routers/repo/view.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/routers/repo/view.go b/routers/repo/view.go index 3d1a8fc23..cd59ec920 100755 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -578,6 +578,7 @@ func safeURL(address string) string { type ContributorInfo struct { UserInfo *models.User // nil for contributor who is not a registered user + RelAvatarLink string `json:"rel_avatar_link"` UserName string `json:"user_name"` Email string `json:"email"` CommitCnt int `json:"commit_cnt"` @@ -626,7 +627,7 @@ func Home(ctx *context.Context) { } else { // new committer info var newContributor = &ContributorInfo{ - user, user.Name, user.Email, c.CommitCnt, + user, user.RelAvatarLink(), user.Name, user.Email, c.CommitCnt, } count++ contributorInfos = append(contributorInfos, newContributor) @@ -639,7 +640,7 @@ func Home(ctx *context.Context) { existedContributorInfo.CommitCnt += c.CommitCnt } else { var newContributor = &ContributorInfo{ - user, "", c.Email, c.CommitCnt, + user, "", "",c.Email, c.CommitCnt, } count++ contributorInfos = append(contributorInfos, newContributor) @@ -942,7 +943,7 @@ func ContributorsAPI(ctx *context.Context) { } else { // new committer info var newContributor = &ContributorInfo{ - user, user.Name, user.Email, c.CommitCnt, + user, user.RelAvatarLink(),user.Name, user.Email,c.CommitCnt, } count++ contributorInfos = append(contributorInfos, newContributor) @@ -955,7 +956,7 @@ func ContributorsAPI(ctx *context.Context) { existedContributorInfo.CommitCnt += c.CommitCnt } else { var newContributor = &ContributorInfo{ - user, "", c.Email, c.CommitCnt, + user, "", "",c.Email,c.CommitCnt, } count++ contributorInfos = append(contributorInfos, newContributor) From bf6f0075781d9586d5644f7de85d6340bbd2804e Mon Sep 17 00:00:00 2001 From: ychao_1983 Date: Wed, 10 Nov 2021 16:37:35 +0800 Subject: [PATCH 19/27] =?UTF-8?q?=E7=BB=99=E5=89=8D=E7=AB=AF=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E6=80=BB=E8=AE=B0=E5=BD=95=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routers/api/v1/repo/repo_dashbord.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routers/api/v1/repo/repo_dashbord.go b/routers/api/v1/repo/repo_dashbord.go index e48bda50d..743f366e3 100644 --- a/routers/api/v1/repo/repo_dashbord.go +++ b/routers/api/v1/repo/repo_dashbord.go @@ -21,6 +21,7 @@ type ProjectsPeriodData struct { LastUpdatedTime string `json:"lastUpdatedTime"` PageSize int `json:"pageSize"` TotalPage int `json:"totalPage"` + TotalCount int64 `json:"totalCount"` PageRecords []*models.RepoStatistic `json:"pageRecords"` } @@ -107,6 +108,7 @@ func GetAllProjectsPeriodStatistics(ctx *context.Context) { RecordBeginTime: recordBeginTime.Format(DATE_FORMAT), PageSize: pageSize, TotalPage: getTotalPage(total, pageSize), + TotalCount: total, LastUpdatedTime: latestUpdatedTime, PageRecords: models.GetRepoStatisticByRawSql(generatePageSql(beginTime, endTime, latestDate, q, orderBy, page, pageSize)), } From 159d80f5d04ba07f64ed3a6a8169d4b756eabf80 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Wed, 10 Nov 2021 17:12:46 +0800 Subject: [PATCH 20/27] mod visiable count --- templates/org/home.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index ad5a8e02d..7e9970d2b 100755 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -39,7 +39,7 @@

{{.i18n.Tr "org.people"}} From 5a55552a6c74cc5dff8ff0cb825749c003400d47 Mon Sep 17 00:00:00 2001 From: zhoupzh Date: Wed, 10 Nov 2021 17:16:36 +0800 Subject: [PATCH 21/27] fix issue --- templates/repo/contributors.tmpl | 44 +------------ web_src/js/components/Contributors.vue | 109 +++++++++++++++++++++++++++++++++ web_src/js/index.js | 17 +++++ 3 files changed, 128 insertions(+), 42 deletions(-) create mode 100644 web_src/js/components/Contributors.vue diff --git a/templates/repo/contributors.tmpl b/templates/repo/contributors.tmpl index 71b706331..de00e7961 100755 --- a/templates/repo/contributors.tmpl +++ b/templates/repo/contributors.tmpl @@ -1,49 +1,9 @@ {{template "base/head" .}} -
{{template "repo/header" .}} -
+
+ -
-

- - -

-
- {{range .ContributorInfo}} -
- {{if .UserInfo}} - - {{else if .Email}} - - {{end}} - -
-
- {{if .UserInfo}} - {{.UserInfo.Name}} - {{else if .Email}} - {{.Email}} - {{end}} -
- Commits: {{.CommitCnt}} -
- -
- - {{end}} - -
- - {{template "base/paginate" .}} - -
{{template "base/footer" .}} diff --git a/web_src/js/components/Contributors.vue b/web_src/js/components/Contributors.vue new file mode 100644 index 000000000..2446e0bed --- /dev/null +++ b/web_src/js/components/Contributors.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/web_src/js/index.js b/web_src/js/index.js index a117ee73d..560683b7e 100755 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -37,6 +37,7 @@ import ObsUploader from './components/ObsUploader.vue'; import EditAboutInfo from './components/EditAboutInfo.vue'; import Images from './components/Images.vue' import EditTopics from './components/EditTopics.vue' +import Contributors from './components/Contributors.vue' Vue.use(ElementUI); Vue.prototype.$axios = axios; @@ -2969,6 +2970,7 @@ $(document).ready(async () => { initObsUploader(); initVueEditAbout(); initVueEditTopic(); + initVueContributors(); initVueImages(); initTeamSettings(); initCtrlEnterSubmit(); @@ -3682,6 +3684,21 @@ function initVueEditTopic() { render:h=>h(EditTopics) }) } + +function initVueContributors() { + const el = document.getElementById('Contributors'); + + if (!el) { + return; + } + + new Vue({ + el:'#Contributors', + render:h=>h(Contributors) + }) +} + + function initVueImages() { const el = document.getElementById('images'); console.log("el",el) From 61d46048b78fae96b888745fa4a80388f046636f Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Wed, 10 Nov 2021 17:26:06 +0800 Subject: [PATCH 22/27] creator visible --- models/org.go | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 models/org.go diff --git a/models/org.go b/models/org.go old mode 100644 new mode 100755 index 58afc5cb5..e8006d55f --- a/models/org.go +++ b/models/org.go @@ -182,6 +182,7 @@ func CreateOrganization(org, owner *User) (err error) { if _, err = sess.Insert(&OrgUser{ UID: owner.ID, OrgID: org.ID, + IsPublic: setting.Service.DefaultOrgMemberVisible, }); err != nil { return fmt.Errorf("insert org-user relation: %v", err) } From 56780e5d91fa8aa9858cd934da48aebb71fc2eb9 Mon Sep 17 00:00:00 2001 From: zouap Date: Wed, 10 Nov 2021 17:39:09 +0800 Subject: [PATCH 23/27] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=9C=8B=E6=9D=BF=E7=95=8C=E9=9D=A2=E6=9F=A5=E8=AF=A2=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=8F=8Agit=20clone=E4=B8=8B=E8=BD=BD=E6=AC=A1?= =?UTF-8?q?=E6=95=B0=E7=BA=A0=E6=AD=A3=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zouap --- models/repo.go | 23 ++++++++++++++++++++++- routers/repo/http.go | 6 ++++++ routers/repo/user_data_analysis.go | 14 ++++++++++++++ routers/routes/routes.go | 2 +- 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/models/repo.go b/models/repo.go index c8629875e..1a5cf122c 100755 --- a/models/repo.go +++ b/models/repo.go @@ -210,9 +210,12 @@ type Repository struct { Balance string `xorm:"NOT NULL DEFAULT '0'"` BlockChainStatus RepoBlockChainStatus `xorm:"NOT NULL DEFAULT 0"` - // git clone total count + // git clone and git pull total count CloneCnt int64 `xorm:"NOT NULL DEFAULT 0"` + // only git clone total count + GitCloneCnt int64 `xorm:"NOT NULL DEFAULT 0"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` @@ -2473,6 +2476,24 @@ func (repo *Repository) IncreaseCloneCnt() { return } +func (repo *Repository) IncreaseGitCloneCnt() { + sess := x.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + return + } + if _, err := sess.Exec("UPDATE `repository` SET git_clone_cnt = git_clone_cnt + 1 WHERE id = ?", repo.ID); err != nil { + return + } + + if err := sess.Commit(); err != nil { + return + } + + return +} + func UpdateRepositoryCommitNum(repo *Repository) error { if _, err := x.Exec("UPDATE `repository` SET num_commit = ? where id = ?", repo.NumCommit, repo.ID); err != nil { return err diff --git a/routers/repo/http.go b/routers/repo/http.go index ed6276466..ad2abf567 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -317,6 +317,12 @@ func HTTP(ctx *context.Context) { go repo.IncreaseCloneCnt() } + if ctx.Req.Method == "POST" { + if strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") { + go repo.IncreaseGitCloneCnt() + } + } + w := ctx.Resp r := ctx.Req.Request cfg := &serviceConfig{ diff --git a/routers/repo/user_data_analysis.go b/routers/repo/user_data_analysis.go index 7dc7af321..68cccd478 100755 --- a/routers/repo/user_data_analysis.go +++ b/routers/repo/user_data_analysis.go @@ -1,13 +1,27 @@ package repo import ( + "fmt" + "net/http" "time" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" ) +func QueryUserStaticData(ctx *context.Context) { + startDate := ctx.Query("startDate") + endDate := ctx.Query("endDate") + log.Info("startDate=" + startDate + " endDate=" + endDate) + startTime, _ := time.Parse("2006-01-02", startDate) + endTime, _ := time.Parse("2006-01-02", endDate) + log.Info("startTime=" + fmt.Sprint(startTime.Unix()) + " endDate=" + fmt.Sprint(endTime.Unix())) + ctx.JSON(http.StatusOK, models.QueryUserStaticData(startTime.Unix(), endTime.Unix())) + +} + func TimingCountDataByDate(date string) { t, _ := time.Parse("2006-01-02", date) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index a4b8f8aa1..9a416f264 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -791,7 +791,7 @@ func RegisterRoutes(m *macaron.Macaron) { }, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef()) m.Post("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action) - + m.Get("/tool/query_user_static", repo.QueryUserStaticData) // Grouping for those endpoints not requiring authentication m.Group("/:username/:reponame", func() { m.Group("/milestone", func() { From 89f618d53335b773dd2c60788d63e14ae38b315f Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Thu, 11 Nov 2021 09:55:55 +0800 Subject: [PATCH 24/27] fix time error --- modules/storage/obs.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/storage/obs.go b/modules/storage/obs.go index 8e72c03c4..a7ea8a91f 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -5,13 +5,12 @@ package storage import ( + "github.com/unknwon/com" "io" "path" "strconv" "strings" - "github.com/unknwon/com" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/obs" "code.gitea.io/gitea/modules/setting" @@ -213,7 +212,7 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { } fileInfo := FileInfo{ - ModTime: val.LastModified.Format("2006-01-02 15:04:05"), + ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"), FileName: fileName, Size: val.Size, IsDir:isDir, From c932eb3d4fc8e930b102426d0e05e4d420261523 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Thu, 11 Nov 2021 09:56:48 +0800 Subject: [PATCH 25/27] fix time error --- modules/storage/obs.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/storage/obs.go b/modules/storage/obs.go index a7ea8a91f..7c8f780ef 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -5,7 +5,6 @@ package storage import ( - "github.com/unknwon/com" "io" "path" "strconv" @@ -14,6 +13,8 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/obs" "code.gitea.io/gitea/modules/setting" + + "github.com/unknwon/com" ) type FileInfo struct { From e3a53f5a5dcc57ad12c8aef99887d882851b7bf0 Mon Sep 17 00:00:00 2001 From: lewis <747342561@qq.com> Date: Thu, 11 Nov 2021 09:58:21 +0800 Subject: [PATCH 26/27] fix time error --- modules/storage/obs.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/storage/obs.go b/modules/storage/obs.go index 7c8f780ef..239580adb 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -185,10 +185,10 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { for _, val := range output.Contents { str1 := strings.Split(val.Key, "/") var isDir bool - var fileName,nextParentDir string + var fileName, nextParentDir string if strings.HasSuffix(val.Key, "/") { //dirs in next level dir - if len(str1) - len(strPrefix) > 2 { + if len(str1)-len(strPrefix) > 2 { continue } fileName = str1[len(str1)-2] @@ -199,12 +199,12 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { nextParentDir = parentDir + "/" + fileName } - if fileName == strPrefix[len(strPrefix)-1] || (fileName + "/") == setting.OutPutPath { + if fileName == strPrefix[len(strPrefix)-1] || (fileName+"/") == setting.OutPutPath { continue } } else { //files in next level dir - if len(str1) - len(strPrefix) > 1 { + if len(str1)-len(strPrefix) > 1 { continue } fileName = str1[len(str1)-1] @@ -213,10 +213,10 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { } fileInfo := FileInfo{ - ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"), + ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"), FileName: fileName, - Size: val.Size, - IsDir:isDir, + Size: val.Size, + IsDir: isDir, ParenDir: nextParentDir, } fileInfos = append(fileInfos, fileInfo) @@ -257,7 +257,7 @@ func GetObsCreateSignedUrl(jobName, parentDir, fileName string) (string, error) input := &obs.CreateSignedUrlInput{} input.Bucket = setting.Bucket input.Key = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir, fileName), "/") - + input.Expires = 60 * 60 input.Method = obs.HttpMethodGet From a34f532107dc872efdbf24c76ac87cb061c7fb54 Mon Sep 17 00:00:00 2001 From: ychao_1983 Date: Thu, 11 Nov 2021 10:18:22 +0800 Subject: [PATCH 27/27] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=9C=8B=E6=9D=BF?= =?UTF-8?q?=E6=89=80=E6=9C=89=E5=91=A8=E6=9C=9F=E6=95=B0=E6=8D=AE=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E9=9A=8F=E7=9D=80=E7=BD=91=E7=AB=99=E5=8F=91=E5=B1=95?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=95=B0=E5=8F=AF=E8=83=BD=E5=BE=88=E5=A4=A7?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E4=B8=BA=E5=90=8E=E7=AB=AF=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/cron/tasks_basic.go | 12 ++++ modules/setting/setting.go | 2 + options/locale/locale_en-US.ini | 13 ++++ options/locale/locale_zh-CN.ini | 13 ++++ routers/api/v1/api.go | 1 + routers/api/v1/repo/repo_dashbord.go | 123 +++++++++++++++++++++++++++++++++++ 6 files changed, 164 insertions(+) diff --git a/modules/cron/tasks_basic.go b/modules/cron/tasks_basic.go index ed9829cef..eac081a8f 100755 --- a/modules/cron/tasks_basic.go +++ b/modules/cron/tasks_basic.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/migrations" repository_service "code.gitea.io/gitea/modules/repository" + api_repo "code.gitea.io/gitea/routers/api/v1/repo" "code.gitea.io/gitea/routers/repo" mirror_service "code.gitea.io/gitea/services/mirror" ) @@ -195,6 +196,17 @@ func registerHandleUserStatistic() { }) } +func registerHandleClearRepoStatisticFile() { + RegisterTaskFatal("handle_repo_clear_statistic_file", &BaseConfig{ + Enabled: true, + RunAtStart: false, + Schedule: "@daily", + }, func(ctx context.Context, _ *models.User, _ Config) error { + api_repo.ClearUnusedStatisticsFile() + return nil + }) +} + func initBasicTasks() { registerUpdateMirrorTask() registerRepoHealthCheck() diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 738284c8e..09d04b4f1 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -545,6 +545,7 @@ var ( GrowthCommit float64 GrowthComments float64 RecordBeginTime string + Path string }{} ) @@ -1326,6 +1327,7 @@ func SetRadarMapConfig() { RadarMap.GrowthCommit = sec.Key("growth_commit").MustFloat64(0.2) RadarMap.GrowthComments = sec.Key("growth_comments").MustFloat64(0.2) RadarMap.RecordBeginTime = sec.Key("record_beigin_time").MustString("2021-11-05") + RadarMap.Path = sec.Key("PATH").MustString("data/projectborad") } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index d29740037..fca4e2850 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2157,6 +2157,19 @@ repos.stars = Stars repos.forks = Forks repos.issues = Issues repos.size = Size +repos.id=ID +repos.projectName=Project Name +repos.isPrivate=Private +repos.openi=OpenI +repos.visit=Visit +repos.download=Code Download +repos.pr=PR +repos.commit=Commit +repos.closedIssues=Closed Issue +repos.contributor=Contributor +repos.yes=Yes +repos.no=No + datasets.dataset_manage_panel= Dataset Manage datasets.owner=Owner diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index bcc8a2ef6..614e8ad92 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -2159,6 +2159,19 @@ repos.stars=点赞数 repos.forks=派生数 repos.issues=任务数 repos.size=大小 +repos.id=ID +repos.projectName=项目名称 +repos.isPrivate=私有 +repos.openi=OpenI指数 +repos.visit=浏览量 +repos.download=代码下载量 +repos.pr=PR数 +repos.commit=Commit数 +repos.closedIssues=已解决任务数 +repos.contributor=贡献者数 +repos.yes=是 +repos.no=否 + datasets.dataset_manage_panel=数据集管理 datasets.owner=所有者 diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8b068d612..b2e701998 100755 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -531,6 +531,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/project", func() { m.Get("", adminReq, repo.GetAllProjectsPeriodStatistics) + m.Get("/download", adminReq, repo.ServeAllProjectsPeriodStatisticsFile) m.Group("/:id", func() { m.Get("", adminReq, repo.GetProjectLatestStatistics) m.Get("/period", adminReq, repo.GetProjectPeriodStatistics) diff --git a/routers/api/v1/repo/repo_dashbord.go b/routers/api/v1/repo/repo_dashbord.go index 743f366e3..4555d8a5c 100644 --- a/routers/api/v1/repo/repo_dashbord.go +++ b/routers/api/v1/repo/repo_dashbord.go @@ -1,8 +1,12 @@ package repo import ( + "encoding/csv" "fmt" + "io/ioutil" "net/http" + "os" + "path" "strconv" "time" @@ -117,6 +121,125 @@ func GetAllProjectsPeriodStatistics(ctx *context.Context) { } +func ServeAllProjectsPeriodStatisticsFile(ctx *context.Context) { + + recordBeginTime, err := getRecordBeginTime() + if err != nil { + log.Error("Can not get record begin time", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) + return + } + beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime) + if err != nil { + log.Error("Parameter is wrong", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong")) + return + } + q := ctx.QueryTrim("q") + page := ctx.QueryInt("page") + if page <= 0 { + page = 1 + } + pageSize := 1000 + orderBy := getOrderBy(ctx) + + _, latestDate, err := models.GetRepoStatLastUpdatedTime() + if err != nil { + log.Error("Can not query the last updated time.", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("repo.last_update_time_error")) + return + } + + countSql := generateCountSql(beginTime, endTime, latestDate, q) + total, err := models.CountRepoStatByRawSql(countSql) + if err != nil { + log.Error("Can not query total count.", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("repo.total_count_get_error")) + return + } + + fileName := getFileName(ctx, beginTime, endTime) + + if err := os.MkdirAll(setting.RadarMap.Path, os.ModePerm); err != nil { + ctx.Error(http.StatusBadRequest, fmt.Errorf("Failed to create dir %s: %v", setting.AvatarUploadPath, err).Error()) + } + + totalPage := getTotalPage(total, pageSize) + + f, e := os.Create(fileName) + defer f.Close() + if e != nil { + log.Warn("Failed to create file", e) + } + writer := csv.NewWriter(f) + writer.Write(allProjectsPeroidHeader(ctx)) + for i := 0; i <= totalPage; i++ { + + pageRecords := models.GetRepoStatisticByRawSql(generatePageSql(beginTime, endTime, latestDate, q, orderBy, i+1, pageSize)) + for _, record := range pageRecords { + e = writer.Write(allProjectsPeroidValues(record, ctx)) + if e != nil { + log.Warn("Failed to write record", e) + } + } + writer.Flush() + + } + + ctx.ServeFile(fileName) + +} + +func getFileName(ctx *context.Context, beginTime time.Time, endTime time.Time) string { + baseName := setting.RadarMap.Path + "/" + if ctx.QueryTrim("type") != "" { + baseName = baseName + ctx.QueryTrim("type") + "_" + } + if ctx.QueryTrim("q") != "" { + baseName = baseName + ctx.QueryTrim("q") + "_" + } + baseName = baseName + beginTime.Format(DATE_FORMAT) + "_to_" + endTime.Format(DATE_FORMAT) + "_" + strconv.FormatInt(time.Now().Unix(), 10) + ".csv" + return baseName +} + +func ClearUnusedStatisticsFile() { + fileInfos, err := ioutil.ReadDir(setting.RadarMap.Path) + if err != nil { + log.Warn("can not read dir: "+setting.RadarMap.Path, err) + return + } + + for _, fileInfo := range fileInfos { + if !fileInfo.IsDir() && fileInfo.ModTime().Before(time.Now().AddDate(0, 0, -1)) { + os.Remove(path.Join(setting.RadarMap.Path, fileInfo.Name())) + } + } + +} + +func allProjectsPeroidHeader(ctx *context.Context) []string { + + return []string{ctx.Tr("repos.id"), ctx.Tr("repos.projectName"), ctx.Tr("repos.isPrivate"), ctx.Tr("repos.openi"), ctx.Tr("repos.visit"), ctx.Tr("repos.download"), ctx.Tr("repos.pr"), ctx.Tr("repos.commit"), + ctx.Tr("repos.watches"), ctx.Tr("repos.stars"), ctx.Tr("repos.forks"), ctx.Tr("repos.issues"), ctx.Tr("repos.closedIssues"), ctx.Tr("repos.contributor")} + +} + +func allProjectsPeroidValues(rs *models.RepoStatistic, ctx *context.Context) []string { + return []string{strconv.FormatInt(rs.RepoID, 10), rs.Name, getIsPrivateDisplay(rs.IsPrivate, ctx), strconv.FormatFloat(rs.RadarTotal, 'f', 2, 64), + strconv.FormatInt(rs.NumVisits, 10), strconv.FormatInt(rs.NumDownloads, 10), strconv.FormatInt(rs.NumPulls, 10), strconv.FormatInt(rs.NumCommits, 10), + strconv.FormatInt(rs.NumWatches, 10), strconv.FormatInt(rs.NumStars, 10), strconv.FormatInt(rs.NumForks, 10), strconv.FormatInt(rs.NumIssues, 10), + strconv.FormatInt(rs.NumClosedIssues, 10), strconv.FormatInt(rs.NumContributor, 10), + } +} + +func getIsPrivateDisplay(private bool, ctx *context.Context) string { + if private { + return ctx.Tr("repos.yes") + } else { + return ctx.Tr("repos.no") + } +} + func GetProjectLatestStatistics(ctx *context.Context) { repoId := ctx.Params(":id") recordBeginTime, err := getRecordBeginTime()