Files

98 lines
2.9 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package project
import (
"context"
"strconv"
"code.gitea.io/gitea/models/db"
"xorm.io/builder"
)
// CountProjectColumns returns the total number of columns for a project
func CountProjectColumns(ctx context.Context, projectID int64) (int64, error) {
return db.GetEngine(ctx).Where("project_id=?", projectID).Count(&Column{})
}
// GetProjectColumns returns a list of columns for a project with pagination
func GetProjectColumns(ctx context.Context, projectID int64, opts db.ListOptions) (ColumnList, error) {
columns := make([]*Column, 0, opts.PageSize)
s := db.GetEngine(ctx).Where("project_id=?", projectID).OrderBy("sorting, id")
if !opts.IsListAll() {
db.SetSessionPagination(s, &opts)
}
if err := s.Find(&columns); err != nil {
return nil, err
}
return columns, nil
}
// LoadIssueCounts populates NumIssues, NumOpenIssues, and NumClosedIssues on
// every column in the list using two grouped queries against project_issue
// joined with issue. Columns with no attached issues stay at zero counts —
// nothing else has to be wired up by the caller.
func (cl ColumnList) LoadIssueCounts(ctx context.Context) error {
if len(cl) == 0 {
return nil
}
columnIDs := make([]int64, 0, len(cl))
for _, c := range cl {
columnIDs = append(columnIDs, c.ID)
}
openCounts, err := countColumnIssuesByState(ctx, columnIDs, false)
if err != nil {
return err
}
closedCounts, err := countColumnIssuesByState(ctx, columnIDs, true)
if err != nil {
return err
}
for _, c := range cl {
c.NumOpenIssues = openCounts[c.ID]
c.NumClosedIssues = closedCounts[c.ID]
c.NumIssues = c.NumOpenIssues + c.NumClosedIssues
}
return nil
}
func countColumnIssuesByState(ctx context.Context, columnIDs []int64, isClosed bool) (map[int64]int64, error) {
out := make(map[int64]int64, len(columnIDs))
cond := builder.In("project_issue.project_board_id", columnIDs).
And(builder.Eq{"issue.is_closed": isClosed})
sub := builder.Select("project_issue.project_board_id AS project_board_id", "COUNT(*) AS cnt").
From("project_issue").
InnerJoin("issue", "issue.id = project_issue.issue_id").
Where(cond).
GroupBy("project_issue.project_board_id")
rows, err := db.GetEngine(ctx).Query(sub)
if err != nil {
return nil, err
}
for _, r := range rows {
columnID, _ := strconv.ParseInt(string(r["project_board_id"]), 10, 64)
cnt, _ := strconv.ParseInt(string(r["cnt"]), 10, 64)
out[columnID] = cnt
}
return out, nil
}
func GetColumnsByIDs(ctx context.Context, projectID int64, columnsIDs []int64) (ColumnList, error) {
columns := make([]*Column, 0, len(columnsIDs))
if len(columnsIDs) == 0 {
return columns, nil
}
if err := db.GetEngine(ctx).
Where("project_id =?", projectID).
In("id", columnsIDs).
OrderBy("sorting").Find(&columns); err != nil {
return nil, err
}
return columns, nil
}