From d445ebafdf6745f01eff776c5e5ba2c63ee2b60d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 26 Dec 2022 00:32:29 +0800 Subject: [PATCH 1/4] Rename project -> board, board -> column --- models/activities/statistic.go | 10 +- models/{project/project.go => board/board.go} | 153 +++++----- .../project_test.go => board/board_test.go} | 30 +- models/board/column.go | 269 +++++++++++++++++ models/{project => board}/issue.go | 34 +-- models/{project => board}/main_test.go | 0 models/issues/comment.go | 14 +- models/issues/issue.go | 20 +- models/issues/issue_list.go | 16 +- models/issues/issue_project.go | 64 ++-- models/migrations/v1_13/v146.go | 4 +- models/project/board.go | 275 ------------------ models/repo.go | 4 +- modules/metrics/collector.go | 4 +- routers/web/repo/issue.go | 34 +-- routers/web/repo/projects.go | 208 ++++++------- routers/web/user/profile.go | 6 +- routers/web/web.go | 24 +- services/forms/repo_form.go | 52 +--- services/issue/issue.go | 4 +- 20 files changed, 598 insertions(+), 627 deletions(-) rename models/{project/project.go => board/board.go} (64%) rename models/{project/project_test.go => board/board_test.go} (61%) create mode 100644 models/board/column.go rename models/{project => board}/issue.go (70%) rename models/{project => board}/main_test.go (100%) delete mode 100644 models/project/board.go diff --git a/models/activities/statistic.go b/models/activities/statistic.go index 138f4d8fe9e92..c6820c849d950 100644 --- a/models/activities/statistic.go +++ b/models/activities/statistic.go @@ -6,11 +6,11 @@ package activities import ( asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/auth" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" - project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" @@ -26,8 +26,8 @@ type Statistic struct { Comment, Oauth, Follow, Mirror, Release, AuthSource, Webhook, Milestone, Label, HookTask, - Team, UpdateTask, Project, - ProjectBoard, Attachment int64 + Team, UpdateTask, Board, + BoardColumn, Attachment int64 IssueByLabel []IssueByLabelCount IssueByRepository []IssueByRepositoryCount } @@ -108,7 +108,7 @@ func GetStatistic() (stats Statistic) { stats.Counter.HookTask, _ = e.Count(new(webhook.HookTask)) 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.Board, _ = e.Count(new(board_model.Board)) + stats.Counter.BoardColumn, _ = e.Count(new(board_model.Board)) return stats } diff --git a/models/project/project.go b/models/board/board.go similarity index 64% rename from models/project/project.go rename to models/board/board.go index bcf1166408f85..4a3863730ae65 100644 --- a/models/project/project.go +++ b/models/board/board.go @@ -17,14 +17,17 @@ import ( ) type ( - // ProjectsConfig is used to identify the type of board that is being created - ProjectsConfig struct { - BoardType BoardType + // BoardsConfig is used to identify the type of board that is being created + BoardsConfig struct { + ColumnType BoardType Translation string } // Type is used to identify the type of project in question and ownership Type uint8 + + // ColumnType is used to represent a project board type + BoardType uint8 ) const ( @@ -38,54 +41,56 @@ const ( TypeOrganization ) -// ErrProjectNotExist represents a "ProjectNotExist" kind of error. -type ErrProjectNotExist struct { - ID int64 - RepoID int64 -} +const ( + // BoardTypeNone is a board type that has no predefined columns + BoardTypeNone BoardType = iota -// IsErrProjectNotExist checks if an error is a ErrProjectNotExist -func IsErrProjectNotExist(err error) bool { - _, ok := err.(ErrProjectNotExist) - return ok -} + // ColumnTypeBasicKanban is a project board type that has basic predefined columns + BoardTypeBasicKanban -func (err ErrProjectNotExist) Error() string { - return fmt.Sprintf("projects does not exist [id: %d]", err.ID) -} + // ColumnTypeBugTriage is a project board type that has predefined columns suited to hunting down bugs + BoardTypeBugTriage +) -func (err ErrProjectNotExist) Unwrap() error { - return util.ErrNotExist +// 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 + } } -// ErrProjectBoardNotExist represents a "ProjectBoardNotExist" kind of error. -type ErrProjectBoardNotExist struct { - BoardID int64 +// ErrBoardNotExist represents a "BoardNotExist" kind of error. +type ErrBoardNotExist struct { + ID int64 + RepoID int64 } -// IsErrProjectBoardNotExist checks if an error is a ErrProjectBoardNotExist -func IsErrProjectBoardNotExist(err error) bool { - _, ok := err.(ErrProjectBoardNotExist) +// IsErrBoardNotExist checks if an error is a ErrBoardNotExist +func IsErrBoardNotExist(err error) bool { + _, ok := err.(ErrBoardNotExist) return ok } -func (err ErrProjectBoardNotExist) Error() string { - return fmt.Sprintf("project board does not exist [id: %d]", err.BoardID) +func (err ErrBoardNotExist) Error() string { + return fmt.Sprintf("board does not exist [id: %d]", err.ID) } -func (err ErrProjectBoardNotExist) Unwrap() error { +func (err ErrBoardNotExist) Unwrap() error { return util.ErrNotExist } -// Project represents a project board -type Project struct { +// Board represents a board +type Board struct { ID int64 `xorm:"pk autoincr"` Title string `xorm:"INDEX NOT NULL"` Description string `xorm:"TEXT"` RepoID int64 `xorm:"INDEX"` CreatorID int64 `xorm:"NOT NULL"` IsClosed bool `xorm:"INDEX"` - BoardType BoardType + ColumnType BoardType Type Type RenderedContent string `xorm:"-"` @@ -96,12 +101,12 @@ type Project struct { } func init() { - db.RegisterModel(new(Project)) + db.RegisterModel(new(Board)) } -// GetProjectsConfig retrieves the types of configurations projects could have -func GetProjectsConfig() []ProjectsConfig { - return []ProjectsConfig{ +// GetBoardsConfig retrieves the types of configurations projects could have +func GetBoardsConfig() []BoardsConfig { + return []BoardsConfig{ {BoardTypeNone, "repo.projects.type.none"}, {BoardTypeBasicKanban, "repo.projects.type.basic_kanban"}, {BoardTypeBugTriage, "repo.projects.type.bug_triage"}, @@ -127,10 +132,10 @@ type SearchOptions struct { Type Type } -// GetProjects returns a list of all projects that have been created in the repository -func GetProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, error) { +// FindBoards returns a list of all boards that have been created in the repository +func FindBoards(ctx context.Context, opts SearchOptions) ([]*Board, int64, error) { e := db.GetEngine(ctx) - projects := make([]*Project, 0, setting.UI.IssuePagingNum) + projects := make([]*Board, 0, setting.UI.IssuePagingNum) var cond builder.Cond = builder.Eq{"repo_id": opts.RepoID} switch opts.IsClosed { @@ -144,7 +149,7 @@ func GetProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, er cond = cond.And(builder.Eq{"type": opts.Type}) } - count, err := e.Where(cond).Count(new(Project)) + count, err := e.Where(cond).Count(new(Board)) if err != nil { return nil, 0, fmt.Errorf("Count: %w", err) } @@ -169,10 +174,10 @@ func GetProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, er return projects, count, e.Find(&projects) } -// NewProject creates a new Project -func NewProject(p *Project) error { - if !IsBoardTypeValid(p.BoardType) { - p.BoardType = BoardTypeNone +// NewBoard creates a new board +func NewBoard(p *Board) error { + if !IsBoardTypeValid(p.ColumnType) { + p.ColumnType = BoardTypeNone } if !IsTypeValid(p.Type) { @@ -193,29 +198,29 @@ func NewProject(p *Project) error { return err } - if err := createBoardsForProjectsType(ctx, p); err != nil { + if err := createColumnsForBoardType(ctx, p); err != nil { return err } return committer.Commit() } -// GetProjectByID returns the projects in a repository -func GetProjectByID(ctx context.Context, id int64) (*Project, error) { - p := new(Project) +// GetBoardByID returns the borad in a repository +func GetBoardByID(ctx context.Context, id int64) (*Board, error) { + p := new(Board) has, err := db.GetEngine(ctx).ID(id).Get(p) if err != nil { return nil, err } else if !has { - return nil, ErrProjectNotExist{ID: id} + return nil, ErrBoardNotExist{ID: id} } return p, nil } -// UpdateProject updates project properties -func UpdateProject(ctx context.Context, p *Project) error { +// UpdateBoard updates board properties +func UpdateBoard(ctx context.Context, p *Board) error { _, err := db.GetEngine(ctx).ID(p.ID).Cols( "title", "description", @@ -223,7 +228,7 @@ func UpdateProject(ctx context.Context, p *Project) error { return err } -func updateRepositoryProjectCount(ctx context.Context, repoID int64) error { +func updateRepositoryBoardCount(ctx context.Context, repoID int64) error { if _, err := db.GetEngine(ctx).Exec(builder.Update( builder.Eq{ "`num_projects`": builder.Select("count(*)").From("`project`"). @@ -245,46 +250,46 @@ func updateRepositoryProjectCount(ctx context.Context, repoID int64) error { return nil } -// ChangeProjectStatusByRepoIDAndID toggles a project between opened and closed -func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) error { +// ChangeBoardStatusByRepoIDAndID toggles a board between opened and closed +func ChangeBoardStatusByRepoIDAndID(repoID, boardID int64, isClosed bool) error { ctx, committer, err := db.TxContext(db.DefaultContext) if err != nil { return err } defer committer.Close() - p := new(Project) + p := new(Board) - has, err := db.GetEngine(ctx).ID(projectID).Where("repo_id = ?", repoID).Get(p) + has, err := db.GetEngine(ctx).ID(boardID).Where("repo_id = ?", repoID).Get(p) if err != nil { return err } else if !has { - return ErrProjectNotExist{ID: projectID, RepoID: repoID} + return ErrBoardNotExist{ID: boardID, RepoID: repoID} } - if err := changeProjectStatus(ctx, p, isClosed); err != nil { + if err := changeBoardStatus(ctx, p, isClosed); err != nil { return err } return committer.Commit() } -// ChangeProjectStatus toggle a project between opened and closed -func ChangeProjectStatus(p *Project, isClosed bool) error { +// ChangeBoardStatus toggle a board between opened and closed +func ChangeBoardStatus(p *Board, isClosed bool) error { ctx, committer, err := db.TxContext(db.DefaultContext) if err != nil { return err } defer committer.Close() - if err := changeProjectStatus(ctx, p, isClosed); err != nil { + if err := changeBoardStatus(ctx, p, isClosed); err != nil { return err } return committer.Commit() } -func changeProjectStatus(ctx context.Context, p *Project, isClosed bool) error { +func changeBoardStatus(ctx context.Context, p *Board, isClosed bool) error { p.IsClosed = isClosed p.ClosedDateUnix = timeutil.TimeStampNow() count, err := db.GetEngine(ctx).ID(p.ID).Where("repo_id = ? AND is_closed = ?", p.RepoID, !isClosed).Cols("is_closed", "closed_date_unix").Update(p) @@ -295,38 +300,38 @@ func changeProjectStatus(ctx context.Context, p *Project, isClosed bool) error { return nil } - return updateRepositoryProjectCount(ctx, p.RepoID) + return updateRepositoryBoardCount(ctx, p.RepoID) } -// DeleteProjectByID deletes a project from a repository. if it's not in a database +// DeleteBoardByID deletes a project from a repository. if it's not in a database // transaction, it will start a new database transaction -func DeleteProjectByID(ctx context.Context, id int64) error { +func DeleteBoardByID(ctx context.Context, id int64) error { return db.AutoTx(ctx, func(ctx context.Context) error { - p, err := GetProjectByID(ctx, id) + p, err := GetBoardByID(ctx, id) if err != nil { - if IsErrProjectNotExist(err) { + if IsErrBoardNotExist(err) { return nil } return err } - if err := deleteProjectIssuesByProjectID(ctx, id); err != nil { + if err := deleteBoardIssuesByBoardID(ctx, id); err != nil { return err } - if err := deleteBoardByProjectID(ctx, id); err != nil { + if err := deleteColumnsByBoardID(ctx, id); err != nil { return err } - if _, err = db.GetEngine(ctx).ID(p.ID).Delete(new(Project)); err != nil { + if _, err = db.GetEngine(ctx).ID(p.ID).Delete(new(Board)); err != nil { return err } - return updateRepositoryProjectCount(ctx, p.RepoID) + return updateRepositoryBoardCount(ctx, p.RepoID) }) } -func DeleteProjectByRepoID(ctx context.Context, repoID int64) error { +func DeleteBoardByRepoID(ctx context.Context, repoID int64) error { switch { case setting.Database.UseSQLite3: 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 { @@ -335,7 +340,7 @@ func DeleteProjectByRepoID(ctx context.Context, repoID int64) error { 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 { return err } - if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil { + if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { return err } case setting.Database.UsePostgreSQL: @@ -345,7 +350,7 @@ func DeleteProjectByRepoID(ctx context.Context, repoID int64) error { 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 { return err } - if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil { + if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { return err } default: @@ -355,10 +360,10 @@ func DeleteProjectByRepoID(ctx context.Context, repoID int64) error { 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 { return err } - if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil { + if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { return err } } - return updateRepositoryProjectCount(ctx, repoID) + return updateRepositoryBoardCount(ctx, repoID) } diff --git a/models/project/project_test.go b/models/board/board_test.go similarity index 61% rename from models/project/project_test.go rename to models/board/board_test.go index 4fde0fc7ce3a4..2d4411f0b51ee 100644 --- a/models/project/project_test.go +++ b/models/board/board_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestIsProjectTypeValid(t *testing.T) { +func TestIsBoardTypeValid(t *testing.T) { const UnknownType Type = 15 cases := []struct { @@ -31,52 +31,52 @@ func TestIsProjectTypeValid(t *testing.T) { } } -func TestGetProjects(t *testing.T) { +func TestFindBoards(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projects, _, err := GetProjects(db.DefaultContext, SearchOptions{RepoID: 1}) + projects, _, err := FindBoards(db.DefaultContext, SearchOptions{RepoID: 1}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures assert.Len(t, projects, 1) - projects, _, err = GetProjects(db.DefaultContext, SearchOptions{RepoID: 3}) + projects, _, err = FindBoards(db.DefaultContext, SearchOptions{RepoID: 3}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures assert.Len(t, projects, 1) } -func TestProject(t *testing.T) { +func TestBoard(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - project := &Project{ + board := &Board{ Type: TypeRepository, - BoardType: BoardTypeBasicKanban, + ColumnType: BoardTypeBasicKanban, Title: "New Project", RepoID: 1, CreatedUnix: timeutil.TimeStampNow(), CreatorID: 2, } - assert.NoError(t, NewProject(project)) + assert.NoError(t, NewBoard(board)) - _, err := GetProjectByID(db.DefaultContext, project.ID) + _, err := GetBoardByID(db.DefaultContext, board.ID) assert.NoError(t, err) // Update project - project.Title = "Updated title" - assert.NoError(t, UpdateProject(db.DefaultContext, project)) + board.Title = "Updated title" + assert.NoError(t, UpdateBoard(db.DefaultContext, board)) - projectFromDB, err := GetProjectByID(db.DefaultContext, project.ID) + projectFromDB, err := GetBoardByID(db.DefaultContext, board.ID) assert.NoError(t, err) - assert.Equal(t, project.Title, projectFromDB.Title) + assert.Equal(t, board.Title, projectFromDB.Title) - assert.NoError(t, ChangeProjectStatus(project, true)) + assert.NoError(t, ChangeBoardStatus(board, true)) // Retrieve from DB afresh to check if it is truly closed - projectFromDB, err = GetProjectByID(db.DefaultContext, project.ID) + projectFromDB, err = GetBoardByID(db.DefaultContext, board.ID) assert.NoError(t, err) assert.True(t, projectFromDB.IsClosed) diff --git a/models/board/column.go b/models/board/column.go new file mode 100644 index 0000000000000..680c3815738bf --- /dev/null +++ b/models/board/column.go @@ -0,0 +1,269 @@ +// 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" + "code.gitea.io/gitea/modules/util" + + "xorm.io/builder" +) + +// ColumnColorPattern is a regexp witch can validate BoardColor +var ColumnColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$") + +// ErrColumnNotExist represents a "ProjectBoardNotExist" kind of error. +type ErrColumnNotExist struct { + ColumnID int64 +} + +// IsErrProjectBoardNotExist checks if an error is a ErrProjectBoardNotExist +func IsErrProjectBoardNotExist(err error) bool { + _, ok := err.(ErrColumnNotExist) + return ok +} + +func (err ErrColumnNotExist) Error() string { + return fmt.Sprintf("project board does not exist [id: %d]", err.ColumnID) +} + +func (err ErrColumnNotExist) Unwrap() error { + return util.ErrNotExist +} + +// Column is used to represent columns on a board +type Column 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)"` + + BoardID 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" +} + +// NumIssues return counter of all issues assigned to the board +func (b *Column) NumIssues() int { + c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). + Where("project_id=?", b.BoardID). + 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)) +} + +func createColumnsForBoardType(ctx context.Context, board *Board) error { + var items []string + + switch board.ColumnType { + + 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: board.CreatorID, + Title: v, + ID: board.ID, + }) + } + + return db.Insert(ctx, columns) +} + +// NewColumn adds a new project board to a given project +func NewColumn(board *Column) error { + if len(board.Color) != 0 && !ColumnColorPattern.MatchString(board.Color) { + return fmt.Errorf("bad color code: %s", board.Color) + } + + _, err := db.GetEngine(db.DefaultContext).Insert(board) + return err +} + +// DeleteColumnByID removes all issues references to the project board. +func DeleteColumnByID(boardID int64) error { + ctx, committer, err := db.TxContext(db.DefaultContext) + if err != nil { + return err + } + defer committer.Close() + + if err := deleteColumnByID(ctx, boardID); err != nil { + return err + } + + return committer.Commit() +} + +func deleteColumnByID(ctx context.Context, columnID int64) error { + column, err := GetColumn(ctx, columnID) + if err != nil { + if IsErrProjectBoardNotExist(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 deleteColumnsByBoardID(ctx context.Context, boardID int64) error { + _, err := db.GetEngine(ctx).Where("project_id=?", boardID).Delete(&Column{}) + return err +} + +// GetBoard fetches the current board 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, ErrColumnNotExist{ColumnID: columnID} + } + + return column, nil +} + +// UpdateColumn updates a board 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 +} + +// ColumnList is a list of all project boards in a repository +type ColumnList []*Column + +// FindColumns fetches all columns related to a board +// if no default board set, first board is a temporary "Uncategorized" board +func FindColumns(ctx context.Context, boardID int64) (ColumnList, error) { + columns := make([]*Column, 0, 5) + + if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", boardID, false).OrderBy("Sorting").Find(&columns); err != nil { + return nil, err + } + + defaultB, err := getDefaultColumn(ctx, boardID) + 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, boardID int64) (*Column, error) { + var board Column + exist, err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", boardID, true).Get(&board) + if err != nil { + return nil, err + } + if exist { + return &board, nil + } + + // represents a board for issues not assigned to one + return &Column{ + BoardID: boardID, + Title: "Uncategorized", + Default: true, + }, nil +} + +// SetDefaultColumn represents a board for issues not assigned to one +// if boardID is 0 unset default +func SetDefaultColumn(boardID, columnID int64) error { + _, err := db.GetEngine(db.DefaultContext).Where(builder.Eq{ + "project_id": boardID, + "`default`": true, + }).Cols("`default`").Update(&Column{Default: false}) + if err != nil { + return err + } + + if boardID > 0 { + _, err = db.GetEngine(db.DefaultContext).ID(boardID).Where(builder.Eq{"project_id": boardID}). + Cols("`default`").Update(&Column{Default: true}) + } + + return err +} + +// UpdateColumnSorting update project board sorting +func UpdateColumnSorting(bs ColumnList) 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/board/issue.go similarity index 70% rename from models/project/issue.go rename to models/board/issue.go index 3269197d6cde3..b28ebb5c51529 100644 --- a/models/project/issue.go +++ b/models/board/issue.go @@ -11,30 +11,30 @@ import ( "code.gitea.io/gitea/modules/log" ) -// ProjectIssue saves relation from issue to a project -type ProjectIssue struct { //revive:disable-line:exported - ID int64 `xorm:"pk autoincr"` - IssueID int64 `xorm:"INDEX"` - ProjectID int64 `xorm:"INDEX"` +// BoardIssue saves relation from issue to a project +type BoardIssue struct { //revive:disable-line:exported + ID int64 `xorm:"pk autoincr"` + IssueID int64 `xorm:"INDEX"` + BoardID int64 `xorm:"INDEX"` // If 0, then it has not been added to a specific board in the project - ProjectBoardID int64 `xorm:"INDEX"` + BoardColumnID int64 `xorm:"INDEX"` // the sorting order on the board Sorting int64 `xorm:"NOT NULL DEFAULT 0"` } func init() { - db.RegisterModel(new(ProjectIssue)) + db.RegisterModel(new(BoardIssue)) } -func deleteProjectIssuesByProjectID(ctx context.Context, projectID int64) error { - _, err := db.GetEngine(ctx).Where("project_id=?", projectID).Delete(&ProjectIssue{}) +func deleteBoardIssuesByBoardID(ctx context.Context, projectID int64) error { + _, err := db.GetEngine(ctx).Where("project_id=?", projectID).Delete(&BoardIssue{}) return err } // NumIssues return counter of all issues assigned to a project -func (p *Project) NumIssues() int { +func (p *Board) NumIssues() int { c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). Where("project_id=?", p.ID). GroupBy("issue_id"). @@ -48,7 +48,7 @@ func (p *Project) NumIssues() int { } // NumClosedIssues return counter of closed issues assigned to a project -func (p *Project) NumClosedIssues() int { +func (p *Board) NumClosedIssues() int { c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). Join("INNER", "issue", "project_issue.issue_id=issue.id"). Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, true). @@ -62,7 +62,7 @@ func (p *Project) NumClosedIssues() int { } // NumOpenIssues return counter of open issues assigned to a project -func (p *Project) NumOpenIssues() int { +func (p *Board) NumOpenIssues() int { c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). Join("INNER", "issue", "project_issue.issue_id=issue.id"). Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, false). @@ -75,8 +75,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 { +// MoveIssuesOnBoardColumn moves or keeps issues in a column and sorts them inside that column +func MoveIssuesOnBoardColumn(column *Column, sortedIssueIDs map[int64]int64) error { return db.WithTx(db.DefaultContext, func(ctx context.Context) error { sess := db.GetEngine(ctx) @@ -84,7 +84,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(BoardIssue)).Where("project_id=?", column.BoardID).In("issue_id", issueIDs).Count() if err != nil { return err } @@ -93,7 +93,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_board_id=?, sorting=? WHERE issue_id=?", column.ID, sorting, issueID) if err != nil { return err } @@ -102,7 +102,7 @@ func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) erro }) } -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 } diff --git a/models/project/main_test.go b/models/board/main_test.go similarity index 100% rename from models/project/main_test.go rename to models/board/main_test.go diff --git a/models/issues/comment.go b/models/issues/comment.go index 612f17aa5af68..8744f15b6b581 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -13,10 +13,10 @@ import ( "strings" "unicode/utf8" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" "code.gitea.io/gitea/models/organization" - project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" @@ -231,8 +231,8 @@ type Comment struct { RemovedLabels []*Label `xorm:"-"` OldProjectID int64 ProjectID int64 - OldProject *project_model.Project `xorm:"-"` - Project *project_model.Project `xorm:"-"` + OldBoard *board_model.Board `xorm:"-"` + Board *board_model.Board `xorm:"-"` OldMilestoneID int64 MilestoneID int64 OldMilestone *Milestone `xorm:"-"` @@ -493,22 +493,22 @@ func (c *Comment) LoadLabel() error { // LoadProject if comment.Type is CommentTypeProject, then load project. func (c *Comment) LoadProject() error { if c.OldProjectID > 0 { - var oldProject project_model.Project + var oldProject board_model.Board has, err := db.GetEngine(db.DefaultContext).ID(c.OldProjectID).Get(&oldProject) if err != nil { return err } else if has { - c.OldProject = &oldProject + c.OldBoard = &oldProject } } if c.ProjectID > 0 { - var project project_model.Project + var project board_model.Board has, err := db.GetEngine(db.DefaultContext).ID(c.ProjectID).Get(&project) if err != nil { return err } else if has { - c.Project = &project + c.Board = &project } } diff --git a/models/issues/issue.go b/models/issues/issue.go index f45e635c0ecea..5b3b9b6706acc 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -11,11 +11,11 @@ import ( "sort" "strings" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" - project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unit" @@ -110,14 +110,14 @@ type Issue struct { PosterID int64 `xorm:"INDEX"` Poster *user_model.User `xorm:"-"` OriginalAuthor string - OriginalAuthorID int64 `xorm:"index"` - Title string `xorm:"name"` - Content string `xorm:"LONGTEXT"` - RenderedContent string `xorm:"-"` - Labels []*Label `xorm:"-"` - MilestoneID int64 `xorm:"INDEX"` - Milestone *Milestone `xorm:"-"` - Project *project_model.Project `xorm:"-"` + OriginalAuthorID int64 `xorm:"index"` + Title string `xorm:"name"` + Content string `xorm:"LONGTEXT"` + RenderedContent string `xorm:"-"` + Labels []*Label `xorm:"-"` + MilestoneID int64 `xorm:"INDEX"` + Milestone *Milestone `xorm:"-"` + Board *board_model.Board `xorm:"-"` Priority int AssigneeID int64 `xorm:"-"` Assignee *user_model.User `xorm:"-"` @@ -2304,7 +2304,7 @@ func DeleteIssuesByRepoID(ctx context.Context, repoID int64) (attachmentPaths [] } if _, err = sess.In("issue_id", deleteCond). - Delete(&project_model.ProjectIssue{}); err != nil { + Delete(&board_model.BoardIssue{}); err != nil { return } diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index e22e48c0bb4bd..100034ba01bf7 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -7,8 +7,8 @@ import ( "context" "fmt" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" - project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" @@ -214,21 +214,21 @@ func (issues IssueList) loadMilestones(ctx context.Context) error { return nil } -func (issues IssueList) getProjectIDs() []int64 { +func (issues IssueList) getBoardIDs() []int64 { ids := make(container.Set[int64], len(issues)) for _, issue := range issues { - ids.Add(issue.ProjectID()) + ids.Add(issue.BoardID()) } return ids.Values() } -func (issues IssueList) loadProjects(ctx context.Context) error { - projectIDs := issues.getProjectIDs() +func (issues IssueList) loadBoards(ctx context.Context) error { + projectIDs := issues.getBoardIDs() if len(projectIDs) == 0 { return nil } - projectMaps := make(map[int64]*project_model.Project, len(projectIDs)) + projectMaps := make(map[int64]*board_model.Board, len(projectIDs)) left := len(projectIDs) for left > 0 { limit := db.DefaultMaxInSize @@ -246,7 +246,7 @@ func (issues IssueList) loadProjects(ctx context.Context) error { } for _, issue := range issues { - issue.Project = projectMaps[issue.ProjectID()] + issue.Board = projectMaps[issue.BoardID()] } return nil } @@ -526,7 +526,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error { return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err) } - if err := issues.loadProjects(ctx); err != nil { + if err := issues.loadBoards(ctx); err != nil { return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err) } diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index 8e559f13c92c5..26743e2e30c18 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -7,8 +7,8 @@ import ( "context" "fmt" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" - project_model "code.gitea.io/gitea/models/project" user_model "code.gitea.io/gitea/models/user" ) @@ -18,31 +18,31 @@ func (issue *Issue) LoadProject() (err error) { } func (issue *Issue) loadProject(ctx context.Context) (err error) { - if issue.Project == nil { - var p project_model.Project + if issue.Board == nil { + var p board_model.Board if _, err = db.GetEngine(ctx).Table("project"). Join("INNER", "project_issue", "project.id=project_issue.project_id"). Where("project_issue.issue_id = ?", issue.ID). Get(&p); err != nil { return err } - issue.Project = &p + issue.Board = &p } return err } // ProjectID return project id if issue was assigned to one -func (issue *Issue) ProjectID() int64 { - return issue.projectID(db.DefaultContext) +func (issue *Issue) BoardID() int64 { + return issue.boardID(db.DefaultContext) } -func (issue *Issue) projectID(ctx context.Context) int64 { - var ip project_model.ProjectIssue +func (issue *Issue) boardID(ctx context.Context) int64 { + var ip board_model.BoardIssue has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip) if err != nil || !has { return 0 } - return ip.ProjectID + return ip.BoardID } // ProjectBoardID return project board id if issue was assigned to one @@ -51,22 +51,22 @@ func (issue *Issue) ProjectBoardID() int64 { } func (issue *Issue) projectBoardID(ctx context.Context) int64 { - var ip project_model.ProjectIssue + var ip board_model.BoardIssue has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip) if err != nil || !has { return 0 } - return ip.ProjectBoardID + return ip.BoardColumnID } -// LoadIssuesFromBoard load issues assigned to this board -func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) { +// LoadIssuesFromBoardColumn load issues assigned to this column +func LoadIssuesFromBoardColumn(ctx context.Context, b *board_model.Column) (IssueList, error) { issueList := make([]*Issue, 0, 10) if b.ID != 0 { issues, err := Issues(ctx, &IssuesOptions{ ProjectBoardID: b.ID, - ProjectID: b.ProjectID, + ProjectID: b.BoardID, SortType: "project-column-sorting", }) if err != nil { @@ -78,7 +78,7 @@ func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList if b.Default { issues, err := Issues(ctx, &IssuesOptions{ ProjectBoardID: -1, // Issues without ProjectBoardID - ProjectID: b.ProjectID, + ProjectID: b.BoardID, SortType: "project-column-sorting", }) if err != nil { @@ -95,10 +95,10 @@ func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList } // LoadIssuesFromBoardList load issues assigned to the boards -func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (map[int64]IssueList, error) { +func LoadIssuesFromBoardList(ctx context.Context, bs board_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 := LoadIssuesFromBoardColumn(ctx, bs[i]) if err != nil { return nil, err } @@ -115,19 +115,19 @@ func ChangeProjectAssign(issue *Issue, doer *user_model.User, newProjectID int64 } defer committer.Close() - if err := addUpdateIssueProject(ctx, issue, doer, newProjectID); err != nil { + if err := addUpdateIssueBoard(ctx, issue, doer, newProjectID); err != nil { return err } return committer.Commit() } -func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error { - oldProjectID := issue.projectID(ctx) +func addUpdateIssueBoard(ctx context.Context, issue *Issue, doer *user_model.User, newBoardID int64) error { + oldBoardID := issue.boardID(ctx) // Only check if we add a new project and not remove it. - if newProjectID > 0 { - newProject, err := project_model.GetProjectByID(ctx, newProjectID) + if newBoardID > 0 { + newProject, err := board_model.GetBoardByID(ctx, newBoardID) if err != nil { return err } @@ -136,7 +136,7 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U } } - if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&project_model.ProjectIssue{}); err != nil { + if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&board_model.BoardIssue{}); err != nil { return err } @@ -144,27 +144,27 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U return err } - if oldProjectID > 0 || newProjectID > 0 { + if oldBoardID > 0 || newBoardID > 0 { if _, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeProject, Doer: doer, Repo: issue.Repo, Issue: issue, - OldProjectID: oldProjectID, - ProjectID: newProjectID, + OldProjectID: oldBoardID, + ProjectID: newBoardID, }); err != nil { return err } } - return db.Insert(ctx, &project_model.ProjectIssue{ - IssueID: issue.ID, - ProjectID: newProjectID, + return db.Insert(ctx, &board_model.BoardIssue{ + IssueID: issue.ID, + BoardID: newBoardID, }) } // MoveIssueAcrossProjectBoards move a card from one board to another -func MoveIssueAcrossProjectBoards(issue *Issue, board *project_model.Board) error { +func MoveIssueAcrossProjectBoards(issue *Issue, board *board_model.Board) error { ctx, committer, err := db.TxContext(db.DefaultContext) if err != nil { return err @@ -172,7 +172,7 @@ func MoveIssueAcrossProjectBoards(issue *Issue, board *project_model.Board) erro defer committer.Close() sess := db.GetEngine(ctx) - var pis project_model.ProjectIssue + var pis board_model.BoardIssue has, err := sess.Where("issue_id=?", issue.ID).Get(&pis) if err != nil { return err @@ -182,7 +182,7 @@ 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 + pis.BoardColumnID = board.ID if _, err := sess.ID(pis.ID).Cols("project_board_id").Update(&pis); err != nil { return err } diff --git a/models/migrations/v1_13/v146.go b/models/migrations/v1_13/v146.go index 5db8b0a4374ac..b322c35918739 100644 --- a/models/migrations/v1_13/v146.go +++ b/models/migrations/v1_13/v146.go @@ -24,8 +24,8 @@ func AddProjectsInfo(x *xorm.Engine) error { CreatorID int64 `xorm:"NOT NULL"` IsClosed bool `xorm:"INDEX"` - BoardType ProjectBoardType - Type ProjectType + ColumnType ProjectBoardType + Type ProjectType ClosedDateUnix timeutil.TimeStamp CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` diff --git a/models/project/board.go b/models/project/board.go deleted file mode 100644 index d8468f0cb55c6..0000000000000 --- a/models/project/board.go +++ /dev/null @@ -1,275 +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 - - // 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(db.DefaultContext) - 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/repo.go b/models/repo.go index e95887077c955..cc890f78c021d 100644 --- a/models/repo.go +++ b/models/repo.go @@ -14,12 +14,12 @@ import ( activities_model "code.gitea.io/gitea/models/activities" admin_model "code.gitea.io/gitea/models/admin" asymkey_model "code.gitea.io/gitea/models/asymkey" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" - project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" secret_model "code.gitea.io/gitea/models/secret" system_model "code.gitea.io/gitea/models/system" @@ -193,7 +193,7 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error { } } - if err := project_model.DeleteProjectByRepoID(ctx, repoID); err != nil { + if err := board_model.DeleteBoardByRepoID(ctx, repoID); err != nil { return fmt.Errorf("unable to delete projects for repo[%d]: %w", repoID, err) } diff --git a/modules/metrics/collector.go b/modules/metrics/collector.go index 17f8dd133fcd1..66be420b185a9 100755 --- a/modules/metrics/collector.go +++ b/modules/metrics/collector.go @@ -320,12 +320,12 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( c.Projects, prometheus.GaugeValue, - float64(stats.Counter.Project), + float64(stats.Counter.Board), ) ch <- prometheus.MustNewConstMetric( c.ProjectBoards, prometheus.GaugeValue, - float64(stats.Counter.ProjectBoard), + float64(stats.Counter.BoardColumn), ) ch <- prometheus.MustNewConstMetric( c.PublicKeys, diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index d315525dac879..c3753b11d7c21 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -18,12 +18,12 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" - project_model "code.gitea.io/gitea/models/project" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" @@ -363,9 +363,9 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti } if ctx.Repo.CanWriteIssuesOrPulls(ctx.Params(":type") == "pulls") { - projects, _, err := project_model.GetProjects(ctx, project_model.SearchOptions{ + projects, _, err := board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, - Type: project_model.TypeRepository, + Type: board_model.TypeRepository, IsClosed: util.OptionalBoolOf(isShowClosed), }) if err != nil { @@ -475,22 +475,22 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { var err error - ctx.Data["OpenProjects"], _, err = project_model.GetProjects(ctx, project_model.SearchOptions{ + ctx.Data["OpenProjects"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, Page: -1, IsClosed: util.OptionalBoolFalse, - Type: project_model.TypeRepository, + Type: board_model.TypeRepository, }) if err != nil { ctx.ServerError("GetProjects", err) return } - ctx.Data["ClosedProjects"], _, err = project_model.GetProjects(ctx, project_model.SearchOptions{ + ctx.Data["ClosedProjects"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, Page: -1, IsClosed: util.OptionalBoolTrue, - Type: project_model.TypeRepository, + Type: board_model.TypeRepository, }) if err != nil { ctx.ServerError("GetProjects", err) @@ -826,11 +826,11 @@ func NewIssue(ctx *context.Context) { projectID := ctx.FormInt64("project") if projectID > 0 && isProjectsEnabled { - project, err := project_model.GetProjectByID(ctx, projectID) + project, err := board_model.GetBoardByID(ctx, projectID) if err != nil { - log.Error("GetProjectByID: %d: %v", projectID, err) + log.Error("GetBoardByID: %d: %v", projectID, err) } else if project.RepoID != ctx.Repo.Repository.ID { - log.Error("GetProjectByID: %d: %v", projectID, fmt.Errorf("project[%d] not in repo [%d]", project.ID, ctx.Repo.Repository.ID)) + log.Error("GetBoardByID: %d: %v", projectID, fmt.Errorf("project[%d] not in repo [%d]", project.ID, ctx.Repo.Repository.ID)) } else { ctx.Data["project_id"] = projectID ctx.Data["Project"] = project @@ -982,9 +982,9 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull } if form.ProjectID > 0 { - p, err := project_model.GetProjectByID(ctx, form.ProjectID) + p, err := board_model.GetBoardByID(ctx, form.ProjectID) if err != nil { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) return nil, nil, 0, 0 } if p.RepoID != ctx.Repo.Repository.ID { @@ -1490,17 +1490,17 @@ func ViewIssue(ctx *context.Context) { return } - ghostProject := &project_model.Project{ + ghostProject := &board_model.Board{ ID: -1, Title: ctx.Tr("repo.issues.deleted_project"), } - if comment.OldProjectID > 0 && comment.OldProject == nil { - comment.OldProject = ghostProject + if comment.OldProjectID > 0 && comment.OldBoard == nil { + comment.OldBoard = ghostProject } - if comment.ProjectID > 0 && comment.Project == nil { - comment.Project = ghostProject + if comment.ProjectID > 0 && comment.Board == nil { + comment.Board = ghostProject } } else if comment.Type == issues_model.CommentTypeAssignees || comment.Type == issues_model.CommentTypeReviewRequest { diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 75cd290b8f0cb..9c0e28f56ab9e 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -10,9 +10,9 @@ import ( "net/url" "strings" + board_model "code.gitea.io/gitea/models/board" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/perm" - project_model "code.gitea.io/gitea/models/project" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -47,8 +47,8 @@ func MustEnableProjects(ctx *context.Context) { } } -// Projects renders the home page of projects -func Projects(ctx *context.Context) { +// Boards renders the home page of boards +func Boards(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.project_board") sortType := ctx.FormTrim("sort") @@ -70,15 +70,15 @@ func Projects(ctx *context.Context) { total = repo.NumClosedProjects } - projects, count, err := project_model.GetProjects(ctx, project_model.SearchOptions{ + projects, count, err := board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, Page: page, IsClosed: util.OptionalBoolOf(isShowClosed), SortType: sortType, - Type: project_model.TypeRepository, + Type: board_model.TypeRepository, }) if err != nil { - ctx.ServerError("GetProjects", err) + ctx.ServerError("FindBoards", err) return } @@ -120,35 +120,35 @@ func Projects(ctx *context.Context) { ctx.HTML(http.StatusOK, tplProjects) } -// NewProject render creating a project page -func NewProject(ctx *context.Context) { +// NewBoard render creating a project page +func NewBoard(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.new") - ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig() + ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.HTML(http.StatusOK, tplProjectsNew) } -// NewProjectPost creates a new project -func NewProjectPost(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.CreateProjectForm) +// NewBoardPost creates a new project +func NewBoardPost(ctx *context.Context) { + form := web.GetForm(ctx).(*forms.CreateBoardForm) ctx.Data["Title"] = ctx.Tr("repo.projects.new") if ctx.HasError() { ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) - ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig() + ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() ctx.HTML(http.StatusOK, tplProjectsNew) return } - if err := project_model.NewProject(&project_model.Project{ + if err := board_model.NewBoard(&board_model.Board{ RepoID: ctx.Repo.Repository.ID, Title: form.Title, Description: form.Content, CreatorID: ctx.Doer.ID, - BoardType: form.BoardType, - Type: project_model.TypeRepository, + ColumnType: form.ColumnType, + Type: board_model.TypeRepository, }); err != nil { - ctx.ServerError("NewProject", err) + ctx.ServerError("NewBoard", err) return } @@ -156,8 +156,8 @@ func NewProjectPost(ctx *context.Context) { ctx.Redirect(ctx.Repo.RepoLink + "/projects") } -// ChangeProjectStatus updates the status of a project between "open" and "close" -func ChangeProjectStatus(ctx *context.Context) { +// ChangeBoardStatus updates the status of a board between "open" and "close" +func ChangeBoardStatus(ctx *context.Context) { toClose := false switch ctx.Params(":action") { case "open": @@ -169,8 +169,8 @@ func ChangeProjectStatus(ctx *context.Context) { } id := ctx.ParamsInt64(":id") - if err := project_model.ChangeProjectStatusByRepoIDAndID(ctx.Repo.Repository.ID, id, toClose); err != nil { - if project_model.IsErrProjectNotExist(err) { + if err := board_model.ChangeBoardStatusByRepoIDAndID(ctx.Repo.Repository.ID, id, toClose); err != nil { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", err) } else { ctx.ServerError("ChangeProjectStatusByIDAndRepoID", err) @@ -180,14 +180,14 @@ func ChangeProjectStatus(ctx *context.Context) { ctx.Redirect(ctx.Repo.RepoLink + "/projects?state=" + url.QueryEscape(ctx.Params(":action"))) } -// DeleteProject delete a project -func DeleteProject(ctx *context.Context) { - p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) +// DeleteBoard delete a board +func DeleteBoard(ctx *context.Context) { + p, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return } @@ -196,8 +196,8 @@ func DeleteProject(ctx *context.Context) { return } - if err := project_model.DeleteProjectByID(ctx, p.ID); err != nil { - ctx.Flash.Error("DeleteProjectByID: " + err.Error()) + if err := board_model.DeleteBoardByID(ctx, p.ID); err != nil { + ctx.Flash.Error("DeleteBoardByID: " + err.Error()) } else { ctx.Flash.Success(ctx.Tr("repo.projects.deletion_success")) } @@ -207,18 +207,18 @@ func DeleteProject(ctx *context.Context) { }) } -// EditProject allows a project to be edited -func EditProject(ctx *context.Context) { +// EditBoard allows a board to be edited +func EditBoard(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["PageIsEditProjects"] = true ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) - p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + p, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return } @@ -233,9 +233,9 @@ func EditProject(ctx *context.Context) { ctx.HTML(http.StatusOK, tplProjectsNew) } -// EditProjectPost response for editing a project -func EditProjectPost(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.CreateProjectForm) +// EditBoardPost response for editing a board +func EditBoardPost(ctx *context.Context) { + form := web.GetForm(ctx).(*forms.CreateBoardForm) ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["PageIsEditProjects"] = true ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) @@ -245,12 +245,12 @@ func EditProjectPost(ctx *context.Context) { return } - p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + p, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return } @@ -261,7 +261,7 @@ func EditProjectPost(ctx *context.Context) { p.Title = form.Title p.Description = form.Content - if err = project_model.UpdateProject(ctx, p); err != nil { + if err = board_model.UpdateBoard(ctx, p); err != nil { ctx.ServerError("UpdateProjects", err) return } @@ -270,14 +270,14 @@ func EditProjectPost(ctx *context.Context) { ctx.Redirect(ctx.Repo.RepoLink + "/projects") } -// ViewProject renders the project board for a project -func ViewProject(ctx *context.Context) { - project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) +// ViewBoard renders the columns for a board +func ViewBoard(ctx *context.Context) { + project, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return } @@ -286,7 +286,7 @@ func ViewProject(ctx *context.Context) { return } - boards, err := project_model.GetBoards(ctx, project.ID) + boards, err := board_model.FindColumns(ctx, project.ID) if err != nil { ctx.ServerError("GetProjectBoards", err) return @@ -353,7 +353,7 @@ func UpdateIssueProject(ctx *context.Context) { projectID := ctx.FormInt64("id") for _, issue := range issues { - oldProjectID := issue.ProjectID() + oldProjectID := issue.BoardID() if oldProjectID == projectID { continue } @@ -369,8 +369,8 @@ func UpdateIssueProject(ctx *context.Context) { }) } -// DeleteProjectBoard allows for the deletion of a project board -func DeleteProjectBoard(ctx *context.Context) { +// DeleteBoardColumn allows for the deletion of a board column +func DeleteBoardColumn(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.", @@ -385,22 +385,22 @@ func DeleteProjectBoard(ctx *context.Context) { return } - project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + project, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return } - pb, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID")) + pb, err := board_model.GetColumn(ctx, ctx.ParamsInt64(":boardID")) if err != nil { ctx.ServerError("GetProjectBoard", err) return } - if pb.ProjectID != ctx.ParamsInt64(":id") { + if pb.BoardID != 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), }) @@ -414,7 +414,7 @@ func DeleteProjectBoard(ctx *context.Context) { return } - if err := project_model.DeleteBoardByID(ctx.ParamsInt64(":boardID")); err != nil { + if err := board_model.DeleteBoardByID(ctx, ctx.ParamsInt64(":boardID")); err != nil { ctx.ServerError("DeleteProjectBoardByID", err) return } @@ -424,9 +424,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) +// AddBoardColumnPost allows a new column to be added to a board. +func AddBoardColumnPost(ctx *context.Context) { + form := web.GetForm(ctx).(*forms.EditBoardColumnForm) 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.", @@ -434,23 +434,23 @@ func AddBoardToProjectPost(ctx *context.Context) { return } - project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + board, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return } - if err := project_model.NewBoard(&project_model.Board{ - ProjectID: project.ID, + if err := board_model.NewColumn(&board_model.Column{ + BoardID: board.ID, Title: form.Title, Color: form.Color, CreatorID: ctx.Doer.ID, }); err != nil { - ctx.ServerError("NewProjectBoard", err) + ctx.ServerError("NewBoardBoard", err) return } @@ -459,7 +459,7 @@ func AddBoardToProjectPost(ctx *context.Context) { }) } -func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Board) { +func checkBoardColumnChangePermissions(ctx *context.Context) (*board_model.Board, *board_model.Column) { if ctx.Doer == nil { ctx.JSON(http.StatusForbidden, map[string]string{ "message": "Only signed in users are allowed to perform this action.", @@ -474,56 +474,56 @@ func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Pr return nil, nil } - project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + board, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return nil, nil } - board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID")) + column, err := board_model.GetColumn(ctx, ctx.ParamsInt64(":boardID")) if err != nil { ctx.ServerError("GetProjectBoard", err) return nil, nil } - if board.ProjectID != ctx.ParamsInt64(":id") { + if column.BoardID != 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("BoardColumn[%d] is not in Board[%d] as expected", column.ID, board.ID), }) return nil, nil } - if project.RepoID != ctx.Repo.Repository.ID { + if board.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("BoardColumn[%d] is not in Repository[%d] as expected", column.ID, ctx.Repo.Repository.ID), }) return nil, nil } - return project, board + return board, column } -// EditProjectBoard allows a project board's to be updated -func EditProjectBoard(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.EditProjectBoardForm) - _, board := checkProjectBoardChangePermissions(ctx) +// EditBoardColumn allows a board column's to be updated +func EditBoardColumn(ctx *context.Context) { + form := web.GetForm(ctx).(*forms.EditBoardColumnForm) + _, column := checkBoardColumnChangePermissions(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 { + if err := board_model.UpdateColumn(ctx, column); err != nil { ctx.ServerError("UpdateProjectBoard", err) return } @@ -533,14 +533,14 @@ func EditProjectBoard(ctx *context.Context) { }) } -// SetDefaultProjectBoard set default board for uncategorized issues/pulls -func SetDefaultProjectBoard(ctx *context.Context) { - project, board := checkProjectBoardChangePermissions(ctx) +// SetDefaultBoardColumn set default board column for uncategorized issues/pulls +func SetDefaultBoardColumn(ctx *context.Context) { + board, column := checkBoardColumnChangePermissions(ctx) if ctx.Written() { return } - if err := project_model.SetDefaultBoard(project.ID, board.ID); err != nil { + if err := board_model.SetDefaultColumn(board.ID, column.ID); err != nil { ctx.ServerError("SetDefaultBoard", err) return } @@ -566,12 +566,12 @@ func MoveIssues(ctx *context.Context) { return } - project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + project, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { - if project_model.IsErrProjectNotExist(err) { + if board_model.IsErrBoardNotExist(err) { ctx.NotFound("ProjectNotExist", nil) } else { - ctx.ServerError("GetProjectByID", err) + ctx.ServerError("GetBoardByID", err) } return } @@ -580,25 +580,25 @@ func MoveIssues(ctx *context.Context) { return } - var board *project_model.Board + var column *board_model.Column if ctx.ParamsInt64(":boardID") == 0 { - board = &project_model.Board{ - ID: 0, - ProjectID: project.ID, - Title: ctx.Tr("repo.projects.type.uncategorized"), + column = &board_model.Column{ + ID: 0, + BoardID: project.ID, + Title: ctx.Tr("repo.projects.type.uncategorized"), } } else { - board, err = project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID")) + column, err = board_model.GetColumn(ctx, ctx.ParamsInt64(":boardID")) if err != nil { - if project_model.IsErrProjectBoardNotExist(err) { + if board_model.IsErrProjectBoardNotExist(err) { ctx.NotFound("ProjectBoardNotExist", nil) } else { ctx.ServerError("GetProjectBoard", err) } return } - if board.ProjectID != project.ID { + if column.BoardID != project.ID { ctx.NotFound("BoardNotInProject", nil) return } @@ -644,7 +644,7 @@ func MoveIssues(ctx *context.Context) { } } - if err = project_model.MoveIssuesOnProjectBoard(board, sortedIssueIDs); err != nil { + if err = board_model.MoveIssuesOnBoardColumn(column, sortedIssueIDs); err != nil { ctx.ServerError("MoveIssuesOnProjectBoard", err) return } @@ -657,7 +657,7 @@ func MoveIssues(ctx *context.Context) { // CreateProject renders the generic project creation page func CreateProject(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.new") - ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig() + ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.HTML(http.StatusOK, tplGenericProjectsNew) @@ -678,19 +678,19 @@ func CreateProjectPost(ctx *context.Context, form forms.UserCreateProjectForm) { return } - projectType := project_model.TypeIndividual + projectType := board_model.TypeIndividual if user.IsOrganization() { - projectType = project_model.TypeOrganization + projectType = board_model.TypeOrganization } - if err := project_model.NewProject(&project_model.Project{ + if err := board_model.NewBoard(&board_model.Board{ Title: form.Title, Description: form.Content, CreatorID: user.ID, - BoardType: form.BoardType, + ColumnType: form.ColumnType, Type: projectType, }); err != nil { - ctx.ServerError("NewProject", err) + ctx.ServerError("NewBoard", err) return } diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 0002d56de01ba..25bffe1df213a 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -10,9 +10,9 @@ import ( "strings" activities_model "code.gitea.io/gitea/models/activities" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" - project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" @@ -224,10 +224,10 @@ func Profile(ctx *context.Context) { total = int(count) case "projects": - ctx.Data["OpenProjects"], _, err = project_model.GetProjects(ctx, project_model.SearchOptions{ + ctx.Data["OpenProjects"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ Page: -1, IsClosed: util.OptionalBoolFalse, - Type: project_model.TypeIndividual, + Type: board_model.TypeIndividual, }) if err != nil { ctx.ServerError("GetProjects", err) diff --git a/routers/web/web.go b/routers/web/web.go index 31b3eb9baadac..2e36e4279094d 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1160,23 +1160,23 @@ func RegisterRoutes(m *web.Route) { } m.Group("/projects", func() { - m.Get("", repo.Projects) - m.Get("/{id}", repo.ViewProject) + m.Get("", repo.Boards) + m.Get("/{id}", repo.ViewBoard) m.Group("", func() { - m.Get("/new", repo.NewProject) - m.Post("/new", web.Bind(forms.CreateProjectForm{}), repo.NewProjectPost) + m.Get("/new", repo.NewBoard) + m.Post("/new", web.Bind(forms.CreateBoardForm{}), repo.NewBoardPost) m.Group("/{id}", func() { - m.Post("", web.Bind(forms.EditProjectBoardForm{}), repo.AddBoardToProjectPost) - m.Post("/delete", repo.DeleteProject) + m.Post("", web.Bind(forms.EditBoardColumnForm{}), repo.AddBoardColumnPost) + m.Post("/delete", repo.DeleteBoard) - m.Get("/edit", repo.EditProject) - m.Post("/edit", web.Bind(forms.CreateProjectForm{}), repo.EditProjectPost) - m.Post("/{action:open|close}", repo.ChangeProjectStatus) + m.Get("/edit", repo.EditBoard) + m.Post("/edit", web.Bind(forms.CreateBoardForm{}), repo.EditBoardPost) + m.Post("/{action:open|close}", repo.ChangeBoardStatus) m.Group("/{boardID}", func() { - m.Put("", web.Bind(forms.EditProjectBoardForm{}), repo.EditProjectBoard) - m.Delete("", repo.DeleteProjectBoard) - m.Post("/default", repo.SetDefaultProjectBoard) + m.Put("", web.Bind(forms.EditBoardColumnForm{}), repo.EditBoardColumn) + m.Delete("", repo.DeleteBoardColumn) + m.Post("/default", repo.SetDefaultBoardColumn) m.Post("/move", repo.MoveIssues) }) diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 89a013d9af8d0..862a83e5d3501 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -10,8 +10,8 @@ import ( "strings" "code.gitea.io/gitea/models" + board_model "code.gitea.io/gitea/models/board" issues_model "code.gitea.io/gitea/models/issues" - project_model "code.gitea.io/gitea/models/project" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" @@ -498,43 +498,29 @@ 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 +// CreateBoardForm form for creating a board +type CreateBoardForm struct { + Title string `binding:"Required;MaxSize(100)"` + Content string + ColumnType board_model.BoardType } // UserCreateProjectForm is a from for creating an individual or organization // form. type UserCreateProjectForm struct { - Title string `binding:"Required;MaxSize(100)"` - Content string - BoardType project_model.BoardType - UID int64 `binding:"Required"` + Title string `binding:"Required;MaxSize(100)"` + Content string + ColumnType board_model.BoardType + UID int64 `binding:"Required"` } -// EditProjectBoardForm is a form for editing a project board -type EditProjectBoardForm struct { +// EditBoardColumnForm is a form for editing a project board +type EditBoardColumnForm 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)"` @@ -548,13 +534,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 @@ -580,13 +559,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 { diff --git a/services/issue/issue.go b/services/issue/issue.go index b91ee4fc18b07..f0e6b87fdd7bb 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -7,10 +7,10 @@ import ( "fmt" activities_model "code.gitea.io/gitea/models/activities" + board_model "code.gitea.io/gitea/models/board" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" access_model "code.gitea.io/gitea/models/perm/access" - project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" @@ -260,7 +260,7 @@ func deleteIssue(issue *issues_model.Issue) error { &issues_model.IssueWatch{}, &issues_model.Stopwatch{}, &issues_model.TrackedTime{}, - &project_model.ProjectIssue{}, + &board_model.BoardIssue{}, &repo_model.Attachment{}, &issues_model.PullRequest{}, ); err != nil { From 9b806cba88096a2ac4c870f372e12d5dd4b3a166 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 26 Dec 2022 10:44:05 +0800 Subject: [PATCH 2/4] More renames --- models/board/board.go | 76 +++---- models/board/board_test.go | 22 +- models/board/column.go | 46 ++-- models/board/issue.go | 40 ++-- models/board/main_test.go | 8 +- models/fixtures/{project.yml => board.yml} | 6 +- .../{project_board.yml => board_column.yml} | 6 +- models/fixtures/board_issue.yml | 23 ++ models/fixtures/project_issue.yml | 23 -- models/fixtures/repository.yml | 212 +++++++++--------- models/issues/comment.go | 24 +- models/issues/issue.go | 24 +- models/issues/issue_list.go | 18 +- models/issues/issue_project.go | 62 ++--- models/migrations/base/db.go | 26 +++ models/migrations/migrations.go | 2 + models/migrations/v1_15/v184.go | 17 +- models/migrations/v1_19/v238.go | 43 ++++ models/repo.go | 2 +- models/repo/repo.go | 8 +- models/repo/repo_unit.go | 2 +- models/unit/unit.go | 14 +- modules/context/context.go | 2 +- modules/context/repo.go | 2 +- modules/convert/repository.go | 2 +- modules/doctor/fix16961.go | 2 +- modules/setting/project.go | 8 +- routers/api/v1/repo/repo.go | 6 +- routers/web/repo/{projects.go => boards.go} | 40 ++-- .../repo/{projects_test.go => boards_test.go} | 2 +- routers/web/repo/issue.go | 18 +- routers/web/repo/setting.go | 8 +- routers/web/web.go | 4 +- services/forms/repo_form.go | 4 +- services/forms/user_form_hidden_comments.go | 4 +- 35 files changed, 433 insertions(+), 373 deletions(-) rename models/fixtures/{project.yml => board.yml} (72%) rename models/fixtures/{project_board.yml => board_column.yml} (85%) create mode 100644 models/fixtures/board_issue.yml delete mode 100644 models/fixtures/project_issue.yml create mode 100644 models/migrations/v1_19/v238.go rename routers/web/repo/{projects.go => boards.go} (96%) rename routers/web/repo/{projects_test.go => boards_test.go} (90%) diff --git a/models/board/board.go b/models/board/board.go index 4a3863730ae65..9bf8ea31b20db 100644 --- a/models/board/board.go +++ b/models/board/board.go @@ -1,7 +1,7 @@ // Copyright 2020 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package project +package board import ( "context" @@ -19,41 +19,41 @@ import ( type ( // BoardsConfig is used to identify the type of board that is being created BoardsConfig struct { - ColumnType BoardType + ColumnType ColumnType Translation string } - // Type is used to identify the type of project in question and ownership + // Type is used to identify the type of board in question and ownership Type uint8 - // ColumnType is used to represent a project board type - BoardType uint8 + // ColumnType is used to represent a board board type + ColumnType uint8 ) const ( - // TypeIndividual is a type of project board that is owned by an individual + // TypeIndividual is a type of board board that is owned by an individual TypeIndividual Type = iota + 1 - // TypeRepository is a project that is tied to a repository + // TypeRepository is a board that is tied to a repository TypeRepository - // TypeOrganization is a project that is tied to an organisation + // TypeOrganization is a board that is tied to an organisation TypeOrganization ) const ( // BoardTypeNone is a board type that has no predefined columns - BoardTypeNone BoardType = iota + BoardTypeNone ColumnType = iota - // ColumnTypeBasicKanban is a project board type that has basic predefined columns + // ColumnTypeBasicKanban is a board board type that has basic predefined columns BoardTypeBasicKanban - // ColumnTypeBugTriage is a project board type that has predefined columns suited to hunting down bugs + // ColumnTypeBugTriage is a board board type that has predefined columns suited to hunting down bugs BoardTypeBugTriage ) -// IsBoardTypeValid checks if the project board type is valid -func IsBoardTypeValid(p BoardType) bool { +// IsBoardTypeValid checks if the board board type is valid +func IsBoardTypeValid(p ColumnType) bool { switch p { case BoardTypeNone, BoardTypeBasicKanban, BoardTypeBugTriage: return true @@ -90,7 +90,7 @@ type Board struct { RepoID int64 `xorm:"INDEX"` CreatorID int64 `xorm:"NOT NULL"` IsClosed bool `xorm:"INDEX"` - ColumnType BoardType + ColumnType ColumnType Type Type RenderedContent string `xorm:"-"` @@ -104,7 +104,7 @@ func init() { db.RegisterModel(new(Board)) } -// GetBoardsConfig retrieves the types of configurations projects could have +// GetBoardsConfig retrieves the types of configurations boards could have func GetBoardsConfig() []BoardsConfig { return []BoardsConfig{ {BoardTypeNone, "repo.projects.type.none"}, @@ -113,7 +113,7 @@ func GetBoardsConfig() []BoardsConfig { } } -// IsTypeValid checks if a project type is valid +// IsTypeValid checks if a board type is valid func IsTypeValid(p Type) bool { switch p { case TypeRepository: @@ -123,7 +123,7 @@ func IsTypeValid(p Type) bool { } } -// SearchOptions are options for GetProjects +// SearchOptions are options for FindBoards type SearchOptions struct { RepoID int64 Page int @@ -135,7 +135,7 @@ type SearchOptions struct { // FindBoards returns a list of all boards that have been created in the repository func FindBoards(ctx context.Context, opts SearchOptions) ([]*Board, int64, error) { e := db.GetEngine(ctx) - projects := make([]*Board, 0, setting.UI.IssuePagingNum) + boards := make([]*Board, 0, setting.UI.IssuePagingNum) var cond builder.Cond = builder.Eq{"repo_id": opts.RepoID} switch opts.IsClosed { @@ -171,7 +171,7 @@ func FindBoards(ctx context.Context, opts SearchOptions) ([]*Board, int64, error e.Asc("created_unix") } - return projects, count, e.Find(&projects) + return boards, count, e.Find(&boards) } // NewBoard creates a new board @@ -181,7 +181,7 @@ func NewBoard(p *Board) error { } if !IsTypeValid(p.Type) { - return errors.New("project type is not valid") + return errors.New("board type is not valid") } ctx, committer, err := db.TxContext(db.DefaultContext) @@ -194,7 +194,7 @@ func NewBoard(p *Board) error { return err } - if _, err := db.Exec(ctx, "UPDATE `repository` SET num_projects = num_projects + 1 WHERE id = ?", p.RepoID); err != nil { + if _, err := db.Exec(ctx, "UPDATE `repository` SET num_boards = num_boards + 1 WHERE id = ?", p.RepoID); err != nil { return err } @@ -231,19 +231,19 @@ func UpdateBoard(ctx context.Context, p *Board) error { func updateRepositoryBoardCount(ctx context.Context, repoID int64) error { if _, err := db.GetEngine(ctx).Exec(builder.Update( builder.Eq{ - "`num_projects`": builder.Select("count(*)").From("`project`"). - Where(builder.Eq{"`project`.`repo_id`": repoID}. - And(builder.Eq{"`project`.`type`": TypeRepository})), + "`num_boards`": builder.Select("count(*)").From("`board`"). + Where(builder.Eq{"`board`.`repo_id`": repoID}. + And(builder.Eq{"`board`.`type`": TypeRepository})), }).From("`repository`").Where(builder.Eq{"id": repoID})); err != nil { return err } if _, err := db.GetEngine(ctx).Exec(builder.Update( builder.Eq{ - "`num_closed_projects`": builder.Select("count(*)").From("`project`"). - Where(builder.Eq{"`project`.`repo_id`": repoID}. - And(builder.Eq{"`project`.`type`": TypeRepository}). - And(builder.Eq{"`project`.`is_closed`": true})), + "`num_closed_boards`": builder.Select("count(*)").From("`board`"). + Where(builder.Eq{"`board`.`repo_id`": repoID}. + And(builder.Eq{"`board`.`type`": TypeRepository}). + And(builder.Eq{"`board`.`is_closed`": true})), }).From("`repository`").Where(builder.Eq{"id": repoID})); err != nil { return err } @@ -303,7 +303,7 @@ func changeBoardStatus(ctx context.Context, p *Board, isClosed bool) error { return updateRepositoryBoardCount(ctx, p.RepoID) } -// DeleteBoardByID deletes a project from a repository. if it's not in a database +// DeleteBoardByID deletes a board from a repository. if it's not in a database // transaction, it will start a new database transaction func DeleteBoardByID(ctx context.Context, id int64) error { return db.AutoTx(ctx, func(ctx context.Context) error { @@ -334,33 +334,33 @@ func DeleteBoardByID(ctx context.Context, id int64) error { func DeleteBoardByRepoID(ctx context.Context, repoID int64) error { switch { case setting.Database.UseSQLite3: - 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 { + if _, err := db.GetEngine(ctx).Exec("DELETE FROM board_issue WHERE board_issue.id IN (SELECT board_issue.id FROM board_issue INNER JOIN board WHERE board.id = board_issue.board_id AND board.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 board_column WHERE board_column.id IN (SELECT board_column.id FROM board_column INNER JOIN board WHERE board.id = board_column.board_id AND board.repo_id = ?)", repoID); err != nil { return err } - if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { + if _, err := db.GetEngine(ctx).Table("board").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { return err } case setting.Database.UsePostgreSQL: - 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 { + if _, err := db.GetEngine(ctx).Exec("DELETE FROM board_issue USING board WHERE board.id = board_issue.board_id AND board.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 board_column USING board WHERE board.id = board_column.board_id AND board.repo_id = ? ", repoID); err != nil { return err } - if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { + if _, err := db.GetEngine(ctx).Table("board").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { return err } default: - 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 { + if _, err := db.GetEngine(ctx).Exec("DELETE board_issue FROM board_issue INNER JOIN board ON board.id = board_issue.board_id WHERE board.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 board_column FROM board_column INNER JOIN board ON board.id = board_column.board_id WHERE board.repo_id = ? ", repoID); err != nil { return err } - if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { + if _, err := db.GetEngine(ctx).Table("board").Where("repo_id = ? ", repoID).Delete(&Board{}); err != nil { return err } } diff --git a/models/board/board_test.go b/models/board/board_test.go index 2d4411f0b51ee..5f26235d327f6 100644 --- a/models/board/board_test.go +++ b/models/board/board_test.go @@ -1,7 +1,7 @@ // Copyright 2020 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package project +package board import ( "testing" @@ -34,17 +34,17 @@ func TestIsBoardTypeValid(t *testing.T) { func TestFindBoards(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projects, _, err := FindBoards(db.DefaultContext, SearchOptions{RepoID: 1}) + boards, _, err := FindBoards(db.DefaultContext, SearchOptions{RepoID: 1}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures - assert.Len(t, projects, 1) + assert.Len(t, boards, 1) - projects, _, err = FindBoards(db.DefaultContext, SearchOptions{RepoID: 3}) + boards, _, err = FindBoards(db.DefaultContext, SearchOptions{RepoID: 3}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures - assert.Len(t, projects, 1) + assert.Len(t, boards, 1) } func TestBoard(t *testing.T) { @@ -53,7 +53,7 @@ func TestBoard(t *testing.T) { board := &Board{ Type: TypeRepository, ColumnType: BoardTypeBasicKanban, - Title: "New Project", + Title: "New Board", RepoID: 1, CreatedUnix: timeutil.TimeStampNow(), CreatorID: 2, @@ -64,20 +64,20 @@ func TestBoard(t *testing.T) { _, err := GetBoardByID(db.DefaultContext, board.ID) assert.NoError(t, err) - // Update project + // Update board board.Title = "Updated title" assert.NoError(t, UpdateBoard(db.DefaultContext, board)) - projectFromDB, err := GetBoardByID(db.DefaultContext, board.ID) + boardFromDB, err := GetBoardByID(db.DefaultContext, board.ID) assert.NoError(t, err) - assert.Equal(t, board.Title, projectFromDB.Title) + assert.Equal(t, board.Title, boardFromDB.Title) assert.NoError(t, ChangeBoardStatus(board, true)) // Retrieve from DB afresh to check if it is truly closed - projectFromDB, err = GetBoardByID(db.DefaultContext, board.ID) + boardFromDB, err = GetBoardByID(db.DefaultContext, board.ID) assert.NoError(t, err) - assert.True(t, projectFromDB.IsClosed) + assert.True(t, boardFromDB.IsClosed) } diff --git a/models/board/column.go b/models/board/column.go index 680c3815738bf..8e6bf8a68b446 100644 --- a/models/board/column.go +++ b/models/board/column.go @@ -1,7 +1,7 @@ // Copyright 2020 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package project +package board import ( "context" @@ -19,19 +19,19 @@ import ( // ColumnColorPattern is a regexp witch can validate BoardColor var ColumnColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$") -// ErrColumnNotExist represents a "ProjectBoardNotExist" kind of error. +// ErrColumnNotExist represents a "ColumnNotExist" kind of error. type ErrColumnNotExist struct { ColumnID int64 } -// IsErrProjectBoardNotExist checks if an error is a ErrProjectBoardNotExist -func IsErrProjectBoardNotExist(err error) bool { +// IsErrColumnNotExist checks if an error is a ErrColumnNotExist +func IsErrColumnNotExist(err error) bool { _, ok := err.(ErrColumnNotExist) return ok } func (err ErrColumnNotExist) Error() string { - return fmt.Sprintf("project board does not exist [id: %d]", err.ColumnID) + return fmt.Sprintf("board column does not exist [id: %d]", err.ColumnID) } func (err ErrColumnNotExist) Unwrap() error { @@ -55,14 +55,14 @@ type Column struct { // TableName return the real table name func (Column) TableName() string { - return "project_board" + return "board_column" } // NumIssues return counter of all issues assigned to the board func (b *Column) NumIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). - Where("project_id=?", b.BoardID). - And("project_board_id=?", b.ID). + c, err := db.GetEngine(db.DefaultContext).Table("board_issue"). + Where("board_id=?", b.BoardID). + And("board_column_id=?", b.ID). GroupBy("issue_id"). Cols("issue_id"). Count() @@ -82,10 +82,10 @@ func createColumnsForBoardType(ctx context.Context, board *Board) error { switch board.ColumnType { case BoardTypeBugTriage: - items = setting.Project.ProjectBoardBugTriageType + items = setting.Board.ProjectBoardBugTriageType case BoardTypeBasicKanban: - items = setting.Project.ProjectBoardBasicKanbanType + items = setting.Board.ProjectBoardBasicKanbanType case BoardTypeNone: fallthrough @@ -111,7 +111,7 @@ func createColumnsForBoardType(ctx context.Context, board *Board) error { return db.Insert(ctx, columns) } -// NewColumn adds a new project board to a given project +// NewColumn adds a new board column to a given board func NewColumn(board *Column) error { if len(board.Color) != 0 && !ColumnColorPattern.MatchString(board.Color) { return fmt.Errorf("bad color code: %s", board.Color) @@ -121,7 +121,7 @@ func NewColumn(board *Column) error { return err } -// DeleteColumnByID removes all issues references to the project board. +// DeleteColumnByID removes all issues references to the board column. func DeleteColumnByID(boardID int64) error { ctx, committer, err := db.TxContext(db.DefaultContext) if err != nil { @@ -139,7 +139,7 @@ func DeleteColumnByID(boardID int64) error { func deleteColumnByID(ctx context.Context, columnID int64) error { column, err := GetColumn(ctx, columnID) if err != nil { - if IsErrProjectBoardNotExist(err) { + if IsErrColumnNotExist(err) { return nil } @@ -157,11 +157,11 @@ func deleteColumnByID(ctx context.Context, columnID int64) error { } func deleteColumnsByBoardID(ctx context.Context, boardID int64) error { - _, err := db.GetEngine(ctx).Where("project_id=?", boardID).Delete(&Column{}) + _, err := db.GetEngine(ctx).Where("board_id=?", boardID).Delete(&Column{}) return err } -// GetBoard fetches the current board of a project +// GetColumn fetches the current column of a board func GetColumn(ctx context.Context, columnID int64) (*Column, error) { column := new(Column) @@ -197,7 +197,7 @@ func UpdateColumn(ctx context.Context, column *Column) error { return err } -// ColumnList is a list of all project boards in a repository +// ColumnList is a list of all board columns in a repository type ColumnList []*Column // FindColumns fetches all columns related to a board @@ -205,7 +205,7 @@ type ColumnList []*Column func FindColumns(ctx context.Context, boardID int64) (ColumnList, error) { columns := make([]*Column, 0, 5) - if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", boardID, false).OrderBy("Sorting").Find(&columns); err != nil { + if err := db.GetEngine(ctx).Where("board_id=? AND `default`=?", boardID, false).OrderBy("Sorting").Find(&columns); err != nil { return nil, err } @@ -220,7 +220,7 @@ func FindColumns(ctx context.Context, boardID int64) (ColumnList, error) { // getDefaultColumn return default column and create a dummy if none exist func getDefaultColumn(ctx context.Context, boardID int64) (*Column, error) { var board Column - exist, err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", boardID, true).Get(&board) + exist, err := db.GetEngine(ctx).Where("board_id=? AND `default`=?", boardID, true).Get(&board) if err != nil { return nil, err } @@ -240,22 +240,22 @@ func getDefaultColumn(ctx context.Context, boardID int64) (*Column, error) { // if boardID is 0 unset default func SetDefaultColumn(boardID, columnID int64) error { _, err := db.GetEngine(db.DefaultContext).Where(builder.Eq{ - "project_id": boardID, - "`default`": true, + "board_id": boardID, + "`default`": true, }).Cols("`default`").Update(&Column{Default: false}) if err != nil { return err } if boardID > 0 { - _, err = db.GetEngine(db.DefaultContext).ID(boardID).Where(builder.Eq{"project_id": boardID}). + _, err = db.GetEngine(db.DefaultContext).ID(boardID).Where(builder.Eq{"board_id": boardID}). Cols("`default`").Update(&Column{Default: true}) } return err } -// UpdateColumnSorting update project board sorting +// UpdateColumnSorting update board column sorting func UpdateColumnSorting(bs ColumnList) error { for i := range bs { _, err := db.GetEngine(db.DefaultContext).ID(bs[i].ID).Cols( diff --git a/models/board/issue.go b/models/board/issue.go index b28ebb5c51529..d219c63cae436 100644 --- a/models/board/issue.go +++ b/models/board/issue.go @@ -1,7 +1,7 @@ // Copyright 2020 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package project +package board import ( "context" @@ -11,13 +11,13 @@ import ( "code.gitea.io/gitea/modules/log" ) -// BoardIssue saves relation from issue to a project +// BoardIssue saves relation from issue to a board type BoardIssue struct { //revive:disable-line:exported ID int64 `xorm:"pk autoincr"` IssueID int64 `xorm:"INDEX"` BoardID int64 `xorm:"INDEX"` - // If 0, then it has not been added to a specific board in the project + // If 0, then it has not been added to a specific board in the board BoardColumnID int64 `xorm:"INDEX"` // the sorting order on the board @@ -28,15 +28,15 @@ func init() { db.RegisterModel(new(BoardIssue)) } -func deleteBoardIssuesByBoardID(ctx context.Context, projectID int64) error { - _, err := db.GetEngine(ctx).Where("project_id=?", projectID).Delete(&BoardIssue{}) +func deleteBoardIssuesByBoardID(ctx context.Context, boardID int64) error { + _, err := db.GetEngine(ctx).Where("board_id=?", boardID).Delete(&BoardIssue{}) return err } -// NumIssues return counter of all issues assigned to a project +// NumIssues return counter of all issues assigned to a board func (p *Board) NumIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). - Where("project_id=?", p.ID). + c, err := db.GetEngine(db.DefaultContext).Table("board_issue"). + Where("board_id=?", p.ID). GroupBy("issue_id"). Cols("issue_id"). Count() @@ -47,11 +47,11 @@ func (p *Board) NumIssues() int { return int(c) } -// NumClosedIssues return counter of closed issues assigned to a project +// NumClosedIssues return counter of closed issues assigned to a board func (p *Board) NumClosedIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). - Join("INNER", "issue", "project_issue.issue_id=issue.id"). - Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, true). + c, err := db.GetEngine(db.DefaultContext).Table("board_issue"). + Join("INNER", "issue", "board_issue.issue_id=issue.id"). + Where("board_issue.board_id=? AND issue.is_closed=?", p.ID, true). Cols("issue_id"). Count() if err != nil { @@ -61,11 +61,11 @@ func (p *Board) NumClosedIssues() int { return int(c) } -// NumOpenIssues return counter of open issues assigned to a project +// NumOpenIssues return counter of open issues assigned to a board func (p *Board) NumOpenIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). - Join("INNER", "issue", "project_issue.issue_id=issue.id"). - Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, false). + c, err := db.GetEngine(db.DefaultContext).Table("board_issue"). + Join("INNER", "issue", "board_issue.issue_id=issue.id"). + Where("board_issue.board_id=? AND issue.is_closed=?", p.ID, false). Cols("issue_id"). Count() if err != nil { @@ -84,16 +84,16 @@ func MoveIssuesOnBoardColumn(column *Column, sortedIssueIDs map[int64]int64) err for _, issueID := range sortedIssueIDs { issueIDs = append(issueIDs, issueID) } - count, err := sess.Table(new(BoardIssue)).Where("project_id=?", column.BoardID).In("issue_id", issueIDs).Count() + count, err := sess.Table(new(BoardIssue)).Where("board_id=?", column.BoardID).In("issue_id", issueIDs).Count() if err != nil { return err } if int(count) != len(sortedIssueIDs) { - return fmt.Errorf("all issues have to be added to a project first") + return fmt.Errorf("all issues have to be added to a board first") } for sorting, issueID := range sortedIssueIDs { - _, err = sess.Exec("UPDATE `project_issue` SET project_board_id=?, sorting=? WHERE issue_id=?", column.ID, sorting, issueID) + _, err = sess.Exec("UPDATE `board_issue` SET board_column_id=?, sorting=? WHERE issue_id=?", column.ID, sorting, issueID) if err != nil { return err } @@ -103,6 +103,6 @@ func MoveIssuesOnBoardColumn(column *Column, sortedIssueIDs map[int64]int64) err } 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) + _, err := db.GetEngine(ctx).Exec("UPDATE `board_issue` SET board_column_id = 0 WHERE board_column_id = ? ", b.ID) return err } diff --git a/models/board/main_test.go b/models/board/main_test.go index 816cbeb94a045..588c888d43858 100644 --- a/models/board/main_test.go +++ b/models/board/main_test.go @@ -1,7 +1,7 @@ // Copyright 2020 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package project +package board import ( "path/filepath" @@ -16,9 +16,9 @@ func TestMain(m *testing.M) { unittest.MainTest(m, &unittest.TestOptions{ GiteaRootPath: filepath.Join("..", ".."), FixtureFiles: []string{ - "project.yml", - "project_board.yml", - "project_issue.yml", + "board.yml", + "board_column.yml", + "board_issue.yml", "repository.yml", }, }) diff --git a/models/fixtures/project.yml b/models/fixtures/board.yml similarity index 72% rename from models/fixtures/project.yml rename to models/fixtures/board.yml index 3d42597c5e8ac..63cf9599b5a15 100644 --- a/models/fixtures/project.yml +++ b/models/fixtures/board.yml @@ -1,6 +1,6 @@ - id: 1 - title: First project + title: First board repo_id: 1 is_closed: false creator_id: 2 @@ -9,7 +9,7 @@ - id: 2 - title: second project + title: second board repo_id: 3 is_closed: false creator_id: 3 @@ -18,7 +18,7 @@ - id: 3 - title: project on repo with disabled project + title: board on repo with disabled board repo_id: 4 is_closed: true creator_id: 5 diff --git a/models/fixtures/project_board.yml b/models/fixtures/board_column.yml similarity index 85% rename from models/fixtures/project_board.yml rename to models/fixtures/board_column.yml index 9e06e8c23960b..558be3c0fbdf6 100644 --- a/models/fixtures/project_board.yml +++ b/models/fixtures/board_column.yml @@ -1,6 +1,6 @@ - id: 1 - project_id: 1 + board_id: 1 title: To Do creator_id: 2 created_unix: 1588117528 @@ -8,7 +8,7 @@ - id: 2 - project_id: 1 + board_id: 1 title: In Progress creator_id: 2 created_unix: 1588117528 @@ -16,7 +16,7 @@ - id: 3 - project_id: 1 + board_id: 1 title: Done creator_id: 2 created_unix: 1588117528 diff --git a/models/fixtures/board_issue.yml b/models/fixtures/board_issue.yml new file mode 100644 index 0000000000000..ab9254eb85269 --- /dev/null +++ b/models/fixtures/board_issue.yml @@ -0,0 +1,23 @@ +- + id: 1 + issue_id: 1 + board_id: 1 + board_column_id: 1 + +- + id: 2 + issue_id: 2 + board_id: 1 + board_column_id: 0 # no board assigned + +- + id: 3 + issue_id: 3 + board_id: 1 + board_column_id: 2 + +- + id: 4 + issue_id: 5 + board_id: 1 + board_column_id: 3 diff --git a/models/fixtures/project_issue.yml b/models/fixtures/project_issue.yml deleted file mode 100644 index b1af05908aafb..0000000000000 --- a/models/fixtures/project_issue.yml +++ /dev/null @@ -1,23 +0,0 @@ -- - id: 1 - issue_id: 1 - project_id: 1 - project_board_id: 1 - -- - id: 2 - issue_id: 2 - project_id: 1 - project_board_id: 0 # no board assigned - -- - id: 3 - issue_id: 3 - project_id: 1 - project_board_id: 2 - -- - id: 4 - issue_id: 5 - project_id: 1 - project_board_id: 3 diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml index 19b243fb4e4e5..9e3d4e7f07684 100644 --- a/models/fixtures/repository.yml +++ b/models/fixtures/repository.yml @@ -13,8 +13,8 @@ num_closed_pulls: 0 num_milestones: 3 num_closed_milestones: 1 - num_projects: 1 - num_closed_projects: 0 + num_boards: 1 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -43,8 +43,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: false is_archived: false @@ -73,8 +73,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 1 - num_closed_projects: 0 + num_boards: 1 + num_closed_boards: 0 is_private: true is_empty: false is_archived: false @@ -103,8 +103,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 1 + num_boards: 0 + num_closed_boards: 1 is_private: false is_empty: false is_archived: false @@ -133,8 +133,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -163,8 +163,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -193,8 +193,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -223,8 +223,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -253,8 +253,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -283,8 +283,8 @@ num_closed_pulls: 0 num_milestones: 1 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -313,8 +313,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -343,8 +343,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -373,8 +373,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -404,8 +404,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -434,8 +434,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: false is_archived: false @@ -464,8 +464,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: false is_archived: false @@ -494,8 +494,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -524,8 +524,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -554,8 +554,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -584,8 +584,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -614,8 +614,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -644,8 +644,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -674,8 +674,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -704,8 +704,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -734,8 +734,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -764,8 +764,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -794,8 +794,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -824,8 +824,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -854,8 +854,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -884,8 +884,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -914,8 +914,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: false is_archived: false @@ -944,8 +944,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -974,8 +974,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1004,8 +1004,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -1034,8 +1034,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -1064,8 +1064,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1094,8 +1094,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1124,8 +1124,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1154,8 +1154,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: false is_archived: false @@ -1184,8 +1184,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1214,8 +1214,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: false is_archived: false @@ -1244,8 +1244,8 @@ num_closed_pulls: 0 num_milestones: 1 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1274,8 +1274,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -1304,8 +1304,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1334,8 +1334,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: true is_archived: false @@ -1364,8 +1364,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1394,8 +1394,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1424,8 +1424,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1454,8 +1454,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1484,8 +1484,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: false @@ -1514,8 +1514,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: false is_empty: false is_archived: true @@ -1544,8 +1544,8 @@ num_closed_pulls: 0 num_milestones: 0 num_closed_milestones: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 is_private: true is_empty: true is_archived: false @@ -1575,8 +1575,8 @@ num_milestones: 0 num_closed_milestones: 0 num_watches: 0 - num_projects: 0 - num_closed_projects: 0 + num_boards: 0 + num_closed_boards: 0 status: 0 is_fork: false fork_id: 0 diff --git a/models/issues/comment.go b/models/issues/comment.go index 8744f15b6b581..6f42928884a73 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -122,10 +122,10 @@ const ( CommentTypeMergePull // 29 push to PR head branch CommentTypePullRequestPush - // 30 Project changed - CommentTypeProject - // 31 Project board changed - CommentTypeProjectBoard + // 30 Board changed + CommentTypeBoard + // 31 Board column changed + CommentTypeBoardColumn // 32 Dismiss Review CommentTypeDismissReview // 33 Change issue ref @@ -490,25 +490,25 @@ func (c *Comment) LoadLabel() error { return nil } -// LoadProject if comment.Type is CommentTypeProject, then load project. -func (c *Comment) LoadProject() error { +// LoadBoard if comment.Type is CommentTypeBoard, then load boards. +func (c *Comment) LoadBoard() error { if c.OldProjectID > 0 { - var oldProject board_model.Board - has, err := db.GetEngine(db.DefaultContext).ID(c.OldProjectID).Get(&oldProject) + var oldBoard board_model.Board + has, err := db.GetEngine(db.DefaultContext).ID(c.OldProjectID).Get(&oldBoard) if err != nil { return err } else if has { - c.OldBoard = &oldProject + c.OldBoard = &oldBoard } } if c.ProjectID > 0 { - var project board_model.Board - has, err := db.GetEngine(db.DefaultContext).ID(c.ProjectID).Get(&project) + var board board_model.Board + has, err := db.GetEngine(db.DefaultContext).ID(c.ProjectID).Get(&board) if err != nil { return err } else if has { - c.Board = &project + c.Board = &board } } diff --git a/models/issues/issue.go b/models/issues/issue.go index 5b3b9b6706acc..14b957001e2ba 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -347,7 +347,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return } - if err = issue.loadProject(ctx); err != nil { + if err = issue.loadBoard(ctx); err != nil { return } @@ -1121,8 +1121,8 @@ type IssuesOptions struct { //nolint ReviewRequestedID int64 SubscriberID int64 MilestoneIDs []int64 - ProjectID int64 - ProjectBoardID int64 + BoardID int64 + BoardColumnID int64 IsClosed util.OptionalBool IsPull util.OptionalBool LabelIDs []int64 @@ -1181,8 +1181,8 @@ func sortIssuesSession(sess *xorm.Session, sortType string, priorityRepoID int64 "ELSE 2 END ASC", priorityRepoID). Desc("issue.created_unix"). Desc("issue.id") - case "project-column-sorting": - sess.Asc("project_issue.sorting").Desc("issue.created_unix").Desc("issue.id") + case "board-column-sorting": + sess.Asc("board_issue.sorting").Desc("issue.created_unix").Desc("issue.id") default: sess.Desc("issue.created_unix").Desc("issue.id") } @@ -1248,16 +1248,16 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) { sess.And(builder.Lte{"issue.updated_unix": opts.UpdatedBeforeUnix}) } - if opts.ProjectID > 0 { - sess.Join("INNER", "project_issue", "issue.id = project_issue.issue_id"). - And("project_issue.project_id=?", opts.ProjectID) + if opts.BoardID > 0 { + sess.Join("INNER", "board_issue", "issue.id = board_issue.issue_id"). + And("board_issue.board_id=?", opts.BoardID) } - 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.BoardColumnID != 0 { + if opts.BoardColumnID > 0 { + sess.In("issue.id", builder.Select("issue_id").From("board_issue").Where(builder.Eq{"board_column_id": opts.BoardColumnID})) } 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("board_issue").Where(builder.Eq{"board_column_id": 0})) } } diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index 100034ba01bf7..3d353707e38a7 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -223,30 +223,30 @@ func (issues IssueList) getBoardIDs() []int64 { } func (issues IssueList) loadBoards(ctx context.Context) error { - projectIDs := issues.getBoardIDs() - if len(projectIDs) == 0 { + boardIDs := issues.getBoardIDs() + if len(boardIDs) == 0 { return nil } - projectMaps := make(map[int64]*board_model.Board, len(projectIDs)) - left := len(projectIDs) + boardMaps := make(map[int64]*board_model.Board, len(boardIDs)) + left := len(boardIDs) for left > 0 { limit := db.DefaultMaxInSize if left < limit { limit = left } err := db.GetEngine(ctx). - In("id", projectIDs[:limit]). - Find(&projectMaps) + In("id", boardIDs[:limit]). + Find(&boardMaps) if err != nil { return err } left -= limit - projectIDs = projectIDs[limit:] + boardIDs = boardIDs[limit:] } for _, issue := range issues { - issue.Board = projectMaps[issue.BoardID()] + issue.Board = boardMaps[issue.BoardID()] } return nil } @@ -527,7 +527,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error { } if err := issues.loadBoards(ctx); err != nil { - return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err) + return fmt.Errorf("issue.loadAttributes: loadBoards: %w", err) } if err := issues.loadAssignees(ctx); err != nil { diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index 26743e2e30c18..dbd9578f4c4bc 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -12,17 +12,17 @@ import ( user_model "code.gitea.io/gitea/models/user" ) -// LoadProject load the project the issue was assigned to -func (issue *Issue) LoadProject() (err error) { - return issue.loadProject(db.DefaultContext) +// LoadBoard load the board the issue was assigned to +func (issue *Issue) LoadBoard() (err error) { + return issue.loadBoard(db.DefaultContext) } -func (issue *Issue) loadProject(ctx context.Context) (err error) { +func (issue *Issue) loadBoard(ctx context.Context) (err error) { if issue.Board == nil { var p board_model.Board - if _, err = db.GetEngine(ctx).Table("project"). - Join("INNER", "project_issue", "project.id=project_issue.project_id"). - Where("project_issue.issue_id = ?", issue.ID). + if _, err = db.GetEngine(ctx).Table("board"). + Join("INNER", "board_issue", "board.id=board_issue.board_id"). + Where("board_issue.issue_id = ?", issue.ID). Get(&p); err != nil { return err } @@ -31,7 +31,7 @@ func (issue *Issue) loadProject(ctx context.Context) (err error) { return err } -// ProjectID return project id if issue was assigned to one +// BoardID return board id if issue was assigned to one func (issue *Issue) BoardID() int64 { return issue.boardID(db.DefaultContext) } @@ -45,12 +45,12 @@ func (issue *Issue) boardID(ctx context.Context) int64 { return ip.BoardID } -// ProjectBoardID return project board id if issue was assigned to one -func (issue *Issue) ProjectBoardID() int64 { - return issue.projectBoardID(db.DefaultContext) +// BoardColumnID return board column id if issue was assigned to one +func (issue *Issue) BoardColumnID() int64 { + return issue.boardColumnID(db.DefaultContext) } -func (issue *Issue) projectBoardID(ctx context.Context) int64 { +func (issue *Issue) boardColumnID(ctx context.Context) int64 { var ip board_model.BoardIssue has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip) if err != nil || !has { @@ -65,9 +65,9 @@ func LoadIssuesFromBoardColumn(ctx context.Context, b *board_model.Column) (Issu if b.ID != 0 { issues, err := Issues(ctx, &IssuesOptions{ - ProjectBoardID: b.ID, - ProjectID: b.BoardID, - SortType: "project-column-sorting", + BoardColumnID: b.ID, + BoardID: b.BoardID, + SortType: "board-column-sorting", }) if err != nil { return nil, err @@ -77,9 +77,9 @@ func LoadIssuesFromBoardColumn(ctx context.Context, b *board_model.Column) (Issu if b.Default { issues, err := Issues(ctx, &IssuesOptions{ - ProjectBoardID: -1, // Issues without ProjectBoardID - ProjectID: b.BoardID, - SortType: "project-column-sorting", + BoardColumnID: -1, // Issues without BoardColumnID + BoardID: b.BoardID, + SortType: "board-column-sorting", }) if err != nil { return nil, err @@ -107,15 +107,15 @@ func LoadIssuesFromBoardList(ctx context.Context, bs board_model.ColumnList) (ma return issuesMap, nil } -// ChangeProjectAssign changes the project associated with an issue -func ChangeProjectAssign(issue *Issue, doer *user_model.User, newProjectID int64) error { +// ChangeBoardAssign changes the board associated with an issue +func ChangeBoardAssign(issue *Issue, doer *user_model.User, newBoardID int64) error { ctx, committer, err := db.TxContext(db.DefaultContext) if err != nil { return err } defer committer.Close() - if err := addUpdateIssueBoard(ctx, issue, doer, newProjectID); err != nil { + if err := addUpdateIssueBoard(ctx, issue, doer, newBoardID); err != nil { return err } @@ -125,18 +125,18 @@ func ChangeProjectAssign(issue *Issue, doer *user_model.User, newProjectID int64 func addUpdateIssueBoard(ctx context.Context, issue *Issue, doer *user_model.User, newBoardID int64) error { oldBoardID := issue.boardID(ctx) - // Only check if we add a new project and not remove it. + // Only check if we add a new board and not remove it. if newBoardID > 0 { - newProject, err := board_model.GetBoardByID(ctx, newBoardID) + newBoard, err := board_model.GetBoardByID(ctx, newBoardID) if err != nil { return err } - if newProject.RepoID != issue.RepoID { - return fmt.Errorf("issue's repository is not the same as project's repository") + if newBoard.RepoID != issue.RepoID { + return fmt.Errorf("issue's repository is not the same as board's repository") } } - if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&board_model.BoardIssue{}); err != nil { + if _, err := db.GetEngine(ctx).Where("board_issue.issue_id=?", issue.ID).Delete(&board_model.BoardIssue{}); err != nil { return err } @@ -146,7 +146,7 @@ func addUpdateIssueBoard(ctx context.Context, issue *Issue, doer *user_model.Use if oldBoardID > 0 || newBoardID > 0 { if _, err := CreateComment(ctx, &CreateCommentOptions{ - Type: CommentTypeProject, + Type: CommentTypeBoard, Doer: doer, Repo: issue.Repo, Issue: issue, @@ -163,8 +163,8 @@ func addUpdateIssueBoard(ctx context.Context, issue *Issue, doer *user_model.Use }) } -// MoveIssueAcrossProjectBoards move a card from one board to another -func MoveIssueAcrossProjectBoards(issue *Issue, board *board_model.Board) error { +// MoveIssueAcrossBoardColumns move a card from one column to another +func MoveIssueAcrossBoardColumns(issue *Issue, board *board_model.Board) error { ctx, committer, err := db.TxContext(db.DefaultContext) if err != nil { return err @@ -179,11 +179,11 @@ func MoveIssueAcrossProjectBoards(issue *Issue, board *board_model.Board) error } if !has { - return fmt.Errorf("issue has to be added to a project first") + return fmt.Errorf("issue has to be added to a board first") } pis.BoardColumnID = board.ID - if _, err := sess.ID(pis.ID).Cols("project_board_id").Update(&pis); err != nil { + if _, err := sess.ID(pis.ID).Cols("board_column_id").Update(&pis); err != nil { return err } diff --git a/models/migrations/base/db.go b/models/migrations/base/db.go index dcf99c96ae81f..4a6134930cf25 100644 --- a/models/migrations/base/db.go +++ b/models/migrations/base/db.go @@ -631,3 +631,29 @@ func deleteDB() error { return nil } + +func RenameTable(x *xorm.Engine, oldTable, newTable string) error { + if _, err := x.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", oldTable, newTable)); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", oldTable, newTable, err) + return err + } + return nil +} + +func RenameColumn(sess *xorm.Session, table, oldColumn, newColumn, mySQLType string) error { + switch { + case setting.Database.UseMySQL: + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` CHANGE %s %s %s", table, oldColumn, newColumn, mySQLType)); err != nil { + return err + } + case setting.Database.UseMSSQL: + if _, err := sess.Exec(fmt.Sprintf("sp_rename '%s.%s', '%s', 'COLUMN'", table, oldColumn, newColumn)); err != nil { + return err + } + default: + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME COLUMN %s TO %s", table, oldColumn, newColumn)); err != nil { + return err + } + } + return nil +} diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 9d9c8f5165e47..5a04361f913b6 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -446,6 +446,8 @@ var migrations = []Migration{ NewMigration("Create secrets table", v1_19.CreateSecretsTable), // v237 -> v238 NewMigration("Drop ForeignReference table", v1_19.DropForeignReferenceTable), + // v238 -> v239 + NewMigration("Rename projects related tables to boards", v1_19.RenameProjectsToBoards), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_15/v184.go b/models/migrations/v1_15/v184.go index 48f8b62165cc5..44a30533190f7 100644 --- a/models/migrations/v1_15/v184.go +++ b/models/migrations/v1_15/v184.go @@ -8,7 +8,6 @@ import ( "fmt" "code.gitea.io/gitea/models/migrations/base" - "code.gitea.io/gitea/modules/setting" "xorm.io/xorm" ) @@ -53,19 +52,9 @@ func RenameTaskErrorsToMessage(x *xorm.Engine) error { } } - switch { - case setting.Database.UseMySQL: - if _, err := sess.Exec("ALTER TABLE `task` CHANGE errors message text"); err != nil { - return err - } - case setting.Database.UseMSSQL: - if _, err := sess.Exec("sp_rename 'task.errors', 'message', 'COLUMN'"); err != nil { - return err - } - default: - if _, err := sess.Exec("ALTER TABLE `task` RENAME COLUMN errors TO message"); err != nil { - return err - } + if err := base.RenameColumn(sess, "task", "errors", "message", "text"); err != nil { + return err } + return sess.Commit() } diff --git a/models/migrations/v1_19/v238.go b/models/migrations/v1_19/v238.go new file mode 100644 index 0000000000000..b563fc3b0b749 --- /dev/null +++ b/models/migrations/v1_19/v238.go @@ -0,0 +1,43 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_19 //nolint + +import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" +) + +func RenameProjectsToBoards(x *xorm.Engine) error { + if err := base.RenameTable(x, "project_board", "board_column"); err != nil { + return err + } + if err := base.RenameTable(x, "project_issue", "board_issue"); err != nil { + return err + } + if err := base.RenameTable(x, "project", "board"); err != nil { + return err + } + + sess := x.NewSession() + defer sess.Close() + if err := base.RenameColumn(sess, "board_column", "project_id", "board_id", "bigint"); err != nil { + return err + } + if err := base.RenameColumn(sess, "board_column", "project_id", "board_id", "bigint"); err != nil { + return err + } + if err := base.RenameColumn(sess, "board_issue", "project_id", "board_id", "bigint"); err != nil { + return err + } + if err := base.RenameColumn(sess, "board_issue", "project_board_id", "board_column_id", "bigint"); err != nil { + return err + } + if err := base.RenameColumn(sess, "repository", "num_projects", "num_boards", "INT(11)"); err != nil { + return err + } + if err := base.RenameColumn(sess, "repository", "num_closed_projects", "num_closed_boards", "INT(11)"); err != nil { + return err + } + return nil +} diff --git a/models/repo.go b/models/repo.go index cc890f78c021d..70896d22a54ad 100644 --- a/models/repo.go +++ b/models/repo.go @@ -194,7 +194,7 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error { } if err := board_model.DeleteBoardByRepoID(ctx, repoID); err != nil { - return fmt.Errorf("unable to delete projects for repo[%d]: %w", repoID, err) + return fmt.Errorf("unable to delete boards for repo[%d]: %w", repoID, err) } // Remove LFS objects diff --git a/models/repo/repo.go b/models/repo/repo.go index e5e1ac43b41fd..4c619f6ab952b 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -138,9 +138,9 @@ type Repository struct { NumMilestones int `xorm:"NOT NULL DEFAULT 0"` NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"` NumOpenMilestones int `xorm:"-"` - NumProjects int `xorm:"NOT NULL DEFAULT 0"` - NumClosedProjects int `xorm:"NOT NULL DEFAULT 0"` - NumOpenProjects int `xorm:"-"` + NumBoards int `xorm:"NOT NULL DEFAULT 0"` + NumClosedBoards int `xorm:"NOT NULL DEFAULT 0"` + NumOpenBoards int `xorm:"-"` IsPrivate bool `xorm:"INDEX"` IsEmpty bool `xorm:"INDEX"` @@ -232,7 +232,7 @@ func (repo *Repository) AfterLoad() { repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues repo.NumOpenPulls = repo.NumPulls - repo.NumClosedPulls repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones - repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects + repo.NumOpenBoards = repo.NumBoards - repo.NumClosedBoards } // LoadAttributes loads attributes of the repository. diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go index e20d03e2c5ae3..dd728907a6c67 100644 --- a/models/repo/repo_unit.go +++ b/models/repo/repo_unit.go @@ -174,7 +174,7 @@ func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) { r.Config = new(PullRequestsConfig) case unit.TypeIssues: r.Config = new(IssuesConfig) - case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects, unit.TypePackages: + case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeBoards, unit.TypePackages: fallthrough default: r.Config = new(UnitConfig) diff --git a/models/unit/unit.go b/models/unit/unit.go index c4743dbdb4079..196c6964b3443 100644 --- a/models/unit/unit.go +++ b/models/unit/unit.go @@ -25,7 +25,7 @@ const ( TypeWiki // 5 Wiki TypeExternalWiki // 6 ExternalWiki TypeExternalTracker // 7 ExternalTracker - TypeProjects // 8 Kanban board + TypeBoards // 8 Kanban board TypePackages // 9 Packages ) @@ -50,8 +50,8 @@ func (u Type) String() string { return "TypeExternalWiki" case TypeExternalTracker: return "TypeExternalTracker" - case TypeProjects: - return "TypeProjects" + case TypeBoards: + return "TypeBoards" case TypePackages: return "TypePackages" } @@ -75,7 +75,7 @@ var ( TypeWiki, TypeExternalWiki, TypeExternalTracker, - TypeProjects, + TypeBoards, TypePackages, } @@ -86,7 +86,7 @@ var ( TypePullRequests, TypeReleases, TypeWiki, - TypeProjects, + TypeBoards, TypePackages, } @@ -271,7 +271,7 @@ var ( } UnitProjects = Unit{ - TypeProjects, + TypeBoards, "repo.projects", "/projects", "repo.projects.desc", @@ -297,7 +297,7 @@ var ( TypeReleases: UnitReleases, TypeWiki: UnitWiki, TypeExternalWiki: UnitExternalWiki, - TypeProjects: UnitProjects, + TypeBoards: UnitProjects, TypePackages: UnitPackages, } ) diff --git a/modules/context/context.go b/modules/context/context.go index 0fe00bf787e3d..a3b0348439a79 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -805,7 +805,7 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler { ctx.Data["UnitWikiGlobalDisabled"] = unit.TypeWiki.UnitGlobalDisabled() ctx.Data["UnitIssuesGlobalDisabled"] = unit.TypeIssues.UnitGlobalDisabled() ctx.Data["UnitPullsGlobalDisabled"] = unit.TypePullRequests.UnitGlobalDisabled() - ctx.Data["UnitProjectsGlobalDisabled"] = unit.TypeProjects.UnitGlobalDisabled() + ctx.Data["UnitProjectsGlobalDisabled"] = unit.TypeBoards.UnitGlobalDisabled() ctx.Data["locale"] = locale ctx.Data["AllLangs"] = translation.AllLangs() diff --git a/modules/context/repo.go b/modules/context/repo.go index 71a2b3c0c6ef2..e209f49557409 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -1040,7 +1040,7 @@ func UnitTypes() func(ctx *Context) { ctx.Data["UnitTypeWiki"] = unit_model.TypeWiki ctx.Data["UnitTypeExternalWiki"] = unit_model.TypeExternalWiki ctx.Data["UnitTypeExternalTracker"] = unit_model.TypeExternalTracker - ctx.Data["UnitTypeProjects"] = unit_model.TypeProjects + ctx.Data["UnitTypeBoards"] = unit_model.TypeBoards ctx.Data["UnitTypePackages"] = unit_model.TypePackages } } diff --git a/modules/convert/repository.go b/modules/convert/repository.go index ce53a6669237c..b417d0c5e5ebe 100644 --- a/modules/convert/repository.go +++ b/modules/convert/repository.go @@ -94,7 +94,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc defaultMergeStyle = config.GetDefaultMergeStyle() } hasProjects := false - if _, err := repo.GetUnit(ctx, unit_model.TypeProjects); err == nil { + if _, err := repo.GetUnit(ctx, unit_model.TypeBoards); err == nil { hasProjects = true } diff --git a/modules/doctor/fix16961.go b/modules/doctor/fix16961.go index ea14a9b2c4164..cc7f228454bb2 100644 --- a/modules/doctor/fix16961.go +++ b/modules/doctor/fix16961.go @@ -216,7 +216,7 @@ func fixBrokenRepoUnit16961(repoUnit *repo_model.RepoUnit, bs []byte) (fixed boo } switch repoUnit.Type { - case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects: + case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeBoards: cfg := &repo_model.UnitConfig{} repoUnit.Config = cfg if fixed, err := fixUnitConfig16961(bs, cfg); !fixed { diff --git a/modules/setting/project.go b/modules/setting/project.go index 53e09e8dad82a..cfeb91f03114b 100644 --- a/modules/setting/project.go +++ b/modules/setting/project.go @@ -5,9 +5,9 @@ package setting import "code.gitea.io/gitea/modules/log" -// Project settings +// Board settings var ( - Project = struct { + Board = struct { ProjectBoardBasicKanbanType []string ProjectBoardBugTriageType []string }{ @@ -17,7 +17,7 @@ var ( ) func newProject() { - if err := Cfg.Section("project").MapTo(&Project); err != nil { - log.Fatal("Failed to map Project settings: %v", err) + if err := Cfg.Section("project").MapTo(&Board); err != nil { + log.Fatal("Failed to map Board settings: %v", err) } } diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 349040507810b..bebb9a7f8836b 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -909,14 +909,14 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } } - if opts.HasProjects != nil && !unit_model.TypeProjects.UnitGlobalDisabled() { + if opts.HasProjects != nil && !unit_model.TypeBoards.UnitGlobalDisabled() { if *opts.HasProjects { units = append(units, repo_model.RepoUnit{ RepoID: repo.ID, - Type: unit_model.TypeProjects, + Type: unit_model.TypeBoards, }) } else { - deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeProjects) + deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeBoards) } } diff --git a/routers/web/repo/projects.go b/routers/web/repo/boards.go similarity index 96% rename from routers/web/repo/projects.go rename to routers/web/repo/boards.go index 9c0e28f56ab9e..b92764bd9f661 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/boards.go @@ -34,13 +34,13 @@ const ( // MustEnableProjects check if projects are enabled in settings func MustEnableProjects(ctx *context.Context) { - if unit.TypeProjects.UnitGlobalDisabled() { + if unit.TypeBoards.UnitGlobalDisabled() { ctx.NotFound("EnableKanbanBoard", nil) return } if ctx.Repo.Repository != nil { - if !ctx.Repo.CanRead(unit.TypeProjects) { + if !ctx.Repo.CanRead(unit.TypeBoards) { ctx.NotFound("MustEnableProjects", nil) return } @@ -60,14 +60,14 @@ func Boards(ctx *context.Context) { page = 1 } - ctx.Data["OpenCount"] = repo.NumOpenProjects - ctx.Data["ClosedCount"] = repo.NumClosedProjects + ctx.Data["OpenCount"] = repo.NumOpenBoards + ctx.Data["ClosedCount"] = repo.NumClosedBoards var total int if !isShowClosed { - total = repo.NumOpenProjects + total = repo.NumOpenBoards } else { - total = repo.NumClosedProjects + total = repo.NumClosedBoards } projects, count, err := board_model.FindBoards(ctx, board_model.SearchOptions{ @@ -112,7 +112,7 @@ func Boards(ctx *context.Context) { pager.AddParam(ctx, "state", "State") ctx.Data["Page"] = pager - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) ctx.Data["IsShowClosed"] = isShowClosed ctx.Data["IsProjectsPage"] = true ctx.Data["SortType"] = sortType @@ -124,7 +124,7 @@ func Boards(ctx *context.Context) { func NewBoard(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.new") ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) ctx.HTML(http.StatusOK, tplProjectsNew) } @@ -134,7 +134,7 @@ func NewBoardPost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.new") if ctx.HasError() { - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() ctx.HTML(http.StatusOK, tplProjectsNew) return @@ -211,7 +211,7 @@ func DeleteBoard(ctx *context.Context) { func EditBoard(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["PageIsEditProjects"] = true - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) p, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { @@ -238,7 +238,7 @@ func EditBoardPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.CreateBoardForm) ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["PageIsEditProjects"] = true - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) if ctx.HasError() { ctx.HTML(http.StatusOK, tplProjectsNew) @@ -336,7 +336,7 @@ func ViewBoard(ctx *context.Context) { } ctx.Data["IsProjectsPage"] = true - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) ctx.Data["Project"] = project ctx.Data["IssuesMap"] = issuesMap ctx.Data["Boards"] = boards @@ -358,7 +358,7 @@ func UpdateIssueProject(ctx *context.Context) { continue } - if err := issues_model.ChangeProjectAssign(issue, ctx.Doer, projectID); err != nil { + if err := issues_model.ChangeBoardAssign(issue, ctx.Doer, projectID); err != nil { ctx.ServerError("ChangeProjectAssign", err) return } @@ -378,7 +378,7 @@ func DeleteBoardColumn(ctx *context.Context) { return } - if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeProjects) { + if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeBoards) { ctx.JSON(http.StatusForbidden, map[string]string{ "message": "Only authorized users are allowed to perform this action.", }) @@ -427,7 +427,7 @@ func DeleteBoardColumn(ctx *context.Context) { // AddBoardColumnPost allows a new column to be added to a board. func AddBoardColumnPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.EditBoardColumnForm) - if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeProjects) { + if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeBoards) { ctx.JSON(http.StatusForbidden, map[string]string{ "message": "Only authorized users are allowed to perform this action.", }) @@ -467,7 +467,7 @@ func checkBoardColumnChangePermissions(ctx *context.Context) (*board_model.Board return nil, nil } - if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeProjects) { + if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeBoards) { ctx.JSON(http.StatusForbidden, map[string]string{ "message": "Only authorized users are allowed to perform this action.", }) @@ -559,7 +559,7 @@ func MoveIssues(ctx *context.Context) { return } - if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeProjects) { + if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(perm.AccessModeWrite, unit.TypeBoards) { ctx.JSON(http.StatusForbidden, map[string]string{ "message": "Only authorized users are allowed to perform this action.", }) @@ -591,7 +591,7 @@ func MoveIssues(ctx *context.Context) { } else { column, err = board_model.GetColumn(ctx, ctx.ParamsInt64(":boardID")) if err != nil { - if board_model.IsErrProjectBoardNotExist(err) { + if board_model.IsErrColumnNotExist(err) { ctx.NotFound("ProjectBoardNotExist", nil) } else { ctx.ServerError("GetProjectBoard", err) @@ -658,7 +658,7 @@ func MoveIssues(ctx *context.Context) { func CreateProject(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.new") ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) ctx.HTML(http.StatusOK, tplGenericProjectsNew) } @@ -673,7 +673,7 @@ func CreateProjectPost(ctx *context.Context, form forms.UserCreateProjectForm) { ctx.Data["ContextUser"] = user if ctx.HasError() { - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) ctx.HTML(http.StatusOK, tplGenericProjectsNew) return } diff --git a/routers/web/repo/projects_test.go b/routers/web/repo/boards_test.go similarity index 90% rename from routers/web/repo/projects_test.go rename to routers/web/repo/boards_test.go index c712902ea9f1a..9e1a12d96974a 100644 --- a/routers/web/repo/projects_test.go +++ b/routers/web/repo/boards_test.go @@ -20,7 +20,7 @@ func TestCheckProjectBoardChangePermissions(t *testing.T) { ctx.SetParams(":id", "1") ctx.SetParams(":boardID", "2") - project, board := checkProjectBoardChangePermissions(ctx) + project, board := checkBoardColumnChangePermissions(ctx) assert.NotNil(t, project) assert.NotNil(t, board) assert.False(t, ctx.Written()) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index c3753b11d7c21..95c73af303c94 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -134,7 +134,7 @@ func MustAllowPulls(ctx *context.Context) { } } -func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption util.OptionalBool) { +func issues(ctx *context.Context, milestoneID, boardID int64, isPullOption util.OptionalBool) { var err error viewType := ctx.FormString("type") sortType := ctx.FormString("sort") @@ -255,7 +255,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti MentionedID: mentionedID, ReviewRequestedID: reviewRequestedID, MilestoneIDs: mileIDs, - ProjectID: projectID, + BoardID: boardID, IsClosed: util.OptionalBoolOf(isShowClosed), IsPull: isPullOption, LabelIDs: labelIDs, @@ -808,7 +808,7 @@ func NewIssue(ctx *context.Context) { body := ctx.FormString("body") ctx.Data["BodyQuery"] = body - isProjectsEnabled := ctx.Repo.CanRead(unit.TypeProjects) + isProjectsEnabled := ctx.Repo.CanRead(unit.TypeBoards) ctx.Data["IsProjectsEnabled"] = isProjectsEnabled ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled upload.AddUploadContext(ctx, "comment") @@ -1095,12 +1095,12 @@ func NewIssuePost(ctx *context.Context) { } if projectID > 0 { - if !ctx.Repo.CanRead(unit.TypeProjects) { + if !ctx.Repo.CanRead(unit.TypeBoards) { // User must also be able to see the project. ctx.Error(http.StatusBadRequest, "user hasn't permissions to read projects") return } - if err := issues_model.ChangeProjectAssign(issue, ctx.Doer, projectID); err != nil { + if err := issues_model.ChangeBoardAssign(issue, ctx.Doer, projectID); err != nil { ctx.ServerError("ChangeProjectAssign", err) return } @@ -1240,7 +1240,7 @@ func ViewIssue(ctx *context.Context) { } ctx.Data["RequireTribute"] = true - ctx.Data["IsProjectsEnabled"] = ctx.Repo.CanRead(unit.TypeProjects) + ctx.Data["IsProjectsEnabled"] = ctx.Repo.CanRead(unit.TypeBoards) ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled upload.AddUploadContext(ctx, "comment") @@ -1483,9 +1483,9 @@ func ViewIssue(ctx *context.Context) { if comment.MilestoneID > 0 && comment.Milestone == nil { comment.Milestone = ghostMilestone } - } else if comment.Type == issues_model.CommentTypeProject { + } else if comment.Type == issues_model.CommentTypeBoard { - if err = comment.LoadProject(); err != nil { + if err = comment.LoadBoard(); err != nil { ctx.ServerError("LoadProject", err) return } @@ -1775,7 +1775,7 @@ func ViewIssue(ctx *context.Context) { ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + url.QueryEscape(ctx.Data["Link"].(string)) ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID) ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) - ctx.Data["HasProjectsWritePermission"] = ctx.Repo.CanWrite(unit.TypeProjects) + ctx.Data["HasProjectsWritePermission"] = ctx.Repo.CanWrite(unit.TypeBoards) ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.Doer.IsAdmin) ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons ctx.Data["RefEndName"] = git.RefEndName(issue.Ref) diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index 913ed6c7cb8e9..afbb900fe2a96 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -480,13 +480,13 @@ func SettingsPost(ctx *context.Context) { } } - if form.EnableProjects && !unit_model.TypeProjects.UnitGlobalDisabled() { + if form.EnableProjects && !unit_model.TypeBoards.UnitGlobalDisabled() { units = append(units, repo_model.RepoUnit{ RepoID: repo.ID, - Type: unit_model.TypeProjects, + Type: unit_model.TypeBoards, }) - } else if !unit_model.TypeProjects.UnitGlobalDisabled() { - deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeProjects) + } else if !unit_model.TypeBoards.UnitGlobalDisabled() { + deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeBoards) } if form.EnablePackages && !unit_model.TypePackages.UnitGlobalDisabled() { diff --git a/routers/web/web.go b/routers/web/web.go index 2e36e4279094d..ef290f5c846b4 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -659,8 +659,8 @@ func RegisterRoutes(m *web.Route) { reqRepoPullsReader := context.RequireRepoReader(unit.TypePullRequests) reqRepoIssuesOrPullsWriter := context.RequireRepoWriterOr(unit.TypeIssues, unit.TypePullRequests) reqRepoIssuesOrPullsReader := context.RequireRepoReaderOr(unit.TypeIssues, unit.TypePullRequests) - reqRepoProjectsReader := context.RequireRepoReader(unit.TypeProjects) - reqRepoProjectsWriter := context.RequireRepoWriter(unit.TypeProjects) + reqRepoProjectsReader := context.RequireRepoReader(unit.TypeBoards) + reqRepoProjectsWriter := context.RequireRepoWriter(unit.TypeBoards) reqPackageAccess := func(accessMode perm.AccessMode) func(ctx *context.Context) { return func(ctx *context.Context) { diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 862a83e5d3501..63a2e25ed6b25 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -502,7 +502,7 @@ func (i IssueLockForm) HasValidReason() bool { type CreateBoardForm struct { Title string `binding:"Required;MaxSize(100)"` Content string - ColumnType board_model.BoardType + ColumnType board_model.ColumnType } // UserCreateProjectForm is a from for creating an individual or organization @@ -510,7 +510,7 @@ type CreateBoardForm struct { type UserCreateProjectForm struct { Title string `binding:"Required;MaxSize(100)"` Content string - ColumnType board_model.BoardType + ColumnType board_model.ColumnType UID int64 `binding:"Required"` } diff --git a/services/forms/user_form_hidden_comments.go b/services/forms/user_form_hidden_comments.go index 7eb800a020185..307ad341dfb86 100644 --- a/services/forms/user_form_hidden_comments.go +++ b/services/forms/user_form_hidden_comments.go @@ -64,8 +64,8 @@ var hiddenCommentTypeGroups = hiddenCommentTypeGroupsType{ /*29*/ issues_model.CommentTypePullRequestPush, }, "project": { - /*30*/ issues_model.CommentTypeProject, - /*31*/ issues_model.CommentTypeProjectBoard, + /*30*/ issues_model.CommentTypeBoard, + /*31*/ issues_model.CommentTypeBoardColumn, }, "issue_ref": { /*33*/ issues_model.CommentTypeChangeIssueRef, From 12cd134e4c558f5f318e5bd3556054ce08e22f6b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 26 Dec 2022 11:11:22 +0800 Subject: [PATCH 3/4] more renames --- models/board/board.go | 6 +- models/issues/comment.go | 20 ++--- models/issues/issue_project.go | 12 +-- models/migrations/v1_19/v238.go | 6 ++ models/unit/unit.go | 10 +-- modules/context/context.go | 2 +- modules/convert/issue_comment.go | 4 +- modules/convert/repository.go | 6 +- modules/setting/{project.go => board.go} | 2 +- modules/setting/setting.go | 2 +- modules/structs/issue_comment.go | 4 +- modules/structs/repo.go | 6 +- options/locale/locale_en-US.ini | 76 ++++++++-------- routers/api/v1/repo/repo.go | 4 +- routers/web/repo/boards.go | 86 +++++++++---------- routers/web/repo/boards_test.go | 8 +- routers/web/repo/issue.go | 4 +- routers/web/repo/setting.go | 2 +- routers/web/user/profile.go | 6 +- routers/web/web.go | 12 +-- services/forms/repo_form.go | 10 +-- templates/repo/{projects => boards}/list.tmpl | 0 templates/repo/{projects => boards}/new.tmpl | 0 templates/repo/{projects => boards}/view.tmpl | 0 templates/repo/header.tmpl | 4 +- .../repo/issue/view_content/comments.tmpl | 2 +- templates/user/{project.tmpl => board.tmpl} | 0 tests/integration/links_test.go | 8 +- 28 files changed, 154 insertions(+), 148 deletions(-) rename modules/setting/{project.go => board.go} (96%) rename templates/repo/{projects => boards}/list.tmpl (100%) rename templates/repo/{projects => boards}/new.tmpl (100%) rename templates/repo/{projects => boards}/view.tmpl (100%) rename templates/user/{project.tmpl => board.tmpl} (100%) diff --git a/models/board/board.go b/models/board/board.go index 9bf8ea31b20db..428d8d24d22c6 100644 --- a/models/board/board.go +++ b/models/board/board.go @@ -107,9 +107,9 @@ func init() { // GetBoardsConfig retrieves the types of configurations boards could have func GetBoardsConfig() []BoardsConfig { return []BoardsConfig{ - {BoardTypeNone, "repo.projects.type.none"}, - {BoardTypeBasicKanban, "repo.projects.type.basic_kanban"}, - {BoardTypeBugTriage, "repo.projects.type.bug_triage"}, + {BoardTypeNone, "repo.boards.type.none"}, + {BoardTypeBasicKanban, "repo.boards.type.basic_kanban"}, + {BoardTypeBugTriage, "repo.boards.type.bug_triage"}, } } diff --git a/models/issues/comment.go b/models/issues/comment.go index 6f42928884a73..790f91eb95cea 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -229,8 +229,8 @@ type Comment struct { Label *Label `xorm:"-"` AddedLabels []*Label `xorm:"-"` RemovedLabels []*Label `xorm:"-"` - OldProjectID int64 - ProjectID int64 + OldBoardID int64 + BoardID int64 OldBoard *board_model.Board `xorm:"-"` Board *board_model.Board `xorm:"-"` OldMilestoneID int64 @@ -492,9 +492,9 @@ func (c *Comment) LoadLabel() error { // LoadBoard if comment.Type is CommentTypeBoard, then load boards. func (c *Comment) LoadBoard() error { - if c.OldProjectID > 0 { + if c.OldBoardID > 0 { var oldBoard board_model.Board - has, err := db.GetEngine(db.DefaultContext).ID(c.OldProjectID).Get(&oldBoard) + has, err := db.GetEngine(db.DefaultContext).ID(c.OldBoardID).Get(&oldBoard) if err != nil { return err } else if has { @@ -502,9 +502,9 @@ func (c *Comment) LoadBoard() error { } } - if c.ProjectID > 0 { + if c.BoardID > 0 { var board board_model.Board - has, err := db.GetEngine(db.DefaultContext).ID(c.ProjectID).Get(&board) + has, err := db.GetEngine(db.DefaultContext).ID(c.BoardID).Get(&board) if err != nil { return err } else if has { @@ -795,8 +795,8 @@ func CreateComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, LabelID: LabelID, OldMilestoneID: opts.OldMilestoneID, MilestoneID: opts.MilestoneID, - OldProjectID: opts.OldProjectID, - ProjectID: opts.ProjectID, + OldBoardID: opts.OldBoardID, + BoardID: opts.BoardID, TimeID: opts.TimeID, RemovedAssignee: opts.RemovedAssignee, AssigneeID: opts.AssigneeID, @@ -966,8 +966,8 @@ type CreateCommentOptions struct { DependentIssueID int64 OldMilestoneID int64 MilestoneID int64 - OldProjectID int64 - ProjectID int64 + OldBoardID int64 + BoardID int64 TimeID int64 AssigneeID int64 AssigneeTeamID int64 diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index dbd9578f4c4bc..a4630f1fa46d8 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -146,12 +146,12 @@ func addUpdateIssueBoard(ctx context.Context, issue *Issue, doer *user_model.Use if oldBoardID > 0 || newBoardID > 0 { if _, err := CreateComment(ctx, &CreateCommentOptions{ - Type: CommentTypeBoard, - Doer: doer, - Repo: issue.Repo, - Issue: issue, - OldProjectID: oldBoardID, - ProjectID: newBoardID, + Type: CommentTypeBoard, + Doer: doer, + Repo: issue.Repo, + Issue: issue, + OldBoardID: oldBoardID, + BoardID: newBoardID, }); err != nil { return err } diff --git a/models/migrations/v1_19/v238.go b/models/migrations/v1_19/v238.go index b563fc3b0b749..0f876fddaffe6 100644 --- a/models/migrations/v1_19/v238.go +++ b/models/migrations/v1_19/v238.go @@ -39,5 +39,11 @@ func RenameProjectsToBoards(x *xorm.Engine) error { if err := base.RenameColumn(sess, "repository", "num_closed_projects", "num_closed_boards", "INT(11)"); err != nil { return err } + if err := base.RenameColumn(sess, "comment", "old_project_id", "old_board_id", "bigint"); err != nil { + return err + } + if err := base.RenameColumn(sess, "comment", "project_id", "board_id", "bigint"); err != nil { + return err + } return nil } diff --git a/models/unit/unit.go b/models/unit/unit.go index 196c6964b3443..7e9fa9648f48c 100644 --- a/models/unit/unit.go +++ b/models/unit/unit.go @@ -270,11 +270,11 @@ var ( perm.AccessModeRead, } - UnitProjects = Unit{ + UnitBoards = Unit{ TypeBoards, - "repo.projects", - "/projects", - "repo.projects.desc", + "repo.boards", + "/boards", + "repo.boards.desc", 5, perm.AccessModeOwner, } @@ -297,7 +297,7 @@ var ( TypeReleases: UnitReleases, TypeWiki: UnitWiki, TypeExternalWiki: UnitExternalWiki, - TypeBoards: UnitProjects, + TypeBoards: UnitBoards, TypePackages: UnitPackages, } ) diff --git a/modules/context/context.go b/modules/context/context.go index a3b0348439a79..44e8b787512b6 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -805,7 +805,7 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler { ctx.Data["UnitWikiGlobalDisabled"] = unit.TypeWiki.UnitGlobalDisabled() ctx.Data["UnitIssuesGlobalDisabled"] = unit.TypeIssues.UnitGlobalDisabled() ctx.Data["UnitPullsGlobalDisabled"] = unit.TypePullRequests.UnitGlobalDisabled() - ctx.Data["UnitProjectsGlobalDisabled"] = unit.TypeBoards.UnitGlobalDisabled() + ctx.Data["UnitBoardsGlobalDisabled"] = unit.TypeBoards.UnitGlobalDisabled() ctx.Data["locale"] = locale ctx.Data["AllLangs"] = translation.AllLangs() diff --git a/modules/convert/issue_comment.go b/modules/convert/issue_comment.go index 6044cbcf61343..a51ae3217d1e6 100644 --- a/modules/convert/issue_comment.go +++ b/modules/convert/issue_comment.go @@ -77,8 +77,8 @@ func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_ Created: c.CreatedUnix.AsTime(), Updated: c.UpdatedUnix.AsTime(), - OldProjectID: c.OldProjectID, - ProjectID: c.ProjectID, + OldBoardID: c.OldBoardID, + BoardID: c.BoardID, OldTitle: c.OldTitle, NewTitle: c.NewTitle, diff --git a/modules/convert/repository.go b/modules/convert/repository.go index b417d0c5e5ebe..7fd12ce0e64ca 100644 --- a/modules/convert/repository.go +++ b/modules/convert/repository.go @@ -93,9 +93,9 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc defaultDeleteBranchAfterMerge = config.DefaultDeleteBranchAfterMerge defaultMergeStyle = config.GetDefaultMergeStyle() } - hasProjects := false + hasBoards := false if _, err := repo.GetUnit(ctx, unit_model.TypeBoards); err == nil { - hasProjects = true + hasBoards = true } if err := repo.GetOwner(ctx); err != nil { @@ -171,7 +171,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc ExternalTracker: externalTracker, InternalTracker: internalTracker, HasWiki: hasWiki, - HasProjects: hasProjects, + HasBoards: hasBoards, ExternalWiki: externalWiki, HasPullRequests: hasPullRequests, IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, diff --git a/modules/setting/project.go b/modules/setting/board.go similarity index 96% rename from modules/setting/project.go rename to modules/setting/board.go index cfeb91f03114b..b93420d33df54 100644 --- a/modules/setting/project.go +++ b/modules/setting/board.go @@ -16,7 +16,7 @@ var ( } ) -func newProject() { +func newBoard() { if err := Cfg.Section("project").MapTo(&Board); err != nil { log.Fatal("Failed to map Board settings: %v", err) } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 47e0ae2cda1f5..3673d3f9541f6 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -1346,7 +1346,7 @@ func NewServices() { newIndexerService() newTaskService() NewQueueService() - newProject() + newBoard() newMimeTypeMap() newFederationService() } diff --git a/modules/structs/issue_comment.go b/modules/structs/issue_comment.go index 9e8f5c4bf3321..85d597ef5de35 100644 --- a/modules/structs/issue_comment.go +++ b/modules/structs/issue_comment.go @@ -51,8 +51,8 @@ type TimelineComment struct { // swagger:strfmt date-time Updated time.Time `json:"updated_at"` - OldProjectID int64 `json:"old_project_id"` - ProjectID int64 `json:"project_id"` + OldBoardID int64 `json:"old_project_id"` + BoardID int64 `json:"project_id"` OldMilestone *Milestone `json:"old_milestone"` Milestone *Milestone `json:"milestone"` TrackedTime *TrackedTime `json:"tracked_time"` diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 16f3d9dd26b7b..91a4a8b0ab353 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -86,7 +86,7 @@ type Repository struct { HasWiki bool `json:"has_wiki"` ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"` HasPullRequests bool `json:"has_pull_requests"` - HasProjects bool `json:"has_projects"` + HasBoards bool `json:"has_projects"` IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` AllowMerge bool `json:"allow_merge_commits"` AllowRebase bool `json:"allow_rebase"` @@ -164,8 +164,8 @@ type EditRepoOption struct { DefaultBranch *string `json:"default_branch,omitempty"` // either `true` to allow pull requests, or `false` to prevent pull request. HasPullRequests *bool `json:"has_pull_requests,omitempty"` - // either `true` to enable project unit, or `false` to disable them. - HasProjects *bool `json:"has_projects,omitempty"` + // either `true` to enable board unit, or `false` to disable them. + HasBoards *bool `json:"has_projects,omitempty"` // either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"` // either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 62471abe6f19c..9c66f0782d151 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -530,7 +530,7 @@ followers = Followers starred = Starred Repositories watched = Watched Repositories code = Code -projects = Projects +boards = Projects following = Following follow = Follow unfollow = Unfollow @@ -1184,41 +1184,41 @@ commit.cherry-pick-content = Select branch to cherry-pick onto: ext_issues = Access to External Issues ext_issues.desc = Link to an external issue tracker. -projects = Projects -projects.desc = Manage issues and pulls in project boards. -projects.description = Description (optional) -projects.description_placeholder = Description -projects.create = Create Project -projects.title = Title -projects.new = New project -projects.new_subheader = Coordinate, track, and update your work in one place, so projects stay transparent and on schedule. -projects.create_success = The project '%s' has been created. -projects.deletion = Delete Project -projects.deletion_desc = Deleting a project removes it from all related issues. Continue? -projects.deletion_success = The project has been deleted. -projects.edit = Edit Projects -projects.edit_subheader = Projects organize issues and track progress. -projects.modify = Update Project -projects.edit_success = Project '%s' has been updated. -projects.type.none = "None" -projects.type.basic_kanban = "Basic Kanban" -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.open = Open -projects.close = Close -projects.board.assigned_to = Assigned to +boards = Boards +boards.desc = Manage issues and pulls in project boards. +boards.description = Description (optional) +boards.description_placeholder = Description +boards.create = Create Project +boards.title = Title +boards.new = New project +boards.new_subheader = Coordinate, track, and update your work in one place, so boards stay transparent and on schedule. +boards.create_success = The project '%s' has been created. +boards.deletion = Delete Project +boards.deletion_desc = Deleting a project removes it from all related issues. Continue? +boards.deletion_success = The project has been deleted. +boards.edit = Edit Projects +boards.edit_subheader = Projects organize issues and track progress. +boards.modify = Update Project +boards.edit_success = Project '%s' has been updated. +boards.type.none = "None" +boards.type.basic_kanban = "Basic Kanban" +boards.type.bug_triage = "Bug Triage" +boards.template.desc = "Project template" +boards.template.desc_helper = "Select a project template to get started" +boards.type.uncategorized = Uncategorized +boards.column.edit = "Edit Column" +boards.column.edit_title = "New Column Name" +boards.column.new_title = "New Column Name" +boards.column.new_submit = "Submit" +boards.column.new = "New Column" +boards.column.set_default = "Set Default" +boards.column.set_default_desc = "Set this column as default for uncategorized issues and pulls" +boards.column.delete = "Delete Column" +boards.column.deletion_desc = "Deleting a board column moves all related issues to 'Uncategorized'. Continue?" +boards.column.color = "Color" +boards.open = Open +boards.close = Close +boards.column.assigned_to = Assigned to issues.desc = Organize bug reports, tasks and milestones. issues.filter_assignees = Filter Assignee @@ -1232,9 +1232,9 @@ issues.new.labels = Labels issues.new.add_labels_title = Apply labels issues.new.no_label = No Label issues.new.clear_labels = Clear labels -issues.new.projects = Projects +issues.new.boards = Projects issues.new.add_project_title = Set Project -issues.new.clear_projects = Clear projects +issues.new.clear_projects = Clear boards issues.new.no_projects = No project issues.new.open_projects = Open Projects issues.new.closed_projects = Closed Projects diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index bebb9a7f8836b..636be1f7107af 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -909,8 +909,8 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } } - if opts.HasProjects != nil && !unit_model.TypeBoards.UnitGlobalDisabled() { - if *opts.HasProjects { + if opts.HasBoards != nil && !unit_model.TypeBoards.UnitGlobalDisabled() { + if *opts.HasBoards { units = append(units, repo_model.RepoUnit{ RepoID: repo.ID, Type: unit_model.TypeBoards, diff --git a/routers/web/repo/boards.go b/routers/web/repo/boards.go index b92764bd9f661..a9cb3472bece2 100644 --- a/routers/web/repo/boards.go +++ b/routers/web/repo/boards.go @@ -26,14 +26,14 @@ import ( ) const ( - tplProjects base.TplName = "repo/projects/list" - tplProjectsNew base.TplName = "repo/projects/new" - tplProjectsView base.TplName = "repo/projects/view" - tplGenericProjectsNew base.TplName = "user/project" + tplBoards base.TplName = "repo/boards/list" + tplBoardsNew base.TplName = "repo/boards/new" + tplBoardsView base.TplName = "repo/boards/view" + tplGenericBoardsNew base.TplName = "user/board" ) -// MustEnableProjects check if projects are enabled in settings -func MustEnableProjects(ctx *context.Context) { +// MustEnableBoards check if boards are enabled in settings +func MustEnableBoards(ctx *context.Context) { if unit.TypeBoards.UnitGlobalDisabled() { ctx.NotFound("EnableKanbanBoard", nil) return @@ -41,7 +41,7 @@ func MustEnableProjects(ctx *context.Context) { if ctx.Repo.Repository != nil { if !ctx.Repo.CanRead(unit.TypeBoards) { - ctx.NotFound("MustEnableProjects", nil) + ctx.NotFound("MustEnableBoards", nil) return } } @@ -49,7 +49,7 @@ func MustEnableProjects(ctx *context.Context) { // Boards renders the home page of boards func Boards(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("repo.project_board") + ctx.Data["Title"] = ctx.Tr("repo.board_column") sortType := ctx.FormTrim("sort") @@ -70,7 +70,7 @@ func Boards(ctx *context.Context) { total = repo.NumClosedBoards } - projects, count, err := board_model.FindBoards(ctx, board_model.SearchOptions{ + boards, count, err := board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, Page: page, IsClosed: util.OptionalBoolOf(isShowClosed), @@ -82,20 +82,20 @@ func Boards(ctx *context.Context) { return } - for i := range projects { - projects[i].RenderedContent, err = markdown.RenderString(&markup.RenderContext{ + for i := range boards { + boards[i].RenderedContent, err = markdown.RenderString(&markup.RenderContext{ URLPrefix: ctx.Repo.RepoLink, Metas: ctx.Repo.Repository.ComposeMetas(), GitRepo: ctx.Repo.GitRepo, Ctx: ctx, - }, projects[i].Description) + }, boards[i].Description) if err != nil { ctx.ServerError("RenderString", err) return } } - ctx.Data["Projects"] = projects + ctx.Data["Boards"] = boards if isShowClosed { ctx.Data["State"] = "closed" @@ -112,31 +112,31 @@ func Boards(ctx *context.Context) { pager.AddParam(ctx, "state", "State") ctx.Data["Page"] = pager - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) + ctx.Data["CanWriteBoards"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) ctx.Data["IsShowClosed"] = isShowClosed - ctx.Data["IsProjectsPage"] = true + ctx.Data["IsBoardsPage"] = true ctx.Data["SortType"] = sortType - ctx.HTML(http.StatusOK, tplProjects) + ctx.HTML(http.StatusOK, tplBoards) } -// NewBoard render creating a project page +// NewBoard render creating a board page func NewBoard(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("repo.projects.new") - ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) - ctx.HTML(http.StatusOK, tplProjectsNew) + ctx.Data["Title"] = ctx.Tr("repo.boards.new") + ctx.Data["BoardTypes"] = board_model.GetBoardsConfig() + ctx.Data["CanWriteBoards"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) + ctx.HTML(http.StatusOK, tplBoardsNew) } -// NewBoardPost creates a new project +// NewBoardPost creates a new board func NewBoardPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.CreateBoardForm) - ctx.Data["Title"] = ctx.Tr("repo.projects.new") + ctx.Data["Title"] = ctx.Tr("repo.boards.new") if ctx.HasError() { - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) - ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() - ctx.HTML(http.StatusOK, tplProjectsNew) + ctx.Data["CanWriteBoards"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) + ctx.Data["BoardTypes"] = board_model.GetBoardsConfig() + ctx.HTML(http.StatusOK, tplBoardsNew) return } @@ -152,8 +152,8 @@ func NewBoardPost(ctx *context.Context) { return } - ctx.Flash.Success(ctx.Tr("repo.projects.create_success", form.Title)) - ctx.Redirect(ctx.Repo.RepoLink + "/projects") + ctx.Flash.Success(ctx.Tr("repo.boards.create_success", form.Title)) + ctx.Redirect(ctx.Repo.RepoLink + "/boards") } // ChangeBoardStatus updates the status of a board between "open" and "close" @@ -165,7 +165,7 @@ func ChangeBoardStatus(ctx *context.Context) { case "close": toClose = true default: - ctx.Redirect(ctx.Repo.RepoLink + "/projects") + ctx.Redirect(ctx.Repo.RepoLink + "/boards") } id := ctx.ParamsInt64(":id") @@ -173,11 +173,11 @@ func ChangeBoardStatus(ctx *context.Context) { if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", err) } else { - ctx.ServerError("ChangeProjectStatusByIDAndRepoID", err) + ctx.ServerError("ChangeBoardStatusByRepoIDAndID", err) } return } - ctx.Redirect(ctx.Repo.RepoLink + "/projects?state=" + url.QueryEscape(ctx.Params(":action"))) + ctx.Redirect(ctx.Repo.RepoLink + "/boards?state=" + url.QueryEscape(ctx.Params(":action"))) } // DeleteBoard delete a board @@ -199,17 +199,17 @@ func DeleteBoard(ctx *context.Context) { if err := board_model.DeleteBoardByID(ctx, p.ID); err != nil { ctx.Flash.Error("DeleteBoardByID: " + err.Error()) } else { - ctx.Flash.Success(ctx.Tr("repo.projects.deletion_success")) + ctx.Flash.Success(ctx.Tr("repo.boards.deletion_success")) } ctx.JSON(http.StatusOK, map[string]interface{}{ - "redirect": ctx.Repo.RepoLink + "/projects", + "redirect": ctx.Repo.RepoLink + "/boards", }) } // EditBoard allows a board to be edited func EditBoard(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("repo.projects.edit") + ctx.Data["Title"] = ctx.Tr("repo.boards.edit") ctx.Data["PageIsEditProjects"] = true ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) @@ -230,7 +230,7 @@ func EditBoard(ctx *context.Context) { ctx.Data["title"] = p.Title ctx.Data["content"] = p.Description - ctx.HTML(http.StatusOK, tplProjectsNew) + ctx.HTML(http.StatusOK, tplBoardsNew) } // EditBoardPost response for editing a board @@ -241,7 +241,7 @@ func EditBoardPost(ctx *context.Context) { ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) if ctx.HasError() { - ctx.HTML(http.StatusOK, tplProjectsNew) + ctx.HTML(http.StatusOK, tplBoardsNew) return } @@ -266,8 +266,8 @@ func EditBoardPost(ctx *context.Context) { return } - ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title)) - ctx.Redirect(ctx.Repo.RepoLink + "/projects") + ctx.Flash.Success(ctx.Tr("repo.boards.edit_success", p.Title)) + ctx.Redirect(ctx.Repo.RepoLink + "/boards") } // ViewBoard renders the columns for a board @@ -341,11 +341,11 @@ func ViewBoard(ctx *context.Context) { ctx.Data["IssuesMap"] = issuesMap ctx.Data["Boards"] = boards - ctx.HTML(http.StatusOK, tplProjectsView) + ctx.HTML(http.StatusOK, tplBoardsView) } -// UpdateIssueProject change an issue's project -func UpdateIssueProject(ctx *context.Context) { +// UpdateIssueBoard change an issue's project +func UpdateIssueBoard(ctx *context.Context) { issues := getActionIssues(ctx) if ctx.Written() { return @@ -660,7 +660,7 @@ func CreateProject(ctx *context.Context) { ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) - ctx.HTML(http.StatusOK, tplGenericProjectsNew) + ctx.HTML(http.StatusOK, tplGenericBoardsNew) } // CreateProjectPost creates an individual and/or organization project @@ -674,7 +674,7 @@ func CreateProjectPost(ctx *context.Context, form forms.UserCreateProjectForm) { if ctx.HasError() { ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) - ctx.HTML(http.StatusOK, tplGenericProjectsNew) + ctx.HTML(http.StatusOK, tplGenericBoardsNew) return } diff --git a/routers/web/repo/boards_test.go b/routers/web/repo/boards_test.go index 9e1a12d96974a..ddf7d45ac25f3 100644 --- a/routers/web/repo/boards_test.go +++ b/routers/web/repo/boards_test.go @@ -12,16 +12,16 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCheckProjectBoardChangePermissions(t *testing.T) { +func TestCheckBoardColumnChangePermissions(t *testing.T) { unittest.PrepareTestEnv(t) - ctx := test.MockContext(t, "user2/repo1/projects/1/2") + ctx := test.MockContext(t, "user2/repo1/boards/1/2") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) ctx.SetParams(":id", "1") ctx.SetParams(":boardID", "2") - project, board := checkBoardColumnChangePermissions(ctx) - assert.NotNil(t, project) + board, column := checkBoardColumnChangePermissions(ctx) assert.NotNil(t, board) + assert.NotNil(t, column) assert.False(t, ctx.Written()) } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 95c73af303c94..9eaf64fa7dc27 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1495,11 +1495,11 @@ func ViewIssue(ctx *context.Context) { Title: ctx.Tr("repo.issues.deleted_project"), } - if comment.OldProjectID > 0 && comment.OldBoard == nil { + if comment.OldBoardID > 0 && comment.OldBoard == nil { comment.OldBoard = ghostProject } - if comment.ProjectID > 0 && comment.Board == nil { + if comment.BoardID > 0 && comment.Board == nil { comment.Board = ghostProject } diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index afbb900fe2a96..43dc160bfbb3f 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -480,7 +480,7 @@ func SettingsPost(ctx *context.Context) { } } - if form.EnableProjects && !unit_model.TypeBoards.UnitGlobalDisabled() { + if form.EnableBoards && !unit_model.TypeBoards.UnitGlobalDisabled() { units = append(units, repo_model.RepoUnit{ RepoID: repo.ID, Type: unit_model.TypeBoards, diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 25bffe1df213a..254a827047df4 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -223,14 +223,14 @@ func Profile(ctx *context.Context) { } total = int(count) - case "projects": - ctx.Data["OpenProjects"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ + case "boards": + ctx.Data["OpenBoards"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ Page: -1, IsClosed: util.OptionalBoolFalse, Type: board_model.TypeIndividual, }) if err != nil { - ctx.ServerError("GetProjects", err) + ctx.ServerError("FindBoards", err) return } case "watching": diff --git a/routers/web/web.go b/routers/web/web.go index ef290f5c846b4..cd018d075425f 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -659,8 +659,8 @@ func RegisterRoutes(m *web.Route) { reqRepoPullsReader := context.RequireRepoReader(unit.TypePullRequests) reqRepoIssuesOrPullsWriter := context.RequireRepoWriterOr(unit.TypeIssues, unit.TypePullRequests) reqRepoIssuesOrPullsReader := context.RequireRepoReaderOr(unit.TypeIssues, unit.TypePullRequests) - reqRepoProjectsReader := context.RequireRepoReader(unit.TypeBoards) - reqRepoProjectsWriter := context.RequireRepoWriter(unit.TypeBoards) + reqRepoBoardsReader := context.RequireRepoReader(unit.TypeBoards) + reqRepoBoardsWriter := context.RequireRepoWriter(unit.TypeBoards) reqPackageAccess := func(accessMode perm.AccessMode) func(ctx *context.Context) { return func(ctx *context.Context) { @@ -1015,7 +1015,7 @@ func RegisterRoutes(m *web.Route) { m.Post("/labels", reqRepoIssuesOrPullsWriter, repo.UpdateIssueLabel) m.Post("/milestone", reqRepoIssuesOrPullsWriter, repo.UpdateIssueMilestone) - m.Post("/projects", reqRepoIssuesOrPullsWriter, reqRepoProjectsReader, repo.UpdateIssueProject) + m.Post("/boards", reqRepoIssuesOrPullsWriter, reqRepoBoardsReader, repo.UpdateIssueBoard) m.Post("/assignee", reqRepoIssuesOrPullsWriter, repo.UpdateIssueAssignee) m.Post("/request_review", reqRepoIssuesOrPullsReader, repo.UpdatePullReviewRequest) m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview) @@ -1159,7 +1159,7 @@ func RegisterRoutes(m *web.Route) { m.Get("/packages", repo.Packages) } - m.Group("/projects", func() { + m.Group("/boards", func() { m.Get("", repo.Boards) m.Get("/{id}", repo.ViewBoard) m.Group("", func() { @@ -1181,8 +1181,8 @@ func RegisterRoutes(m *web.Route) { m.Post("/move", repo.MoveIssues) }) }) - }, reqRepoProjectsWriter, context.RepoMustNotBeArchived()) - }, reqRepoProjectsReader, repo.MustEnableProjects) + }, reqRepoBoardsWriter, context.RepoMustNotBeArchived()) + }, reqRepoBoardsReader, repo.MustEnableBoards) m.Group("/wiki", func() { m.Combo("/"). diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 63a2e25ed6b25..84e7c8b429b18 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -145,7 +145,7 @@ type RepoSettingForm struct { TrackerIssueStyle string ExternalTrackerRegexpPattern string EnableCloseIssuesViaCommitInAnyBranch bool - EnableProjects bool + EnableBoards bool EnablePackages bool EnablePulls bool PullsIgnoreWhitespace bool @@ -434,7 +434,7 @@ type CreateIssueForm struct { AssigneeIDs string `form:"assignee_ids"` Ref string `form:"ref"` MilestoneID int64 - ProjectID int64 + BoardID int64 AssigneeID int64 Content string Files []string @@ -505,16 +505,16 @@ type CreateBoardForm struct { ColumnType board_model.ColumnType } -// UserCreateProjectForm is a from for creating an individual or organization +// UserCreateBoardForm is a from for creating an individual or organization // form. -type UserCreateProjectForm struct { +type UserCreateBoardForm struct { Title string `binding:"Required;MaxSize(100)"` Content string ColumnType board_model.ColumnType UID int64 `binding:"Required"` } -// EditBoardColumnForm is a form for editing a project board +// EditBoardColumnForm is a form for editing a board column type EditBoardColumnForm struct { Title string `binding:"Required;MaxSize(100)"` Sorting int8 diff --git a/templates/repo/projects/list.tmpl b/templates/repo/boards/list.tmpl similarity index 100% rename from templates/repo/projects/list.tmpl rename to templates/repo/boards/list.tmpl diff --git a/templates/repo/projects/new.tmpl b/templates/repo/boards/new.tmpl similarity index 100% rename from templates/repo/projects/new.tmpl rename to templates/repo/boards/new.tmpl diff --git a/templates/repo/projects/view.tmpl b/templates/repo/boards/view.tmpl similarity index 100% rename from templates/repo/projects/view.tmpl rename to templates/repo/boards/view.tmpl diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index 4da91e424df9d..8a08378efe62e 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -189,8 +189,8 @@ {{end}} - {{if and (not .UnitProjectsGlobalDisabled) (.Permission.CanRead $.UnitTypeProjects)}} - + {{if and (not .UnitBoardsGlobalDisabled) (.Permission.CanRead $.UnitTypeProjects)}} + {{svg "octicon-project"}} {{.locale.Tr "repo.project_board"}} {{if .Repository.NumOpenProjects}} {{CountFmt .Repository.NumOpenProjects}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index d013c7b761ba2..d537d795bd65b 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -712,7 +712,7 @@ {{template "repo/commits_list_small" dict "comment" . "root" $}} {{end}} {{else if eq .Type 30}} - {{if not $.UnitProjectsGlobalDisabled}} + {{if not $.UnitBoardsGlobalDisabled}}
{{svg "octicon-project"}} {{template "shared/user/avatarlink" .Poster}} diff --git a/templates/user/project.tmpl b/templates/user/board.tmpl similarity index 100% rename from templates/user/project.tmpl rename to templates/user/board.tmpl diff --git a/tests/integration/links_test.go b/tests/integration/links_test.go index 9136f8f9153ae..818c2e6e9707c 100644 --- a/tests/integration/links_test.go +++ b/tests/integration/links_test.go @@ -34,8 +34,8 @@ func TestLinksNoLogin(t *testing.T) { "/api/swagger", "/user2/repo1", "/user2/repo1/", - "/user2/repo1/projects", - "/user2/repo1/projects/1", + "/user2/repo1/boards", + "/user2/repo1/boards/1", "/assets/img/404.png", "/assets/img/500.png", } @@ -68,8 +68,8 @@ func TestNoLoginNotExist(t *testing.T) { defer tests.PrepareTestEnv(t)() links := []string{ - "/user5/repo4/projects", - "/user5/repo4/projects/3", + "/user5/repo4/boards", + "/user5/repo4/boards/3", } for _, link := range links { From 28266992d50e71237373e8fbdce150df29396fba Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 26 Dec 2022 11:34:41 +0800 Subject: [PATCH 4/4] more renames --- options/locale/locale_en-US.ini | 2 +- routers/web/repo/boards.go | 130 ++++++------------ routers/web/repo/issue.go | 90 ++++++------ routers/web/user/profile.go | 2 +- templates/repo/boards/list.tmpl | 22 +-- templates/repo/boards/new.tmpl | 38 ++--- templates/repo/boards/view.tmpl | 68 ++++----- templates/repo/header.tmpl | 8 +- templates/repo/issue/choose.tmpl | 4 +- templates/repo/issue/list.tmpl | 10 +- templates/repo/issue/new_form.tmpl | 30 ++-- .../repo/issue/view_content/comments.tmpl | 12 +- .../repo/issue/view_content/sidebar.tmpl | 24 ++-- templates/repo/settings/options.tmpl | 6 +- templates/shared/issuelist.tmpl | 6 +- 15 files changed, 204 insertions(+), 248 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 9c66f0782d151..d8617467caf85 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1279,7 +1279,7 @@ issues.change_project_at = `modified the project from %s to %s %s` issues.remove_milestone_at = `removed this from the %s milestone %s` issues.remove_project_at = `removed this from the %s project %s` issues.deleted_milestone = `(deleted)` -issues.deleted_project = `(deleted)` +issues.deleted_board = `(deleted)` issues.self_assign_at = `self-assigned this %s` issues.add_assignee_at = `was assigned by %s %s` issues.remove_assignee_at = `was unassigned by %s %s` diff --git a/routers/web/repo/boards.go b/routers/web/repo/boards.go index a9cb3472bece2..98ce954e79e41 100644 --- a/routers/web/repo/boards.go +++ b/routers/web/repo/boards.go @@ -210,8 +210,8 @@ func DeleteBoard(ctx *context.Context) { // EditBoard allows a board to be edited func EditBoard(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.boards.edit") - ctx.Data["PageIsEditProjects"] = true - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) + ctx.Data["PageIsEditBoards"] = true + ctx.Data["CanWriteBoards"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) p, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { @@ -236,9 +236,9 @@ func EditBoard(ctx *context.Context) { // EditBoardPost response for editing a board func EditBoardPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.CreateBoardForm) - ctx.Data["Title"] = ctx.Tr("repo.projects.edit") - ctx.Data["PageIsEditProjects"] = true - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) + ctx.Data["Title"] = ctx.Tr("repo.boards.edit") + ctx.Data["PageIsEditBoards"] = true + ctx.Data["CanWriteBoards"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) if ctx.HasError() { ctx.HTML(http.StatusOK, tplBoardsNew) @@ -262,7 +262,7 @@ func EditBoardPost(ctx *context.Context) { p.Title = form.Title p.Description = form.Content if err = board_model.UpdateBoard(ctx, p); err != nil { - ctx.ServerError("UpdateProjects", err) + ctx.ServerError("UpdateBoard", err) return } @@ -272,7 +272,7 @@ func EditBoardPost(ctx *context.Context) { // ViewBoard renders the columns for a board func ViewBoard(ctx *context.Context) { - project, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) + board, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) @@ -281,24 +281,24 @@ func ViewBoard(ctx *context.Context) { } return } - if project.RepoID != ctx.Repo.Repository.ID { + if board.RepoID != ctx.Repo.Repository.ID { ctx.NotFound("", nil) return } - boards, err := board_model.FindColumns(ctx, project.ID) + boards, err := board_model.FindColumns(ctx, board.ID) if err != nil { - ctx.ServerError("GetProjectBoards", err) + ctx.ServerError("FindColumns", err) return } if boards[0].ID == 0 { - boards[0].Title = ctx.Tr("repo.projects.type.uncategorized") + boards[0].Title = ctx.Tr("repo.boards.type.uncategorized") } issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards) if err != nil { - ctx.ServerError("LoadIssuesOfBoards", err) + ctx.ServerError("LoadIssuesFromBoardList", err) return } @@ -324,42 +324,42 @@ func ViewBoard(ctx *context.Context) { } ctx.Data["LinkedPRs"] = linkedPrsMap - project.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ + board.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ URLPrefix: ctx.Repo.RepoLink, Metas: ctx.Repo.Repository.ComposeMetas(), GitRepo: ctx.Repo.GitRepo, Ctx: ctx, - }, project.Description) + }, board.Description) if err != nil { ctx.ServerError("RenderString", err) return } - ctx.Data["IsProjectsPage"] = true - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) - ctx.Data["Project"] = project + ctx.Data["IsBoardsPage"] = true + ctx.Data["CanWriteBoards"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) + ctx.Data["Board"] = board ctx.Data["IssuesMap"] = issuesMap ctx.Data["Boards"] = boards ctx.HTML(http.StatusOK, tplBoardsView) } -// UpdateIssueBoard change an issue's project +// UpdateIssueBoard change an issue's board func UpdateIssueBoard(ctx *context.Context) { issues := getActionIssues(ctx) if ctx.Written() { return } - projectID := ctx.FormInt64("id") + boardID := ctx.FormInt64("id") for _, issue := range issues { - oldProjectID := issue.BoardID() - if oldProjectID == projectID { + oldBoardID := issue.BoardID() + if oldBoardID == boardID { continue } - if err := issues_model.ChangeBoardAssign(issue, ctx.Doer, projectID); err != nil { - ctx.ServerError("ChangeProjectAssign", err) + if err := issues_model.ChangeBoardAssign(issue, ctx.Doer, boardID); err != nil { + ctx.ServerError("ChangeBoardAssign", err) return } } @@ -385,7 +385,7 @@ func DeleteBoardColumn(ctx *context.Context) { return } - project, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) + board, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { if board_model.IsErrBoardNotExist(err) { ctx.NotFound("", nil) @@ -397,25 +397,25 @@ func DeleteBoardColumn(ctx *context.Context) { pb, err := board_model.GetColumn(ctx, ctx.ParamsInt64(":boardID")) if err != nil { - ctx.ServerError("GetProjectBoard", err) + ctx.ServerError("GetColumn", err) return } if pb.BoardID != 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("BoardColumn[%d] is not in Board[%d] as expected", pb.ID, board.ID), }) return } - if project.RepoID != ctx.Repo.Repository.ID { + if board.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("BoardColumn[%d] is not in Repository[%d] as expected", pb.ID, ctx.Repo.Repository.ID), }) return } if err := board_model.DeleteBoardByID(ctx, ctx.ParamsInt64(":boardID")); err != nil { - ctx.ServerError("DeleteProjectBoardByID", err) + ctx.ServerError("DeleteBoardByID", err) return } @@ -486,7 +486,7 @@ func checkBoardColumnChangePermissions(ctx *context.Context) (*board_model.Board column, err := board_model.GetColumn(ctx, ctx.ParamsInt64(":boardID")) if err != nil { - ctx.ServerError("GetProjectBoard", err) + ctx.ServerError("GetColumn", err) return nil, nil } if column.BoardID != ctx.ParamsInt64(":id") { @@ -524,7 +524,7 @@ func EditBoardColumn(ctx *context.Context) { } if err := board_model.UpdateColumn(ctx, column); err != nil { - ctx.ServerError("UpdateProjectBoard", err) + ctx.ServerError("UpdateColumn", err) return } @@ -566,16 +566,16 @@ func MoveIssues(ctx *context.Context) { return } - project, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) + board, err := board_model.GetBoardByID(ctx, ctx.ParamsInt64(":id")) if err != nil { if board_model.IsErrBoardNotExist(err) { - ctx.NotFound("ProjectNotExist", nil) + ctx.NotFound("BoardNotExist", nil) } else { ctx.ServerError("GetBoardByID", err) } return } - if project.RepoID != ctx.Repo.Repository.ID { + if board.RepoID != ctx.Repo.Repository.ID { ctx.NotFound("InvalidRepoID", nil) return } @@ -585,21 +585,21 @@ func MoveIssues(ctx *context.Context) { if ctx.ParamsInt64(":boardID") == 0 { column = &board_model.Column{ ID: 0, - BoardID: project.ID, - Title: ctx.Tr("repo.projects.type.uncategorized"), + BoardID: board.ID, + Title: ctx.Tr("repo.boards.type.uncategorized"), } } else { column, err = board_model.GetColumn(ctx, ctx.ParamsInt64(":boardID")) if err != nil { if board_model.IsErrColumnNotExist(err) { - ctx.NotFound("ProjectBoardNotExist", nil) + ctx.NotFound("BoardBoardNotExist", nil) } else { - ctx.ServerError("GetProjectBoard", err) + ctx.ServerError("GetColumn", err) } return } - if column.BoardID != project.ID { - ctx.NotFound("BoardNotInProject", nil) + if column.BoardID != board.ID { + ctx.NotFound("ColumnNotInBoard", nil) return } } @@ -638,14 +638,14 @@ func MoveIssues(ctx *context.Context) { } for _, issue := range movedIssues { - if issue.RepoID != project.RepoID { - ctx.ServerError("Some issue's repoID is not equal to project's repoID", errors.New("Some issue's repoID is not equal to project's repoID")) + if issue.RepoID != board.RepoID { + ctx.ServerError("Some issue's repoID is not equal to board's repoID", errors.New("Some issue's repoID is not equal to board's repoID")) return } } if err = board_model.MoveIssuesOnBoardColumn(column, sortedIssueIDs); err != nil { - ctx.ServerError("MoveIssuesOnProjectBoard", err) + ctx.ServerError("MoveIssuesOnBoardColumn", err) return } @@ -653,47 +653,3 @@ func MoveIssues(ctx *context.Context) { "ok": true, }) } - -// CreateProject renders the generic project creation page -func CreateProject(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("repo.projects.new") - ctx.Data["ProjectTypes"] = board_model.GetBoardsConfig() - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) - - ctx.HTML(http.StatusOK, tplGenericBoardsNew) -} - -// CreateProjectPost creates an individual and/or organization project -func CreateProjectPost(ctx *context.Context, form forms.UserCreateProjectForm) { - user := checkContextUser(ctx, form.UID) - if ctx.Written() { - return - } - - ctx.Data["ContextUser"] = user - - if ctx.HasError() { - ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeBoards) - ctx.HTML(http.StatusOK, tplGenericBoardsNew) - return - } - - projectType := board_model.TypeIndividual - if user.IsOrganization() { - projectType = board_model.TypeOrganization - } - - if err := board_model.NewBoard(&board_model.Board{ - Title: form.Title, - Description: form.Content, - CreatorID: user.ID, - ColumnType: form.ColumnType, - Type: projectType, - }); err != nil { - ctx.ServerError("NewBoard", err) - return - } - - ctx.Flash.Success(ctx.Tr("repo.projects.create_success", form.Title)) - ctx.Redirect(setting.AppSubURL + "/") -} diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 9eaf64fa7dc27..9e6b18b30b243 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -363,16 +363,16 @@ func issues(ctx *context.Context, milestoneID, boardID int64, isPullOption util. } if ctx.Repo.CanWriteIssuesOrPulls(ctx.Params(":type") == "pulls") { - projects, _, err := board_model.FindBoards(ctx, board_model.SearchOptions{ + boards, _, err := board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, Type: board_model.TypeRepository, IsClosed: util.OptionalBoolOf(isShowClosed), }) if err != nil { - ctx.ServerError("GetProjects", err) + ctx.ServerError("FindBoards", err) return } - ctx.Data["Projects"] = projects + ctx.Data["Boards"] = boards } ctx.Data["IssueStats"] = issueStats @@ -422,7 +422,7 @@ func Issues(ctx *context.Context) { ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0 } - issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList)) + issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("board"), util.OptionalBoolOf(isPullList)) if ctx.Written() { return } @@ -472,28 +472,28 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R handleTeamMentions(ctx) } -func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { +func retrieveBoards(ctx *context.Context, repo *repo_model.Repository) { var err error - ctx.Data["OpenProjects"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ + ctx.Data["OpenBoards"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, Page: -1, IsClosed: util.OptionalBoolFalse, Type: board_model.TypeRepository, }) if err != nil { - ctx.ServerError("GetProjects", err) + ctx.ServerError("FindBoards", err) return } - ctx.Data["ClosedProjects"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ + ctx.Data["ClosedBoards"], _, err = board_model.FindBoards(ctx, board_model.SearchOptions{ RepoID: repo.ID, Page: -1, IsClosed: util.OptionalBoolTrue, Type: board_model.TypeRepository, }) if err != nil { - ctx.ServerError("GetProjects", err) + ctx.ServerError("FindBoards", err) return } } @@ -716,7 +716,7 @@ func RetrieveRepoMetas(ctx *context.Context, repo *repo_model.Repository, isPull return nil } - retrieveProjects(ctx, repo) + retrieveBoards(ctx, repo) if ctx.Written() { return nil } @@ -808,8 +808,8 @@ func NewIssue(ctx *context.Context) { body := ctx.FormString("body") ctx.Data["BodyQuery"] = body - isProjectsEnabled := ctx.Repo.CanRead(unit.TypeBoards) - ctx.Data["IsProjectsEnabled"] = isProjectsEnabled + isBoardsEnabled := ctx.Repo.CanRead(unit.TypeBoards) + ctx.Data["IsBoardsEnabled"] = isBoardsEnabled ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled upload.AddUploadContext(ctx, "comment") @@ -824,20 +824,20 @@ func NewIssue(ctx *context.Context) { } } - projectID := ctx.FormInt64("project") - if projectID > 0 && isProjectsEnabled { - project, err := board_model.GetBoardByID(ctx, projectID) + boardID := ctx.FormInt64("board") + if boardID > 0 && isBoardsEnabled { + board, err := board_model.GetBoardByID(ctx, boardID) if err != nil { - log.Error("GetBoardByID: %d: %v", projectID, err) - } else if project.RepoID != ctx.Repo.Repository.ID { - log.Error("GetBoardByID: %d: %v", projectID, fmt.Errorf("project[%d] not in repo [%d]", project.ID, ctx.Repo.Repository.ID)) + log.Error("GetBoardByID: %d: %v", boardID, err) + } else if board.RepoID != ctx.Repo.Repository.ID { + log.Error("GetBoardByID: %d: %v", boardID, fmt.Errorf("board[%d] not in repo [%d]", board.ID, ctx.Repo.Repository.ID)) } else { - ctx.Data["project_id"] = projectID - ctx.Data["Project"] = project + ctx.Data["board_id"] = boardID + ctx.Data["Board"] = board } - if len(ctx.Req.URL.Query().Get("project")) > 0 { - ctx.Data["redirect_after_creation"] = "project" + if len(ctx.Req.URL.Query().Get("board")) > 0 { + ctx.Data["redirect_after_creation"] = "board" } } @@ -899,13 +899,13 @@ func NewIssueChooseTemplate(ctx *context.Context) { } if len(issueTemplates) == 0 { - // The "issues/new" and "issues/new/choose" share the same query parameters "project" and "milestone", if no template here, just redirect to the "issues/new" page with these parameters. + // The "issues/new" and "issues/new/choose" share the same query parameters "board" and "milestone", if no template here, just redirect to the "issues/new" page with these parameters. ctx.Redirect(fmt.Sprintf("%s/issues/new?%s", ctx.Repo.Repository.HTMLURL(), ctx.Req.URL.RawQuery), http.StatusSeeOther) return } ctx.Data["milestone"] = ctx.FormInt64("milestone") - ctx.Data["project"] = ctx.FormInt64("project") + ctx.Data["board"] = ctx.FormInt64("board") ctx.HTML(http.StatusOK, tplIssueChoose) } @@ -981,8 +981,8 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull ctx.Data["milestone_id"] = milestoneID } - if form.ProjectID > 0 { - p, err := board_model.GetBoardByID(ctx, form.ProjectID) + if form.BoardID > 0 { + p, err := board_model.GetBoardByID(ctx, form.BoardID) if err != nil { ctx.ServerError("GetBoardByID", err) return nil, nil, 0, 0 @@ -992,8 +992,8 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull return nil, nil, 0, 0 } - ctx.Data["Project"] = p - ctx.Data["project_id"] = form.ProjectID + ctx.Data["Board"] = p + ctx.Data["board_id"] = form.BoardID } // Check assignees @@ -1030,7 +1030,7 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull assigneeIDs = append(assigneeIDs, form.AssigneeID) } - return labelIDs, assigneeIDs, milestoneID, form.ProjectID + return labelIDs, assigneeIDs, milestoneID, form.BoardID } // NewIssuePost response for creating new issue @@ -1048,7 +1048,7 @@ func NewIssuePost(ctx *context.Context) { attachments []string ) - labelIDs, assigneeIDs, milestoneID, projectID := ValidateRepoMetas(ctx, *form, false) + labelIDs, assigneeIDs, milestoneID, boardID := ValidateRepoMetas(ctx, *form, false) if ctx.Written() { return } @@ -1094,21 +1094,21 @@ func NewIssuePost(ctx *context.Context) { return } - if projectID > 0 { + if boardID > 0 { if !ctx.Repo.CanRead(unit.TypeBoards) { - // User must also be able to see the project. - ctx.Error(http.StatusBadRequest, "user hasn't permissions to read projects") + // User must also be able to see the board. + ctx.Error(http.StatusBadRequest, "user hasn't permissions to read boards") return } - if err := issues_model.ChangeBoardAssign(issue, ctx.Doer, projectID); err != nil { - ctx.ServerError("ChangeProjectAssign", err) + if err := issues_model.ChangeBoardAssign(issue, ctx.Doer, boardID); err != nil { + ctx.ServerError("ChangeBoardAssign", err) return } } log.Trace("Issue created: %d/%d", repo.ID, issue.ID) - if ctx.FormString("redirect_after_creation") == "project" { - ctx.Redirect(ctx.Repo.RepoLink + "/projects/" + strconv.FormatInt(form.ProjectID, 10)) + if ctx.FormString("redirect_after_creation") == "board" { + ctx.Redirect(ctx.Repo.RepoLink + "/boards/" + strconv.FormatInt(form.BoardID, 10)) } else { ctx.Redirect(issue.Link()) } @@ -1240,7 +1240,7 @@ func ViewIssue(ctx *context.Context) { } ctx.Data["RequireTribute"] = true - ctx.Data["IsProjectsEnabled"] = ctx.Repo.CanRead(unit.TypeBoards) + ctx.Data["IsBoardsEnabled"] = ctx.Repo.CanRead(unit.TypeBoards) ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled upload.AddUploadContext(ctx, "comment") @@ -1331,7 +1331,7 @@ func ViewIssue(ctx *context.Context) { // Check milestone and assignee. if ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { RetrieveRepoMilestonesAndAssignees(ctx, repo) - retrieveProjects(ctx, repo) + retrieveBoards(ctx, repo) if ctx.Written() { return @@ -1486,21 +1486,21 @@ func ViewIssue(ctx *context.Context) { } else if comment.Type == issues_model.CommentTypeBoard { if err = comment.LoadBoard(); err != nil { - ctx.ServerError("LoadProject", err) + ctx.ServerError("LoadBoard", err) return } - ghostProject := &board_model.Board{ + ghostBoard := &board_model.Board{ ID: -1, - Title: ctx.Tr("repo.issues.deleted_project"), + Title: ctx.Tr("repo.issues.deleted_board"), } if comment.OldBoardID > 0 && comment.OldBoard == nil { - comment.OldBoard = ghostProject + comment.OldBoard = ghostBoard } if comment.BoardID > 0 && comment.Board == nil { - comment.Board = ghostProject + comment.Board = ghostBoard } } else if comment.Type == issues_model.CommentTypeAssignees || comment.Type == issues_model.CommentTypeReviewRequest { @@ -1775,7 +1775,7 @@ func ViewIssue(ctx *context.Context) { ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + url.QueryEscape(ctx.Data["Link"].(string)) ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID) ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) - ctx.Data["HasProjectsWritePermission"] = ctx.Repo.CanWrite(unit.TypeBoards) + ctx.Data["HasBoardsWritePermission"] = ctx.Repo.CanWrite(unit.TypeBoards) ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.Doer.IsAdmin) ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons ctx.Data["RefEndName"] = git.RefEndName(issue.Ref) diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 254a827047df4..0859e19251dc5 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -284,7 +284,7 @@ func Profile(ctx *context.Context) { pager := context.NewPagination(total, setting.UI.User.RepoPagingNum, page, 5) pager.SetDefaultParams(ctx) pager.AddParam(ctx, "tab", "TabName") - if tab != "followers" && tab != "following" && tab != "activity" && tab != "projects" { + if tab != "followers" && tab != "following" && tab != "activity" && tab != "boards" { pager.AddParam(ctx, "language", "Language") } ctx.Data["Page"] = pager diff --git a/templates/repo/boards/list.tmpl b/templates/repo/boards/list.tmpl index 274734f515a04..2b661cf0c04df 100644 --- a/templates/repo/boards/list.tmpl +++ b/templates/repo/boards/list.tmpl @@ -4,20 +4,20 @@
- {{range .Projects}} + {{range .Boards}}
  • - {{svg "octicon-project"}} {{.Title}} + {{svg "octicon-project"}} {{.Title}}
    {{$closedDate:= TimeSinceUnix .ClosedDateUnix $.locale}} {{if .IsClosed}} @@ -57,11 +57,11 @@ {{end}} {{if .Description}} @@ -81,10 +81,10 @@