mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-25 14:55:40 +03:00
milestone: edit
This commit is contained in:
parent
cf90312b8f
commit
74bd6b939c
10 changed files with 132 additions and 74 deletions
|
@ -427,8 +427,8 @@ func runWeb(ctx *cli.Context) {
|
|||
m.Group("/milestones", func() {
|
||||
m.Get("/new", repo.NewMilestone)
|
||||
m.Post("/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
|
||||
m.Get("/:index/edit", repo.MilestoneActions)
|
||||
m.Post("/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.UpdateMilestonePost)
|
||||
m.Get("/:index/edit", repo.EditMilestone)
|
||||
m.Post("/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
|
||||
m.Get("/:index/:action", repo.MilestoneActions)
|
||||
}, reqRepoAdmin)
|
||||
|
||||
|
|
|
@ -404,9 +404,14 @@ milestones.create = Create Milestone
|
|||
milestones.title = Title
|
||||
milestones.desc = Description
|
||||
milestones.due_date = Due Date (optional)
|
||||
milestones.clear = clear
|
||||
milestones.clear = Clear
|
||||
milestones.invalid_due_date_format = Due date format is invalid, must be 'mm/dd/year'.
|
||||
milestones.create_success = Milestone '%s' has been created successfully!
|
||||
milestones.edit = Edit Milestone
|
||||
milestones.edit_subheader = Use better description for milestones so people won't be confused.
|
||||
milestones.cancel = Cancel
|
||||
milestones.modify = Modify Milestone
|
||||
milestones.edit_success = Changes of milestone '%s' has been saved successfully!
|
||||
|
||||
settings = Settings
|
||||
settings.options = Options
|
||||
|
|
|
@ -134,3 +134,24 @@ func IsErrRepoNotExist(err error) bool {
|
|||
func (err ErrRepoNotExist) Error() string {
|
||||
return fmt.Sprintf("repository does not exist [id: %d, uid: %d, name: %s]", err.ID, err.UID, err.Name)
|
||||
}
|
||||
|
||||
// _____ .__.__ __
|
||||
// / \ |__| | ____ _______/ |_ ____ ____ ____
|
||||
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
|
||||
// / Y \ | |_\ ___/ \___ \ | | ( <_> ) | \ ___/
|
||||
// \____|__ /__|____/\___ >____ > |__| \____/|___| /\___ >
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
type ErrMilestoneNotExist struct {
|
||||
ID int64
|
||||
Index int64
|
||||
}
|
||||
|
||||
func IsErrMilestoneNotExist(err error) bool {
|
||||
_, ok := err.(ErrMilestoneNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrMilestoneNotExist) Error() string {
|
||||
return fmt.Sprintf("milestone does not exist [id: %d, index: %d]", err.ID, err.Index)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
var (
|
||||
ErrIssueNotExist = errors.New("Issue does not exist")
|
||||
ErrLabelNotExist = errors.New("Label does not exist")
|
||||
ErrMilestoneNotExist = errors.New("Milestone does not exist")
|
||||
ErrWrongIssueCounter = errors.New("Invalid number of issues for this milestone")
|
||||
ErrAttachmentNotExist = errors.New("Attachment does not exist")
|
||||
ErrAttachmentNotLinked = errors.New("Attachment does not belong to this issue")
|
||||
|
@ -691,7 +690,7 @@ func MilestoneById(id int64) (*Milestone, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrMilestoneNotExist
|
||||
return nil, ErrMilestoneNotExist{id, 0}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
@ -703,7 +702,7 @@ func GetMilestoneByIndex(repoId, idx int64) (*Milestone, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrMilestoneNotExist
|
||||
return nil, ErrMilestoneNotExist{0, idx}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -88,9 +88,9 @@ function initRepository() {
|
|||
inline: true,
|
||||
timepicker: false,
|
||||
startDate: $datepicker.data('start-date'),
|
||||
formatDate: 'm/d/Y',
|
||||
formatDate: 'Y-m-d',
|
||||
onSelectDate: function (ct) {
|
||||
$('#deadline').val(ct.dateFormat('m/d/Y'));
|
||||
$('#deadline').val(ct.dateFormat('Y-m-d'));
|
||||
}
|
||||
});
|
||||
$('#clear-date').click(function () {
|
||||
|
|
|
@ -351,21 +351,21 @@ func ViewIssue(ctx *middleware.Context) {
|
|||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, idx)
|
||||
if err != nil {
|
||||
if err == models.ErrIssueNotExist {
|
||||
ctx.Handle(404, "issue.ViewIssue(GetIssueByIndex)", err)
|
||||
ctx.Handle(404, "GetIssueByIndex", err)
|
||||
} else {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetIssueByIndex)", err)
|
||||
ctx.Handle(500, "GetIssueByIndex", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Get labels.
|
||||
if err = issue.GetLabels(); err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetLabels)", err)
|
||||
ctx.Handle(500, "GetLabels", err)
|
||||
return
|
||||
}
|
||||
labels, err := models.GetLabels(ctx.Repo.Repository.Id)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetLabels.2)", err)
|
||||
ctx.Handle(500, "GetLabels.2", err)
|
||||
return
|
||||
}
|
||||
checkLabels(issue.Labels, labels)
|
||||
|
@ -375,10 +375,10 @@ func ViewIssue(ctx *middleware.Context) {
|
|||
if issue.MilestoneId > 0 {
|
||||
ctx.Data["Milestone"], err = models.MilestoneById(issue.MilestoneId)
|
||||
if err != nil {
|
||||
if err == models.ErrMilestoneNotExist {
|
||||
log.Warn("issue.ViewIssue(GetMilestoneById): %v", err)
|
||||
if models.IsErrMilestoneNotExist(err) {
|
||||
log.Warn("GetMilestoneById: %v", err)
|
||||
} else {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetMilestoneById)", err)
|
||||
ctx.Handle(500, "GetMilestoneById", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -387,36 +387,36 @@ func ViewIssue(ctx *middleware.Context) {
|
|||
// Get all milestones.
|
||||
ctx.Data["OpenMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, -1, false)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err)
|
||||
ctx.Handle(500, "GetMilestones.1: %v", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["ClosedMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, -1, true)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err)
|
||||
ctx.Handle(500, "GetMilestones.2: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Get all collaborators.
|
||||
ctx.Data["Collaborators"], err = ctx.Repo.Repository.GetCollaborators()
|
||||
if err != nil {
|
||||
ctx.Handle(500, "issue.CreateIssue(GetCollaborators)", err)
|
||||
ctx.Handle(500, "GetCollaborators", err)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.IsSigned {
|
||||
// Update issue-user.
|
||||
if err = models.UpdateIssueUserPairByRead(ctx.User.Id, issue.ID); err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(UpdateIssueUserPairByRead): %v", err)
|
||||
ctx.Handle(500, "UpdateIssueUserPairByRead: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get poster and Assignee.
|
||||
if err = issue.GetPoster(); err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetPoster): %v", err)
|
||||
ctx.Handle(500, "GetPoster: %v", err)
|
||||
return
|
||||
} else if err = issue.GetAssignee(); err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetAssignee): %v", err)
|
||||
ctx.Handle(500, "GetAssignee: %v", err)
|
||||
return
|
||||
}
|
||||
issue.RenderedContent = string(base.RenderMarkdown([]byte(issue.Content), ctx.Repo.RepoLink))
|
||||
|
@ -424,7 +424,7 @@ func ViewIssue(ctx *middleware.Context) {
|
|||
// Get comments.
|
||||
comments, err := models.GetIssueComments(issue.ID)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetIssueComments): %v", err)
|
||||
ctx.Handle(500, "GetIssueComments: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -432,7 +432,7 @@ func ViewIssue(ctx *middleware.Context) {
|
|||
for i := range comments {
|
||||
u, err := models.GetUserById(comments[i].PosterId)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "issue.ViewIssue(GetUserById.2): %v", err)
|
||||
ctx.Handle(500, "GetUserById.2: %v", err)
|
||||
return
|
||||
}
|
||||
comments[i].Poster = u
|
||||
|
@ -1051,8 +1051,70 @@ func NewMilestonePost(ctx *middleware.Context, form auth.CreateMilestoneForm) {
|
|||
ctx.Redirect(ctx.Repo.RepoLink + "/milestones")
|
||||
}
|
||||
|
||||
func EditMilestone(ctx *middleware.Context) {}
|
||||
func EditMilestonePost(ctx *middleware.Context) {}
|
||||
func EditMilestone(ctx *middleware.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.milestones.edit")
|
||||
ctx.Data["PageIsMilestones"] = true
|
||||
ctx.Data["PageIsEditMilestone"] = true
|
||||
ctx.Data["DateLang"] = setting.DateLang(ctx.Locale.Language())
|
||||
|
||||
m, err := models.GetMilestoneByIndex(ctx.Repo.Repository.Id, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
if models.IsErrMilestoneNotExist(err) {
|
||||
ctx.Handle(404, "GetMilestoneByIndex", nil)
|
||||
} else {
|
||||
ctx.Handle(500, "GetMilestoneByIndex", 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, MILESTONE_NEW)
|
||||
}
|
||||
|
||||
func EditMilestonePost(ctx *middleware.Context, form auth.CreateMilestoneForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.milestones.edit")
|
||||
ctx.Data["PageIsMilestones"] = true
|
||||
ctx.Data["PageIsEditMilestone"] = true
|
||||
ctx.Data["DateLang"] = setting.DateLang(ctx.Locale.Language())
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, MILESTONE_NEW)
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Deadline) == 0 {
|
||||
form.Deadline = "9999-12-31"
|
||||
}
|
||||
deadline, err := time.Parse("2006-01-02", form.Deadline)
|
||||
if err != nil {
|
||||
ctx.Data["Err_Deadline"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), MILESTONE_NEW, &form)
|
||||
return
|
||||
}
|
||||
|
||||
m, err := models.GetMilestoneByIndex(ctx.Repo.Repository.Id, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
if models.IsErrMilestoneNotExist(err) {
|
||||
ctx.Handle(404, "GetMilestoneByIndex", nil)
|
||||
} else {
|
||||
ctx.Handle(500, "GetMilestoneByIndex", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
m.Name = form.Title
|
||||
m.Content = form.Content
|
||||
m.Deadline = deadline
|
||||
if err = models.UpdateMilestone(m); err != nil {
|
||||
ctx.Handle(500, "UpdateMilestone", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("repo.milestones.edit_success", m.Name))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/milestones")
|
||||
}
|
||||
|
||||
func MilestoneActions(ctx *middleware.Context) {
|
||||
ctx.Data["Title"] = "Update Milestone"
|
||||
|
@ -1067,7 +1129,7 @@ func MilestoneActions(ctx *middleware.Context) {
|
|||
|
||||
mile, err := models.GetMilestoneByIndex(ctx.Repo.Repository.Id, idx)
|
||||
if err != nil {
|
||||
if err == models.ErrMilestoneNotExist {
|
||||
if models.IsErrMilestoneNotExist(err) {
|
||||
ctx.Handle(404, "GetMilestoneByIndex", err)
|
||||
} else {
|
||||
ctx.Handle(500, "GetMilestoneByIndex", err)
|
||||
|
@ -1125,7 +1187,7 @@ func UpdateMilestonePost(ctx *middleware.Context, form auth.CreateMilestoneForm)
|
|||
|
||||
mile, err := models.GetMilestoneByIndex(ctx.Repo.Repository.Id, idx)
|
||||
if err != nil {
|
||||
if err == models.ErrMilestoneNotExist {
|
||||
if models.IsErrMilestoneNotExist(err) {
|
||||
ctx.Handle(404, "GetMilestoneByIndex", err)
|
||||
} else {
|
||||
ctx.Handle(500, "GetMilestoneByIndex", err)
|
||||
|
|
|
@ -8,8 +8,13 @@
|
|||
<div class="ui divider"></div>
|
||||
<div class="sixteen wide column page grid">
|
||||
<h2 class="ui dividing header">
|
||||
{{if .PageIsEditMilestone}}
|
||||
{{.i18n.Tr "repo.milestones.edit"}}
|
||||
<div class="sub header">{{.i18n.Tr "repo.milestones.edit_subheader"}}</div>
|
||||
{{else}}
|
||||
{{.i18n.Tr "repo.milestones.new"}}
|
||||
<div class="sub header">{{.i18n.Tr "repo.milestones.new_subheader"}}</div>
|
||||
{{end}}
|
||||
</h2>
|
||||
<form class="ui form grid" action="{{.Link}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
|
@ -21,7 +26,7 @@
|
|||
<div class="eleven wide column">
|
||||
<div class="field {{if .Err_Title}}error{{end}}">
|
||||
<label>{{.i18n.Tr "repo.milestones.title"}}</label>
|
||||
<input name="title" placeholder="{{.i18n.Tr "repo.milestones.title"}}" value="{{.title}}" required>
|
||||
<input name="title" placeholder="{{.i18n.Tr "repo.milestones.title"}}" value="{{.title}}" autofocus required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{.i18n.Tr "repo.milestones.desc"}}</label>
|
||||
|
@ -41,9 +46,18 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
{{if .PageIsEditMilestone}}
|
||||
<button class="ui right green button">
|
||||
{{.i18n.Tr "repo.milestones.modify"}}
|
||||
</button>
|
||||
<a class="ui right blue basic button" href="{{.RepoLink}}/milestones">
|
||||
{{.i18n.Tr "repo.milestones.cancel"}}
|
||||
</a>
|
||||
{{else}}
|
||||
<button class="ui right green button">
|
||||
{{.i18n.Tr "repo.milestones.create"}}
|
||||
</button>
|
||||
{{end}}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
{{template "base/head_old" .}}
|
||||
{{template "base/navbar" .}}
|
||||
{{template "repo/nav" .}}
|
||||
{{template "repo/toolbar" .}}
|
||||
<div id="body" class="container">
|
||||
<div id="issue">
|
||||
<div class="col-md-3 filter-list">
|
||||
<ul class="list-unstyled">
|
||||
<li><a href="{{.RepoLink}}/milestones"{{if eq .State "open"}} class="active"{{end}}>Open Milestones <strong class="pull-right">{{.Repository.NumOpenMilestones}}</strong></a></li>
|
||||
<li><a href="{{.RepoLink}}/milestones?state=closed"{{if eq .State "closed"}} class="active"{{end}}>Close Milestones <strong class="pull-right">{{.Repository.NumClosedMilestones}}</strong></a></li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<a href="{{.RepoLink}}/milestones/new" class="text-center">
|
||||
<button class="btn btn-default btn-block">Create new milestone</button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="milestones list-group">
|
||||
{{range .Milestones}}
|
||||
<div class="list-group-item milestone-item">
|
||||
<h4 class="title pull-left"><a href="{{$.RepoLink}}/issues?milestone={{.Index}}{{if .IsClosed}}&state=closed{{end}}">{{.Name}}</a></h4>
|
||||
<span class="issue-open label label-success">{{.NumOpenIssues}}</span>
|
||||
<span class="issue-close label label-warning">{{.NumClosedIssues}}</span>
|
||||
<p class="actions pull-right">
|
||||
<a href="{{$.RepoLink}}/milestones/{{.Index}}/edit">Edit</a>
|
||||
{{if .IsClosed}}
|
||||
<a href="{{$.RepoLink}}/milestones/{{.Index}}/open">Open</a>
|
||||
{{else}}
|
||||
<a href="{{$.RepoLink}}/milestones/{{.Index}}/close">Close</a>
|
||||
{{end}}
|
||||
<a class="text-danger" href="{{$.RepoLink}}/milestones/{{.Index}}/delete">Delete</a>
|
||||
<a href="{{$.RepoLink}}/issues?milestone={{.Index}}{{if .IsClosed}}&state=closed{{end}}">Issues</a>
|
||||
</p>
|
||||
<hr/>
|
||||
<p class="description">{{.RenderedContent | Str2html}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer_old" .}}
|
Loading…
Reference in a new issue