| @@ -192,6 +192,8 @@ type SearchRepoOptions struct { | |||
| // False -> include just no courses | |||
| Course util.OptionalBool | |||
| OnlySearchPrivate bool | |||
| RepoIds []int64 | |||
| } | |||
| //SearchOrderBy is used to sort the result | |||
| @@ -206,6 +208,7 @@ type FindReposResponse struct { | |||
| Page int | |||
| PageSize int | |||
| Total int64 | |||
| RepoIds []int64 | |||
| } | |||
| // Strings for sorting result | |||
| @@ -281,6 +284,33 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||
| if opts.StarredByID > 0 { | |||
| cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.StarredByID}))) | |||
| } | |||
| if len(opts.RepoIds) > 0 { | |||
| const MaxINItems = 1000 | |||
| if len(opts.RepoIds) <= MaxINItems { | |||
| cond = cond.And(builder.In("id", opts.RepoIds)) | |||
| } else { | |||
| repoIdsMap := make(map[int][]int64, 0) | |||
| i := 0 | |||
| for j := 0; j < len(opts.RepoIds); j++ { | |||
| if _, ok := repoIdsMap[i]; !ok { | |||
| repoIdsMap[i] = make([]int64, 0) | |||
| } | |||
| repoIdsMap[i] = append(repoIdsMap[i], opts.RepoIds[j]) | |||
| if (j+1)%MaxINItems == 0 { | |||
| i += 1 | |||
| } | |||
| } | |||
| subCond := builder.NewCond() | |||
| for _, repoSplit := range repoIdsMap { | |||
| subCond = subCond.Or(builder.In("id", repoSplit)) | |||
| } | |||
| cond = cond.And(subCond) | |||
| } | |||
| } | |||
| // Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate | |||
| if opts.OwnerID > 0 { | |||
| @@ -10,10 +10,11 @@ import ( | |||
| ) | |||
| const ( | |||
| TechHide = 1 | |||
| TechShow = 2 | |||
| TechShow = 1 | |||
| TechHide = 2 | |||
| TechMigrating = 3 | |||
| TechMigrateFailed = 4 | |||
| TechNotExist = 5 | |||
| ) | |||
| const DefaultTechApprovedStatus = TechShow | |||
| @@ -161,6 +162,16 @@ func GetProjectNames() []string { | |||
| x.Table("tech_converge_base_info").Distinct("project_name").Find(&names) | |||
| return names | |||
| } | |||
| func GetIdByProjectName(name string) []string { | |||
| var ids []int64 | |||
| x.Table("tech_converge_base_info").Cols("id").Where("project_name=?", name).Find(&ids) | |||
| idStrs := make([]string, 0, len(ids)) | |||
| for _, id := range ids { | |||
| idStrs = append(idStrs, strconv.FormatInt(id, 10)) | |||
| } | |||
| return idStrs | |||
| } | |||
| func GetSummitRepoIds() []int64 { | |||
| var ids []int64 | |||
| x.Table("repo_converge_info").Cols("repo_id").Find(&ids) | |||
| @@ -326,10 +337,37 @@ type TechRepoInfo struct { | |||
| Repos []*RepoWithInstitution | |||
| } | |||
| func SearchTechRepoInfo(opt SearchTechOpt) ([]*TechRepoInfo, int64, error) { | |||
| func GetAvailableRepoConvergeInfo(opt *SearchRepoOpt) ([]*RepoConvergeInfo, error) { | |||
| repos := make([]*RepoConvergeInfo, 0) | |||
| err := x.Table("repo_converge_info").Where(buildRepoFilterCond(opt)).Find(&repos) | |||
| return repos, err | |||
| } | |||
| func buildRepoFilterCond(opt *SearchRepoOpt) string { | |||
| sql := "" | |||
| if opt.Institution != "" { | |||
| sql += getPrefixWithoutWhere(sql) + " (institution like '%" + opt.Institution + ",%'" + " or institution like '%," + opt.Institution + "%'" + " or institution = '" + opt.Institution + "')" | |||
| } | |||
| if opt.ProjectName != "" { | |||
| baseInfoIds := GetIdByProjectName(opt.ProjectName) | |||
| if len(baseInfoIds) > 0 { | |||
| sql += getPrefixWithoutWhere(sql) + " id in (" + strings.Join(baseInfoIds, ",") + ")" | |||
| } | |||
| } | |||
| return sql | |||
| } | |||
| func SearchTechRepoInfo(opt *SearchTechOpt) ([]*TechRepoInfo, int64, error) { | |||
| sql := `select a.*,COALESCE(b.count,0) as repo_count, COALESCE(b.max,0) as max from tech_converge_base_info a left join | |||
| (select base_info_id,count(id),max(updated_unix) from repo_converge_info where status=2 GROUP BY base_info_id ) b | |||
| (select base_info_id,count(id),max(updated_unix) from repo_converge_info where status=` + strconv.Itoa(TechShow) + ` GROUP BY base_info_id ) b | |||
| on a.id=b.base_info_id` | |||
| totalSql := "select count(*) from (" + sql + ") c" + buildTechFilterCond(opt) | |||
| total, err := x.SQL(totalSql).Count(new(TechConvergeBaseInfo)) | |||
| @@ -363,7 +401,7 @@ func SearchTechRepoInfo(opt SearchTechOpt) ([]*TechRepoInfo, int64, error) { | |||
| } | |||
| func buildTechFilterCond(opt SearchTechOpt) string { | |||
| func buildTechFilterCond(opt *SearchTechOpt) string { | |||
| sql := "" | |||
| @@ -394,6 +432,13 @@ func getWherePrefix(sql string) string { | |||
| return " and " | |||
| } | |||
| func getPrefixWithoutWhere(sql string) string { | |||
| if sql == "" { | |||
| return "" | |||
| } | |||
| return " and " | |||
| } | |||
| func loadRepoInfoForTech(list []*TechRepoInfo) { | |||
| for _, techRepo := range list { | |||
| @@ -47,11 +47,38 @@ func GetFilterInfo(ctx *context.APIContext) { | |||
| func SearchRepoInfo(ctx *context.APIContext) { | |||
| opts := &models.SearchRepoOpt{} | |||
| opts.Q = ctx.Query("name") | |||
| opts.ProjectName = ctx.Query("tech_name") | |||
| opts.Topic = ctx.Query("topic") | |||
| opts.Institution = ctx.Query("institution_name") | |||
| page := ctx.QueryInt("page") | |||
| if page <= 0 { | |||
| page = 1 | |||
| } | |||
| opts.Page = page | |||
| pageSize := ctx.QueryInt("pageSize") | |||
| if pageSize <= 0 { | |||
| pageSize = 30 | |||
| } | |||
| opts.PageSize = pageSize | |||
| orderBy := ctx.Query("sort") | |||
| opts.OrderBy = orderBy | |||
| infos, total, err := techService.SearchRepoInfoWithInstitution(opts) | |||
| if err != nil { | |||
| log.Error("search has error", err) | |||
| ctx.JSON(http.StatusOK, map[string]interface { | |||
| }{"total": 0, "data": []*models.RepoWithInstitution{}}) | |||
| } else { | |||
| ctx.JSON(http.StatusOK, map[string]interface { | |||
| }{"total": total, "data": infos}) | |||
| } | |||
| } | |||
| func SearchTechProjectInfo(ctx *context.APIContext) { | |||
| opts := models.SearchTechOpt{} | |||
| opts := &models.SearchTechOpt{} | |||
| opts.Q = ctx.Query("name") | |||
| opts.ApplyYear = ctx.QueryInt("apply_year") | |||
| opts.ExecuteYear = ctx.QueryInt("execute_year") | |||
| @@ -67,7 +94,7 @@ func SearchTechProjectInfo(ctx *context.APIContext) { | |||
| pageSize = 15 | |||
| } | |||
| opts.PageSize = pageSize | |||
| orderBy := ctx.Query("orderBy") | |||
| orderBy := ctx.Query("sort") | |||
| if orderBy == "" || orderBy == "count" { | |||
| opts.OrderBy = "order by repo_count desc, max desc " | |||
| } else { | |||
| @@ -169,6 +169,7 @@ type FindReposOptions struct { | |||
| Topic string | |||
| Private bool | |||
| OwnerID int64 | |||
| RepoIds []int64 | |||
| } | |||
| func FindRepos(opts FindReposOptions) (*models.FindReposResponse, error) { | |||
| @@ -224,6 +225,7 @@ func FindRepos(opts FindReposOptions) (*models.FindReposResponse, error) { | |||
| AllLimited: true, | |||
| TopicName: opts.Topic, | |||
| IncludeDescription: setting.UI.SearchRepoDescription, | |||
| RepoIds: opts.RepoIds, | |||
| }) | |||
| if err != nil { | |||
| log.Error("FindRepos error when SearchRepository.%v", err) | |||
| @@ -1,6 +1,9 @@ | |||
| package tech | |||
| import "code.gitea.io/gitea/models" | |||
| import ( | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/services/repository" | |||
| ) | |||
| func FindTech(opt models.FindTechOpt) ([]*models.TechConvergeBrief, error) { | |||
| techList, err := models.FindTech(opt) | |||
| @@ -14,6 +17,55 @@ func FindTech(opt models.FindTechOpt) ([]*models.TechConvergeBrief, error) { | |||
| return r, nil | |||
| } | |||
| func SearchRepoInfoWithInstitution(opt *models.SearchRepoOpt) ([]*models.RepoWithInstitution, int64, error) { | |||
| infos, err := models.GetAvailableRepoConvergeInfo(opt) | |||
| if err != nil { | |||
| return nil, 0, err | |||
| } | |||
| repoIds, institutionMap := getRepoIdAndInstitutionMap(infos) | |||
| result, err := repository.FindRepos(repository.FindReposOptions{ | |||
| ListOptions: models.ListOptions{Page: opt.Page, PageSize: opt.PageSize}, | |||
| Sort: opt.OrderBy, | |||
| Keyword: opt.Q, | |||
| Topic: opt.Topic, | |||
| RepoIds: repoIds, | |||
| }) | |||
| if err != nil { | |||
| return nil, 0, err | |||
| } | |||
| repoResult := make([]*models.RepoWithInstitution, 0, len(result.Repos)) | |||
| for _, repo := range result.Repos { | |||
| repoResult = append(repoResult, &models.RepoWithInstitution{ | |||
| ID: repo.ID, | |||
| OwnerID: repo.OwnerID, | |||
| OwnerName: repo.OwnerName, | |||
| Name: repo.Name, | |||
| Topics: repo.Topics, | |||
| Description: repo.Description, | |||
| Institution: institutionMap[repo.ID], | |||
| UpdatedUnix: repo.UpdatedUnix, | |||
| }) | |||
| } | |||
| return repoResult, result.Total, nil | |||
| } | |||
| func getRepoIdAndInstitutionMap(infos []*models.RepoConvergeInfo) ([]int64, map[int64]string) { | |||
| repoIds := make([]int64, 0, len(infos)) | |||
| institutionMap := make(map[int64]string, 0) | |||
| // We only need the keys | |||
| for _, info := range infos { | |||
| repoIds = append(repoIds, info.RepoID) | |||
| institutionMap[info.RepoID] = info.Institution | |||
| } | |||
| return repoIds, institutionMap | |||
| } | |||
| func IsValidRepoConvergeExists(repoId, baseInfoId int64) (bool, error) { | |||
| list, err := models.GetRepoConverge(models.GetRepoConvergeOpts{ | |||
| Status: []int{models.TechHide, models.TechShow, models.TechMigrating}, | |||