From ff828442f35bb640e488856551a25e51c5c3d2b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=99=E2=97=A6=20The=20Tablet=20=E2=9D=80=20GamerGirla?= =?UTF-8?q?ndCo=20=E2=97=A6=E2=9D=A7?= Date: Tue, 12 Aug 2025 23:30:50 -0400 Subject: [PATCH] create new types for the frontend - `GroupItem`, an interface which describes items displayed in the group sidebar - `groupItemGroup` and `groupItemRepo`, two structs which implement `GroupItem` --- models/shared/group/group_item.go | 141 ++++++++++++++++++++++++++++++ models/shared/group/repo_item.go | 51 +++++++++++ 2 files changed, 192 insertions(+) create mode 100644 models/shared/group/group_item.go create mode 100644 models/shared/group/repo_item.go diff --git a/models/shared/group/group_item.go b/models/shared/group/group_item.go new file mode 100644 index 0000000000..a46ce91ab9 --- /dev/null +++ b/models/shared/group/group_item.go @@ -0,0 +1,141 @@ +package group + +import ( + "context" + "slices" + + "code.gitea.io/gitea/models/db" + group_model "code.gitea.io/gitea/models/group" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" + "xorm.io/builder" +) + +// GroupItem - represents an item in a group, either a repository or a subgroup. +// used to display, for example, the group sidebar +type GroupItem interface { + Link() string + Title() string + Parent() GroupItem + Children(doer *user_model.User) []GroupItem + Avatar(ctx context.Context) string + HasChildren(doer *user_model.User) bool + IsGroup() bool + ID() int64 + Sort() int +} + +type groupItemGroup struct { + Group *group_model.Group +} + +func (g *groupItemGroup) Link() string { + return g.Group.GroupLink() +} + +func (g *groupItemGroup) Title() string { + return g.Group.Name +} + +func (g *groupItemGroup) Parent() GroupItem { + if g.Group.ParentGroupID == 0 { + return nil + } + group, _ := group_model.GetGroupByID(db.DefaultContext, g.Group.ParentGroupID) + return &groupItemGroup{group} +} + +func (g *groupItemGroup) Children(doer *user_model.User) (items []GroupItem) { + repos := make([]*repo_model.Repository, 0) + sess := db.GetEngine(db.DefaultContext) + err := sess.Table("repository"). + Where("group_id = ?", g.Group.ID). + And(builder.In("id", repo_model.AccessibleRepoIDsQuery(doer))). + Find(&repos) + if err != nil { + log.Error("%w", err) + return make([]GroupItem, 0) + } + err = g.Group.LoadAccessibleSubgroups(db.DefaultContext, false, doer) + if err != nil { + return make([]GroupItem, 0) + } + slices.SortStableFunc(g.Group.Subgroups, func(a, b *group_model.Group) int { + return a.SortOrder - b.SortOrder + }) + slices.SortStableFunc(repos, func(a, b *repo_model.Repository) int { + return a.GroupSortOrder - b.GroupSortOrder + }) + for _, sg := range g.Group.Subgroups { + items = append(items, &groupItemGroup{sg}) + } + for _, r := range repos { + items = append(items, &groupItemRepo{r}) + } + return +} + +func (g *groupItemGroup) Avatar(ctx context.Context) string { + return g.Group.AvatarLink(ctx) +} + +func (g *groupItemGroup) HasChildren(doer *user_model.User) bool { + return len(g.Children(doer)) > 0 +} + +func (g *groupItemGroup) IsGroup() bool { + return true +} + +func (g *groupItemGroup) ID() int64 { + return g.Group.ID +} + +func (g *groupItemGroup) Sort() int { + return g.Group.SortOrder +} +func GetTopLevelGroupItemList(ctx context.Context, orgID int64, doer *user_model.User) (rootItems []GroupItem) { + groups, err := group_model.FindGroupsByCond(ctx, &group_model.FindGroupsOptions{ + ParentGroupID: 0, + ActorID: doer.ID, + OwnerID: orgID, + }, group_model. + AccessibleGroupCondition(doer, unit.TypeInvalid)) + if err != nil { + return + } + repos := make([]*repo_model.Repository, 0) + cond := builder.NewCond(). + Or(builder.Eq{"repository.group_id": 0}, builder.IsNull{"repository.group_id"}). + And(builder.Eq{"repository.owner_id": orgID}). + And(builder.In("repository.id", repo_model.AccessibleRepoIDsQuery(doer))) + sess := db.GetEngine(ctx) + err = sess.Table("repository").Where(cond).Find(&repos) + if err != nil { + return + } + slices.SortStableFunc(groups, func(a, b *group_model.Group) int { + return a.SortOrder - b.SortOrder + }) + slices.SortStableFunc(repos, func(a, b *repo_model.Repository) int { + return a.GroupSortOrder - b.GroupSortOrder + }) + for _, g := range groups { + rootItems = append(rootItems, &groupItemGroup{g}) + } + for _, r := range repos { + rootItems = append(rootItems, &groupItemRepo{r}) + } + return +} + +func GroupItemHasChild(it GroupItem, other int64, ctx context.Context, doer *user_model.User) bool { + for _, item := range it.Children(doer) { + if GroupItemHasChild(item, other, ctx, doer) { + return true + } + } + return it.ID() == other +} diff --git a/models/shared/group/repo_item.go b/models/shared/group/repo_item.go new file mode 100644 index 0000000000..ff67fca52f --- /dev/null +++ b/models/shared/group/repo_item.go @@ -0,0 +1,51 @@ +package group + +import ( + "code.gitea.io/gitea/models/db" + group_model "code.gitea.io/gitea/models/group" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "context" +) + +type groupItemRepo struct { + Repo *repo_model.Repository +} + +func (repo *groupItemRepo) Link() string { + return repo.Repo.Link() +} + +func (repo *groupItemRepo) Title() string { + return repo.Repo.Name +} + +func (repo *groupItemRepo) Parent() GroupItem { + if repo.Repo.GroupID == 0 { + return nil + } + group, _ := group_model.GetGroupByID(db.DefaultContext, repo.Repo.GroupID) + return &groupItemGroup{group} +} + +func (repo *groupItemRepo) Children(doer *user_model.User) []GroupItem { + return []GroupItem{} +} + +func (repo *groupItemRepo) Avatar(ctx context.Context) string { + return repo.Repo.AvatarLink(ctx) +} + +func (repo *groupItemRepo) IsGroup() bool { + return false +} + +func (repo *groupItemRepo) HasChildren(doer *user_model.User) bool { return false } + +func (repo *groupItemRepo) ID() int64 { + return repo.Repo.ID +} + +func (repo *groupItemRepo) Sort() int { + return repo.Repo.GroupSortOrder +}