mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Move project files into models/project sub package (#17704)
* Move project files into models/project sub package * Fix test * Fix test * Fix test * Fix build * Fix test * Fix template bug * Fix bug * Fix lint * Fix test * Fix import * Improve codes Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
289
models/project/board.go
Normal file
289
models/project/board.go
Normal file
@@ -0,0 +1,289 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package project
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
type (
|
||||
// BoardType is used to represent a project board type
|
||||
BoardType uint8
|
||||
|
||||
// BoardList is a list of all project boards in a repository
|
||||
BoardList []*Board
|
||||
)
|
||||
|
||||
const (
|
||||
// BoardTypeNone is a project board type that has no predefined columns
|
||||
BoardTypeNone BoardType = iota
|
||||
|
||||
// BoardTypeBasicKanban is a project board type that has basic predefined columns
|
||||
BoardTypeBasicKanban
|
||||
|
||||
// BoardTypeBugTriage is a project board type that has predefined columns suited to hunting down bugs
|
||||
BoardTypeBugTriage
|
||||
)
|
||||
|
||||
// BoardColorPattern is a regexp witch can validate BoardColor
|
||||
var BoardColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$")
|
||||
|
||||
// Board is used to represent boards on a project
|
||||
type Board struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Title string
|
||||
Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board
|
||||
Sorting int8 `xorm:"NOT NULL DEFAULT 0"`
|
||||
Color string `xorm:"VARCHAR(7)"`
|
||||
|
||||
ProjectID int64 `xorm:"INDEX NOT NULL"`
|
||||
CreatorID int64 `xorm:"NOT NULL"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// TableName return the real table name
|
||||
func (Board) TableName() string {
|
||||
return "project_board"
|
||||
}
|
||||
|
||||
// NumIssues return counter of all issues assigned to the board
|
||||
func (b *Board) NumIssues() int {
|
||||
c, err := db.GetEngine(db.DefaultContext).Table("project_issue").
|
||||
Where("project_id=?", b.ProjectID).
|
||||
And("project_board_id=?", b.ID).
|
||||
GroupBy("issue_id").
|
||||
Cols("issue_id").
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return int(c)
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(Board))
|
||||
}
|
||||
|
||||
// IsBoardTypeValid checks if the project board type is valid
|
||||
func IsBoardTypeValid(p BoardType) bool {
|
||||
switch p {
|
||||
case BoardTypeNone, BoardTypeBasicKanban, BoardTypeBugTriage:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func createBoardsForProjectsType(ctx context.Context, project *Project) error {
|
||||
var items []string
|
||||
|
||||
switch project.BoardType {
|
||||
|
||||
case BoardTypeBugTriage:
|
||||
items = setting.Project.ProjectBoardBugTriageType
|
||||
|
||||
case BoardTypeBasicKanban:
|
||||
items = setting.Project.ProjectBoardBasicKanbanType
|
||||
|
||||
case BoardTypeNone:
|
||||
fallthrough
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
boards := make([]Board, 0, len(items))
|
||||
|
||||
for _, v := range items {
|
||||
boards = append(boards, Board{
|
||||
CreatedUnix: timeutil.TimeStampNow(),
|
||||
CreatorID: project.CreatorID,
|
||||
Title: v,
|
||||
ProjectID: project.ID,
|
||||
})
|
||||
}
|
||||
|
||||
return db.Insert(ctx, boards)
|
||||
}
|
||||
|
||||
// NewBoard adds a new project board to a given project
|
||||
func NewBoard(board *Board) error {
|
||||
if len(board.Color) != 0 && !BoardColorPattern.MatchString(board.Color) {
|
||||
return fmt.Errorf("bad color code: %s", board.Color)
|
||||
}
|
||||
|
||||
_, err := db.GetEngine(db.DefaultContext).Insert(board)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteBoardByID removes all issues references to the project board.
|
||||
func DeleteBoardByID(boardID int64) error {
|
||||
ctx, committer, err := db.TxContext()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if err := deleteBoardByID(ctx, boardID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
func deleteBoardByID(ctx context.Context, boardID int64) error {
|
||||
e := db.GetEngine(ctx)
|
||||
board, err := getBoard(e, boardID)
|
||||
if err != nil {
|
||||
if IsErrProjectBoardNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if err = board.removeIssues(e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := e.ID(board.ID).Delete(board); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteBoardByProjectID(e db.Engine, projectID int64) error {
|
||||
_, err := e.Where("project_id=?", projectID).Delete(&Board{})
|
||||
return err
|
||||
}
|
||||
|
||||
// GetBoard fetches the current board of a project
|
||||
func GetBoard(boardID int64) (*Board, error) {
|
||||
return getBoard(db.GetEngine(db.DefaultContext), boardID)
|
||||
}
|
||||
|
||||
func getBoard(e db.Engine, boardID int64) (*Board, error) {
|
||||
board := new(Board)
|
||||
|
||||
has, err := e.ID(boardID).Get(board)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrProjectBoardNotExist{BoardID: boardID}
|
||||
}
|
||||
|
||||
return board, nil
|
||||
}
|
||||
|
||||
// UpdateBoard updates a project board
|
||||
func UpdateBoard(board *Board) error {
|
||||
return updateBoard(db.GetEngine(db.DefaultContext), board)
|
||||
}
|
||||
|
||||
func updateBoard(e db.Engine, board *Board) error {
|
||||
var fieldToUpdate []string
|
||||
|
||||
if board.Sorting != 0 {
|
||||
fieldToUpdate = append(fieldToUpdate, "sorting")
|
||||
}
|
||||
|
||||
if board.Title != "" {
|
||||
fieldToUpdate = append(fieldToUpdate, "title")
|
||||
}
|
||||
|
||||
if len(board.Color) != 0 && !BoardColorPattern.MatchString(board.Color) {
|
||||
return fmt.Errorf("bad color code: %s", board.Color)
|
||||
}
|
||||
fieldToUpdate = append(fieldToUpdate, "color")
|
||||
|
||||
_, err := e.ID(board.ID).Cols(fieldToUpdate...).Update(board)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetBoards fetches all boards related to a project
|
||||
// if no default board set, first board is a temporary "Uncategorized" board
|
||||
func GetBoards(projectID int64) (BoardList, error) {
|
||||
return getBoards(db.GetEngine(db.DefaultContext), projectID)
|
||||
}
|
||||
|
||||
func getBoards(e db.Engine, projectID int64) ([]*Board, error) {
|
||||
boards := make([]*Board, 0, 5)
|
||||
|
||||
if err := e.Where("project_id=? AND `default`=?", projectID, false).OrderBy("Sorting").Find(&boards); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defaultB, err := getDefaultBoard(e, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append([]*Board{defaultB}, boards...), nil
|
||||
}
|
||||
|
||||
// getDefaultBoard return default board and create a dummy if none exist
|
||||
func getDefaultBoard(e db.Engine, projectID int64) (*Board, error) {
|
||||
var board Board
|
||||
exist, err := e.Where("project_id=? AND `default`=?", projectID, true).Get(&board)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exist {
|
||||
return &board, nil
|
||||
}
|
||||
|
||||
// represents a board for issues not assigned to one
|
||||
return &Board{
|
||||
ProjectID: projectID,
|
||||
Title: "Uncategorized",
|
||||
Default: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetDefaultBoard represents a board for issues not assigned to one
|
||||
// if boardID is 0 unset default
|
||||
func SetDefaultBoard(projectID, boardID int64) error {
|
||||
_, err := db.GetEngine(db.DefaultContext).Where(builder.Eq{
|
||||
"project_id": projectID,
|
||||
"`default`": true,
|
||||
}).Cols("`default`").Update(&Board{Default: false})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if boardID > 0 {
|
||||
_, err = db.GetEngine(db.DefaultContext).ID(boardID).Where(builder.Eq{"project_id": projectID}).
|
||||
Cols("`default`").Update(&Board{Default: true})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateBoardSorting update project board sorting
|
||||
func UpdateBoardSorting(bs BoardList) error {
|
||||
for i := range bs {
|
||||
_, err := db.GetEngine(db.DefaultContext).ID(bs[i].ID).Cols(
|
||||
"sorting",
|
||||
).Update(bs[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user