diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2018-11-29 09:46:30 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-29 09:46:30 +0800 |
commit | 2dc805c0c6e85099f3f346ba78f3a52abf032ce4 (patch) | |
tree | 2adeae8beaa207c80908914d3f6e48d82e2ae21d /routers/repo/milestone.go | |
parent | d5d847e5c4f0cf1470fc51f96d57917e4d9f5d83 (diff) | |
download | gitea-2dc805c0c6e85099f3f346ba78f3a52abf032ce4.tar.gz gitea-2dc805c0c6e85099f3f346ba78f3a52abf032ce4.zip |
Milestone issues and pull requests (#5293)
* add milestone issues and pulls page instead of redirecting issues page
* add milestone when creating issue from milestone page
* refactor to merge similiar codes as a new function issues
* remove milestone info on milestone issues list
* fix missing params
Diffstat (limited to 'routers/repo/milestone.go')
-rw-r--r-- | routers/repo/milestone.go | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/routers/repo/milestone.go b/routers/repo/milestone.go new file mode 100644 index 0000000000..eb2141e995 --- /dev/null +++ b/routers/repo/milestone.go @@ -0,0 +1,262 @@ +// 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 + } + + 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 + } + + 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) + + ctx.HTML(200, tplMilestoneIssues) +} |