@@ -137,6 +137,7 @@ func init() { | |||
new(OfficialTag), | |||
new(OfficialTagRepos), | |||
new(WechatBindLog), | |||
new(OrgStatistic), | |||
) | |||
tablesStatistic = append(tablesStatistic, | |||
@@ -8,6 +8,7 @@ package models | |||
import ( | |||
"fmt" | |||
"os" | |||
"strconv" | |||
"strings" | |||
"code.gitea.io/gitea/modules/log" | |||
@@ -19,6 +20,17 @@ import ( | |||
"xorm.io/xorm" | |||
) | |||
type OrgStatistic struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
OrgID int64 `xorm:"UNIQUE"` | |||
NumScore int `xorm:"INDEX NOT NULL DEFAULT 0"` | |||
} | |||
type OrgScore struct { | |||
*User | |||
Score string | |||
} | |||
// IsOwnedBy returns true if given user is in the owner team. | |||
func (org *User) IsOwnedBy(uid int64) (bool, error) { | |||
return IsOrganizationOwner(org.ID, uid) | |||
@@ -135,6 +147,93 @@ func (org *User) RemoveOrgRepo(repoID int64) error { | |||
return org.removeOrgRepo(x, repoID) | |||
} | |||
func UpdateOrgStatistics() { | |||
ids, err := GetOrganizationsId() | |||
if err != nil { | |||
return | |||
} | |||
for _, id := range ids { | |||
org := User{ID: id} | |||
orgStat := &OrgStatistic{OrgID: id} | |||
numScore, err := org.getOrgStatistics() | |||
if err == nil { | |||
has, _ := x.Get(orgStat) | |||
orgStat.NumScore = numScore | |||
if has { | |||
x.ID(orgStat.ID).Cols("num_score").Update(&orgStat) | |||
} else { | |||
x.Insert(orgStat) | |||
} | |||
} | |||
} | |||
} | |||
func (org *User) getOrgStatistics() (int, error) { | |||
count, err := getRepositoryCount(x, org) | |||
if err != nil { | |||
return 0, err | |||
} | |||
err = org.GetRepositories(ListOptions{int(count), 1}) | |||
if err != nil { | |||
return 0, err | |||
} | |||
var numScore = 0 | |||
for _, repo := range org.Repos { | |||
numScore += int(getOpenIByRepoId(repo.ID)) | |||
} | |||
return numScore, nil | |||
} | |||
func FindTopNStarsOrgs(n int) ([]*OrgScore, error) { | |||
sql := "select a.id,sum(b.num_stars) score from \"user\" a ,repository b where a.id=b.owner_id and a.type=1 group by a.id order by score desc limit " + strconv.Itoa(n) | |||
return findTopNOrgs(sql) | |||
} | |||
func FindTopNMembersOrgs(n int) ([]*OrgScore, error) { | |||
sql := "select id, count(user_id) score from" + | |||
" (select org_id as id, uid as user_id from org_user " + | |||
"union select a.id,b.user_id from \"user\" a,collaboration b,repository c " + | |||
"where a.type=1 and a.id=c.owner_id and b.repo_id=c.id) d " + | |||
"group by id order by score desc limit " + strconv.Itoa(n) | |||
return findTopNOrgs(sql) | |||
} | |||
func FindTopNOpenIOrgs(n int) ([]*OrgScore, error) { | |||
sql := "select org_id id,num_score score from org_statistic order by num_score desc limit 10" + strconv.Itoa(n) | |||
return findTopNOrgs(sql) | |||
} | |||
func findTopNOrgs(sql string) ([]*OrgScore, error) { | |||
resutls, err := x.QueryString(sql) | |||
if err != nil { | |||
return nil, err | |||
} | |||
var orgScore []*OrgScore | |||
for _, record := range resutls { | |||
id, _ := strconv.ParseInt(record["id"], 10, 64) | |||
user, err := getUserByID(x, id) | |||
if err != nil { | |||
continue | |||
} | |||
orgScore = append(orgScore, &OrgScore{user, record["score"]}) | |||
} | |||
return orgScore, nil | |||
} | |||
// CreateOrganization creates record of a new organization. | |||
func CreateOrganization(org, owner *User) (err error) { | |||
if !owner.CanCreateOrganization() { | |||
@@ -73,6 +73,16 @@ func (repo *RepoStatistic) DisplayName() string { | |||
return repo.Alias | |||
} | |||
func getOpenIByRepoId(repoId int64) float64 { | |||
repoStatistic := new(RepoStatistic) | |||
has, err := xStatistic.Cols("radar_total").Where("repo_id=?", repoId).Desc("id").Limit(1).Get(repoStatistic) | |||
if !has || err != nil { | |||
return 0 | |||
} | |||
return repoStatistic.RadarTotal | |||
} | |||
func DeleteRepoStatDaily(date string) error { | |||
sess := xStatistic.NewSession() | |||
defer sess.Close() | |||
@@ -185,6 +185,17 @@ func registerHandleSummaryStatistic() { | |||
}) | |||
} | |||
func registerHandleOrgStatistic() { | |||
RegisterTaskFatal("handle_org_statistic", &BaseConfig{ | |||
Enabled: true, | |||
RunAtStart: false, | |||
Schedule: "0 0 2 * * ?", | |||
}, func(ctx context.Context, _ *models.User, _ Config) error { | |||
models.UpdateOrgStatistics() | |||
return nil | |||
}) | |||
} | |||
func registerSyncCloudbrainStatus() { | |||
RegisterTaskFatal("sync_cloudbrain_status", &BaseConfig{ | |||
Enabled: true, | |||
@@ -215,4 +226,5 @@ func initBasicTasks() { | |||
registerHandleSummaryStatistic() | |||
registerSyncCloudbrainStatus() | |||
registerHandleOrgStatistic() | |||
} |
@@ -418,17 +418,38 @@ func ExploreOrganizations(ctx *context.Context) { | |||
ctx.Data["PageIsExploreOrganizations"] = true | |||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | |||
visibleTypes := []structs.VisibleType{structs.VisibleTypePublic} | |||
if ctx.User != nil { | |||
visibleTypes = append(visibleTypes, structs.VisibleTypeLimited, structs.VisibleTypePrivate) | |||
N := 10 | |||
starInfo, err := models.FindTopNStarsOrgs(N) | |||
if err != nil { | |||
log.Error("GetStarOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
ctx.ServerError("GetStarOrgInfos", err) | |||
return | |||
} | |||
memberInfo, err := models.FindTopNMembersOrgs(N) | |||
if err != nil { | |||
log.Error("GetMemberOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
ctx.ServerError("GetMemberOrgInfos", err) | |||
return | |||
} | |||
openIInfo, err := models.FindTopNOpenIOrgs(N) | |||
if err != nil { | |||
log.Error("GetOpenIOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
ctx.ServerError("GetOpenIOrgInfos", err) | |||
return | |||
} | |||
RenderUserSearch(ctx, &models.SearchUserOptions{ | |||
Actor: ctx.User, | |||
Type: models.UserTypeOrganization, | |||
ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum}, | |||
Visible: visibleTypes, | |||
}, tplExploreOrganizations) | |||
recommendOrgs, err := models.GetRecommendOrgInfos() | |||
if err != nil { | |||
log.Error("GetRecommendOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
ctx.ServerError("GetRecommendOrgInfos", err) | |||
return | |||
} | |||
ctx.Data["RecommendOrgs"] = recommendOrgs | |||
ctx.Data["StarOrgs"] = starInfo | |||
ctx.Data["MemberOrgs"] = memberInfo | |||
ctx.Data["ActiveOrgs"] = openIInfo | |||
ctx.HTML(http.StatusOK, tplExploreOrganizations) | |||
} | |||
// ExploreCode render explore code page | |||
@@ -44,6 +44,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) | |||
m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | |||
m.Post("/tool/repo_stat/:date", RepoStatisticManually) | |||
m.Get("/tool/org_stat", OrgStatisticManually) | |||
m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit) | |||
}, CheckInternalToken) | |||
@@ -45,6 +45,10 @@ func RepoStatisticManually(ctx *macaron.Context) { | |||
repo.TimingCountDataByDate(date) | |||
} | |||
func OrgStatisticManually() { | |||
models.UpdateOrgStatistics() | |||
} | |||
func UpdateRepoVisit(ctx *macaron.Context) { | |||
date := ctx.Params("date") | |||
log.Info("date(%s)", date) | |||