71d52e432e
Deploy MokoGitea / deploy (push) Successful in 5m8s
Add IsRequired field to IssueStatusDef. Open and Closed statuses are seeded as required and cannot be deleted. Delete attempts return an error flash in the web UI and ErrStatusRequired in the model layer. API response now includes is_required field.
118 lines
3.6 KiB
Go
118 lines
3.6 KiB
Go
// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package org
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
issues_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/issues"
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/context"
|
|
)
|
|
|
|
const tplOrgIssueStatuses templates.TplName = "org/settings/issue_statuses"
|
|
|
|
// SettingsIssueStatuses shows the org-level issue statuses management page.
|
|
func SettingsIssueStatuses(ctx *context.Context) {
|
|
ctx.Data["Title"] = ctx.Tr("org.settings.issue_statuses")
|
|
ctx.Data["PageIsOrgSettings"] = true
|
|
ctx.Data["PageIsSettingsIssueStatuses"] = true
|
|
|
|
defs, err := issues_model.GetAllIssueStatusDefsByOrg(ctx, ctx.Org.Organization.ID)
|
|
if err != nil {
|
|
ctx.ServerError("GetAllIssueStatusDefsByOrg", err)
|
|
return
|
|
}
|
|
ctx.Data["IssueStatuses"] = defs
|
|
|
|
ctx.HTML(http.StatusOK, tplOrgIssueStatuses)
|
|
}
|
|
|
|
// SettingsIssueStatusesCreatePost creates a new org-level issue status.
|
|
func SettingsIssueStatusesCreatePost(ctx *context.Context) {
|
|
sortOrder, _ := strconv.Atoi(ctx.FormString("sort_order"))
|
|
|
|
def := &issues_model.IssueStatusDef{
|
|
OrgID: ctx.Org.Organization.ID,
|
|
Name: ctx.FormString("name"),
|
|
Color: ctx.FormString("color"),
|
|
Description: ctx.FormString("description"),
|
|
ClosesIssue: ctx.FormString("closes_issue") == "on",
|
|
SortOrder: sortOrder,
|
|
IsActive: true,
|
|
}
|
|
|
|
if def.Name == "" {
|
|
ctx.Flash.Error("Status name is required")
|
|
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-statuses")
|
|
return
|
|
}
|
|
|
|
if err := issues_model.CreateIssueStatusDef(ctx, def); err != nil {
|
|
ctx.ServerError("CreateIssueStatusDef", err)
|
|
return
|
|
}
|
|
|
|
ctx.Flash.Success(ctx.Tr("org.settings.issue_status_created"))
|
|
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-statuses")
|
|
}
|
|
|
|
// SettingsIssueStatusesEditPost updates an org-level issue status.
|
|
func SettingsIssueStatusesEditPost(ctx *context.Context) {
|
|
id := ctx.PathParamInt64("id")
|
|
def, err := issues_model.GetIssueStatusDefByID(ctx, id)
|
|
if err != nil {
|
|
ctx.ServerError("GetIssueStatusDefByID", err)
|
|
return
|
|
}
|
|
if def.OrgID != ctx.Org.Organization.ID {
|
|
ctx.NotFound(nil)
|
|
return
|
|
}
|
|
|
|
def.Name = ctx.FormString("name")
|
|
def.Color = ctx.FormString("color")
|
|
def.Description = ctx.FormString("description")
|
|
def.ClosesIssue = ctx.FormString("closes_issue") == "on"
|
|
def.IsActive = ctx.FormString("is_active") == "on"
|
|
sortOrder, _ := strconv.Atoi(ctx.FormString("sort_order"))
|
|
def.SortOrder = sortOrder
|
|
|
|
if err := issues_model.UpdateIssueStatusDef(ctx, def); err != nil {
|
|
ctx.ServerError("UpdateIssueStatusDef", err)
|
|
return
|
|
}
|
|
|
|
ctx.Flash.Success(ctx.Tr("org.settings.issue_status_updated"))
|
|
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-statuses")
|
|
}
|
|
|
|
// SettingsIssueStatusesDeletePost deletes an org-level issue status.
|
|
func SettingsIssueStatusesDeletePost(ctx *context.Context) {
|
|
id := ctx.PathParamInt64("id")
|
|
def, err := issues_model.GetIssueStatusDefByID(ctx, id)
|
|
if err != nil {
|
|
ctx.ServerError("GetIssueStatusDefByID", err)
|
|
return
|
|
}
|
|
if def.OrgID != ctx.Org.Organization.ID {
|
|
ctx.NotFound(nil)
|
|
return
|
|
}
|
|
|
|
if err := issues_model.DeleteIssueStatusDef(ctx, id); err != nil {
|
|
if issues_model.IsErrStatusRequired(err) {
|
|
ctx.Flash.Error("Cannot delete required status: " + def.Name)
|
|
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-statuses")
|
|
return
|
|
}
|
|
ctx.ServerError("DeleteIssueStatusDef", err)
|
|
return
|
|
}
|
|
|
|
ctx.Flash.Success(ctx.Tr("org.settings.issue_status_deleted"))
|
|
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-statuses")
|
|
}
|