mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Implement Issue Config (#20956)
Closes #20955 This PR adds the possibility to disable blank Issues, when the Repo has templates. This can be done by creating the file `.gitea/issue_config.yaml` with the content `blank_issues_enabled` in the Repo.
This commit is contained in:
@@ -1169,6 +1169,8 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
}, reqAdmin())
|
||||
}, reqAnyRepoReader())
|
||||
m.Get("/issue_templates", context.ReferencesGitRepo(), repo.GetIssueTemplates)
|
||||
m.Get("/issue_config", context.ReferencesGitRepo(), repo.GetIssueConfig)
|
||||
m.Get("/issue_config/validate", context.ReferencesGitRepo(), repo.ValidateIssueConfig)
|
||||
m.Get("/languages", reqRepoReader(unit.TypeCode), repo.GetLanguages)
|
||||
}, repoAssignment())
|
||||
})
|
||||
|
@@ -1144,3 +1144,58 @@ func GetIssueTemplates(ctx *context.APIContext) {
|
||||
|
||||
ctx.JSON(http.StatusOK, ctx.IssueTemplatesFromDefaultBranch())
|
||||
}
|
||||
|
||||
// GetIssueConfig returns the issue config for a repo
|
||||
func GetIssueConfig(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/issue_config repository repoGetIssueConfig
|
||||
// ---
|
||||
// summary: Returns the issue config for a repo
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: owner
|
||||
// in: path
|
||||
// description: owner of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: repo
|
||||
// in: path
|
||||
// description: name of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepoIssueConfig"
|
||||
issueConfig, _ := ctx.IssueConfigFromDefaultBranch()
|
||||
ctx.JSON(http.StatusOK, issueConfig)
|
||||
}
|
||||
|
||||
// ValidateIssueConfig returns validation errors for the issue config
|
||||
func ValidateIssueConfig(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/issue_config/validate repository repoValidateIssueConfig
|
||||
// ---
|
||||
// summary: Returns the validation information for a issue config
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: owner
|
||||
// in: path
|
||||
// description: owner of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: repo
|
||||
// in: path
|
||||
// description: name of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepoIssueConfigValidation"
|
||||
_, err := ctx.IssueConfigFromDefaultBranch()
|
||||
|
||||
if err == nil {
|
||||
ctx.JSON(http.StatusOK, api.IssueConfigValidation{Valid: true, Message: ""})
|
||||
} else {
|
||||
ctx.JSON(http.StatusOK, api.IssueConfigValidation{Valid: false, Message: err.Error()})
|
||||
}
|
||||
}
|
||||
|
@@ -386,3 +386,17 @@ type swaggerRepoCollaboratorPermission struct {
|
||||
// in:body
|
||||
Body api.RepoCollaboratorPermission `json:"body"`
|
||||
}
|
||||
|
||||
// RepoIssueConfig
|
||||
// swagger:response RepoIssueConfig
|
||||
type swaggerRepoIssueConfig struct {
|
||||
// in:body
|
||||
Body api.IssueConfig `json:"body"`
|
||||
}
|
||||
|
||||
// RepoIssueConfigValidation
|
||||
// swagger:response RepoIssueConfigValidation
|
||||
type swaggerRepoIssueConfigValidation struct {
|
||||
// in:body
|
||||
Body api.IssueConfigValidation `json:"body"`
|
||||
}
|
||||
|
@@ -435,7 +435,7 @@ func Issues(ctx *context.Context) {
|
||||
}
|
||||
ctx.Data["Title"] = ctx.Tr("repo.issues")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0
|
||||
ctx.Data["NewIssueChooseTemplate"] = ctx.HasIssueTemplatesOrContactLinks()
|
||||
}
|
||||
|
||||
issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList))
|
||||
@@ -848,7 +848,7 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles
|
||||
func NewIssue(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0
|
||||
ctx.Data["NewIssueChooseTemplate"] = ctx.HasIssueTemplatesOrContactLinks()
|
||||
ctx.Data["RequireTribute"] = true
|
||||
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
|
||||
title := ctx.FormString("title")
|
||||
@@ -946,12 +946,16 @@ func NewIssueChooseTemplate(ctx *context.Context) {
|
||||
ctx.Flash.Warning(renderErrorOfTemplates(ctx, errs), true)
|
||||
}
|
||||
|
||||
if len(issueTemplates) == 0 {
|
||||
if !ctx.HasIssueTemplatesOrContactLinks() {
|
||||
// The "issues/new" and "issues/new/choose" share the same query parameters "project" and "milestone", if no template here, just redirect to the "issues/new" page with these parameters.
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/new?%s", ctx.Repo.Repository.Link(), ctx.Req.URL.RawQuery), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
issueConfig, err := ctx.IssueConfigFromDefaultBranch()
|
||||
ctx.Data["IssueConfig"] = issueConfig
|
||||
ctx.Data["IssueConfigError"] = err // ctx.Flash.Err makes problems here
|
||||
|
||||
ctx.Data["milestone"] = ctx.FormInt64("milestone")
|
||||
ctx.Data["project"] = ctx.FormInt64("project")
|
||||
|
||||
@@ -1086,7 +1090,7 @@ func NewIssuePost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.CreateIssueForm)
|
||||
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0
|
||||
ctx.Data["NewIssueChooseTemplate"] = ctx.HasIssueTemplatesOrContactLinks()
|
||||
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
|
||||
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
|
||||
upload.AddUploadContext(ctx, "comment")
|
||||
@@ -1280,7 +1284,7 @@ func ViewIssue(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0
|
||||
ctx.Data["NewIssueChooseTemplate"] = ctx.HasIssueTemplatesOrContactLinks()
|
||||
}
|
||||
|
||||
if issue.IsPull && !ctx.Repo.CanRead(unit.TypeIssues) {
|
||||
|
@@ -348,6 +348,9 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
|
||||
if ctx.Repo.TreePath == ".editorconfig" {
|
||||
_, editorconfigErr := ctx.Repo.GetEditorconfig(ctx.Repo.Commit)
|
||||
ctx.Data["FileError"] = editorconfigErr
|
||||
} else if ctx.Repo.IsIssueConfig(ctx.Repo.TreePath) {
|
||||
_, issueConfigErr := ctx.Repo.GetIssueConfig(ctx.Repo.TreePath, ctx.Repo.Commit)
|
||||
ctx.Data["FileError"] = issueConfigErr
|
||||
}
|
||||
|
||||
isDisplayingSource := ctx.FormString("display") == "source"
|
||||
|
Reference in New Issue
Block a user