@@ -190,6 +190,7 @@ func runWeb(*cli.Context) { | |||
r.Post("/issues/milestones/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost) | |||
r.Get("/issues/milestones/:index/edit", repo.UpdateMilestone) | |||
r.Post("/issues/milestones/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.UpdateMilestonePost) | |||
r.Get("/issues/milestones/:index/:action", repo.UpdateMilestone) | |||
r.Post("/comment/:action", repo.Comment) | |||
r.Get("/releases/new", repo.ReleasesNew) | |||
}, reqSignIn, middleware.RepoAssignment(true)) | |||
@@ -471,6 +471,64 @@ func UpdateMilestone(m *Milestone) error { | |||
return err | |||
} | |||
// ChangeMilestoneStatus changes the milestone open/closed status. | |||
func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) { | |||
repo, err := GetRepositoryById(m.RepoId) | |||
if err != nil { | |||
return err | |||
} | |||
sess := orm.NewSession() | |||
defer sess.Close() | |||
if err = sess.Begin(); err != nil { | |||
return err | |||
} | |||
m.IsClosed = isClosed | |||
if _, err = sess.Id(m.Id).AllCols().Update(m); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
if isClosed { | |||
repo.NumClosedMilestones++ | |||
} else { | |||
repo.NumClosedMilestones-- | |||
} | |||
if _, err = sess.Id(repo.Id).Update(repo); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
return sess.Commit() | |||
} | |||
// DeleteMilestone deletes a milestone. | |||
func DeleteMilestone(m *Milestone) (err error) { | |||
sess := orm.NewSession() | |||
defer sess.Close() | |||
if err = sess.Begin(); err != nil { | |||
return err | |||
} | |||
if _, err = sess.Delete(m); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
rawSql := "UPDATE `repository` SET num_milestones = num_milestones - 1 WHERE id = ?" | |||
if _, err = sess.Exec(rawSql, m.RepoId); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
rawSql = "UPDATE `issue` SET milestone_id = 0 WHERE milestone_id = ?" | |||
if _, err = sess.Exec(rawSql, m.Id); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
return sess.Commit() | |||
} | |||
// Issue types. | |||
const ( | |||
IT_PLAIN = iota // Pure comment. | |||
@@ -567,6 +567,34 @@ func UpdateMilestone(ctx *middleware.Context, params martini.Params) { | |||
} | |||
return | |||
} | |||
action := params["action"] | |||
if len(action) > 0 { | |||
switch action { | |||
case "open": | |||
if mile.IsClosed { | |||
if err = models.ChangeMilestoneStatus(mile, false); err != nil { | |||
ctx.Handle(500, "issue.UpdateMilestone(ChangeMilestoneStatus)", err) | |||
return | |||
} | |||
} | |||
case "close": | |||
if !mile.IsClosed { | |||
if err = models.ChangeMilestoneStatus(mile, true); err != nil { | |||
ctx.Handle(500, "issue.UpdateMilestone(ChangeMilestoneStatus)", err) | |||
return | |||
} | |||
} | |||
case "delete": | |||
if err = models.DeleteMilestone(mile); err != nil { | |||
ctx.Handle(500, "issue.UpdateMilestone(DeleteMilestone)", err) | |||
return | |||
} | |||
} | |||
ctx.Redirect(ctx.Repo.RepoLink + "/issues/milestones") | |||
return | |||
} | |||
mile.DeadlineString = mile.Deadline.UTC().Format("01/02/2006") | |||
if mile.DeadlineString == "12/31/9999" { | |||
mile.DeadlineString = "" | |||
@@ -583,16 +611,16 @@ func UpdateMilestonePost(ctx *middleware.Context, params martini.Params, form au | |||
idx, _ := base.StrTo(params["index"]).Int64() | |||
if idx == 0 { | |||
ctx.Handle(404, "issue.UpdateMilestone", nil) | |||
ctx.Handle(404, "issue.UpdateMilestonePost", nil) | |||
return | |||
} | |||
mile, err := models.GetMilestoneByIndex(ctx.Repo.Repository.Id, idx) | |||
if err != nil { | |||
if err == models.ErrMilestoneNotExist { | |||
ctx.Handle(404, "issue.UpdateMilestone(GetMilestoneByIndex)", err) | |||
ctx.Handle(404, "issue.UpdateMilestonePost(GetMilestoneByIndex)", err) | |||
} else { | |||
ctx.Handle(500, "issue.UpdateMilestone(GetMilestoneByIndex)", err) | |||
ctx.Handle(500, "issue.UpdateMilestonePost(GetMilestoneByIndex)", err) | |||
} | |||
return | |||
} | |||
@@ -23,9 +23,12 @@ | |||
<span class="issue-close label label-warning">{{.NumOpenIssues}}</span> | |||
<p class="actions pull-right"> | |||
<a href="{{$.RepoLink}}/issues/milestones/{{.Index}}/edit">Edit</a> | |||
<!-- <a href="#">Open</a> | |||
<a href="#">Close</a> --> | |||
<!-- <a class="text-danger" href="#">Delete</a> --> | |||
{{if .IsClosed}} | |||
<a href="{{$.RepoLink}}/issues/milestones/{{.Index}}/open">Open</a> | |||
{{else}} | |||
<a href="{{$.RepoLink}}/issues/milestones/{{.Index}}/close">Close</a> | |||
{{end}} | |||
<a class="text-danger" href="{{$.RepoLink}}/issues/milestones/{{.Index}}/delete">Delete</a> | |||
<a href="{{$.RepoLink}}/issues?milestone={{.Index}}{{if .IsClosed}}&state=closed{{end}}">Issues</a> | |||
</p> | |||
<hr/> | |||