| @@ -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/> | |||