fix(issue): display error toast on batch action failures instead of reloading page (#38593)

Batch operations in the issues list (labels, milestones, projects,
assignees, etc.) could fail silently because `updateIssuesMeta` caught
and suppressed fetch errors internally. The caller would then proceed to
reload the page, clearing all selected issue checkboxes and giving the
impression that the operation had succeeded.

- Remove updateIssuesMeta and use our "fetch-action" framework to handle errors and page reloading
- Refactor backend code to use ctx.JSONError

---------

Signed-off-by: Sudhanshu Singh <sudhanshuwriterblc@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Shudhanshu Singh
2026-07-23 09:33:47 +00:00
committed by GitHub
co-authored by wxiaoguang
parent ee10ae168c
commit 6ac19f6226
5 changed files with 27 additions and 46 deletions
+1 -3
View File
@@ -11,7 +11,6 @@ import (
issues_model "gitea.dev/models/issues"
"gitea.dev/models/organization"
"gitea.dev/modules/label"
"gitea.dev/modules/log"
repo_module "gitea.dev/modules/repository"
"gitea.dev/modules/templates"
"gitea.dev/modules/util"
@@ -224,8 +223,7 @@ func UpdateIssueLabel(ctx *context.Context) {
}
}
default:
log.Warn("Unrecognized action: %s", action)
ctx.HTTPError(http.StatusInternalServerError)
ctx.JSONError("invalid action: " + action)
return
}
+2 -6
View File
@@ -21,7 +21,6 @@ import (
user_model "gitea.dev/models/user"
issue_indexer "gitea.dev/modules/indexer/issues"
db_indexer "gitea.dev/modules/indexer/issues/db"
"gitea.dev/modules/log"
"gitea.dev/modules/optional"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
@@ -407,8 +406,7 @@ func UpdateIssueStatus(ctx *context.Context) {
action := ctx.FormString("action")
if action != "open" && action != "close" {
log.Warn("Unrecognized action: %s", action)
ctx.JSONOK()
ctx.JSONError("invalid action: " + action)
return
}
@@ -428,9 +426,7 @@ func UpdateIssueStatus(ctx *context.Context) {
if action == "close" && !issue.IsClosed {
if err := issue_service.CloseIssue(ctx, issue, ctx.Doer, ""); err != nil {
if issues_model.IsErrDependenciesLeft(err) {
ctx.JSON(http.StatusPreconditionFailed, map[string]any{
"error": ctx.Tr("repo.issues.dependency.issue_batch_close_blocked", issue.Index),
})
ctx.JSONError(ctx.Tr("repo.issues.dependency.issue_batch_close_blocked", issue.Index))
return
}
ctx.ServerError("CloseIssue", err)