@@ -5,12 +5,14 @@ package project
55
66import (
77 "context"
8+ "errors"
89 "fmt"
910 "regexp"
1011
1112 "code.gitea.io/gitea/models/db"
1213 "code.gitea.io/gitea/modules/setting"
1314 "code.gitea.io/gitea/modules/timeutil"
15+ "code.gitea.io/gitea/modules/util"
1416
1517 "xorm.io/builder"
1618)
@@ -82,6 +84,17 @@ func (b *Board) NumIssues(ctx context.Context) int {
8284 return int (c )
8385}
8486
87+ func (b * Board ) GetIssues (ctx context.Context ) ([]* ProjectIssue , error ) {
88+ issues := make ([]* ProjectIssue , 0 , 5 )
89+ if err := db .GetEngine (ctx ).Where ("project_id=?" , b .ProjectID ).
90+ And ("project_board_id=?" , b .ID ).
91+ OrderBy ("sorting, id" ).
92+ Find (& issues ); err != nil {
93+ return nil , err
94+ }
95+ return issues , nil
96+ }
97+
8598func init () {
8699 db .RegisterModel (new (Board ))
87100}
@@ -150,12 +163,27 @@ func createBoardsForProjectsType(ctx context.Context, project *Project) error {
150163 return db .Insert (ctx , boards )
151164}
152165
166+ // maxProjectColumns max columns allowed in a project, this should not bigger than 127
167+ // because sorting is int8 in database
168+ const maxProjectColumns = 20
169+
153170// NewBoard adds a new project board to a given project
154171func NewBoard (ctx context.Context , board * Board ) error {
155172 if len (board .Color ) != 0 && ! BoardColorPattern .MatchString (board .Color ) {
156173 return fmt .Errorf ("bad color code: %s" , board .Color )
157174 }
158-
175+ res := struct {
176+ MaxSorting int64
177+ ColumnCount int64
178+ }{}
179+ if _ , err := db .GetEngine (ctx ).Select ("max(sorting) as max_sorting, count(*) as column_count" ).Table ("project_board" ).
180+ Where ("project_id=?" , board .ProjectID ).Get (& res ); err != nil {
181+ return err
182+ }
183+ if res .ColumnCount >= maxProjectColumns {
184+ return fmt .Errorf ("NewBoard: maximum number of columns reached" )
185+ }
186+ board .Sorting = int8 (util .Iif (res .ColumnCount > 0 , res .MaxSorting + 1 , 0 ))
159187 _ , err := db .GetEngine (ctx ).Insert (board )
160188 return err
161189}
@@ -189,7 +217,17 @@ func deleteBoardByID(ctx context.Context, boardID int64) error {
189217 return fmt .Errorf ("deleteBoardByID: cannot delete default board" )
190218 }
191219
192- if err = board .removeIssues (ctx ); err != nil {
220+ // move all issues to the default column
221+ project , err := GetProjectByID (ctx , board .ProjectID )
222+ if err != nil {
223+ return err
224+ }
225+ defaultColumn , err := project .GetDefaultBoard (ctx )
226+ if err != nil {
227+ return err
228+ }
229+
230+ if err = board .moveIssuesToAnotherColumn (ctx , defaultColumn ); err != nil {
193231 return err
194232 }
195233
@@ -242,21 +280,15 @@ func UpdateBoard(ctx context.Context, board *Board) error {
242280// GetBoards fetches all boards related to a project
243281func (p * Project ) GetBoards (ctx context.Context ) (BoardList , error ) {
244282 boards := make ([]* Board , 0 , 5 )
245-
246- if err := db .GetEngine (ctx ).Where ("project_id=? AND `default`=?" , p .ID , false ).OrderBy ("sorting" ).Find (& boards ); err != nil {
283+ if err := db .GetEngine (ctx ).Where ("project_id=?" , p .ID ).OrderBy ("sorting, id" ).Find (& boards ); err != nil {
247284 return nil , err
248285 }
249286
250- defaultB , err := p .getDefaultBoard (ctx )
251- if err != nil {
252- return nil , err
253- }
254-
255- return append ([]* Board {defaultB }, boards ... ), nil
287+ return boards , nil
256288}
257289
258- // getDefaultBoard return default board and ensure only one exists
259- func (p * Project ) getDefaultBoard (ctx context.Context ) (* Board , error ) {
290+ // GetDefaultBoard return default board and ensure only one exists
291+ func (p * Project ) GetDefaultBoard (ctx context.Context ) (* Board , error ) {
260292 var board Board
261293 has , err := db .GetEngine (ctx ).
262294 Where ("project_id=? AND `default` = ?" , p .ID , true ).
@@ -316,3 +348,42 @@ func UpdateBoardSorting(ctx context.Context, bs BoardList) error {
316348 return nil
317349 })
318350}
351+
352+ func GetColumnsByIDs (ctx context.Context , projectID int64 , columnsIDs []int64 ) (BoardList , error ) {
353+ columns := make ([]* Board , 0 , 5 )
354+ if err := db .GetEngine (ctx ).
355+ Where ("project_id =?" , projectID ).
356+ In ("id" , columnsIDs ).
357+ OrderBy ("sorting" ).Find (& columns ); err != nil {
358+ return nil , err
359+ }
360+ return columns , nil
361+ }
362+
363+ // MoveColumnsOnProject sorts columns in a project
364+ func MoveColumnsOnProject (ctx context.Context , project * Project , sortedColumnIDs map [int64 ]int64 ) error {
365+ return db .WithTx (ctx , func (ctx context.Context ) error {
366+ sess := db .GetEngine (ctx )
367+ columnIDs := util .ValuesOfMap (sortedColumnIDs )
368+ movedColumns , err := GetColumnsByIDs (ctx , project .ID , columnIDs )
369+ if err != nil {
370+ return err
371+ }
372+ if len (movedColumns ) != len (sortedColumnIDs ) {
373+ return errors .New ("some columns do not exist" )
374+ }
375+
376+ for _ , column := range movedColumns {
377+ if column .ProjectID != project .ID {
378+ return fmt .Errorf ("column[%d]'s projectID is not equal to project's ID [%d]" , column .ProjectID , project .ID )
379+ }
380+ }
381+
382+ for sorting , columnID := range sortedColumnIDs {
383+ if _ , err := sess .Exec ("UPDATE `project_board` SET sorting=? WHERE id=?" , sorting , columnID ); err != nil {
384+ return err
385+ }
386+ }
387+ return nil
388+ })
389+ }
0 commit comments