0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-04-03 16:52:10 +02:00
This commit is contained in:
Lunny Xiao 2026-04-02 20:12:14 -07:00
parent e583e569f2
commit d425b436cd
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
9 changed files with 103 additions and 88 deletions

View File

@ -247,33 +247,6 @@ func UpdateColumn(ctx context.Context, column *Column) error {
return err
}
// GetColumns fetches all columns related to a project
func (p *Project) GetColumns(ctx context.Context) (ColumnList, error) {
columns := make([]*Column, 0, 5)
if err := db.GetEngine(ctx).Where("project_id=?", p.ID).OrderBy("sorting, id").Find(&columns); err != nil {
return nil, err
}
return columns, nil
}
// CountColumns returns the total number of columns for a project
func (p *Project) CountColumns(ctx context.Context) (int64, error) {
return db.GetEngine(ctx).Where("project_id=?", p.ID).Count(&Column{})
}
// GetColumnsPaginated fetches a page of columns for a project
func (p *Project) GetColumnsPaginated(ctx context.Context, opts db.ListOptions) (ColumnList, error) {
columns := make([]*Column, 0, opts.PageSize)
if err := db.SetSessionPagination(db.GetEngine(ctx), &opts).
Where("project_id=?", p.ID).
OrderBy("sorting, id").
Find(&columns); err != nil {
return nil, err
}
return columns, nil
}
// getDefaultColumnWithFallback return default column if one exists
// otherwise return the first column by sorting and set it as default column
func (p *Project) getDefaultColumnWithFallback(ctx context.Context) (*Column, error) {
@ -368,20 +341,6 @@ func UpdateColumnSorting(ctx context.Context, cl ColumnList) error {
})
}
func GetColumnsByIDs(ctx context.Context, projectID int64, columnsIDs []int64) (ColumnList, error) {
columns := make([]*Column, 0, 5)
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
}
// MoveColumnsOnProject sorts columns in a project
func MoveColumnsOnProject(ctx context.Context, project *Project, sortedColumnIDs map[int64]int64) error {
return db.WithTx(ctx, func(ctx context.Context) error {

View File

@ -0,0 +1,42 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package project
import (
"context"
"code.gitea.io/gitea/models/db"
)
// CountColumns 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
}
func GetColumnsByIDs(ctx context.Context, projectID int64, columnsIDs []int64) (ColumnList, error) {
columns := make([]*Column, 0, 5)
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
}

View File

@ -0,0 +1,49 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package project
import (
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
"github.com/stretchr/testify/assert"
)
func TestCountColumns(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
project, err := GetProjectByID(t.Context(), 1)
assert.NoError(t, err)
count, err := CountProjectColumns(t.Context(), project.ID)
assert.NoError(t, err)
assert.EqualValues(t, 3, count)
}
func TestGetColumnsPaginated(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
project, err := GetProjectByID(t.Context(), 1)
assert.NoError(t, err)
// Page 1, limit 2 — returns first 2 columns
page1, err := GetProjectColumns(t.Context(), project.ID, db.ListOptions{Page: 1, PageSize: 2})
assert.NoError(t, err)
assert.Len(t, page1, 2)
// Page 2, limit 2 — returns remaining column
page2, err := GetProjectColumns(t.Context(), project.ID, db.ListOptions{Page: 2, PageSize: 2})
assert.NoError(t, err)
assert.Len(t, page2, 1)
// Page 1 and page 2 together cover all columns with no overlap
allIDs := make(map[int64]bool)
for _, c := range append(page1, page2...) {
assert.False(t, allIDs[c.ID], "duplicate column ID %d across pages", c.ID)
allIDs[c.ID] = true
}
assert.Len(t, allIDs, 3)
}

View File

@ -80,7 +80,7 @@ func Test_MoveColumnsOnProject(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
project1 := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1})
columns, err := project1.GetColumns(t.Context())
columns, err := GetProjectColumns(t.Context(), project1.ID, db.ListOptionsAll)
assert.NoError(t, err)
assert.Len(t, columns, 3)
assert.EqualValues(t, 0, columns[0].Sorting) // even if there is no default sorting, the code should also work
@ -94,7 +94,7 @@ func Test_MoveColumnsOnProject(t *testing.T) {
})
assert.NoError(t, err)
columnsAfter, err := project1.GetColumns(t.Context())
columnsAfter, err := GetProjectColumns(t.Context(), project1.ID, db.ListOptionsAll)
assert.NoError(t, err)
assert.Len(t, columnsAfter, 3)
assert.Equal(t, columns[1].ID, columnsAfter[0].ID)
@ -106,7 +106,7 @@ func Test_NewColumn(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
project1 := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1})
columns, err := project1.GetColumns(t.Context())
columns, err := GetProjectColumns(t.Context(), project1.ID, db.ListOptionsAll)
assert.NoError(t, err)
assert.Len(t, columns, 3)
@ -124,39 +124,3 @@ func Test_NewColumn(t *testing.T) {
assert.Error(t, err)
assert.Contains(t, err.Error(), "maximum number of columns reached")
}
func TestCountColumns(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
project, err := GetProjectByID(t.Context(), 1)
assert.NoError(t, err)
count, err := project.CountColumns(t.Context())
assert.NoError(t, err)
assert.EqualValues(t, 3, count)
}
func TestGetColumnsPaginated(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
project, err := GetProjectByID(t.Context(), 1)
assert.NoError(t, err)
// Page 1, limit 2 — returns first 2 columns
page1, err := project.GetColumnsPaginated(t.Context(), db.ListOptions{Page: 1, PageSize: 2})
assert.NoError(t, err)
assert.Len(t, page1, 2)
// Page 2, limit 2 — returns remaining column
page2, err := project.GetColumnsPaginated(t.Context(), db.ListOptions{Page: 2, PageSize: 2})
assert.NoError(t, err)
assert.Len(t, page2, 1)
// Page 1 and page 2 together cover all columns with no overlap
allIDs := make(map[int64]bool)
for _, c := range append(page1, page2...) {
assert.False(t, allIDs[c.ID], "duplicate column ID %d across pages", c.ID)
allIDs[c.ID] = true
}
assert.Len(t, allIDs, 3)
}

View File

@ -385,14 +385,14 @@ func ListProjectColumns(ctx *context.APIContext) {
return
}
total, err := project.CountColumns(ctx)
total, err := project_model.CountProjectColumns(ctx, project.ID)
if err != nil {
ctx.APIErrorInternal(err)
return
}
listOptions := utils.GetListOptions(ctx)
columns, err := project.GetColumnsPaginated(ctx, listOptions)
columns, err := project_model.GetProjectColumns(ctx, project.ID, listOptions)
if err != nil {
ctx.APIErrorInternal(err)
return

View File

@ -318,7 +318,7 @@ func ViewProject(ctx *context.Context) {
return
}
columns, err := project.GetColumns(ctx)
columns, err := project_model.GetProjectColumns(ctx, project.ID, db.ListOptionsAll)
if err != nil {
ctx.ServerError("GetProjectColumns", err)
return

View File

@ -173,7 +173,7 @@ func (d *IssuePageMetaData) retrieveProjectData(ctx *context.Context) {
return
}
d.ProjectsData.SelectedProjectIDs = []int64{d.Issue.Project.ID}
columns, err := d.Issue.Project.GetColumns(ctx)
columns, err := project_model.GetProjectColumns(ctx, d.Issue.Project.ID, db.ListOptionsAll)
if err != nil {
ctx.ServerError("GetProjectColumns", err)
return

View File

@ -292,7 +292,7 @@ func ViewProject(ctx *context.Context) {
return
}
columns, err := project.GetColumns(ctx)
columns, err := project_model.GetProjectColumns(ctx, project.ID, db.ListOptionsAll)
if err != nil {
ctx.ServerError("GetProjectColumns", err)
return

View File

@ -9,6 +9,7 @@ import (
"strconv"
"testing"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
project_model "code.gitea.io/gitea/models/project"
repo_model "code.gitea.io/gitea/models/repo"
@ -59,7 +60,7 @@ func TestMoveRepoProjectColumns(t *testing.T) {
assert.NoError(t, err)
}
columns, err := project1.GetColumns(t.Context())
columns, err := project_model.GetProjectColumns(t.Context(), project1.ID, db.ListOptionsAll)
assert.NoError(t, err)
assert.Len(t, columns, 3)
assert.EqualValues(t, 0, columns[0].Sorting)
@ -79,7 +80,7 @@ func TestMoveRepoProjectColumns(t *testing.T) {
})
sess.MakeRequest(t, req, http.StatusOK)
columnsAfter, err := project1.GetColumns(t.Context())
columnsAfter, err := project_model.GetProjectColumns(t.Context(), project1.ID, db.ListOptionsAll)
assert.NoError(t, err)
assert.Len(t, columnsAfter, 3)
assert.Equal(t, columns[1].ID, columnsAfter[0].ID)
@ -189,7 +190,7 @@ func TestOrgProjectFilterByMilestone(t *testing.T) {
require.NoError(t, project_model.NewProject(t.Context(), &project))
// Get the default column
columns, err := project.GetColumns(t.Context())
columns, err := project_model.GetProjectColumns(t.Context(), project.ID, db.ListOptionsAll)
require.NoError(t, err)
require.NotEmpty(t, columns)
defaultColumnID := columns[0].ID