diff --git a/models/project/column.go b/models/project/column.go index 3afa2bfba6..31f541ae8b 100644 --- a/models/project/column.go +++ b/models/project/column.go @@ -265,9 +265,9 @@ func (p *Project) CountColumns(ctx context.Context) (int64, error) { // 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.GetEngine(ctx).Where("project_id=?", p.ID). + if err := db.SetSessionPagination(db.GetEngine(ctx), &opts). + Where("project_id=?", p.ID). OrderBy("sorting, id"). - Limit(opts.PageSize, (opts.Page-1)*opts.PageSize). Find(&columns); err != nil { return nil, err } diff --git a/models/project/column_test.go b/models/project/column_test.go index 948e012c62..0a07943fe1 100644 --- a/models/project/column_test.go +++ b/models/project/column_test.go @@ -7,6 +7,7 @@ import ( "fmt" "testing" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" @@ -123,3 +124,39 @@ 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) +} diff --git a/routers/api/v1/repo/project.go b/routers/api/v1/repo/project.go index c734ac4f2b..616d601116 100644 --- a/routers/api/v1/repo/project.go +++ b/routers/api/v1/repo/project.go @@ -13,10 +13,10 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/convert" project_service "code.gitea.io/gitea/services/projects" - "code.gitea.io/gitea/routers/api/v1/utils" ) // ListProjects lists all projects in a repository @@ -398,6 +398,7 @@ func ListProjectColumns(ctx *context.APIContext) { return } + ctx.SetLinkHeader(int(total), listOptions.PageSize) ctx.SetTotalCountHeader(total) ctx.JSON(http.StatusOK, convert.ToProjectColumnList(ctx, columns)) }