@@ -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