parent
							
								
									ac97ea573c
								
							
						
					
					
						commit
						c69c01d2b6
					
				
					 6 changed files with 73 additions and 16 deletions
				
			
		|  | @ -36,6 +36,7 @@ type ProjectBoard 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:"DEFAULT 0"` | ||||
| 
 | ||||
| 	ProjectID int64 `xorm:"INDEX NOT NULL"` | ||||
| 	CreatorID int64 `xorm:"NOT NULL"` | ||||
|  | @ -157,15 +158,24 @@ func getProjectBoard(e Engine, boardID int64) (*ProjectBoard, error) { | |||
| 	return board, nil | ||||
| } | ||||
| 
 | ||||
| // UpdateProjectBoard updates the title of a project board
 | ||||
| // UpdateProjectBoard updates a project board
 | ||||
| func UpdateProjectBoard(board *ProjectBoard) error { | ||||
| 	return updateProjectBoard(x, board) | ||||
| } | ||||
| 
 | ||||
| func updateProjectBoard(e Engine, board *ProjectBoard) error { | ||||
| 	_, err := e.ID(board.ID).Cols( | ||||
| 		"title", | ||||
| 	).Update(board) | ||||
| 	var fieldToUpdate []string | ||||
| 
 | ||||
| 	if board.Sorting != 0 { | ||||
| 		fieldToUpdate = append(fieldToUpdate, "sorting") | ||||
| 	} | ||||
| 
 | ||||
| 	if board.Title != "" { | ||||
| 		fieldToUpdate = append(fieldToUpdate, "title") | ||||
| 	} | ||||
| 
 | ||||
| 	_, err := e.ID(board.ID).Cols(fieldToUpdate...).Update(board) | ||||
| 
 | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
|  | @ -178,7 +188,7 @@ func GetProjectBoards(projectID int64) (ProjectBoardList, error) { | |||
| func getProjectBoards(e Engine, projectID int64) ([]*ProjectBoard, error) { | ||||
| 	var boards = make([]*ProjectBoard, 0, 5) | ||||
| 
 | ||||
| 	if err := e.Where("project_id=? AND `default`=?", projectID, false).Find(&boards); err != nil { | ||||
| 	if err := e.Where("project_id=? AND `default`=?", projectID, false).OrderBy("Sorting").Find(&boards); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
|  | @ -277,3 +287,17 @@ func (bs ProjectBoardList) LoadIssues() (IssueList, error) { | |||
| 	} | ||||
| 	return issues, nil | ||||
| } | ||||
| 
 | ||||
| // UpdateProjectBoardSorting update project board sorting
 | ||||
| func UpdateProjectBoardSorting(bs ProjectBoardList) error { | ||||
| 	for i := range bs { | ||||
| 		_, err := x.ID(bs[i].ID).Cols( | ||||
| 			"sorting", | ||||
| 		).Update(bs[i]) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -487,10 +487,10 @@ type UserCreateProjectForm struct { | |||
| 	UID       int64 `binding:"Required"` | ||||
| } | ||||
| 
 | ||||
| // EditProjectBoardTitleForm is a form for editing the title of a project's
 | ||||
| // board
 | ||||
| type EditProjectBoardTitleForm struct { | ||||
| 	Title string `binding:"Required;MaxSize(100)"` | ||||
| // EditProjectBoardForm is a form for editing a project board
 | ||||
| type EditProjectBoardForm struct { | ||||
| 	Title   string `binding:"Required;MaxSize(100)"` | ||||
| 	Sorting int8 | ||||
| } | ||||
| 
 | ||||
| //    _____  .__.__                   __
 | ||||
|  |  | |||
|  | @ -403,7 +403,7 @@ func DeleteProjectBoard(ctx *context.Context) { | |||
| 
 | ||||
| // AddBoardToProjectPost allows a new board to be added to a project.
 | ||||
| func AddBoardToProjectPost(ctx *context.Context) { | ||||
| 	form := web.GetForm(ctx).(*auth.EditProjectBoardTitleForm) | ||||
| 	form := web.GetForm(ctx).(*auth.EditProjectBoardForm) | ||||
| 	if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(models.AccessModeWrite, models.UnitTypeProjects) { | ||||
| 		ctx.JSON(403, map[string]string{ | ||||
| 			"message": "Only authorized users are allowed to perform this action.", | ||||
|  | @ -481,9 +481,9 @@ func checkProjectBoardChangePermissions(ctx *context.Context) (*models.Project, | |||
| 	return project, board | ||||
| } | ||||
| 
 | ||||
| // EditProjectBoardTitle allows a project board's title to be updated
 | ||||
| func EditProjectBoardTitle(ctx *context.Context) { | ||||
| 	form := web.GetForm(ctx).(*auth.EditProjectBoardTitleForm) | ||||
| // EditProjectBoard allows a project board's to be updated
 | ||||
| func EditProjectBoard(ctx *context.Context) { | ||||
| 	form := web.GetForm(ctx).(*auth.EditProjectBoardForm) | ||||
| 	_, board := checkProjectBoardChangePermissions(ctx) | ||||
| 	if ctx.Written() { | ||||
| 		return | ||||
|  | @ -493,6 +493,10 @@ func EditProjectBoardTitle(ctx *context.Context) { | |||
| 		board.Title = form.Title | ||||
| 	} | ||||
| 
 | ||||
| 	if form.Sorting != 0 { | ||||
| 		board.Sorting = form.Sorting | ||||
| 	} | ||||
| 
 | ||||
| 	if err := models.UpdateProjectBoard(board); err != nil { | ||||
| 		ctx.ServerError("UpdateProjectBoard", err) | ||||
| 		return | ||||
|  |  | |||
|  | @ -853,7 +853,7 @@ func RegisterRoutes(m *web.Route) { | |||
| 				m.Get("/new", repo.NewProject) | ||||
| 				m.Post("/new", bindIgnErr(auth.CreateProjectForm{}), repo.NewProjectPost) | ||||
| 				m.Group("/{id}", func() { | ||||
| 					m.Post("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.AddBoardToProjectPost) | ||||
| 					m.Post("", bindIgnErr(auth.EditProjectBoardForm{}), repo.AddBoardToProjectPost) | ||||
| 					m.Post("/delete", repo.DeleteProject) | ||||
| 
 | ||||
| 					m.Get("/edit", repo.EditProject) | ||||
|  | @ -861,7 +861,7 @@ func RegisterRoutes(m *web.Route) { | |||
| 					m.Post("/{action:open|close}", repo.ChangeProjectStatus) | ||||
| 
 | ||||
| 					m.Group("/{boardID}", func() { | ||||
| 						m.Put("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.EditProjectBoardTitle) | ||||
| 						m.Put("", bindIgnErr(auth.EditProjectBoardForm{}), repo.EditProjectBoard) | ||||
| 						m.Delete("", repo.DeleteProjectBoard) | ||||
| 						m.Post("/default", repo.SetDefaultProjectBoard) | ||||
| 
 | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ | |||
| 		<div class="board"> | ||||
| 			{{ range $board := .Boards }} | ||||
| 
 | ||||
| 			<div class="ui segment board-column"> | ||||
| 			<div class="ui segment board-column" data-id="{{.ID}}" data-sorting="{{.Sorting}}" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}"> | ||||
| 				<div class="board-column-header"> | ||||
| 					<div class="ui large label board-label">{{.Title}}</div> | ||||
| 					{{if and $.CanWriteProjects (not $.Repository.IsArchived) $.PageIsProjects (ne .ID 0)}} | ||||
|  |  | |||
|  | @ -8,6 +8,34 @@ export default async function initProject() { | |||
|   const {Sortable} = await import(/* webpackChunkName: "sortable" */'sortablejs'); | ||||
|   const boardColumns = document.getElementsByClassName('board-column'); | ||||
| 
 | ||||
|   new Sortable( | ||||
|     document.getElementsByClassName('board')[0], | ||||
|     { | ||||
|       group: 'board-column', | ||||
|       draggable: '.board-column', | ||||
|       animation: 150, | ||||
|       onSort: () => { | ||||
|         const board = document.getElementsByClassName('board')[0]; | ||||
|         const boardColumns = board.getElementsByClassName('board-column'); | ||||
| 
 | ||||
|         boardColumns.forEach((column, i) => { | ||||
|           if (parseInt($(column).data('sorting')) !== i) { | ||||
|             $.ajax({ | ||||
|               url: $(column).data('url'), | ||||
|               data: JSON.stringify({sorting: i}), | ||||
|               headers: { | ||||
|                 'X-Csrf-Token': csrf, | ||||
|                 'X-Remote': true, | ||||
|               }, | ||||
|               contentType: 'application/json', | ||||
|               method: 'PUT', | ||||
|             }); | ||||
|           } | ||||
|         }); | ||||
|       }, | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   for (const column of boardColumns) { | ||||
|     new Sortable( | ||||
|       column.getElementsByClassName('board')[0], | ||||
|  | @ -74,6 +102,7 @@ export default async function initProject() { | |||
| 
 | ||||
|     window.location.reload(); | ||||
|   }); | ||||
| 
 | ||||
|   $('.delete-project-board').each(function () { | ||||
|     $(this).click(function (e) { | ||||
|       e.preventDefault(); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue