diff --git a/models/activities/statistic.go b/models/activities/statistic.go index ea785a3ee2629..b830055e363fc 100644 --- a/models/activities/statistic.go +++ b/models/activities/statistic.go @@ -28,7 +28,7 @@ type Statistic struct { Mirror, Release, AuthSource, Webhook, Milestone, Label, HookTask, Team, UpdateTask, Project, - ProjectBoard, Attachment int64 + ProjectColumn, Attachment int64 IssueByLabel []IssueByLabelCount IssueByRepository []IssueByRepositoryCount } @@ -110,6 +110,6 @@ func GetStatistic() (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 } diff --git a/models/fixtures/project_board.yml b/models/fixtures/project_column.yml similarity index 100% rename from models/fixtures/project_board.yml rename to models/fixtures/project_column.yml diff --git a/models/fixtures/project_issue.yml b/models/fixtures/project_issue.yml index b1af05908aafb..6a486ace23e2e 100644 --- a/models/fixtures/project_issue.yml +++ b/models/fixtures/project_issue.yml @@ -2,22 +2,22 @@ id: 1 issue_id: 1 project_id: 1 - project_board_id: 1 + project_column_id: 1 - id: 2 issue_id: 2 project_id: 1 - project_board_id: 0 # no board assigned + project_column_id: 0 # no board assigned - id: 3 issue_id: 3 project_id: 1 - project_board_id: 2 + project_column_id: 2 - id: 4 issue_id: 5 project_id: 1 - project_board_id: 3 + project_column_id: 3 diff --git a/models/issues/issue.go b/models/issues/issue.go index 49bc229c6bd03..2f8fef3e88196 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -1189,7 +1189,7 @@ type IssuesOptions struct { //nolint SubscriberID int64 MilestoneIDs []int64 ProjectID int64 - ProjectBoardID int64 + ProjectColumnID int64 IsClosed util.OptionalBool IsPull util.OptionalBool LabelIDs []int64 @@ -1320,11 +1320,11 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) { And("project_issue.project_id=?", opts.ProjectID) } - if opts.ProjectBoardID != 0 { - if opts.ProjectBoardID > 0 { - sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_board_id": opts.ProjectBoardID})) + if opts.ProjectColumnID != 0 { + if opts.ProjectColumnID > 0 { + sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_column_id": opts.ProjectColumnID})) } else { - sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_board_id": 0})) + sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_column_id": 0})) } } diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index 8299087c5b108..14b18d0220e66 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -46,29 +46,29 @@ 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() int64 { - return issue.projectBoardID(db.DefaultContext) +// ProjectColumnID returns project column id if issue was assigned to one +func (issue *Issue) ProjectColumnID() int64 { + return issue.projectColumnID(db.DefaultContext) } -func (issue *Issue) projectBoardID(ctx context.Context) int64 { +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(b *project_model.Board) (IssueList, error) { +// LoadIssuesFromColumn loads issues assigned to this column +func LoadIssuesFromColumn(b *project_model.Column) (IssueList, error) { issueList := make([]*Issue, 0, 10) if b.ID != 0 { issues, err := Issues(&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 @@ -78,9 +78,9 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { if b.Default { issues, err := Issues(&IssuesOptions{ - ProjectBoardID: -1, // Issues without ProjectBoardID - ProjectID: b.ProjectID, - SortType: "project-column-sorting", + ProjectColumnID: -1, // Issues without ProjectColumnID + ProjectID: b.ProjectID, + SortType: "project-column-sorting", }) if err != nil { return nil, err @@ -95,11 +95,11 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { return issueList, nil } -// LoadIssuesFromBoardList load issues assigned to the boards -func LoadIssuesFromBoardList(bs project_model.BoardList) (map[int64]IssueList, error) { +// LoadIssuesFromColumnList load issues assigned to the columns +func LoadIssuesFromColumnList(bs project_model.Columns) (map[int64]IssueList, error) { issuesMap := make(map[int64]IssueList, len(bs)) for i := range bs { - il, err := LoadIssuesFromBoard(bs[i]) + il, err := LoadIssuesFromColumn(bs[i]) if err != nil { return nil, err } @@ -164,8 +164,8 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U }) } -// MoveIssueAcrossProjectBoards move a card from one board to another -func MoveIssueAcrossProjectBoards(issue *Issue, board *project_model.Board) error { +// MoveIssueAcrossProjectColumn move a card from one column to another +func MoveIssueAcrossProjectColumns(issue *Issue, column *project_model.Column) error { ctx, committer, err := db.TxContext() if err != nil { return err @@ -183,8 +183,8 @@ func MoveIssueAcrossProjectBoards(issue *Issue, board *project_model.Board) erro return fmt.Errorf("issue has to be added to a project first") } - pis.ProjectBoardID = board.ID - if _, err := sess.ID(pis.ID).Cols("project_board_id").Update(&pis); err != nil { + pis.ProjectColumnID = column.ID + if _, err := sess.ID(pis.ID).Cols("project_column_id").Update(&pis); err != nil { return err } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 28ffc998860bf..b4e008ae61b6c 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -413,6 +413,8 @@ var migrations = []Migration{ NewMigration("Add badges to users", createUserBadgesTable), // v225 -> v226 NewMigration("Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT", alterPublicGPGKeyContentFieldsToMediumText), + // v226 -> 227 + NewMigration("Rename project boards to columns", renameProjectBoardsToColumns), } // GetCurrentDBVersion returns the current db version @@ -1014,3 +1016,39 @@ func modifyColumn(x *xorm.Engine, tableName string, col *schemas.Column) error { } return nil } + +func renameTable(sess *xorm.Session, old, new string) error { + dialect := sess.Engine().Dialect().URI().DBType + + switch dialect { + case schemas.MYSQL: + _, err := sess.Exec(fmt.Sprintf("RENAME TABLE `%s` TO `%s`;", old, new)) + return err + case schemas.POSTGRES, schemas.SQLITE: + _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`;", old, new)) + return err + case schemas.MSSQL: + _, err := sess.Exec(fmt.Sprintf("sp_rename `%s`,`%s`", old, new)) + return err + default: + return fmt.Errorf("dialect '%s' not supported", dialect) + } +} + +func renameColumn(sess *xorm.Session, table, old, new string) error { + dialect := sess.Engine().Dialect().URI().DBType + + switch dialect { + case schemas.MYSQL: + _, err := sess.Exec("ALTER TABLE `task` CHANGE errors message text") + return err + case schemas.POSTGRES, schemas.SQLITE: + _, err := sess.Exec("ALTER TABLE `task` RENAME COLUMN errors TO message") + return err + case schemas.MSSQL: + _, err := sess.Exec("sp_rename 'task.errors', 'message', 'COLUMN'") + return err + default: + return fmt.Errorf("dialect '%s' not supported", dialect) + } +} diff --git a/models/migrations/v226.go b/models/migrations/v226.go new file mode 100644 index 0000000000000..62eb39e43f074 --- /dev/null +++ b/models/migrations/v226.go @@ -0,0 +1,27 @@ +// Copyright 2022 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 migrations + +import ( + "xorm.io/xorm" +) + +func renameProjectBoardsToColumns(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return err + } + + if err := renameTable(sess, "project_board", "project_column"); err != nil { + return err + } + + if err := renameColumn(sess, "project_issue", "project_board_id", "project_column_id"); err != nil { + return err + } + + return sess.Commit() +} diff --git a/models/project/board.go b/models/project/board.go deleted file mode 100644 index be7119ee4db3a..0000000000000 --- a/models/project/board.go +++ /dev/null @@ -1,276 +0,0 @@ -// 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 { - board, err := GetBoard(ctx, boardID) - if err != nil { - if IsErrProjectBoardNotExist(err) { - return nil - } - - return err - } - - 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 -// if no default board set, first board is a temporary "Uncategorized" board -func GetBoards(ctx context.Context, projectID int64) (BoardList, error) { - boards := make([]*Board, 0, 5) - - if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", projectID, false).OrderBy("Sorting").Find(&boards); err != nil { - return nil, err - } - - defaultB, err := getDefaultBoard(ctx, 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(ctx context.Context, projectID int64) (*Board, error) { - var board Board - exist, err := db.GetEngine(ctx).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 -} diff --git a/models/project/column.go b/models/project/column.go new file mode 100644 index 0000000000000..79485ec589438 --- /dev/null +++ b/models/project/column.go @@ -0,0 +1,276 @@ +// 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 + + // Columns is a list of all project columns in a repository + Columns []*Column +) + +const ( + // BoardTypeNone is a project board type that has no predefined columns + BoardTypeNone BoardType = iota + + // BoardTypeBasicKanban is a project Column type that has basic predefined columns + BoardTypeBasicKanban + + // BoardTypeBugTriage is a project type that has predefined columns suited to hunting down bugs + BoardTypeBugTriage +) + +// ColumnColorPattern is a regexp witch can validate ColumnColor +var ColumnColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$") + +// Column is used to represent columns 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_column" +} + +// NumIssues return counter of all issues assigned to the column +func (b *Column) NumIssues() int { + c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). + Where("project_id=?", b.ProjectID). + And("project_column_id=?", b.ID). + GroupBy("issue_id"). + Cols("issue_id"). + Count() + if err != nil { + return 0 + } + return int(c) +} + +func init() { + db.RegisterModel(new(Column)) +} + +// IsColumnTypeValid 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 createColumnsForProjectsType(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 + } + + columns := make([]Column, 0, len(items)) + + for _, v := range items { + columns = append(columns, Column{ + CreatedUnix: timeutil.TimeStampNow(), + CreatorID: project.CreatorID, + Title: v, + ProjectID: project.ID, + }) + } + + return db.Insert(ctx, columns) +} + +// NewColumn adds a new column to a given project +func NewColumn(column *Column) error { + if len(column.Color) != 0 && !ColumnColorPattern.MatchString(column.Color) { + return fmt.Errorf("bad color code: %s", column.Color) + } + + _, err := db.GetEngine(db.DefaultContext).Insert(column) + return err +} + +// DeleteColumnByID removes all issues references to the column +func DeleteColumnByID(columnID int64) error { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := deleteColumnByID(ctx, columnID); err != nil { + return err + } + + return committer.Commit() +} + +func deleteColumnByID(ctx context.Context, columnID int64) error { + column, err := GetColumn(ctx, columnID) + if err != nil { + if IsErrProjectColumnNotExist(err) { + return nil + } + + return err + } + + 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 column of a project +func GetColumn(ctx context.Context, columnID int64) (*Column, error) { + column := new(Column) + + has, err := db.GetEngine(ctx).ID(columnID).Get(column) + if err != nil { + return nil, err + } else if !has { + return nil, ErrProjectColumnNotExist{ColumnID: columnID} + } + + return column, 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 columns related to a project +// if no default column is set, first column is a temporary "Uncategorized" column +func GetColumns(ctx context.Context, projectID int64) (Columns, error) { + columns := make([]*Column, 0, 5) + + if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", projectID, false).OrderBy("Sorting").Find(&columns); err != nil { + return nil, err + } + + defaultB, err := getDefaultColumn(ctx, projectID) + if err != nil { + return nil, err + } + + return append([]*Column{defaultB}, columns...), nil +} + +// getDefaultColumn return default column and create a dummy if none exist +func getDefaultColumn(ctx context.Context, projectID int64) (*Column, error) { + var column Column + exist, err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", projectID, true).Get(&column) + if err != nil { + return nil, err + } + if exist { + return &column, nil + } + + // represents a column for issues not assigned to one + return &Column{ + ProjectID: projectID, + Title: "Uncategorized", + Default: true, + }, nil +} + +// SetDefaultColumn represents a column for issues not assigned to one +// if columnID is 0 unset default +func SetDefaultColumn(projectID, columnID int64) error { + _, err := db.GetEngine(db.DefaultContext).Where(builder.Eq{ + "project_id": projectID, + "`default`": true, + }).Cols("`default`").Update(&Column{Default: false}) + if err != nil { + return err + } + + if columnID > 0 { + _, err = db.GetEngine(db.DefaultContext).ID(columnID).Where(builder.Eq{"project_id": projectID}). + Cols("`default`").Update(&Column{Default: true}) + } + + return err +} + +// UpdateCoumnSorting update column sorting +func UpdateColumnSorting(bs Columns) 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 +} diff --git a/models/project/issue.go b/models/project/issue.go index 59af7063a546f..ec1ea882dc30c 100644 --- a/models/project/issue.go +++ b/models/project/issue.go @@ -18,10 +18,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 on the project + ProjectColumnID int64 `xorm:"INDEX"` - // the sorting order on the board + // the sorting order in the column Sorting int64 `xorm:"NOT NULL DEFAULT 0"` } @@ -76,8 +76,8 @@ func (p *Project) NumOpenIssues() int { return int(c) } -// MoveIssuesOnProjectBoard moves or keeps issues in a column and sorts them inside that column -func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) error { +// MoveIssuesOnProjectColumn moves or keeps issues in a column and sorts them inside that column +func MoveIssuesOnProjectColumn(column *Column, sortedIssueIDs map[int64]int64) error { return db.WithTx(func(ctx context.Context) error { sess := db.GetEngine(ctx) @@ -85,7 +85,7 @@ func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) erro for _, issueID := range sortedIssueIDs { issueIDs = append(issueIDs, issueID) } - count, err := sess.Table(new(ProjectIssue)).Where("project_id=?", board.ProjectID).In("issue_id", issueIDs).Count() + count, err := sess.Table(new(ProjectIssue)).Where("project_id=?", column.ProjectID).In("issue_id", issueIDs).Count() if err != nil { return err } @@ -94,7 +94,7 @@ func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) erro } for sorting, issueID := range sortedIssueIDs { - _, err = sess.Exec("UPDATE `project_issue` SET project_board_id=?, sorting=? WHERE issue_id=?", board.ID, sorting, issueID) + _, err = sess.Exec("UPDATE `project_issue` SET project_column_id=?, sorting=? WHERE issue_id=?", column.ID, sorting, issueID) if err != nil { return err } @@ -103,7 +103,7 @@ func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) erro }) } -func (b *Board) removeIssues(ctx context.Context) error { - _, err := db.GetEngine(ctx).Exec("UPDATE `project_issue` SET project_board_id = 0 WHERE project_board_id = ? ", b.ID) +func (b *Column) removeIssues(ctx context.Context) error { + _, err := db.GetEngine(ctx).Exec("UPDATE `project_issue` SET project_column_id = 0 WHERE project_column_id = ? ", b.ID) return err } diff --git a/models/project/main_test.go b/models/project/main_test.go index 2e97b3a5ef3b5..d4afd6b139ebc 100644 --- a/models/project/main_test.go +++ b/models/project/main_test.go @@ -18,7 +18,7 @@ func TestMain(m *testing.M) { GiteaRootPath: filepath.Join("..", ".."), FixtureFiles: []string{ "project.yml", - "project_board.yml", + "project_column.yml", "project_issue.yml", "repository.yml", }, diff --git a/models/project/project.go b/models/project/project.go index 86a77947d8838..0d8750902047e 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -55,19 +55,19 @@ func (err ErrProjectNotExist) Error() string { return fmt.Sprintf("projects does not exist [id: %d]", err.ID) } -// ErrProjectBoardNotExist represents a "ProjectBoardNotExist" kind of error. -type ErrProjectBoardNotExist struct { - BoardID int64 +// ErrProjectColumnNotExist represents a "ErrProjectColumnNotExist" 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 ErrProjectColumnNotExist +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) } // Project represents a project board @@ -186,7 +186,7 @@ func NewProject(p *Project) error { return err } - if err := createBoardsForProjectsType(ctx, p); err != nil { + if err := createColumnsForProjectsType(ctx, p); err != nil { return err } @@ -320,7 +320,7 @@ func DeleteProjectByIDCtx(ctx context.Context, id int64) error { return err } - if err := deleteBoardByProjectID(ctx, id); err != nil { + if err := deleteColumnByProjectID(ctx, id); err != nil { return err } @@ -337,7 +337,7 @@ func DeleteProjectByRepoIDCtx(ctx context.Context, repoID int64) error { if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_issue WHERE project_issue.id IN (SELECT project_issue.id FROM project_issue INNER JOIN project WHERE project.id = project_issue.project_id AND project.repo_id = ?)", repoID); err != nil { return err } - if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_board WHERE project_board.id IN (SELECT project_board.id FROM project_board INNER JOIN project WHERE project.id = project_board.project_id AND project.repo_id = ?)", repoID); err != nil { + if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_column WHERE project_column.id IN (SELECT project_column.id FROM project_column INNER JOIN project WHERE project.id = project_column.project_id AND project.repo_id = ?)", repoID); err != nil { return err } if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil { @@ -347,7 +347,7 @@ func DeleteProjectByRepoIDCtx(ctx context.Context, repoID int64) error { if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_issue USING project WHERE project.id = project_issue.project_id AND project.repo_id = ? ", repoID); err != nil { return err } - if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_board USING project WHERE project.id = project_board.project_id AND project.repo_id = ? ", repoID); err != nil { + if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_column USING project WHERE project.id = project_column.project_id AND project.repo_id = ? ", repoID); err != nil { return err } if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil { @@ -357,7 +357,7 @@ func DeleteProjectByRepoIDCtx(ctx context.Context, repoID int64) error { if _, err := db.GetEngine(ctx).Exec("DELETE project_issue FROM project_issue INNER JOIN project ON project.id = project_issue.project_id WHERE project.repo_id = ? ", repoID); err != nil { return err } - if _, err := db.GetEngine(ctx).Exec("DELETE project_board FROM project_board INNER JOIN project ON project.id = project_board.project_id WHERE project.repo_id = ? ", repoID); err != nil { + if _, err := db.GetEngine(ctx).Exec("DELETE project_column FROM project_column INNER JOIN project ON project.id = project_column.project_id WHERE project.repo_id = ? ", repoID); err != nil { return err } if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil { diff --git a/modules/metrics/collector.go b/modules/metrics/collector.go index dcd80b05a97dc..c3b81be5d3183 100755 --- a/modules/metrics/collector.go +++ b/modules/metrics/collector.go @@ -33,7 +33,7 @@ type Collector struct { Oauths *prometheus.Desc Organizations *prometheus.Desc Projects *prometheus.Desc - ProjectBoards *prometheus.Desc + ProjectColumns *prometheus.Desc PublicKeys *prometheus.Desc Releases *prometheus.Desc Repositories *prometheus.Desc @@ -138,9 +138,9 @@ func NewCollector() Collector { "Number of projects", nil, nil, ), - ProjectBoards: prometheus.NewDesc( - namespace+"projects_boards", - "Number of project boards", + ProjectColumns: prometheus.NewDesc( + namespace+"projects_columns", + "Number of project columns", nil, nil, ), PublicKeys: prometheus.NewDesc( @@ -211,7 +211,7 @@ func (c Collector) Describe(ch chan<- *prometheus.Desc) { ch <- c.Oauths ch <- c.Organizations ch <- c.Projects - ch <- c.ProjectBoards + ch <- c.ProjectColumns ch <- c.PublicKeys ch <- c.Releases ch <- c.Repositories @@ -324,9 +324,9 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) { float64(stats.Counter.Project), ) ch <- prometheus.MustNewConstMetric( - c.ProjectBoards, + c.ProjectColumns, prometheus.GaugeValue, - float64(stats.Counter.ProjectBoard), + float64(stats.Counter.ProjectColumn), ) ch <- prometheus.MustNewConstMetric( c.PublicKeys, diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 1dba1d71d8ffe..549d3142e586b 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -57,7 +57,7 @@ new_mirror = New Mirror new_fork = New Repository Fork new_org = New Organization new_project = New Project -new_project_board = New Project board +new_project_column = New Project column manage_org = Manage Organizations admin_panel = Site Administration account_settings = Account Settings @@ -1017,7 +1017,7 @@ branches = Branches tags = Tags issues = Issues pulls = Pull Requests -project_board = Projects +project_column = Projects packages = Packages labels = Labels org_labels_desc = Organization level labels that can be used with all repositories under this organization @@ -1183,19 +1183,19 @@ projects.type.bug_triage = "Bug Triage" projects.template.desc = "Project template" projects.template.desc_helper = "Select a project template to get started" projects.type.uncategorized = Uncategorized -projects.board.edit = "Edit board" -projects.board.edit_title = "New Board Name" -projects.board.new_title = "New Board Name" -projects.board.new_submit = "Submit" -projects.board.new = "New Board" -projects.board.set_default = "Set Default" -projects.board.set_default_desc = "Set this board as default for uncategorized issues and pulls" -projects.board.delete = "Delete Board" -projects.board.deletion_desc = "Deleting a project board moves all related issues to 'Uncategorized'. Continue?" -projects.board.color = "Color" +projects.column.edit = "Edit column" +projects.column.edit_title = "New column Name" +projects.column.new_title = "New column Name" +projects.column.new_submit = "Submit" +projects.column.new = "New column" +projects.column.set_default = "Set Default" +projects.column.set_default_desc = "Set this column as default for uncategorized issues and pulls" +projects.column.delete = "Delete column" +projects.column.deletion_desc = "Deleting a project column moves all related issues to 'Uncategorized'. Continue?" +projects.column.color = "Color" projects.open = Open projects.close = Close -projects.board.assigned_to = Assigned to +projects.column.assigned_to = Assigned to issues.desc = Organize bug reports, tasks and milestones. issues.filter_assignees = Filter Assignee diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index f054ad6e540bd..0a0d26480444a 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -50,7 +50,7 @@ func MustEnableProjects(ctx *context.Context) { // Projects renders the home page of projects func Projects(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("repo.project_board") + ctx.Data["Title"] = ctx.Tr("repo.project_column") sortType := ctx.FormTrim("sort") @@ -271,7 +271,7 @@ func EditProjectPost(ctx *context.Context) { ctx.Redirect(ctx.Repo.RepoLink + "/projects") } -// ViewProject renders the project board for a project +// ViewProject renders the project column for a project func ViewProject(ctx *context.Context) { project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) if err != nil { @@ -287,19 +287,19 @@ func ViewProject(ctx *context.Context) { return } - boards, err := project_model.GetBoards(ctx, project.ID) + columns, err := project_model.GetColumns(ctx, project.ID) if err != nil { - ctx.ServerError("GetProjectBoards", err) + ctx.ServerError("GetProjectColumns", err) return } - if boards[0].ID == 0 { - boards[0].Title = ctx.Tr("repo.projects.type.uncategorized") + if columns[0].ID == 0 { + columns[0].Title = ctx.Tr("repo.projects.type.uncategorized") } - issuesMap, err := issues_model.LoadIssuesFromBoardList(boards) + issuesMap, err := issues_model.LoadIssuesFromColumnList(columns) if err != nil { - ctx.ServerError("LoadIssuesOfBoards", err) + ctx.ServerError("LoadIssuesOfColumns", err) return } @@ -340,7 +340,7 @@ func ViewProject(ctx *context.Context) { ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.Data["Project"] = project ctx.Data["IssuesMap"] = issuesMap - ctx.Data["Boards"] = boards + ctx.Data["Columns"] = columns ctx.HTML(http.StatusOK, tplProjectsView) } @@ -370,8 +370,8 @@ func UpdateIssueProject(ctx *context.Context) { }) } -// DeleteProjectBoard allows for the deletion of a project board -func DeleteProjectBoard(ctx *context.Context) { +// DeleteProjectColumn allows for the deletion of a project column +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.", @@ -396,27 +396,27 @@ func DeleteProjectBoard(ctx *context.Context) { return } - pb, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID")) + pb, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":columnID")) if err != nil { - ctx.ServerError("GetProjectBoard", err) + ctx.ServerError("GetProjectColumn", err) return } if pb.ProjectID != ctx.ParamsInt64(":id") { ctx.JSON(http.StatusUnprocessableEntity, map[string]string{ - "message": fmt.Sprintf("ProjectBoard[%d] is not in Project[%d] as expected", pb.ID, project.ID), + "message": fmt.Sprintf("ProjectColumn[%d] is not in Project[%d] as expected", pb.ID, project.ID), }) return } if project.RepoID != ctx.Repo.Repository.ID { ctx.JSON(http.StatusUnprocessableEntity, map[string]string{ - "message": fmt.Sprintf("ProjectBoard[%d] is not in Repository[%d] as expected", pb.ID, ctx.Repo.Repository.ID), + "message": fmt.Sprintf("ProjectColumn[%d] is not in Repository[%d] as expected", pb.ID, ctx.Repo.Repository.ID), }) return } - if err := project_model.DeleteBoardByID(ctx.ParamsInt64(":boardID")); err != nil { - ctx.ServerError("DeleteProjectBoardByID", err) + if err := project_model.DeleteColumnByID(ctx.ParamsInt64(":columnID")); err != nil { + ctx.ServerError("DeleteProjectColumnByID", err) return } @@ -425,9 +425,9 @@ 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) +// AddColumnToProjectPost allows a new column to be added to a project. +func AddColumnToProjectPost(ctx *context.Context) { + 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.", @@ -445,13 +445,13 @@ func AddBoardToProjectPost(ctx *context.Context) { return } - if err := project_model.NewBoard(&project_model.Board{ + if err := project_model.NewColumn(&project_model.Column{ ProjectID: project.ID, Title: form.Title, Color: form.Color, CreatorID: ctx.Doer.ID, }); err != nil { - ctx.ServerError("NewProjectBoard", err) + ctx.ServerError("NewProjectColumn", err) return } @@ -460,7 +460,7 @@ func AddBoardToProjectPost(ctx *context.Context) { }) } -func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Board) { +func checkProjectColumnChangePermissions(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.", @@ -485,47 +485,47 @@ func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Pr return nil, nil } - board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID")) + column, err := project_model.GetColumn(ctx, ctx.ParamsInt64(":columnID")) if err != nil { - ctx.ServerError("GetProjectBoard", err) + ctx.ServerError("GetProjectColumn", err) return nil, nil } - if board.ProjectID != ctx.ParamsInt64(":id") { + if column.ProjectID != ctx.ParamsInt64(":id") { ctx.JSON(http.StatusUnprocessableEntity, map[string]string{ - "message": fmt.Sprintf("ProjectBoard[%d] is not in Project[%d] as expected", board.ID, project.ID), + "message": fmt.Sprintf("ProjectColumn[%d] is not in Project[%d] as expected", column.ID, project.ID), }) return nil, nil } if project.RepoID != ctx.Repo.Repository.ID { ctx.JSON(http.StatusUnprocessableEntity, map[string]string{ - "message": fmt.Sprintf("ProjectBoard[%d] is not in Repository[%d] as expected", board.ID, ctx.Repo.Repository.ID), + "message": fmt.Sprintf("ProjectColumn[%d] is not in Repository[%d] as expected", column.ID, ctx.Repo.Repository.ID), }) return nil, nil } - return project, board + return project, column } -// EditProjectBoard allows a project board's to be updated -func EditProjectBoard(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.EditProjectBoardForm) - _, board := checkProjectBoardChangePermissions(ctx) +// EditProjectColumn allows a project column's to be updated +func EditProjectColumn(ctx *context.Context) { + form := web.GetForm(ctx).(*forms.EditProjectColumnForm) + _, column := checkProjectColumnChangePermissions(ctx) if ctx.Written() { return } if form.Title != "" { - board.Title = form.Title + column.Title = form.Title } - board.Color = form.Color + column.Color = form.Color if form.Sorting != 0 { - board.Sorting = form.Sorting + column.Sorting = form.Sorting } - if err := project_model.UpdateBoard(ctx, board); err != nil { - ctx.ServerError("UpdateProjectBoard", err) + if err := project_model.UpdateColumn(ctx, column); err != nil { + ctx.ServerError("UpdateProjectColumn", err) return } @@ -534,15 +534,15 @@ func EditProjectBoard(ctx *context.Context) { }) } -// SetDefaultProjectBoard set default board for uncategorized issues/pulls -func SetDefaultProjectBoard(ctx *context.Context) { - project, board := checkProjectBoardChangePermissions(ctx) +// SetDefaultProjectColumn set default column for uncategorized issues/pulls +func SetDefaultProjectColumn(ctx *context.Context) { + project, column := checkProjectColumnChangePermissions(ctx) if ctx.Written() { return } - if err := project_model.SetDefaultBoard(project.ID, board.ID); err != nil { - ctx.ServerError("SetDefaultBoard", err) + if err := project_model.SetDefaultColumn(project.ID, column.ID); err != nil { + ctx.ServerError("SetDefaultColumn", err) return } @@ -581,26 +581,26 @@ func MoveIssues(ctx *context.Context) { return } - var board *project_model.Board + var column *project_model.Column - if ctx.ParamsInt64(":boardID") == 0 { - board = &project_model.Board{ + if ctx.ParamsInt64(":columnID") == 0 { + column = &project_model.Column{ ID: 0, ProjectID: project.ID, Title: ctx.Tr("repo.projects.type.uncategorized"), } } else { - board, err = project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID")) + column, err = project_model.GetColumn(ctx, ctx.ParamsInt64(":columnID")) 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 } - if board.ProjectID != project.ID { - ctx.NotFound("BoardNotInProject", nil) + if column.ProjectID != project.ID { + ctx.NotFound("ColumnNotInProject", nil) return } } @@ -645,8 +645,8 @@ func MoveIssues(ctx *context.Context) { } } - if err = project_model.MoveIssuesOnProjectBoard(board, sortedIssueIDs); err != nil { - ctx.ServerError("MoveIssuesOnProjectBoard", err) + if err = project_model.MoveIssuesOnProjectColumn(column, sortedIssueIDs); err != nil { + ctx.ServerError("MoveIssuesOnProjectColumn", err) return } diff --git a/routers/web/repo/projects_test.go b/routers/web/repo/projects_test.go index 62fb0457400bd..f5ffec96d19c0 100644 --- a/routers/web/repo/projects_test.go +++ b/routers/web/repo/projects_test.go @@ -13,16 +13,16 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCheckProjectBoardChangePermissions(t *testing.T) { +func TestCheckProjectColumnChangePermissions(t *testing.T) { unittest.PrepareTestEnv(t) ctx := test.MockContext(t, "user2/repo1/projects/1/2") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) ctx.SetParams(":id", "1") - ctx.SetParams(":boardID", "2") + ctx.SetParams(":columnID", "2") - project, board := checkProjectBoardChangePermissions(ctx) + project, column := checkProjectColumnChangePermissions(ctx) assert.NotNil(t, project) - assert.NotNil(t, board) + assert.NotNil(t, column) assert.False(t, ctx.Written()) } diff --git a/routers/web/web.go b/routers/web/web.go index acce07189185c..96603e98bb4a4 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1055,17 +1055,17 @@ func RegisterRoutes(m *web.Route) { m.Get("/new", repo.NewProject) m.Post("/new", bindIgnErr(forms.CreateProjectForm{}), repo.NewProjectPost) m.Group("/{id}", func() { - m.Post("", bindIgnErr(forms.EditProjectBoardForm{}), repo.AddBoardToProjectPost) + m.Post("", bindIgnErr(forms.EditProjectColumnForm{}), repo.AddColumnToProjectPost) m.Post("/delete", repo.DeleteProject) m.Get("/edit", repo.EditProject) m.Post("/edit", bindIgnErr(forms.CreateProjectForm{}), repo.EditProjectPost) m.Post("/{action:open|close}", repo.ChangeProjectStatus) - m.Group("/{boardID}", func() { - m.Put("", bindIgnErr(forms.EditProjectBoardForm{}), repo.EditProjectBoard) - m.Delete("", repo.DeleteProjectBoard) - m.Post("/default", repo.SetDefaultProjectBoard) + m.Group("/{columnID}", func() { + m.Put("", bindIgnErr(forms.EditProjectColumnForm{}), repo.EditProjectColumn) + m.Delete("", repo.DeleteProjectColumn) + m.Post("/default", repo.SetDefaultProjectColumn) m.Post("/move", repo.MoveIssues) }) diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index c1e9cb3197c0b..edcfc08aabac5 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -521,8 +521,8 @@ type UserCreateProjectForm struct { UID int64 `binding:"Required"` } -// EditProjectBoardForm is a form for editing a project board -type EditProjectBoardForm struct { +// EditProjectColumnForm is a form for editing a project column +type EditProjectColumnForm struct { Title string `binding:"Required;MaxSize(100)"` Sorting int8 Color string `binding:"MaxSize(7)"` diff --git a/templates/repo/projects/view.tmpl b/templates/repo/projects/view.tmpl index 262efd2e0e800..a40bbe3041525 100644 --- a/templates/repo/projects/view.tmpl +++ b/templates/repo/projects/view.tmpl @@ -9,23 +9,23 @@