| @@ -1999,3 +1999,16 @@ func IsErrJobNotExist(err error) bool { | |||
| func (err ErrJobNotExist) Error() string { | |||
| return fmt.Sprintf("the job does not exist") | |||
| } | |||
| type ErrTagNotExist struct { | |||
| TagID int64 | |||
| } | |||
| func (err ErrTagNotExist) Error() string { | |||
| return fmt.Sprintf("the tag does not exist") | |||
| } | |||
| func IsErrTagNotExist(err error) bool { | |||
| _, ok := err.(ErrTagNotExist) | |||
| return ok | |||
| } | |||
| @@ -134,6 +134,8 @@ func init() { | |||
| new(BlockChain), | |||
| new(RecommendOrg), | |||
| new(AiModelManage), | |||
| new(OfficialTag), | |||
| new(OfficialTagRepos), | |||
| ) | |||
| tablesStatistic = append(tablesStatistic, | |||
| @@ -0,0 +1,107 @@ | |||
| package models | |||
| import ( | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "fmt" | |||
| ) | |||
| const DefaultOrgTagLimit = -1 | |||
| type OfficialTag struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| Name string `xorm:"NOT NULL"` | |||
| Limit int `xorm:"NOT NULL default(-1)"` | |||
| CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
| UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||
| } | |||
| type OfficialTagRepos struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| OrgID int64 `xorm:"NOT NULL INDEX"` | |||
| TagID int64 `xorm:"NOT NULL"` | |||
| RepoID int64 `xorm:"NOT NULL INDEX"` | |||
| CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
| UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||
| } | |||
| type TagReposBrief struct { | |||
| RepoID int64 | |||
| RepoName string | |||
| TagID int64 | |||
| } | |||
| type TagReposSelected struct { | |||
| RepoID int64 | |||
| RepoName string | |||
| Selected bool | |||
| } | |||
| func GetTagByID(id int64) (*OfficialTag, error) { | |||
| r := &OfficialTag{ | |||
| ID: id, | |||
| } | |||
| has, err := x.Get(r) | |||
| if err != nil { | |||
| return nil, err | |||
| } else if !has { | |||
| return nil, ErrTagNotExist{0} | |||
| } | |||
| return r, nil | |||
| } | |||
| func UpdateTagReposByID(tagID, orgID int64, repoIdList []int64) error { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| if err := sess.Begin(); err != nil { | |||
| return fmt.Errorf("UpdateTagReposByID[tagId: %d, orgID: %d,error:%v", tagID, orgID, err) | |||
| } | |||
| //delete old tag repos | |||
| r := &OfficialTagRepos{ | |||
| TagID: tagID, | |||
| OrgID: orgID, | |||
| } | |||
| _, err := sess.Delete(r) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| //add new tag repos | |||
| data := make([]*OfficialTagRepos, 0) | |||
| for _, repoId := range repoIdList { | |||
| data = append(data, &OfficialTagRepos{ | |||
| OrgID: orgID, | |||
| TagID: tagID, | |||
| RepoID: repoId, | |||
| }) | |||
| } | |||
| _, err = sess.Insert(&data) | |||
| if err != nil { | |||
| sess.Rollback() | |||
| return err | |||
| } | |||
| return sess.Commit() | |||
| } | |||
| func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | |||
| t := make([]TagReposBrief, 0) | |||
| const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false" | |||
| if err := x.SQL(SQLCmd, tagID, orgID).Find(&t); err != nil { | |||
| return nil, err | |||
| } | |||
| r := make([]TagReposSelected, 0) | |||
| for _, v := range t { | |||
| selected := false | |||
| if v.TagID > 0 { | |||
| selected = true | |||
| } | |||
| r = append(r, TagReposSelected{ | |||
| RepoID: v.RepoID, | |||
| RepoName: v.RepoName, | |||
| Selected: selected, | |||
| }) | |||
| } | |||
| return r, nil | |||
| } | |||
| @@ -70,3 +70,7 @@ type CreateTeamForm struct { | |||
| func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | |||
| return validate(errs, ctx.Data, f, ctx.Locale) | |||
| } | |||
| type SubmitReposOfTagForm struct { | |||
| RepoList []int64 | |||
| } | |||
| @@ -0,0 +1,98 @@ | |||
| // 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 org | |||
| import ( | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/context" | |||
| "errors" | |||
| "strconv" | |||
| ) | |||
| // SubmitTags submit repos of org tag | |||
| func SubmitTags(ctx *context.Context, form auth.SubmitReposOfTagForm) { | |||
| org, tag := getOrgAndTagFromContext(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| } | |||
| err := models.UpdateTagReposByID(tag.ID, org.ID, form.RepoList) | |||
| if err != nil { | |||
| ctx.ServerError("UpdateTagReposByID", err) | |||
| return | |||
| } | |||
| ctx.JSON(200, map[string]interface{}{ | |||
| "code": "00", | |||
| "msg": "success", | |||
| }) | |||
| } | |||
| // GetTagRepos get repos under org tag | |||
| func GetTagRepos(ctx *context.Context) { | |||
| org, tag := getOrgAndTagFromContext(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| } | |||
| r, err := models.GetTagRepos(tag.ID, org.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetTagRepos", err) | |||
| return | |||
| } | |||
| ctx.JSON(200, map[string]interface{}{ | |||
| "code": "00", | |||
| "msg": "success", | |||
| "data": r, | |||
| }) | |||
| } | |||
| // getDashboardContextUser finds out dashboard is viewing as which context user. | |||
| func getOrgAndTagFromContext(ctx *context.Context) (*models.User, *models.OfficialTag) { | |||
| var org *models.User | |||
| var tag *models.OfficialTag | |||
| var err error | |||
| orgName := ctx.Params(":org") | |||
| if len(orgName) > 0 { | |||
| // Organization. | |||
| org, err = models.GetUserByName(orgName) | |||
| if err != nil { | |||
| if models.IsErrUserNotExist(err) { | |||
| ctx.NotFound("GetUserByName", err) | |||
| } else { | |||
| ctx.ServerError("GetUserByName", err) | |||
| } | |||
| return nil, nil | |||
| } | |||
| if !org.IsOrganization() { | |||
| ctx.ServerError("GetUserByName", errors.New("it is not an organization")) | |||
| return nil, nil | |||
| } | |||
| } | |||
| tagIdStr := ctx.Query("tagId") | |||
| if len(tagIdStr) == 0 { | |||
| ctx.ServerError("GetTagInfo", errors.New("tag is not exist")) | |||
| return nil, nil | |||
| } | |||
| tagId, _ := strconv.ParseInt(tagIdStr, 10, 32) | |||
| tag, err = models.GetTagByID(tagId) | |||
| if err != nil { | |||
| if models.IsErrTagNotExist(err) { | |||
| ctx.NotFound("GetTagInfo", err) | |||
| } else { | |||
| ctx.ServerError("GetTagInfo", err) | |||
| } | |||
| return nil, nil | |||
| } | |||
| return org, tag | |||
| } | |||
| @@ -627,6 +627,10 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/org", func() { | |||
| m.Group("/:org", func() { | |||
| m.Get("/members", org.Members) | |||
| m.Group("/org_tag", func() { | |||
| m.Get("/repo_list", org.GetTagRepos) | |||
| m.Post("/repo_submit", bindIgnErr(auth.SubmitReposOfTagForm{}), org.SubmitTags) | |||
| }) | |||
| }, context.OrgAssignment()) | |||
| }) | |||
| m.Group("/org", func() { | |||