feat(issues): status dropdown replaces close button #528

Merged
jmiller merged 1 commits from feat/status-replaces-close into dev 2026-06-06 19:13:34 +00:00
3 changed files with 75 additions and 18 deletions
+39
View File
@@ -184,6 +184,45 @@ func NewComment(ctx *context.Context) {
}
} // end if: handle close or reopen
// Handle custom status from the status dropdown (replaces close button for issues with org statuses).
if statusIDStr := ctx.Req.FormValue("status_id"); statusIDStr != "" && statusIDStr != "" {
if statusIDStr == "reopen" {
// Reopen via dropdown
if issue.IsClosed {
if err := issue_service.ReopenIssue(ctx, issue, ctx.Doer, ""); err != nil {
log.Error("ReopenIssue via status dropdown: %v", err)
}
if err := issues_model.SetIssueStatusID(ctx, issue.ID, 0); err != nil {
log.Error("SetIssueStatusID: %v", err)
}
}
} else if statusIDStr == "close" {
// Plain close via dropdown
if !issue.IsClosed {
if err := issue_service.CloseIssue(ctx, issue, ctx.Doer, ""); err != nil {
log.Error("CloseIssue via status dropdown: %v", err)
}
}
} else if statusID, err := strconv.ParseInt(statusIDStr, 10, 64); err == nil && statusID > 0 {
// Custom status selected
statusDef, err := issues_model.GetIssueStatusDefByID(ctx, statusID)
if err == nil && statusDef.OrgID == ctx.Repo.Repository.OwnerID {
if err := issues_model.SetIssueStatusID(ctx, issue.ID, statusID); err != nil {
log.Error("SetIssueStatusID: %v", err)
}
if statusDef.ClosesIssue && !issue.IsClosed {
if err := issue_service.CloseIssue(ctx, issue, ctx.Doer, ""); err != nil {
log.Error("CloseIssue via custom status: %v", err)
}
} else if !statusDef.ClosesIssue && issue.IsClosed {
if err := issue_service.ReopenIssue(ctx, issue, ctx.Doer, ""); err != nil {
log.Error("ReopenIssue via custom status: %v", err)
}
}
}
}
}
ctx.JSONRedirect(redirect)
}
+36 -16
View File
@@ -85,24 +85,44 @@
<div class="field footer">
<div class="flex-text-block tw-justify-end">
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .DisableStatusChange)}}
{{$btnIconColor := ""}}{{$btnIcon := ""}}{{$btnTextNoComment := ""}}{{$btnTextWithComment := ""}}{{$btnValue := ""}}
{{if .Issue.IsClosed}}
{{$btnValue = "reopen"}}
{{$btnIconColor = "tw-text-green"}}
{{$btnIcon = Iif .Issue.IsPull "octicon-git-pull-request" "octicon-issue-reopened"}}
{{$btnTextNoComment = ctx.Locale.Tr (Iif .Issue.IsPull "repo.pulls.reopen" "repo.issues.reopen_issue")}}
{{$btnTextWithComment = ctx.Locale.Tr "repo.issues.reopen_comment_issue"}}{{/* general: Reopen with Comment */}}
{{if and .IssueStatusDefs (not .Issue.IsPull)}}
<select name="status_id" class="ui compact dropdown" style="min-width:140px;padding:7px 10px;border:1px solid var(--color-secondary);border-radius:4px;background:var(--color-body);">
<option value="">-- {{ctx.Locale.Tr "repo.issues.status"}} --</option>
{{range .IssueStatusDefs}}
{{if not .ClosesIssue}}
<option value="{{.ID}}" {{if eq .ID $.Issue.StatusID}}selected{{end}}>{{.Name}}</option>
{{end}}
{{end}}
<option disabled>---</option>
{{range .IssueStatusDefs}}
{{if .ClosesIssue}}
<option value="{{.ID}}" {{if eq .ID $.Issue.StatusID}}selected{{end}}>{{.Name}} (close)</option>
{{end}}
{{end}}
{{if .Issue.IsClosed}}
<option value="reopen">{{ctx.Locale.Tr "repo.issues.reopen_issue"}}</option>
{{end}}
</select>
{{else}}
{{$btnValue = "close"}}
{{$btnIconColor = "tw-text-red"}}
{{$btnIcon = Iif .Issue.IsPull "octicon-git-pull-request-closed" "octicon-issue-closed"}}
{{$btnTextNoComment = ctx.Locale.Tr (Iif .Issue.IsPull "repo.pulls.close" "repo.issues.close")}}
{{$btnTextWithComment = ctx.Locale.Tr "repo.issues.close_comment_issue"}}{{/* general: Close with Comment */}}
{{$btnIconColor := ""}}{{$btnIcon := ""}}{{$btnTextNoComment := ""}}{{$btnTextWithComment := ""}}{{$btnValue := ""}}
{{if .Issue.IsClosed}}
{{$btnValue = "reopen"}}
{{$btnIconColor = "tw-text-green"}}
{{$btnIcon = Iif .Issue.IsPull "octicon-git-pull-request" "octicon-issue-reopened"}}
{{$btnTextNoComment = ctx.Locale.Tr (Iif .Issue.IsPull "repo.pulls.reopen" "repo.issues.reopen_issue")}}
{{$btnTextWithComment = ctx.Locale.Tr "repo.issues.reopen_comment_issue"}}
{{else}}
{{$btnValue = "close"}}
{{$btnIconColor = "tw-text-red"}}
{{$btnIcon = Iif .Issue.IsPull "octicon-git-pull-request-closed" "octicon-issue-closed"}}
{{$btnTextNoComment = ctx.Locale.Tr (Iif .Issue.IsPull "repo.pulls.close" "repo.issues.close")}}
{{$btnTextWithComment = ctx.Locale.Tr "repo.issues.close_comment_issue"}}
{{end}}
<button id="status-button" class="ui button" data-status="{{$btnTextNoComment}}" data-status-and-comment="{{$btnTextWithComment}}" name="status" value="{{$btnValue}}">
<span class="status-button-icon {{$btnIconColor}}">{{svg $btnIcon}}</span>
<span class="status-button-text">{{$btnTextNoComment}}</span>
</button>
{{end}}
<button id="status-button" class="ui button" data-status="{{$btnTextNoComment}}" data-status-and-comment="{{$btnTextWithComment}}" name="status" value="{{$btnValue}}">
<span class="status-button-icon {{$btnIconColor}}">{{svg $btnIcon}}</span>
<span class="status-button-text">{{$btnTextNoComment}}</span>
</button>
{{end}}
<button id="comment-button" class="ui primary button">
{{ctx.Locale.Tr "repo.issues.create_comment"}}
@@ -7,8 +7,6 @@
{{template "repo/issue/sidebar/label_list" $.IssuePageMetaData}}
{{template "repo/issue/sidebar/issue_status" $}}
{{template "repo/issue/sidebar/issue_priority" $}}
{{template "repo/issue/sidebar/custom_fields" $}}