mirror of https://github.com/go-gitea/gitea.git
Rename project board -> column to make the UI less confusion
This commit is contained in:
parent
8acc7aab4c
commit
43729085ac
|
@ -30,7 +30,7 @@ type Statistic struct {
|
|||
Mirror, Release, AuthSource, Webhook,
|
||||
Milestone, Label, HookTask,
|
||||
Team, UpdateTask, Project,
|
||||
ProjectBoard, Attachment,
|
||||
ProjectColumn, Attachment,
|
||||
Branches, Tags, CommitStatus int64
|
||||
IssueByLabel []IssueByLabelCount
|
||||
IssueByRepository []IssueByRepositoryCount
|
||||
|
@ -115,6 +115,6 @@ func GetStatistic(ctx context.Context) (stats Statistic) {
|
|||
stats.Counter.Team, _ = e.Count(new(organization.Team))
|
||||
stats.Counter.Attachment, _ = e.Count(new(repo_model.Attachment))
|
||||
stats.Counter.Project, _ = e.Count(new(project_model.Project))
|
||||
stats.Counter.ProjectBoard, _ = e.Count(new(project_model.Board))
|
||||
stats.Counter.ProjectColumn, _ = e.Count(new(project_model.Column))
|
||||
return stats
|
||||
}
|
||||
|
|
|
@ -37,22 +37,22 @@ func (issue *Issue) projectID(ctx context.Context) int64 {
|
|||
return ip.ProjectID
|
||||
}
|
||||
|
||||
// ProjectBoardID return project board id if issue was assigned to one
|
||||
func (issue *Issue) ProjectBoardID(ctx context.Context) int64 {
|
||||
// ProjectColumnID return project column id if issue was assigned to one
|
||||
func (issue *Issue) ProjectColumnID(ctx context.Context) int64 {
|
||||
var ip project_model.ProjectIssue
|
||||
has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
|
||||
if err != nil || !has {
|
||||
return 0
|
||||
}
|
||||
return ip.ProjectBoardID
|
||||
return ip.ProjectColumnID
|
||||
}
|
||||
|
||||
// LoadIssuesFromBoard load issues assigned to this board
|
||||
func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) {
|
||||
// LoadIssuesFromColumn load issues assigned to this board
|
||||
func LoadIssuesFromColumn(ctx context.Context, b *project_model.Column) (IssueList, error) {
|
||||
issueList, err := Issues(ctx, &IssuesOptions{
|
||||
ProjectBoardID: b.ID,
|
||||
ProjectID: b.ProjectID,
|
||||
SortType: "project-column-sorting",
|
||||
ProjectColumnID: b.ID,
|
||||
ProjectID: b.ProjectID,
|
||||
SortType: "project-column-sorting",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -60,9 +60,9 @@ func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList
|
|||
|
||||
if b.Default {
|
||||
issues, err := Issues(ctx, &IssuesOptions{
|
||||
ProjectBoardID: db.NoConditionID,
|
||||
ProjectID: b.ProjectID,
|
||||
SortType: "project-column-sorting",
|
||||
ProjectColumnID: db.NoConditionID,
|
||||
ProjectID: b.ProjectID,
|
||||
SortType: "project-column-sorting",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -77,11 +77,11 @@ func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList
|
|||
return issueList, nil
|
||||
}
|
||||
|
||||
// LoadIssuesFromBoardList load issues assigned to the boards
|
||||
func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (map[int64]IssueList, error) {
|
||||
// LoadIssuesFromColumnList load issues assigned to the boards
|
||||
func LoadIssuesFromColumnList(ctx context.Context, bs project_model.ColumnList) (map[int64]IssueList, error) {
|
||||
issuesMap := make(map[int64]IssueList, len(bs))
|
||||
for i := range bs {
|
||||
il, err := LoadIssuesFromBoard(ctx, bs[i])
|
||||
il, err := LoadIssuesFromColumn(ctx, bs[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ type IssuesOptions struct { //nolint
|
|||
SubscriberID int64
|
||||
MilestoneIDs []int64
|
||||
ProjectID int64
|
||||
ProjectBoardID int64
|
||||
ProjectColumnID int64
|
||||
IsClosed optional.Option[bool]
|
||||
IsPull optional.Option[bool]
|
||||
LabelIDs []int64
|
||||
|
@ -169,12 +169,12 @@ func applyProjectCondition(sess *xorm.Session, opts *IssuesOptions) *xorm.Sessio
|
|||
return sess
|
||||
}
|
||||
|
||||
func applyProjectBoardCondition(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
|
||||
// opts.ProjectBoardID == 0 means all project boards,
|
||||
func applyProjectColumnCondition(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
|
||||
// opts.ProjectColumnID == 0 means all project columns,
|
||||
// do not need to apply any condition
|
||||
if opts.ProjectBoardID > 0 {
|
||||
sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_board_id": opts.ProjectBoardID}))
|
||||
} else if opts.ProjectBoardID == db.NoConditionID {
|
||||
if opts.ProjectColumnID > 0 {
|
||||
sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_board_id": opts.ProjectColumnID}))
|
||||
} else if opts.ProjectColumnID == db.NoConditionID {
|
||||
sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_board_id": 0}))
|
||||
}
|
||||
return sess
|
||||
|
@ -246,7 +246,7 @@ func applyConditions(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
|
|||
|
||||
applyProjectCondition(sess, opts)
|
||||
|
||||
applyProjectBoardCondition(sess, opts)
|
||||
applyProjectColumnCondition(sess, opts)
|
||||
|
||||
if opts.IsPull.Has() {
|
||||
sess.And("issue.is_pull=?", opts.IsPull.Value())
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
func Test_CheckProjectColumnsConsistency(t *testing.T) {
|
||||
// Prepare and load the testing database
|
||||
x, deferable := base.PrepareTestEnv(t, 0, new(project.Project), new(project.Board))
|
||||
x, deferable := base.PrepareTestEnv(t, 0, new(project.Project), new(project.Column))
|
||||
defer deferable()
|
||||
if x == nil || t.Failed() {
|
||||
return
|
||||
|
@ -23,22 +23,22 @@ func Test_CheckProjectColumnsConsistency(t *testing.T) {
|
|||
|
||||
assert.NoError(t, CheckProjectColumnsConsistency(x))
|
||||
|
||||
// check if default board was added
|
||||
var defaultBoard project.Board
|
||||
has, err := x.Where("project_id=? AND `default` = ?", 1, true).Get(&defaultBoard)
|
||||
// check if default column was added
|
||||
var defaultColumn project.Column
|
||||
has, err := x.Where("project_id=? AND `default` = ?", 1, true).Get(&defaultColumn)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.Equal(t, int64(1), defaultBoard.ProjectID)
|
||||
assert.True(t, defaultBoard.Default)
|
||||
assert.Equal(t, int64(1), defaultColumn.ProjectID)
|
||||
assert.True(t, defaultColumn.Default)
|
||||
|
||||
// check if multiple defaults, previous were removed and last will be kept
|
||||
expectDefaultBoard, err := project.GetBoard(db.DefaultContext, 2)
|
||||
expectDefaultColumn, err := project.GetColumn(db.DefaultContext, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(2), expectDefaultBoard.ProjectID)
|
||||
assert.False(t, expectDefaultBoard.Default)
|
||||
assert.Equal(t, int64(2), expectDefaultColumn.ProjectID)
|
||||
assert.False(t, expectDefaultColumn.Default)
|
||||
|
||||
expectNonDefaultBoard, err := project.GetBoard(db.DefaultContext, 3)
|
||||
expectNonDefaultColumn, err := project.GetColumn(db.DefaultContext, 3)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(2), expectNonDefaultBoard.ProjectID)
|
||||
assert.True(t, expectNonDefaultBoard.Default)
|
||||
assert.Equal(t, int64(2), expectNonDefaultColumn.ProjectID)
|
||||
assert.True(t, expectNonDefaultColumn.Default)
|
||||
}
|
||||
|
|
|
@ -1,320 +0,0 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
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
|
||||
|
||||
// CardType is used to represent a project board card type
|
||||
CardType 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
|
||||
)
|
||||
|
||||
const (
|
||||
// CardTypeTextOnly is a project board card type that is text only
|
||||
CardTypeTextOnly CardType = iota
|
||||
|
||||
// CardTypeImagesAndText is a project board card type that has images and text
|
||||
CardTypeImagesAndText
|
||||
)
|
||||
|
||||
// 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(ctx context.Context) int {
|
||||
c, err := db.GetEngine(ctx).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
|
||||
}
|
||||
}
|
||||
|
||||
// IsCardTypeValid checks if the project board card type is valid
|
||||
func IsCardTypeValid(p CardType) bool {
|
||||
switch p {
|
||||
case CardTypeTextOnly, CardTypeImagesAndText:
|
||||
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
|
||||
}
|
||||
|
||||
board := Board{
|
||||
CreatedUnix: timeutil.TimeStampNow(),
|
||||
CreatorID: project.CreatorID,
|
||||
Title: "Backlog",
|
||||
ProjectID: project.ID,
|
||||
Default: true,
|
||||
}
|
||||
if err := db.Insert(ctx, board); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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(ctx context.Context, board *Board) error {
|
||||
if len(board.Color) != 0 && !BoardColorPattern.MatchString(board.Color) {
|
||||
return fmt.Errorf("bad color code: %s", board.Color)
|
||||
}
|
||||
|
||||
_, err := db.GetEngine(ctx).Insert(board)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteBoardByID removes all issues references to the project board.
|
||||
func DeleteBoardByID(ctx context.Context, boardID int64) error {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
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 {
|
||||
board, err := GetBoard(ctx, boardID)
|
||||
if err != nil {
|
||||
if IsErrProjectBoardNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if board.Default {
|
||||
return fmt.Errorf("deleteBoardByID: cannot delete default board")
|
||||
}
|
||||
|
||||
if err = board.removeIssues(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := db.GetEngine(ctx).ID(board.ID).NoAutoCondition().Delete(board); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteBoardByProjectID(ctx context.Context, projectID int64) error {
|
||||
_, err := db.GetEngine(ctx).Where("project_id=?", projectID).Delete(&Board{})
|
||||
return err
|
||||
}
|
||||
|
||||
// GetBoard fetches the current board of a project
|
||||
func GetBoard(ctx context.Context, boardID int64) (*Board, error) {
|
||||
board := new(Board)
|
||||
has, err := db.GetEngine(ctx).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(ctx context.Context, 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 := db.GetEngine(ctx).ID(board.ID).Cols(fieldToUpdate...).Update(board)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetBoards fetches all boards related to a project
|
||||
func (p *Project) GetBoards(ctx context.Context) (BoardList, error) {
|
||||
boards := make([]*Board, 0, 5)
|
||||
|
||||
if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", p.ID, false).OrderBy("sorting").Find(&boards); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defaultB, err := p.getDefaultBoard(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append([]*Board{defaultB}, boards...), nil
|
||||
}
|
||||
|
||||
// getDefaultBoard return default board and ensure only one exists
|
||||
func (p *Project) getDefaultBoard(ctx context.Context) (*Board, error) {
|
||||
var board Board
|
||||
has, err := db.GetEngine(ctx).
|
||||
Where("project_id=? AND `default` = ?", p.ID, true).
|
||||
Desc("id").Get(&board)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if has {
|
||||
return &board, nil
|
||||
}
|
||||
|
||||
// create a default board if none is found
|
||||
board = Board{
|
||||
ProjectID: p.ID,
|
||||
Default: true,
|
||||
Title: "Uncategorized",
|
||||
CreatorID: p.CreatorID,
|
||||
}
|
||||
if _, err := db.GetEngine(ctx).Insert(&board); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &board, nil
|
||||
}
|
||||
|
||||
// SetDefaultBoard represents a board for issues not assigned to one
|
||||
func SetDefaultBoard(ctx context.Context, projectID, boardID int64) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
if _, err := GetBoard(ctx, boardID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := db.GetEngine(ctx).Where(builder.Eq{
|
||||
"project_id": projectID,
|
||||
"`default`": true,
|
||||
}).Cols("`default`").Update(&Board{Default: false}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := db.GetEngine(ctx).ID(boardID).
|
||||
Where(builder.Eq{"project_id": projectID}).
|
||||
Cols("`default`").Update(&Board{Default: true})
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateBoardSorting update project board sorting
|
||||
func UpdateBoardSorting(ctx context.Context, bs BoardList) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
for i := range bs {
|
||||
if _, err := db.GetEngine(ctx).ID(bs[i].ID).Cols(
|
||||
"sorting",
|
||||
).Update(bs[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2020 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 TestGetDefaultBoard(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
projectWithoutDefault, err := GetProjectByID(db.DefaultContext, 5)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// check if default board was added
|
||||
board, err := projectWithoutDefault.getDefaultBoard(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(5), board.ProjectID)
|
||||
assert.Equal(t, "Uncategorized", board.Title)
|
||||
|
||||
projectWithMultipleDefaults, err := GetProjectByID(db.DefaultContext, 6)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// check if multiple defaults were removed
|
||||
board, err = projectWithMultipleDefaults.getDefaultBoard(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(6), board.ProjectID)
|
||||
assert.Equal(t, int64(9), board.ID)
|
||||
|
||||
// set 8 as default board
|
||||
assert.NoError(t, SetDefaultBoard(db.DefaultContext, board.ProjectID, 8))
|
||||
|
||||
// then 9 will become a non-default board
|
||||
board, err = GetBoard(db.DefaultContext, 9)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(6), board.ProjectID)
|
||||
assert.False(t, board.Default)
|
||||
}
|
|
@ -0,0 +1,287 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
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 (
|
||||
|
||||
// CardType is used to represent a project column card type
|
||||
CardType uint8
|
||||
|
||||
// ColumnList is a list of all project columns in a repository
|
||||
ColumnList []*Column
|
||||
)
|
||||
|
||||
const (
|
||||
// CardTypeTextOnly is a project column card type that is text only
|
||||
CardTypeTextOnly CardType = iota
|
||||
|
||||
// CardTypeImagesAndText is a project column card type that has images and text
|
||||
CardTypeImagesAndText
|
||||
)
|
||||
|
||||
// ColumnColorPattern is a regexp witch can validate ColumnColor
|
||||
var ColumnColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$")
|
||||
|
||||
// Column is used to represent column on a project
|
||||
type Column struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Title string
|
||||
Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific column will be assigned to this column
|
||||
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 (Column) TableName() string {
|
||||
return "project_board" // FIXME: the legacy table name should be project_column
|
||||
}
|
||||
|
||||
// NumIssues return counter of all issues assigned to the column
|
||||
func (b *Column) NumIssues(ctx context.Context) int {
|
||||
c, err := db.GetEngine(ctx).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(Column))
|
||||
}
|
||||
|
||||
// IsCardTypeValid checks if the project column card type is valid
|
||||
func IsCardTypeValid(p CardType) bool {
|
||||
switch p {
|
||||
case CardTypeTextOnly, CardTypeImagesAndText:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func createColumnsForProjectsBoradViewType(ctx context.Context, project *Project) error {
|
||||
var items []string
|
||||
|
||||
switch project.BoardViewType {
|
||||
case BoardViewTypeBugTriage:
|
||||
items = setting.Project.ProjectBoardBugTriageType
|
||||
case BoardViewTypeBasicKanban:
|
||||
items = setting.Project.ProjectBoardBasicKanbanType
|
||||
case BoardViewTypeNone:
|
||||
fallthrough
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
column := Column{
|
||||
CreatedUnix: timeutil.TimeStampNow(),
|
||||
CreatorID: project.CreatorID,
|
||||
Title: "Backlog",
|
||||
ProjectID: project.ID,
|
||||
Default: true,
|
||||
}
|
||||
if err := db.Insert(ctx, column); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
boards := make([]Column, 0, len(items))
|
||||
for _, v := range items {
|
||||
boards = append(boards, Column{
|
||||
CreatedUnix: timeutil.TimeStampNow(),
|
||||
CreatorID: project.CreatorID,
|
||||
Title: v,
|
||||
ProjectID: project.ID,
|
||||
})
|
||||
}
|
||||
|
||||
return db.Insert(ctx, boards)
|
||||
})
|
||||
}
|
||||
|
||||
// NewColumn adds a new project column to a given project
|
||||
func NewColumn(ctx context.Context, column *Column) error {
|
||||
if len(column.Color) != 0 && !ColumnColorPattern.MatchString(column.Color) {
|
||||
return fmt.Errorf("bad color code: %s", column.Color)
|
||||
}
|
||||
|
||||
_, err := db.GetEngine(ctx).Insert(column)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteColumnByID removes all issues references to the project board.
|
||||
func DeleteColumnByID(ctx context.Context, columnID int64) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
return deleteColumnByID(ctx, columnID)
|
||||
})
|
||||
}
|
||||
|
||||
func deleteColumnByID(ctx context.Context, columnID int64) error {
|
||||
column, err := GetColumn(ctx, columnID)
|
||||
if err != nil {
|
||||
if IsErrProjectColumnNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if column.Default {
|
||||
return fmt.Errorf("deleteBoardByID: cannot delete default board")
|
||||
}
|
||||
|
||||
if err = column.removeIssues(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := db.GetEngine(ctx).ID(column.ID).NoAutoCondition().Delete(column); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteColumnByProjectID(ctx context.Context, projectID int64) error {
|
||||
_, err := db.GetEngine(ctx).Where("project_id=?", projectID).Delete(&Column{})
|
||||
return err
|
||||
}
|
||||
|
||||
// GetColumn fetches the current board of a project
|
||||
func GetColumn(ctx context.Context, columnID int64) (*Column, error) {
|
||||
board := new(Column)
|
||||
has, err := db.GetEngine(ctx).ID(columnID).Get(board)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrProjectColumnNotExist{ColumnID: columnID}
|
||||
}
|
||||
|
||||
return board, nil
|
||||
}
|
||||
|
||||
// UpdateColumn updates a project column
|
||||
func UpdateColumn(ctx context.Context, column *Column) error {
|
||||
var fieldToUpdate []string
|
||||
|
||||
if column.Sorting != 0 {
|
||||
fieldToUpdate = append(fieldToUpdate, "sorting")
|
||||
}
|
||||
|
||||
if column.Title != "" {
|
||||
fieldToUpdate = append(fieldToUpdate, "title")
|
||||
}
|
||||
|
||||
if len(column.Color) != 0 && !ColumnColorPattern.MatchString(column.Color) {
|
||||
return fmt.Errorf("bad color code: %s", column.Color)
|
||||
}
|
||||
fieldToUpdate = append(fieldToUpdate, "color")
|
||||
|
||||
_, err := db.GetEngine(ctx).ID(column.ID).Cols(fieldToUpdate...).Update(column)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetColumns fetches all boards related to a project
|
||||
func (p *Project) GetColumns(ctx context.Context) (ColumnList, error) {
|
||||
boards := make([]*Column, 0, 5)
|
||||
|
||||
if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", p.ID, false).OrderBy("sorting").Find(&boards); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defaultB, err := p.getDefaultColumn(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append([]*Column{defaultB}, boards...), nil
|
||||
}
|
||||
|
||||
// getDefaultColumn return default column and ensure only one exists
|
||||
func (p *Project) getDefaultColumn(ctx context.Context) (*Column, error) {
|
||||
var column Column
|
||||
has, err := db.GetEngine(ctx).
|
||||
Where("project_id=? AND `default` = ?", p.ID, true).
|
||||
Desc("id").Get(&column)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if has {
|
||||
return &column, nil
|
||||
}
|
||||
|
||||
// create a default column if none is found
|
||||
column = Column{
|
||||
ProjectID: p.ID,
|
||||
Default: true,
|
||||
Title: "Uncategorized",
|
||||
CreatorID: p.CreatorID,
|
||||
}
|
||||
if _, err := db.GetEngine(ctx).Insert(&column); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &column, nil
|
||||
}
|
||||
|
||||
// SetDefaultColumn represents a column for issues not assigned to one
|
||||
func SetDefaultColumn(ctx context.Context, projectID, columnID int64) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
if _, err := GetColumn(ctx, columnID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := db.GetEngine(ctx).Where(builder.Eq{
|
||||
"project_id": projectID,
|
||||
"`default`": true,
|
||||
}).Cols("`default`").Update(&Column{Default: false}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := db.GetEngine(ctx).ID(columnID).
|
||||
Where(builder.Eq{"project_id": projectID}).
|
||||
Cols("`default`").Update(&Column{Default: true})
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateColumnSorting update project column sorting
|
||||
func UpdateColumnSorting(ctx context.Context, cl ColumnList) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
for i := range cl {
|
||||
if _, err := db.GetEngine(ctx).ID(cl[i].ID).Cols(
|
||||
"sorting",
|
||||
).Update(cl[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2020 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 TestGetDefaultcolumn(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
projectWithoutDefault, err := GetProjectByID(db.DefaultContext, 5)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// check if default column was added
|
||||
column, err := projectWithoutDefault.getDefaultColumn(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(5), column.ProjectID)
|
||||
assert.Equal(t, "Uncategorized", column.Title)
|
||||
|
||||
projectWithMultipleDefaults, err := GetProjectByID(db.DefaultContext, 6)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// check if multiple defaults were removed
|
||||
column, err = projectWithMultipleDefaults.getDefaultColumn(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(6), column.ProjectID)
|
||||
assert.Equal(t, int64(9), column.ID)
|
||||
|
||||
// set 8 as default column
|
||||
assert.NoError(t, SetDefaultColumn(db.DefaultContext, column.ProjectID, 8))
|
||||
|
||||
// then 9 will become a non-default column
|
||||
column, err = GetColumn(db.DefaultContext, 9)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(6), column.ProjectID)
|
||||
assert.False(t, column.Default)
|
||||
}
|
|
@ -17,10 +17,10 @@ type ProjectIssue struct { //revive:disable-line:exported
|
|||
IssueID int64 `xorm:"INDEX"`
|
||||
ProjectID int64 `xorm:"INDEX"`
|
||||
|
||||
// If 0, then it has not been added to a specific board in the project
|
||||
ProjectBoardID int64 `xorm:"INDEX"`
|
||||
// If 0, then it has not been added to a specific column in the project
|
||||
ProjectColumnID int64 `xorm:"'project_board_id' INDEX"`
|
||||
|
||||
// the sorting order on the board
|
||||
// the sorting order on the column
|
||||
Sorting int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,8 @@ func (p *Project) NumOpenIssues(ctx context.Context) int {
|
|||
return int(c)
|
||||
}
|
||||
|
||||
// MoveIssuesOnProjectBoard moves or keeps issues in a column and sorts them inside that column
|
||||
func MoveIssuesOnProjectBoard(ctx context.Context, board *Board, sortedIssueIDs map[int64]int64) error {
|
||||
// MoveIssuesOnProjectColumn moves or keeps issues in a column and sorts them inside that column
|
||||
func MoveIssuesOnProjectColumn(ctx context.Context, board *Column, sortedIssueIDs map[int64]int64) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
|
@ -102,7 +102,7 @@ func MoveIssuesOnProjectBoard(ctx context.Context, board *Board, sortedIssueIDs
|
|||
})
|
||||
}
|
||||
|
||||
func (b *Board) removeIssues(ctx context.Context) error {
|
||||
func (b *Column) removeIssues(ctx context.Context) error {
|
||||
_, err := db.GetEngine(ctx).Exec("UPDATE `project_issue` SET project_board_id = 0 WHERE project_board_id = ? ", b.ID)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -21,12 +21,6 @@ import (
|
|||
)
|
||||
|
||||
type (
|
||||
// BoardConfig is used to identify the type of board that is being created
|
||||
BoardConfig struct {
|
||||
BoardType BoardType
|
||||
Translation string
|
||||
}
|
||||
|
||||
// CardConfig is used to identify the type of board card that is being used
|
||||
CardConfig struct {
|
||||
CardType CardType
|
||||
|
@ -68,39 +62,39 @@ func (err ErrProjectNotExist) Unwrap() error {
|
|||
return util.ErrNotExist
|
||||
}
|
||||
|
||||
// ErrProjectBoardNotExist represents a "ProjectBoardNotExist" kind of error.
|
||||
type ErrProjectBoardNotExist struct {
|
||||
BoardID int64
|
||||
// ErrProjectColumnNotExist represents a "ProjectBoardNotExist" kind of error.
|
||||
type ErrProjectColumnNotExist struct {
|
||||
ColumnID int64
|
||||
}
|
||||
|
||||
// IsErrProjectBoardNotExist checks if an error is a ErrProjectBoardNotExist
|
||||
func IsErrProjectBoardNotExist(err error) bool {
|
||||
_, ok := err.(ErrProjectBoardNotExist)
|
||||
// IsErrProjectColumnNotExist checks if an error is a ErrProjectBoardNotExist
|
||||
func IsErrProjectColumnNotExist(err error) bool {
|
||||
_, ok := err.(ErrProjectColumnNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrProjectBoardNotExist) Error() string {
|
||||
return fmt.Sprintf("project board does not exist [id: %d]", err.BoardID)
|
||||
func (err ErrProjectColumnNotExist) Error() string {
|
||||
return fmt.Sprintf("project column does not exist [id: %d]", err.ColumnID)
|
||||
}
|
||||
|
||||
func (err ErrProjectBoardNotExist) Unwrap() error {
|
||||
func (err ErrProjectColumnNotExist) Unwrap() error {
|
||||
return util.ErrNotExist
|
||||
}
|
||||
|
||||
// Project represents a project board
|
||||
type Project struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Title string `xorm:"INDEX NOT NULL"`
|
||||
Description string `xorm:"TEXT"`
|
||||
OwnerID int64 `xorm:"INDEX"`
|
||||
Owner *user_model.User `xorm:"-"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
Repo *repo_model.Repository `xorm:"-"`
|
||||
CreatorID int64 `xorm:"NOT NULL"`
|
||||
IsClosed bool `xorm:"INDEX"`
|
||||
BoardType BoardType
|
||||
CardType CardType
|
||||
Type Type
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Title string `xorm:"INDEX NOT NULL"`
|
||||
Description string `xorm:"TEXT"`
|
||||
OwnerID int64 `xorm:"INDEX"`
|
||||
Owner *user_model.User `xorm:"-"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
Repo *repo_model.Repository `xorm:"-"`
|
||||
CreatorID int64 `xorm:"NOT NULL"`
|
||||
IsClosed bool `xorm:"INDEX"`
|
||||
BoardViewType BoardViewType `xorm:"'board_type'"`
|
||||
CardType CardType
|
||||
Type Type
|
||||
|
||||
RenderedContent template.HTML `xorm:"-"`
|
||||
|
||||
|
@ -165,15 +159,6 @@ func init() {
|
|||
db.RegisterModel(new(Project))
|
||||
}
|
||||
|
||||
// GetBoardConfig retrieves the types of configurations project boards could have
|
||||
func GetBoardConfig() []BoardConfig {
|
||||
return []BoardConfig{
|
||||
{BoardTypeNone, "repo.projects.type.none"},
|
||||
{BoardTypeBasicKanban, "repo.projects.type.basic_kanban"},
|
||||
{BoardTypeBugTriage, "repo.projects.type.bug_triage"},
|
||||
}
|
||||
}
|
||||
|
||||
// GetCardConfig retrieves the types of configurations project board cards could have
|
||||
func GetCardConfig() []CardConfig {
|
||||
return []CardConfig{
|
||||
|
@ -244,8 +229,8 @@ func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy {
|
|||
|
||||
// NewProject creates a new Project
|
||||
func NewProject(ctx context.Context, p *Project) error {
|
||||
if !IsBoardTypeValid(p.BoardType) {
|
||||
p.BoardType = BoardTypeNone
|
||||
if !IsBoardViewTypeValid(p.BoardViewType) {
|
||||
p.BoardViewType = BoardViewTypeNone
|
||||
}
|
||||
|
||||
if !IsCardTypeValid(p.CardType) {
|
||||
|
@ -256,27 +241,19 @@ func NewProject(ctx context.Context, p *Project) error {
|
|||
return util.NewInvalidArgumentErrorf("project type is not valid")
|
||||
}
|
||||
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if err := db.Insert(ctx, p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.RepoID > 0 {
|
||||
if _, err := db.Exec(ctx, "UPDATE `repository` SET num_projects = num_projects + 1 WHERE id = ?", p.RepoID); err != nil {
|
||||
return db.WithTx(ctx, func(tx context.Context) error {
|
||||
if err := db.Insert(ctx, p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := createBoardsForProjectsType(ctx, p); err != nil {
|
||||
return err
|
||||
}
|
||||
if p.RepoID > 0 {
|
||||
if _, err := db.Exec(ctx, "UPDATE `repository` SET num_projects = num_projects + 1 WHERE id = ?", p.RepoID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return committer.Commit()
|
||||
return createColumnsForProjectsBoradViewType(ctx, p)
|
||||
})
|
||||
}
|
||||
|
||||
// GetProjectByID returns the projects in a repository
|
||||
|
@ -410,7 +387,7 @@ func DeleteProjectByID(ctx context.Context, id int64) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := deleteBoardByProjectID(ctx, id); err != nil {
|
||||
if err := deleteColumnByProjectID(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -51,13 +51,13 @@ func TestProject(t *testing.T) {
|
|||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
project := &Project{
|
||||
Type: TypeRepository,
|
||||
BoardType: BoardTypeBasicKanban,
|
||||
CardType: CardTypeTextOnly,
|
||||
Title: "New Project",
|
||||
RepoID: 1,
|
||||
CreatedUnix: timeutil.TimeStampNow(),
|
||||
CreatorID: 2,
|
||||
Type: TypeRepository,
|
||||
BoardViewType: BoardViewTypeBasicKanban,
|
||||
CardType: CardTypeTextOnly,
|
||||
Title: "New Project",
|
||||
RepoID: 1,
|
||||
CreatedUnix: timeutil.TimeStampNow(),
|
||||
CreatorID: 2,
|
||||
}
|
||||
|
||||
assert.NoError(t, NewProject(db.DefaultContext, project))
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package project
|
||||
|
||||
type (
|
||||
// BoardViewType is used to represent a project column type
|
||||
BoardViewType uint8
|
||||
|
||||
// BoardConfig is used to identify the type of board that is being created
|
||||
BoardConfig struct {
|
||||
BoardType BoardViewType
|
||||
Translation string
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// BoardViewTypeNone is a project board type that has no predefined columns
|
||||
BoardViewTypeNone BoardViewType = iota
|
||||
|
||||
// BoardViewTypeBasicKanban is a project board type that has basic predefined columns
|
||||
BoardViewTypeBasicKanban
|
||||
|
||||
// BoardViewTypeBugTriage is a project board type that has predefined columns suited to hunting down bugs
|
||||
BoardViewTypeBugTriage
|
||||
)
|
||||
|
||||
// GetBoardViewConfig retrieves the types of configurations project boards could have
|
||||
func GetBoardViewConfig() []BoardConfig {
|
||||
return []BoardConfig{
|
||||
{BoardViewTypeNone, "repo.projects.type.none"},
|
||||
{BoardViewTypeBasicKanban, "repo.projects.type.basic_kanban"},
|
||||
{BoardViewTypeBugTriage, "repo.projects.type.bug_triage"},
|
||||
}
|
||||
}
|
||||
|
||||
// IsBoardViewTypeValid checks if the project board type is valid
|
||||
func IsBoardViewTypeValid(p BoardViewType) bool {
|
||||
switch p {
|
||||
case BoardViewTypeNone, BoardViewTypeBasicKanban, BoardViewTypeBugTriage:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -228,8 +228,8 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
|||
if options.ProjectID.Has() {
|
||||
queries = append(queries, inner_bleve.NumericEqualityQuery(options.ProjectID.Value(), "project_id"))
|
||||
}
|
||||
if options.ProjectBoardID.Has() {
|
||||
queries = append(queries, inner_bleve.NumericEqualityQuery(options.ProjectBoardID.Value(), "project_board_id"))
|
||||
if options.ProjectColumnID.Has() {
|
||||
queries = append(queries, inner_bleve.NumericEqualityQuery(options.ProjectColumnID.Value(), "project_board_id"))
|
||||
}
|
||||
|
||||
if options.PosterID.Has() {
|
||||
|
|
|
@ -61,7 +61,7 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
|
|||
ReviewedID: convertID(options.ReviewedID),
|
||||
SubscriberID: convertID(options.SubscriberID),
|
||||
ProjectID: convertID(options.ProjectID),
|
||||
ProjectBoardID: convertID(options.ProjectBoardID),
|
||||
ProjectColumnID: convertID(options.ProjectColumnID),
|
||||
IsClosed: options.IsClosed,
|
||||
IsPull: options.IsPull,
|
||||
IncludedLabelNames: nil,
|
||||
|
|
|
@ -50,7 +50,7 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
|
|||
}
|
||||
|
||||
searchOpt.ProjectID = convertID(opts.ProjectID)
|
||||
searchOpt.ProjectBoardID = convertID(opts.ProjectBoardID)
|
||||
searchOpt.ProjectColumnID = convertID(opts.ProjectColumnID)
|
||||
searchOpt.PosterID = convertID(opts.PosterID)
|
||||
searchOpt.AssigneeID = convertID(opts.AssigneeID)
|
||||
searchOpt.MentionID = convertID(opts.MentionedID)
|
||||
|
|
|
@ -198,8 +198,8 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
|||
if options.ProjectID.Has() {
|
||||
query.Must(elastic.NewTermQuery("project_id", options.ProjectID.Value()))
|
||||
}
|
||||
if options.ProjectBoardID.Has() {
|
||||
query.Must(elastic.NewTermQuery("project_board_id", options.ProjectBoardID.Value()))
|
||||
if options.ProjectColumnID.Has() {
|
||||
query.Must(elastic.NewTermQuery("project_board_id", options.ProjectColumnID.Value()))
|
||||
}
|
||||
|
||||
if options.PosterID.Has() {
|
||||
|
|
|
@ -369,13 +369,13 @@ func searchIssueInProject(t *testing.T) {
|
|||
},
|
||||
{
|
||||
SearchOptions{
|
||||
ProjectBoardID: optional.Some(int64(1)),
|
||||
ProjectColumnID: optional.Some(int64(1)),
|
||||
},
|
||||
[]int64{1},
|
||||
},
|
||||
{
|
||||
SearchOptions{
|
||||
ProjectBoardID: optional.Some(int64(0)), // issue with in default board
|
||||
ProjectColumnID: optional.Some(int64(0)), // issue with in default board
|
||||
},
|
||||
[]int64{2},
|
||||
},
|
||||
|
|
|
@ -89,8 +89,8 @@ type SearchOptions struct {
|
|||
|
||||
MilestoneIDs []int64 // milestones the issues have
|
||||
|
||||
ProjectID optional.Option[int64] // project the issues belong to
|
||||
ProjectBoardID optional.Option[int64] // project board the issues belong to
|
||||
ProjectID optional.Option[int64] // project the issues belong to
|
||||
ProjectColumnID optional.Option[int64] // project column the issues belong to
|
||||
|
||||
PosterID optional.Option[int64] // poster of the issues
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ var cases = []*testIndexerCase{
|
|||
Paginator: &db.ListOptions{
|
||||
PageSize: 5,
|
||||
},
|
||||
ProjectBoardID: optional.Some(int64(1)),
|
||||
ProjectColumnID: optional.Some(int64(1)),
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, 5, len(result.Hits))
|
||||
|
@ -361,7 +361,7 @@ var cases = []*testIndexerCase{
|
|||
Paginator: &db.ListOptions{
|
||||
PageSize: 5,
|
||||
},
|
||||
ProjectBoardID: optional.Some(int64(0)),
|
||||
ProjectColumnID: optional.Some(int64(0)),
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, 5, len(result.Hits))
|
||||
|
|
|
@ -174,8 +174,8 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
|||
if options.ProjectID.Has() {
|
||||
query.And(inner_meilisearch.NewFilterEq("project_id", options.ProjectID.Value()))
|
||||
}
|
||||
if options.ProjectBoardID.Has() {
|
||||
query.And(inner_meilisearch.NewFilterEq("project_board_id", options.ProjectBoardID.Value()))
|
||||
if options.ProjectColumnID.Has() {
|
||||
query.And(inner_meilisearch.NewFilterEq("project_board_id", options.ProjectColumnID.Value()))
|
||||
}
|
||||
|
||||
if options.PosterID.Has() {
|
||||
|
|
|
@ -105,7 +105,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
|
|||
NoLabel: len(labels) == 0,
|
||||
MilestoneID: issue.MilestoneID,
|
||||
ProjectID: projectID,
|
||||
ProjectBoardID: issue.ProjectBoardID(ctx),
|
||||
ProjectBoardID: issue.ProjectColumnID(ctx),
|
||||
PosterID: issue.PosterID,
|
||||
AssigneeID: issue.AssigneeID,
|
||||
MentionIDs: mentionIDs,
|
||||
|
|
|
@ -338,7 +338,7 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) {
|
|||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProjectBoards,
|
||||
prometheus.GaugeValue,
|
||||
float64(stats.Counter.ProjectBoard),
|
||||
float64(stats.Counter.ProjectColumn),
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PublicKeys,
|
||||
|
|
|
@ -141,7 +141,7 @@ func canWriteProjects(ctx *context.Context) bool {
|
|||
// RenderNewProject render creating a project page
|
||||
func RenderNewProject(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
|
||||
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
|
||||
ctx.Data["BoardTypes"] = project_model.GetBoardViewConfig()
|
||||
ctx.Data["CardTypes"] = project_model.GetCardConfig()
|
||||
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
|
||||
ctx.Data["PageIsViewProjects"] = true
|
||||
|
@ -170,12 +170,12 @@ func NewProjectPost(ctx *context.Context) {
|
|||
}
|
||||
|
||||
newProject := project_model.Project{
|
||||
OwnerID: ctx.ContextUser.ID,
|
||||
Title: form.Title,
|
||||
Description: form.Content,
|
||||
CreatorID: ctx.Doer.ID,
|
||||
BoardType: form.BoardType,
|
||||
CardType: form.CardType,
|
||||
OwnerID: ctx.ContextUser.ID,
|
||||
Title: form.Title,
|
||||
Description: form.Content,
|
||||
CreatorID: ctx.Doer.ID,
|
||||
BoardViewType: form.BoardType,
|
||||
CardType: form.CardType,
|
||||
}
|
||||
|
||||
if ctx.ContextUser.IsOrganization() {
|
||||
|
@ -327,13 +327,13 @@ func ViewProject(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
boards, err := project.GetBoards(ctx)
|
||||
boards, err := project.GetColumns(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProjectBoards", err)
|
||||
return
|
||||
}
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards)
|
||||
issuesMap, err := issues_model.LoadIssuesFromColumnList(ctx, boards)
|
||||
if err != nil {
|
||||
ctx.ServerError("LoadIssuesOfBoards", err)
|
||||
return
|
||||
|
@ -458,8 +458,8 @@ func UpdateIssueProject(ctx *context.Context) {
|
|||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// DeleteProjectBoard allows for the deletion of a project board
|
||||
func DeleteProjectBoard(ctx *context.Context) {
|
||||
// DeleteProjectColumn allows for the deletion of a project board
|
||||
func DeleteProjectColumn(ctx *context.Context) {
|
||||
if ctx.Doer == nil {
|
||||
ctx.JSON(http.StatusForbidden, map[string]string{
|
||||
"message": "Only signed in users are allowed to perform this action.",
|
||||
|
@ -473,7 +473,7 @@ func DeleteProjectBoard(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
pb, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
pb, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
return
|
||||
|
@ -492,7 +492,7 @@ func DeleteProjectBoard(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := project_model.DeleteBoardByID(ctx, ctx.ParamsInt64(":boardID")); err != nil {
|
||||
if err := project_model.DeleteColumnByID(ctx, ctx.ParamsInt64(":boardID")); err != nil {
|
||||
ctx.ServerError("DeleteProjectBoardByID", err)
|
||||
return
|
||||
}
|
||||
|
@ -500,9 +500,9 @@ func DeleteProjectBoard(ctx *context.Context) {
|
|||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// AddBoardToProjectPost allows a new board to be added to a project.
|
||||
func AddBoardToProjectPost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectBoardForm)
|
||||
// AddColumnToProjectPost allows a new board to be added to a project.
|
||||
func AddColumnToProjectPost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectColumnForm)
|
||||
|
||||
project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
|
@ -510,7 +510,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := project_model.NewBoard(ctx, &project_model.Board{
|
||||
if err := project_model.NewColumn(ctx, &project_model.Column{
|
||||
ProjectID: project.ID,
|
||||
Title: form.Title,
|
||||
Color: form.Color,
|
||||
|
@ -524,7 +524,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
|
|||
}
|
||||
|
||||
// CheckProjectBoardChangePermissions check permission
|
||||
func CheckProjectBoardChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Board) {
|
||||
func CheckProjectBoardChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Column) {
|
||||
if ctx.Doer == nil {
|
||||
ctx.JSON(http.StatusForbidden, map[string]string{
|
||||
"message": "Only signed in users are allowed to perform this action.",
|
||||
|
@ -538,7 +538,7 @@ func CheckProjectBoardChangePermissions(ctx *context.Context) (*project_model.Pr
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
board, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
return nil, nil
|
||||
|
@ -559,9 +559,9 @@ func CheckProjectBoardChangePermissions(ctx *context.Context) (*project_model.Pr
|
|||
return project, board
|
||||
}
|
||||
|
||||
// EditProjectBoard allows a project board's to be updated
|
||||
func EditProjectBoard(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectBoardForm)
|
||||
// EditProjectColumn allows a project board's to be updated
|
||||
func EditProjectColumn(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectColumnForm)
|
||||
_, board := CheckProjectBoardChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
|
@ -577,7 +577,7 @@ func EditProjectBoard(ctx *context.Context) {
|
|||
board.Sorting = form.Sorting
|
||||
}
|
||||
|
||||
if err := project_model.UpdateBoard(ctx, board); err != nil {
|
||||
if err := project_model.UpdateColumn(ctx, board); err != nil {
|
||||
ctx.ServerError("UpdateProjectBoard", err)
|
||||
return
|
||||
}
|
||||
|
@ -592,7 +592,7 @@ func SetDefaultProjectBoard(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := project_model.SetDefaultBoard(ctx, project.ID, board.ID); err != nil {
|
||||
if err := project_model.SetDefaultColumn(ctx, project.ID, board.ID); err != nil {
|
||||
ctx.ServerError("SetDefaultBoard", err)
|
||||
return
|
||||
}
|
||||
|
@ -619,9 +619,9 @@ func MoveIssues(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
board, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetProjectBoard", project_model.IsErrProjectBoardNotExist, err)
|
||||
ctx.NotFoundOrServerError("GetProjectBoard", project_model.IsErrProjectColumnNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -671,7 +671,7 @@ func MoveIssues(ctx *context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
if err = project_model.MoveIssuesOnProjectBoard(ctx, board, sortedIssueIDs); err != nil {
|
||||
if err = project_model.MoveIssuesOnProjectColumn(ctx, board, sortedIssueIDs); err != nil {
|
||||
ctx.ServerError("MoveIssuesOnProjectBoard", err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2826,12 +2826,12 @@ func ListIssues(ctx *context.Context) {
|
|||
Page: ctx.FormInt("page"),
|
||||
PageSize: convert.ToCorrectPageSize(ctx.FormInt("limit")),
|
||||
},
|
||||
Keyword: keyword,
|
||||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||
IsPull: isPull,
|
||||
IsClosed: isClosed,
|
||||
ProjectBoardID: projectID,
|
||||
SortBy: issue_indexer.SortByCreatedDesc,
|
||||
Keyword: keyword,
|
||||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||
IsPull: isPull,
|
||||
IsClosed: isClosed,
|
||||
ProjectID: projectID,
|
||||
SortBy: issue_indexer.SortByCreatedDesc,
|
||||
}
|
||||
if since != 0 {
|
||||
searchOpt.UpdatedAfterUnix = optional.Some(since)
|
||||
|
|
|
@ -132,7 +132,7 @@ func Projects(ctx *context.Context) {
|
|||
// RenderNewProject render creating a project page
|
||||
func RenderNewProject(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
|
||||
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
|
||||
ctx.Data["BoardTypes"] = project_model.GetBoardViewConfig()
|
||||
ctx.Data["CardTypes"] = project_model.GetCardConfig()
|
||||
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
|
||||
ctx.Data["CancelLink"] = ctx.Repo.Repository.Link() + "/projects"
|
||||
|
@ -150,13 +150,13 @@ func NewProjectPost(ctx *context.Context) {
|
|||
}
|
||||
|
||||
if err := project_model.NewProject(ctx, &project_model.Project{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Title: form.Title,
|
||||
Description: form.Content,
|
||||
CreatorID: ctx.Doer.ID,
|
||||
BoardType: form.BoardType,
|
||||
CardType: form.CardType,
|
||||
Type: project_model.TypeRepository,
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Title: form.Title,
|
||||
Description: form.Content,
|
||||
CreatorID: ctx.Doer.ID,
|
||||
BoardViewType: form.BoardType,
|
||||
CardType: form.CardType,
|
||||
Type: project_model.TypeRepository,
|
||||
}); err != nil {
|
||||
ctx.ServerError("NewProject", err)
|
||||
return
|
||||
|
@ -309,13 +309,13 @@ func ViewProject(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
boards, err := project.GetBoards(ctx)
|
||||
boards, err := project.GetColumns(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProjectBoards", err)
|
||||
return
|
||||
}
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards)
|
||||
issuesMap, err := issues_model.LoadIssuesFromColumnList(ctx, boards)
|
||||
if err != nil {
|
||||
ctx.ServerError("LoadIssuesOfBoards", err)
|
||||
return
|
||||
|
@ -432,7 +432,7 @@ func DeleteProjectBoard(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
pb, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
pb, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
return
|
||||
|
@ -451,7 +451,7 @@ func DeleteProjectBoard(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := project_model.DeleteBoardByID(ctx, ctx.ParamsInt64(":boardID")); err != nil {
|
||||
if err := project_model.DeleteColumnByID(ctx, ctx.ParamsInt64(":boardID")); err != nil {
|
||||
ctx.ServerError("DeleteProjectBoardByID", err)
|
||||
return
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ func DeleteProjectBoard(ctx *context.Context) {
|
|||
|
||||
// AddBoardToProjectPost allows a new board to be added to a project.
|
||||
func AddBoardToProjectPost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectBoardForm)
|
||||
form := web.GetForm(ctx).(*forms.EditProjectColumnForm)
|
||||
if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeProjects) {
|
||||
ctx.JSON(http.StatusForbidden, map[string]string{
|
||||
"message": "Only authorized users are allowed to perform this action.",
|
||||
|
@ -479,7 +479,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := project_model.NewBoard(ctx, &project_model.Board{
|
||||
if err := project_model.NewColumn(ctx, &project_model.Column{
|
||||
ProjectID: project.ID,
|
||||
Title: form.Title,
|
||||
Color: form.Color,
|
||||
|
@ -492,7 +492,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
|
|||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Board) {
|
||||
func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Column) {
|
||||
if ctx.Doer == nil {
|
||||
ctx.JSON(http.StatusForbidden, map[string]string{
|
||||
"message": "Only signed in users are allowed to perform this action.",
|
||||
|
@ -517,7 +517,7 @@ func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Pr
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
board, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
return nil, nil
|
||||
|
@ -538,9 +538,9 @@ func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Pr
|
|||
return project, board
|
||||
}
|
||||
|
||||
// EditProjectBoard allows a project board's to be updated
|
||||
func EditProjectBoard(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectBoardForm)
|
||||
// EditProjectColumn allows a project board's to be updated
|
||||
func EditProjectColumn(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectColumnForm)
|
||||
_, board := checkProjectBoardChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
|
@ -556,7 +556,7 @@ func EditProjectBoard(ctx *context.Context) {
|
|||
board.Sorting = form.Sorting
|
||||
}
|
||||
|
||||
if err := project_model.UpdateBoard(ctx, board); err != nil {
|
||||
if err := project_model.UpdateColumn(ctx, board); err != nil {
|
||||
ctx.ServerError("UpdateProjectBoard", err)
|
||||
return
|
||||
}
|
||||
|
@ -564,14 +564,14 @@ func EditProjectBoard(ctx *context.Context) {
|
|||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// SetDefaultProjectBoard set default board for uncategorized issues/pulls
|
||||
func SetDefaultProjectBoard(ctx *context.Context) {
|
||||
// SetDefaultProjectColumn set default board for uncategorized issues/pulls
|
||||
func SetDefaultProjectColumn(ctx *context.Context) {
|
||||
project, board := checkProjectBoardChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.SetDefaultBoard(ctx, project.ID, board.ID); err != nil {
|
||||
if err := project_model.SetDefaultColumn(ctx, project.ID, board.ID); err != nil {
|
||||
ctx.ServerError("SetDefaultBoard", err)
|
||||
return
|
||||
}
|
||||
|
@ -609,12 +609,12 @@ func MoveIssues(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
board, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectBoardNotExist(err) {
|
||||
ctx.NotFound("ProjectBoardNotExist", nil)
|
||||
if project_model.IsErrProjectColumnNotExist(err) {
|
||||
ctx.NotFound("ProjectColumnNotExist", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
ctx.ServerError("GetProjectColumn", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -664,8 +664,8 @@ func MoveIssues(ctx *context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
if err = project_model.MoveIssuesOnProjectBoard(ctx, board, sortedIssueIDs); err != nil {
|
||||
ctx.ServerError("MoveIssuesOnProjectBoard", err)
|
||||
if err = project_model.MoveIssuesOnProjectColumn(ctx, board, sortedIssueIDs); err != nil {
|
||||
ctx.ServerError("MoveIssuesOnProjectColumn", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -997,7 +997,7 @@ func registerRoutes(m *web.Route) {
|
|||
m.Get("/new", org.RenderNewProject)
|
||||
m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
|
||||
m.Group("/{id}", func() {
|
||||
m.Post("", web.Bind(forms.EditProjectBoardForm{}), org.AddBoardToProjectPost)
|
||||
m.Post("", web.Bind(forms.EditProjectColumnForm{}), org.AddColumnToProjectPost)
|
||||
m.Post("/delete", org.DeleteProject)
|
||||
|
||||
m.Get("/edit", org.RenderEditProject)
|
||||
|
@ -1005,8 +1005,8 @@ func registerRoutes(m *web.Route) {
|
|||
m.Post("/{action:open|close}", org.ChangeProjectStatus)
|
||||
|
||||
m.Group("/{boardID}", func() {
|
||||
m.Put("", web.Bind(forms.EditProjectBoardForm{}), org.EditProjectBoard)
|
||||
m.Delete("", org.DeleteProjectBoard)
|
||||
m.Put("", web.Bind(forms.EditProjectColumnForm{}), org.EditProjectColumn)
|
||||
m.Delete("", org.DeleteProjectColumn)
|
||||
m.Post("/default", org.SetDefaultProjectBoard)
|
||||
|
||||
m.Post("/move", org.MoveIssues)
|
||||
|
@ -1336,7 +1336,7 @@ func registerRoutes(m *web.Route) {
|
|||
m.Get("/new", repo.RenderNewProject)
|
||||
m.Post("/new", web.Bind(forms.CreateProjectForm{}), repo.NewProjectPost)
|
||||
m.Group("/{id}", func() {
|
||||
m.Post("", web.Bind(forms.EditProjectBoardForm{}), repo.AddBoardToProjectPost)
|
||||
m.Post("", web.Bind(forms.EditProjectColumnForm{}), repo.AddBoardToProjectPost)
|
||||
m.Post("/delete", repo.DeleteProject)
|
||||
|
||||
m.Get("/edit", repo.RenderEditProject)
|
||||
|
@ -1344,9 +1344,9 @@ func registerRoutes(m *web.Route) {
|
|||
m.Post("/{action:open|close}", repo.ChangeProjectStatus)
|
||||
|
||||
m.Group("/{boardID}", func() {
|
||||
m.Put("", web.Bind(forms.EditProjectBoardForm{}), repo.EditProjectBoard)
|
||||
m.Put("", web.Bind(forms.EditProjectColumnForm{}), repo.EditProjectColumn)
|
||||
m.Delete("", repo.DeleteProjectBoard)
|
||||
m.Post("/default", repo.SetDefaultProjectBoard)
|
||||
m.Post("/default", repo.SetDefaultProjectColumn)
|
||||
|
||||
m.Post("/move", repo.MoveIssues)
|
||||
})
|
||||
|
|
|
@ -504,18 +504,11 @@ func (i IssueLockForm) HasValidReason() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// __________ __ __
|
||||
// \______ \_______ ____ |__| ____ _____/ |_ ______
|
||||
// | ___/\_ __ \/ _ \ | |/ __ \_/ ___\ __\/ ___/
|
||||
// | | | | \( <_> ) | \ ___/\ \___| | \___ \
|
||||
// |____| |__| \____/\__| |\___ >\___ >__| /____ >
|
||||
// \______| \/ \/ \/
|
||||
|
||||
// CreateProjectForm form for creating a project
|
||||
type CreateProjectForm struct {
|
||||
Title string `binding:"Required;MaxSize(100)"`
|
||||
Content string
|
||||
BoardType project_model.BoardType
|
||||
BoardType project_model.BoardViewType
|
||||
CardType project_model.CardType
|
||||
}
|
||||
|
||||
|
@ -524,25 +517,18 @@ type CreateProjectForm struct {
|
|||
type UserCreateProjectForm struct {
|
||||
Title string `binding:"Required;MaxSize(100)"`
|
||||
Content string
|
||||
BoardType project_model.BoardType
|
||||
BoardType project_model.BoardViewType
|
||||
CardType project_model.CardType
|
||||
UID int64 `binding:"Required"`
|
||||
}
|
||||
|
||||
// EditProjectBoardForm is a form for editing a project board
|
||||
type EditProjectBoardForm struct {
|
||||
// EditProjectColumnForm is a form for editing a project board
|
||||
type EditProjectColumnForm struct {
|
||||
Title string `binding:"Required;MaxSize(100)"`
|
||||
Sorting int8
|
||||
Color string `binding:"MaxSize(7)"`
|
||||
}
|
||||
|
||||
// _____ .__.__ __
|
||||
// / \ |__| | ____ _______/ |_ ____ ____ ____
|
||||
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
|
||||
// / Y \ | |_\ ___/ \___ \ | | ( <_> ) | \ ___/
|
||||
// \____|__ /__|____/\___ >____ > |__| \____/|___| /\___ >
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
// CreateMilestoneForm form for creating milestone
|
||||
type CreateMilestoneForm struct {
|
||||
Title string `binding:"Required;MaxSize(50)"`
|
||||
|
@ -556,13 +542,6 @@ func (f *CreateMilestoneForm) Validate(req *http.Request, errs binding.Errors) b
|
|||
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// .____ ___. .__
|
||||
// | | _____ \_ |__ ____ | |
|
||||
// | | \__ \ | __ \_/ __ \| |
|
||||
// | |___ / __ \| \_\ \ ___/| |__
|
||||
// |_______ (____ /___ /\___ >____/
|
||||
// \/ \/ \/ \/
|
||||
|
||||
// CreateLabelForm form for creating label
|
||||
type CreateLabelForm struct {
|
||||
ID int64
|
||||
|
@ -590,13 +569,6 @@ func (f *InitializeLabelsForm) Validate(req *http.Request, errs binding.Errors)
|
|||
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __________ .__ .__ __________ __
|
||||
// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
|
||||
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
|
||||
// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
|
||||
// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
|
||||
// \/ \/ |__| \/ \/
|
||||
|
||||
// MergePullRequestForm form for merging Pull Request
|
||||
// swagger:model MergePullRequestOption
|
||||
type MergePullRequestForm struct {
|
||||
|
|
Loading…
Reference in New Issue