2018-11-29 04:46:30 +03:00
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/Unknwon/paginater"
)
const (
tplMilestone base . TplName = "repo/issue/milestones"
tplMilestoneNew base . TplName = "repo/issue/milestone_new"
tplMilestoneEdit base . TplName = "repo/issue/milestone_edit"
tplMilestoneIssues base . TplName = "repo/issue/milestone_issues"
)
// Milestones render milestones page
func Milestones ( ctx * context . Context ) {
ctx . Data [ "Title" ] = ctx . Tr ( "repo.milestones" )
ctx . Data [ "PageIsIssueList" ] = true
ctx . Data [ "PageIsMilestones" ] = true
isShowClosed := ctx . Query ( "state" ) == "closed"
openCount , closedCount , err := models . MilestoneStats ( ctx . Repo . Repository . ID )
if err != nil {
ctx . ServerError ( "MilestoneStats" , err )
return
}
ctx . Data [ "OpenCount" ] = openCount
ctx . Data [ "ClosedCount" ] = closedCount
sortType := ctx . Query ( "sort" )
page := ctx . QueryInt ( "page" )
if page <= 1 {
page = 1
}
var total int
if ! isShowClosed {
total = int ( openCount )
} else {
total = int ( closedCount )
}
ctx . Data [ "Page" ] = paginater . New ( total , setting . UI . IssuePagingNum , page , 5 )
miles , err := models . GetMilestones ( ctx . Repo . Repository . ID , page , isShowClosed , sortType )
if err != nil {
ctx . ServerError ( "GetMilestones" , err )
return
}
if ctx . Repo . Repository . IsTimetrackerEnabled ( ) {
if miles . LoadTotalTrackedTimes ( ) ; err != nil {
ctx . ServerError ( "LoadTotalTrackedTimes" , err )
return
}
}
for _ , m := range miles {
m . RenderedContent = string ( markdown . Render ( [ ] byte ( m . Content ) , ctx . Repo . RepoLink , ctx . Repo . Repository . ComposeMetas ( ) ) )
}
ctx . Data [ "Milestones" ] = miles
if isShowClosed {
ctx . Data [ "State" ] = "closed"
} else {
ctx . Data [ "State" ] = "open"
}
ctx . Data [ "SortType" ] = sortType
ctx . Data [ "IsShowClosed" ] = isShowClosed
ctx . HTML ( 200 , tplMilestone )
}
// NewMilestone render creating milestone page
func NewMilestone ( ctx * context . Context ) {
ctx . Data [ "Title" ] = ctx . Tr ( "repo.milestones.new" )
ctx . Data [ "PageIsIssueList" ] = true
ctx . Data [ "PageIsMilestones" ] = true
ctx . Data [ "RequireDatetimepicker" ] = true
ctx . Data [ "DateLang" ] = setting . DateLang ( ctx . Locale . Language ( ) )
ctx . HTML ( 200 , tplMilestoneNew )
}
// NewMilestonePost response for creating milestone
func NewMilestonePost ( ctx * context . Context , form auth . CreateMilestoneForm ) {
ctx . Data [ "Title" ] = ctx . Tr ( "repo.milestones.new" )
ctx . Data [ "PageIsIssueList" ] = true
ctx . Data [ "PageIsMilestones" ] = true
ctx . Data [ "RequireDatetimepicker" ] = true
ctx . Data [ "DateLang" ] = setting . DateLang ( ctx . Locale . Language ( ) )
if ctx . HasError ( ) {
ctx . HTML ( 200 , tplMilestoneNew )
return
}
if len ( form . Deadline ) == 0 {
form . Deadline = "9999-12-31"
}
deadline , err := time . ParseInLocation ( "2006-01-02" , form . Deadline , time . Local )
if err != nil {
ctx . Data [ "Err_Deadline" ] = true
ctx . RenderWithErr ( ctx . Tr ( "repo.milestones.invalid_due_date_format" ) , tplMilestoneNew , & form )
return
}
2019-01-01 20:56:47 +03:00
deadline = time . Date ( deadline . Year ( ) , deadline . Month ( ) , deadline . Day ( ) , 23 , 59 , 59 , 0 , deadline . Location ( ) )
2018-11-29 04:46:30 +03:00
if err = models . NewMilestone ( & models . Milestone {
RepoID : ctx . Repo . Repository . ID ,
Name : form . Title ,
Content : form . Content ,
DeadlineUnix : util . TimeStamp ( deadline . Unix ( ) ) ,
} ) ; err != nil {
ctx . ServerError ( "NewMilestone" , err )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.milestones.create_success" , form . Title ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/milestones" )
}
// EditMilestone render edting milestone page
func EditMilestone ( ctx * context . Context ) {
ctx . Data [ "Title" ] = ctx . Tr ( "repo.milestones.edit" )
ctx . Data [ "PageIsMilestones" ] = true
ctx . Data [ "PageIsEditMilestone" ] = true
ctx . Data [ "RequireDatetimepicker" ] = true
ctx . Data [ "DateLang" ] = setting . DateLang ( ctx . Locale . Language ( ) )
m , err := models . GetMilestoneByRepoID ( ctx . Repo . Repository . ID , ctx . ParamsInt64 ( ":id" ) )
if err != nil {
if models . IsErrMilestoneNotExist ( err ) {
ctx . NotFound ( "" , nil )
} else {
ctx . ServerError ( "GetMilestoneByRepoID" , err )
}
return
}
ctx . Data [ "title" ] = m . Name
ctx . Data [ "content" ] = m . Content
if len ( m . DeadlineString ) > 0 {
ctx . Data [ "deadline" ] = m . DeadlineString
}
ctx . HTML ( 200 , tplMilestoneNew )
}
// EditMilestonePost response for edting milestone
func EditMilestonePost ( ctx * context . Context , form auth . CreateMilestoneForm ) {
ctx . Data [ "Title" ] = ctx . Tr ( "repo.milestones.edit" )
ctx . Data [ "PageIsMilestones" ] = true
ctx . Data [ "PageIsEditMilestone" ] = true
ctx . Data [ "RequireDatetimepicker" ] = true
ctx . Data [ "DateLang" ] = setting . DateLang ( ctx . Locale . Language ( ) )
if ctx . HasError ( ) {
ctx . HTML ( 200 , tplMilestoneNew )
return
}
if len ( form . Deadline ) == 0 {
form . Deadline = "9999-12-31"
}
deadline , err := time . ParseInLocation ( "2006-01-02" , form . Deadline , time . Local )
if err != nil {
ctx . Data [ "Err_Deadline" ] = true
ctx . RenderWithErr ( ctx . Tr ( "repo.milestones.invalid_due_date_format" ) , tplMilestoneNew , & form )
return
}
2019-01-01 20:56:47 +03:00
deadline = time . Date ( deadline . Year ( ) , deadline . Month ( ) , deadline . Day ( ) , 23 , 59 , 59 , 0 , deadline . Location ( ) )
2018-11-29 04:46:30 +03:00
m , err := models . GetMilestoneByRepoID ( ctx . Repo . Repository . ID , ctx . ParamsInt64 ( ":id" ) )
if err != nil {
if models . IsErrMilestoneNotExist ( err ) {
ctx . NotFound ( "" , nil )
} else {
ctx . ServerError ( "GetMilestoneByRepoID" , err )
}
return
}
m . Name = form . Title
m . Content = form . Content
m . DeadlineUnix = util . TimeStamp ( deadline . Unix ( ) )
if err = models . UpdateMilestone ( m ) ; err != nil {
ctx . ServerError ( "UpdateMilestone" , err )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.milestones.edit_success" , m . Name ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/milestones" )
}
// ChangeMilestonStatus response for change a milestone's status
func ChangeMilestonStatus ( ctx * context . Context ) {
m , err := models . GetMilestoneByRepoID ( ctx . Repo . Repository . ID , ctx . ParamsInt64 ( ":id" ) )
if err != nil {
if models . IsErrMilestoneNotExist ( err ) {
ctx . NotFound ( "" , err )
} else {
ctx . ServerError ( "GetMilestoneByRepoID" , err )
}
return
}
switch ctx . Params ( ":action" ) {
case "open" :
if m . IsClosed {
if err = models . ChangeMilestoneStatus ( m , false ) ; err != nil {
ctx . ServerError ( "ChangeMilestoneStatus" , err )
return
}
}
ctx . Redirect ( ctx . Repo . RepoLink + "/milestones?state=open" )
case "close" :
if ! m . IsClosed {
m . ClosedDateUnix = util . TimeStampNow ( )
if err = models . ChangeMilestoneStatus ( m , true ) ; err != nil {
ctx . ServerError ( "ChangeMilestoneStatus" , err )
return
}
}
ctx . Redirect ( ctx . Repo . RepoLink + "/milestones?state=closed" )
default :
ctx . Redirect ( ctx . Repo . RepoLink + "/milestones" )
}
}
// DeleteMilestone delete a milestone
func DeleteMilestone ( ctx * context . Context ) {
if err := models . DeleteMilestoneByRepoID ( ctx . Repo . Repository . ID , ctx . QueryInt64 ( "id" ) ) ; err != nil {
ctx . Flash . Error ( "DeleteMilestoneByRepoID: " + err . Error ( ) )
} else {
ctx . Flash . Success ( ctx . Tr ( "repo.milestones.deletion_success" ) )
}
ctx . JSON ( 200 , map [ string ] interface { } {
"redirect" : ctx . Repo . RepoLink + "/milestones" ,
} )
}
// MilestoneIssuesAndPulls lists all the issues and pull requests of the milestone
func MilestoneIssuesAndPulls ( ctx * context . Context ) {
milestoneID := ctx . ParamsInt64 ( ":id" )
milestone , err := models . GetMilestoneByID ( milestoneID )
if err != nil {
ctx . ServerError ( "GetMilestoneByID" , err )
return
}
ctx . Data [ "Title" ] = milestone . Name
ctx . Data [ "Milestone" ] = milestone
issues ( ctx , milestoneID , util . OptionalBoolNone )
2019-03-15 18:50:27 +03:00
perm , err := models . GetUserRepoPermission ( ctx . Repo . Repository , ctx . User )
if err != nil {
ctx . ServerError ( "GetUserRepoPermission" , err )
return
}
ctx . Data [ "CanWriteIssues" ] = perm . CanWriteIssuesOrPulls ( false )
ctx . Data [ "CanWritePulls" ] = perm . CanWriteIssuesOrPulls ( true )
2018-11-29 04:46:30 +03:00
ctx . HTML ( 200 , tplMilestoneIssues )
}