{{.DescriptionHTML}}
{{end}} - {{if .Topics }} -diff --git a/models/models.go b/models/models.go index 67892399a..2fab3d0dc 100755 --- a/models/models.go +++ b/models/models.go @@ -129,6 +129,7 @@ func init() { new(Cloudbrain), new(FileChunk), new(BlockChain), + new(RecommendOrg), ) gonicNames := []string{"SSL", "UID"} diff --git a/models/recommend_org.go b/models/recommend_org.go new file mode 100755 index 000000000..6632f9aed --- /dev/null +++ b/models/recommend_org.go @@ -0,0 +1,65 @@ +package models + +import ( + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/timeutil" +) + +type RecommendOrg struct { + ID int64 `xorm:"pk autoincr"` + Order int64 `xorm:"INDEX NOT NULL unique"` + OrgID int64 `xorm:"INDEX NOT NULL unique"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` +} + +type RecommendOrgInfo struct { + RecommendOrg `xorm:"extends"` + User `xorm:"extends"` +} + +type RecommendOrgList []*RecommendOrg +type RecommendOrgInfoList []*RecommendOrgInfo + +func getRecommendOrgs(e Engine) (RecommendOrgList, error) { + orgs := make(RecommendOrgList, 0, 10) + err := e.Asc("order"). + Find(&orgs) + return orgs, err +} + +func GetRecommendOrgs() (RecommendOrgList, error) { + return getRecommendOrgs(x) +} + +func getRecommendOrgInfos(e Engine) (RecommendOrgInfoList, error) { + orgs := make(RecommendOrgInfoList, 0, 10) + if err := e.Table(&RecommendOrg{}).Join("INNER", "`user`", "`user`.id = `recommend_org`.org_id"). + OrderBy("recommend_org.order").Find(&orgs); err != nil { + return orgs, err + } + return orgs, nil +} + +func GetRecommendOrgInfos() (RecommendOrgInfoList, error) { + return getRecommendOrgInfos(x) +} + +func delRecommendOrgs(e Engine) error { + sql := "delete from recommend_org" + _, err := e.Exec(sql) + return err +} + +func UpdateRecommendOrgs(orgs RecommendOrgList) error { + if err := delRecommendOrgs(x); err != nil { + log.Error("delRecommendOrgs failed:%v", err.Error()) + return err + } + + if _, err := x.Insert(&orgs); err != nil { + log.Error("Insert failed:%v", err.Error()) + return err + } + + return nil +} diff --git a/models/repo.go b/models/repo.go index f4c396677..2742c3e31 100755 --- a/models/repo.go +++ b/models/repo.go @@ -175,6 +175,7 @@ type Repository struct { NumMilestones int `xorm:"NOT NULL DEFAULT 0"` NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"` NumOpenMilestones int `xorm:"-"` + NumCommit int64 `xorm:"NOT NULL DEFAULT 0"` IsPrivate bool `xorm:"INDEX"` IsEmpty bool `xorm:"INDEX"` @@ -213,6 +214,9 @@ type Repository struct { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` + + Hot int64 `xorm:"-"` + Active int64 `xorm:"-"` } // SanitizedOriginalURL returns a sanitized OriginalURL @@ -1411,6 +1415,15 @@ func GetRepositoriesByForkID(forkID int64) ([]*Repository, error) { return getRepositoriesByForkID(x, forkID) } +func getALLRepositories(e Engine) ([]*Repository, error) { + repos := make([]*Repository, 0, 1000) + return repos, e.Find(&repos) +} + +func GetAllRepositories() ([]*Repository, error) { + return getALLRepositories(x) +} + func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) { repo.LowerName = strings.ToLower(repo.Name) @@ -2413,6 +2426,7 @@ func updateRepositoryCols(e Engine, repo *Repository, cols ...string) error { } // UpdateRepositoryCols updates repository's columns +// Notice: it will update the updated_unix automatically, be careful to use this func UpdateRepositoryCols(repo *Repository, cols ...string) error { return updateRepositoryCols(x, repo, cols...) } @@ -2442,3 +2456,11 @@ func (repo *Repository) IncreaseCloneCnt() { 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 + } + + return nil +} diff --git a/models/repo_list.go b/models/repo_list.go index cbc67da54..57b6ebbd6 100755 --- a/models/repo_list.go +++ b/models/repo_list.go @@ -198,6 +198,8 @@ const ( SearchOrderByForks SearchOrderBy = "num_forks ASC" SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC" + SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC" + SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC" ) // SearchRepositoryCondition creates a query condition according search repository options diff --git a/modules/context/auth.go b/modules/context/auth.go index 6aee002b5..3f53e6fce 100755 --- a/modules/context/auth.go +++ b/modules/context/auth.go @@ -26,6 +26,7 @@ type ToggleOptions struct { AdminRequired bool DisableCSRF bool BasicAuthRequired bool + OperationRequired bool } // Toggle returns toggle options as middleware @@ -142,6 +143,15 @@ func Toggle(options *ToggleOptions) macaron.Handler { return } } + + if options.OperationRequired { + //todo: add isOperator judgement + if !ctx.User.IsAdmin { + ctx.Error(403) + return + } + ctx.Data["PageIsOperation"] = true + } } } diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 4a02056ed..fbee11b79 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -335,7 +335,7 @@ SSPIDefaultLanguage=默认语言 require_error=不能为空。 alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 -alpha_dash_dot_error=' 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 +alpha_dash_dot_error=应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 git_ref_name_error=` 必须是格式良好的 git 引用名称。` size_error=长度必须为 %s。 min_size_error=长度最小为 %s 个字符。 diff --git a/public/img/loading.png b/public/img/loading.png index c5ba3d9cd..ba7ae058e 100644 Binary files a/public/img/loading.png and b/public/img/loading.png differ diff --git a/public/img/org-baai@2x-80.jpg b/public/img/org-baai@2x-80.jpg new file mode 100644 index 000000000..9cefbcfb0 Binary files /dev/null and b/public/img/org-baai@2x-80.jpg differ diff --git a/public/img/org-engineclub@2x-80.jpg b/public/img/org-engineclub@2x-80.jpg new file mode 100644 index 000000000..3e81173d3 Binary files /dev/null and b/public/img/org-engineclub@2x-80.jpg differ diff --git a/public/img/org-modelzoo@2x-80.jpg b/public/img/org-modelzoo@2x-80.jpg new file mode 100644 index 000000000..da48266c5 Binary files /dev/null and b/public/img/org-modelzoo@2x-80.jpg differ diff --git a/public/img/org-openi@2x-80.jpg b/public/img/org-openi@2x-80.jpg new file mode 100644 index 000000000..3e0f8b6fe Binary files /dev/null and b/public/img/org-openi@2x-80.jpg differ diff --git a/public/img/org-platform@2x-80.jpg b/public/img/org-platform@2x-80.jpg new file mode 100644 index 000000000..809bd9edb Binary files /dev/null and b/public/img/org-platform@2x-80.jpg differ diff --git a/public/img/org-tensorlayer@2x-80.jpg b/public/img/org-tensorlayer@2x-80.jpg new file mode 100644 index 000000000..d82eda72d Binary files /dev/null and b/public/img/org-tensorlayer@2x-80.jpg differ diff --git a/routers/home.go b/routers/home.go index 2fc9db023..dcaba8d19 100755 --- a/routers/home.go +++ b/routers/home.go @@ -7,6 +7,7 @@ package routers import ( "bytes" + "net/http" "strings" "code.gitea.io/gitea/models" @@ -136,11 +137,17 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { orderBy = models.SearchOrderByForksReverse case "fewestforks": orderBy = models.SearchOrderByForks + case "hot": + orderBy = models.SearchOrderByHot + case "active": + orderBy = models.SearchOrderByActive + default: ctx.Data["SortType"] = "recentupdate" orderBy = models.SearchOrderByRecentUpdated } + //todo:support other topics keyword := strings.Trim(ctx.Query("q"), " ") topicOnly := ctx.QueryBool("topic") ctx.Data["TopicOnly"] = topicOnly @@ -164,6 +171,11 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { ctx.ServerError("SearchRepository", err) return } + + for _, repo := range repos { + repo.Hot = int64(repo.NumWatches) + int64(repo.NumStars) + int64(repo.NumForks) + int64(repo.CloneCnt) + repo.Active = int64(repo.NumIssues) + int64(repo.NumPulls) + int64(repo.NumCommit) + } ctx.Data["Keyword"] = keyword ctx.Data["Total"] = count ctx.Data["Repos"] = repos @@ -174,7 +186,15 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { pager.AddParam(ctx, "topic", "TopicOnly") ctx.Data["Page"] = pager - ctx.HTML(200, opts.TplName) + 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.HTML(http.StatusOK, opts.TplName) } // ExploreRepos render explore repositories page diff --git a/routers/operation/orgs.go b/routers/operation/orgs.go new file mode 100755 index 000000000..755c22172 --- /dev/null +++ b/routers/operation/orgs.go @@ -0,0 +1,64 @@ +// Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2020 The Gitea Authors. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package operation + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers" +) + +const ( + tplOrgs base.TplName = "admin/org/list" +) + +type UpdateRecommendOrgs struct { + OrgInfos string `binding:"required"` +} + +type OrgInfo struct { + OrgID int64 `json:"org_id"` + Order int64 `json:"order"` +} + +type OrgInfos struct { + OrgInfo []OrgInfo `json:"org_infos"` +} + +// Organizations show all the organizations recommended +func Organizations(ctx *context.Context) { + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminOrganizations"] = true + + routers.RenderUserSearch(ctx, &models.SearchUserOptions{ + Type: models.UserTypeOrganization, + ListOptions: models.ListOptions{ + PageSize: setting.UI.Admin.OrgPagingNum, + }, + Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, + }, tplOrgs) +} + +// UpdateRecommendOrganizations update the organizations recommended +func UpdateRecommendOrganizations(ctx *context.Context, req OrgInfos) { + orgs := make(models.RecommendOrgList, 0, 10) + for _, org := range req.OrgInfo { + orgs = append(orgs, &models.RecommendOrg{ + OrgID: org.OrgID, + Order: org.Order, + }) + } + + if err := models.UpdateRecommendOrgs(orgs); err != nil { + log.Error("UpdateRecommendOrgs failed:%v", err.Error(), ctx.Data["MsgID"]) + ctx.ServerError("UpdateRecommendOrgs failed", err) + return + } +} diff --git a/routers/private/cmd.go b/routers/private/cmd.go new file mode 100755 index 000000000..3c44ae697 --- /dev/null +++ b/routers/private/cmd.go @@ -0,0 +1,37 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package private + +import ( + "gitea.com/macaron/macaron" + "net/http" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" +) + +func UpdateAllRepoCommitCnt(ctx *macaron.Context) { + repos, err := models.GetAllRepositories() + if err != nil { + log.Error("GetAllRepositories failed:%v", err.Error(), ctx.Data["MsgID"]) + ctx.JSON(http.StatusInternalServerError, map[string]string{ + "error_msg": "GetAllRepositories failed", + }) + return + } + + for i, repo := range repos { + log.Info("%d:begin updateRepoCommitCnt(id = %d, name = %s)", i, repo.ID, repo.Name) + if err = updateRepoCommitCnt(ctx, repo); err != nil { + log.Error("updateRepoCommitCnt(id = %d, name = %s) failed:%v", repo.ID, repo.Name, err.Error(), ctx.Data["MsgID"]) + continue + } + log.Info("%d:finish updateRepoCommitCnt(id = %d, name = %s)", i, repo.ID, repo.Name) + } + + ctx.JSON(http.StatusOK, map[string]string{ + "error_msg": "", + }) +} diff --git a/routers/private/hook.go b/routers/private/hook.go old mode 100644 new mode 100755 index 4b57aff58..a673362fa --- a/routers/private/hook.go +++ b/routers/private/hook.go @@ -520,12 +520,40 @@ func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) { } } } + + if err := updateRepoCommitCnt(ctx, repo); err != nil { + log.Error("updateRepoCommitCnt failed:%v", err.Error(), ctx.Data["MsgID"]) + } + ctx.JSON(http.StatusOK, private.HookPostReceiveResult{ Results: results, RepoWasEmpty: wasEmpty, }) } +func updateRepoCommitCnt(ctx *macaron.Context, repo *models.Repository) error { + gitRepo, err := git.OpenRepository(repo.RepoPath()) + if err != nil { + log.Error("OpenRepository failed:%v", err.Error(), ctx.Data["MsgID"]) + return err + } + defer gitRepo.Close() + + count, err := gitRepo.GetAllCommitsCount() + if err != nil { + log.Error("GetAllCommitsCount failed:%v", err.Error(), ctx.Data["MsgID"]) + return err + } + + repo.NumCommit = count + if err = models.UpdateRepositoryCommitNum(repo); err != nil { + log.Error("UpdateRepositoryCommitNum failed:%v", err.Error(), ctx.Data["MsgID"]) + return err + } + + return nil +} + // SetDefaultBranch updates the default branch func SetDefaultBranch(ctx *macaron.Context) { ownerName := ctx.Params(":owner") diff --git a/routers/private/internal.go b/routers/private/internal.go old mode 100644 new mode 100755 index 5bc01b0ae..9d5f7b31c --- a/routers/private/internal.go +++ b/routers/private/internal.go @@ -42,6 +42,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/manager/shutdown", Shutdown) m.Post("/manager/restart", Restart) m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) + m.Post("/cmd/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) }, CheckInternalToken) } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 56c0c3237..892368315 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -6,6 +6,7 @@ package routes import ( "bytes" + "code.gitea.io/gitea/routers/operation" "encoding/gob" "net/http" "path" @@ -539,6 +540,15 @@ func RegisterRoutes(m *macaron.Macaron) { }, adminReq) // ***** END: Admin ***** + operationReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, OperationRequired: true}) + + // ***** START: Operation ***** + m.Group("/operation", func() { + m.Get("/config/recommend_org", operation.Organizations) + m.Post("/config/recommend_org", bindIgnErr(operation.OrgInfos{}), operation.UpdateRecommendOrganizations) + }, operationReq) + // ***** END: Operation ***** + m.Group("", func() { m.Get("/:username", user.Profile) }, ignSignIn) diff --git a/templates/explore/repo_left.tmpl b/templates/explore/repo_left.tmpl new file mode 100755 index 000000000..b9ff2ef20 --- /dev/null +++ b/templates/explore/repo_left.tmpl @@ -0,0 +1,83 @@ + + +
{{.DescriptionHTML}}
{{end}} - {{if .Topics }} -
\ No newline at end of file
+
+
+
+云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源;调试使用的数据集也需要上传到对应的环境。
云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源;调试使用的数据集也需要上传到对应的环境。