Make PR form use toast to show error message (#29545)
 (cherry picked from commit 27deea7330f83ddb37c918afbb4159053d8847cb)
This commit is contained in:
		
							parent
							
								
									d509031e84
								
							
						
					
					
						commit
						221a28436a
					
				
					 7 changed files with 35 additions and 30 deletions
				
			
		| 
						 | 
					@ -231,7 +231,7 @@ func CreateBranch(ctx *context.Context) {
 | 
				
			||||||
			if len(e.Message) == 0 {
 | 
								if len(e.Message) == 0 {
 | 
				
			||||||
				ctx.Flash.Error(ctx.Tr("repo.editor.push_rejected_no_message"))
 | 
									ctx.Flash.Error(ctx.Tr("repo.editor.push_rejected_no_message"))
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
									flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
					"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
										"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
				
			||||||
					"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
										"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
				
			||||||
					"Details": utils.SanitizeFlashErrorString(e.Message),
 | 
										"Details": utils.SanitizeFlashErrorString(e.Message),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -382,7 +382,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
 | 
				
			||||||
			if len(errPushRej.Message) == 0 {
 | 
								if len(errPushRej.Message) == 0 {
 | 
				
			||||||
				ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplEditFile, &form)
 | 
									ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplEditFile, &form)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
									flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
					"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
										"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
				
			||||||
					"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
										"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
				
			||||||
					"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
 | 
										"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
 | 
				
			||||||
| 
						 | 
					@ -394,7 +394,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
 | 
				
			||||||
				ctx.RenderWithErr(flashError, tplEditFile, &form)
 | 
									ctx.RenderWithErr(flashError, tplEditFile, &form)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
								flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
				"Message": ctx.Tr("repo.editor.fail_to_update_file", form.TreePath),
 | 
									"Message": ctx.Tr("repo.editor.fail_to_update_file", form.TreePath),
 | 
				
			||||||
				"Summary": ctx.Tr("repo.editor.fail_to_update_file_summary"),
 | 
									"Summary": ctx.Tr("repo.editor.fail_to_update_file_summary"),
 | 
				
			||||||
				"Details": utils.SanitizeFlashErrorString(err.Error()),
 | 
									"Details": utils.SanitizeFlashErrorString(err.Error()),
 | 
				
			||||||
| 
						 | 
					@ -590,7 +590,7 @@ func DeleteFilePost(ctx *context.Context) {
 | 
				
			||||||
			if len(errPushRej.Message) == 0 {
 | 
								if len(errPushRej.Message) == 0 {
 | 
				
			||||||
				ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplDeleteFile, &form)
 | 
									ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplDeleteFile, &form)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
									flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
					"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
										"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
				
			||||||
					"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
										"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
				
			||||||
					"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
 | 
										"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
 | 
				
			||||||
| 
						 | 
					@ -797,7 +797,7 @@ func UploadFilePost(ctx *context.Context) {
 | 
				
			||||||
			if len(errPushRej.Message) == 0 {
 | 
								if len(errPushRej.Message) == 0 {
 | 
				
			||||||
				ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplUploadFile, &form)
 | 
									ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplUploadFile, &form)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
									flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
					"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
										"Message": ctx.Tr("repo.editor.push_rejected"),
 | 
				
			||||||
					"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
										"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
 | 
				
			||||||
					"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
 | 
										"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ import (
 | 
				
			||||||
	stdCtx "context"
 | 
						stdCtx "context"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"html/template"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
| 
						 | 
					@ -1022,7 +1023,7 @@ func NewIssue(ctx *context.Context) {
 | 
				
			||||||
	ctx.HTML(http.StatusOK, tplIssueNew)
 | 
						ctx.HTML(http.StatusOK, tplIssueNew)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func renderErrorOfTemplates(ctx *context.Context, errs map[string]error) string {
 | 
					func renderErrorOfTemplates(ctx *context.Context, errs map[string]error) template.HTML {
 | 
				
			||||||
	var files []string
 | 
						var files []string
 | 
				
			||||||
	for k := range errs {
 | 
						for k := range errs {
 | 
				
			||||||
		files = append(files, k)
 | 
							files = append(files, k)
 | 
				
			||||||
| 
						 | 
					@ -1034,14 +1035,14 @@ func renderErrorOfTemplates(ctx *context.Context, errs map[string]error) string
 | 
				
			||||||
		lines = append(lines, fmt.Sprintf("%s: %v", file, errs[file]))
 | 
							lines = append(lines, fmt.Sprintf("%s: %v", file, errs[file]))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
						flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
		"Message": ctx.Tr("repo.issues.choose.ignore_invalid_templates"),
 | 
							"Message": ctx.Tr("repo.issues.choose.ignore_invalid_templates"),
 | 
				
			||||||
		"Summary": ctx.Tr("repo.issues.choose.invalid_templates", len(errs)),
 | 
							"Summary": ctx.Tr("repo.issues.choose.invalid_templates", len(errs)),
 | 
				
			||||||
		"Details": utils.SanitizeFlashErrorString(strings.Join(lines, "\n")),
 | 
							"Details": utils.SanitizeFlashErrorString(strings.Join(lines, "\n")),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Debug("render flash error: %v", err)
 | 
							log.Debug("render flash error: %v", err)
 | 
				
			||||||
		flashError = ctx.Locale.TrString("repo.issues.choose.ignore_invalid_templates")
 | 
							flashError = ctx.Locale.Tr("repo.issues.choose.ignore_invalid_templates")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return flashError
 | 
						return flashError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3324,7 +3325,7 @@ func ChangeIssueReaction(ctx *context.Context) {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	html, err := ctx.RenderToString(tplReactions, map[string]any{
 | 
						html, err := ctx.RenderToHTML(tplReactions, map[string]any{
 | 
				
			||||||
		"ctxData":   ctx.Data,
 | 
							"ctxData":   ctx.Data,
 | 
				
			||||||
		"ActionURL": fmt.Sprintf("%s/issues/%d/reactions", ctx.Repo.RepoLink, issue.Index),
 | 
							"ActionURL": fmt.Sprintf("%s/issues/%d/reactions", ctx.Repo.RepoLink, issue.Index),
 | 
				
			||||||
		"Reactions": issue.Reactions.GroupByType(),
 | 
							"Reactions": issue.Reactions.GroupByType(),
 | 
				
			||||||
| 
						 | 
					@ -3431,7 +3432,7 @@ func ChangeCommentReaction(ctx *context.Context) {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	html, err := ctx.RenderToString(tplReactions, map[string]any{
 | 
						html, err := ctx.RenderToHTML(tplReactions, map[string]any{
 | 
				
			||||||
		"ctxData":   ctx.Data,
 | 
							"ctxData":   ctx.Data,
 | 
				
			||||||
		"ActionURL": fmt.Sprintf("%s/comments/%d/reactions", ctx.Repo.RepoLink, comment.ID),
 | 
							"ActionURL": fmt.Sprintf("%s/comments/%d/reactions", ctx.Repo.RepoLink, comment.ID),
 | 
				
			||||||
		"Reactions": comment.Reactions.GroupByType(),
 | 
							"Reactions": comment.Reactions.GroupByType(),
 | 
				
			||||||
| 
						 | 
					@ -3574,8 +3575,8 @@ func updateAttachments(ctx *context.Context, item any, files []string) error {
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func attachmentsHTML(ctx *context.Context, attachments []*repo_model.Attachment, content string) string {
 | 
					func attachmentsHTML(ctx *context.Context, attachments []*repo_model.Attachment, content string) template.HTML {
 | 
				
			||||||
	attachHTML, err := ctx.RenderToString(tplAttachment, map[string]any{
 | 
						attachHTML, err := ctx.RenderToHTML(tplAttachment, map[string]any{
 | 
				
			||||||
		"ctxData":     ctx.Data,
 | 
							"ctxData":     ctx.Data,
 | 
				
			||||||
		"Attachments": attachments,
 | 
							"Attachments": attachments,
 | 
				
			||||||
		"Content":     content,
 | 
							"Content":     content,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1159,7 +1159,7 @@ func UpdatePullRequest(ctx *context.Context) {
 | 
				
			||||||
	if err = pull_service.Update(ctx, issue.PullRequest, ctx.Doer, message, rebase); err != nil {
 | 
						if err = pull_service.Update(ctx, issue.PullRequest, ctx.Doer, message, rebase); err != nil {
 | 
				
			||||||
		if models.IsErrMergeConflicts(err) {
 | 
							if models.IsErrMergeConflicts(err) {
 | 
				
			||||||
			conflictError := err.(models.ErrMergeConflicts)
 | 
								conflictError := err.(models.ErrMergeConflicts)
 | 
				
			||||||
			flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
								flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
				"Message": ctx.Tr("repo.pulls.merge_conflict"),
 | 
									"Message": ctx.Tr("repo.pulls.merge_conflict"),
 | 
				
			||||||
				"Summary": ctx.Tr("repo.pulls.merge_conflict_summary"),
 | 
									"Summary": ctx.Tr("repo.pulls.merge_conflict_summary"),
 | 
				
			||||||
				"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
									"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
				
			||||||
| 
						 | 
					@ -1173,7 +1173,7 @@ func UpdatePullRequest(ctx *context.Context) {
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		} else if models.IsErrRebaseConflicts(err) {
 | 
							} else if models.IsErrRebaseConflicts(err) {
 | 
				
			||||||
			conflictError := err.(models.ErrRebaseConflicts)
 | 
								conflictError := err.(models.ErrRebaseConflicts)
 | 
				
			||||||
			flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
								flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
				"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
 | 
									"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
 | 
				
			||||||
				"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
 | 
									"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
 | 
				
			||||||
				"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
									"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
				
			||||||
| 
						 | 
					@ -1305,7 +1305,7 @@ func MergePullRequest(ctx *context.Context) {
 | 
				
			||||||
			ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
 | 
								ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
 | 
				
			||||||
		} else if models.IsErrMergeConflicts(err) {
 | 
							} else if models.IsErrMergeConflicts(err) {
 | 
				
			||||||
			conflictError := err.(models.ErrMergeConflicts)
 | 
								conflictError := err.(models.ErrMergeConflicts)
 | 
				
			||||||
			flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
								flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
				"Message": ctx.Tr("repo.editor.merge_conflict"),
 | 
									"Message": ctx.Tr("repo.editor.merge_conflict"),
 | 
				
			||||||
				"Summary": ctx.Tr("repo.editor.merge_conflict_summary"),
 | 
									"Summary": ctx.Tr("repo.editor.merge_conflict_summary"),
 | 
				
			||||||
				"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
									"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
				
			||||||
| 
						 | 
					@ -1318,7 +1318,7 @@ func MergePullRequest(ctx *context.Context) {
 | 
				
			||||||
			ctx.JSONRedirect(issue.Link())
 | 
								ctx.JSONRedirect(issue.Link())
 | 
				
			||||||
		} else if models.IsErrRebaseConflicts(err) {
 | 
							} else if models.IsErrRebaseConflicts(err) {
 | 
				
			||||||
			conflictError := err.(models.ErrRebaseConflicts)
 | 
								conflictError := err.(models.ErrRebaseConflicts)
 | 
				
			||||||
			flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
								flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
				"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
 | 
									"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
 | 
				
			||||||
				"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
 | 
									"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
 | 
				
			||||||
				"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
									"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
 | 
				
			||||||
| 
						 | 
					@ -1348,7 +1348,7 @@ func MergePullRequest(ctx *context.Context) {
 | 
				
			||||||
			if len(message) == 0 {
 | 
								if len(message) == 0 {
 | 
				
			||||||
				ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected_no_message"))
 | 
									ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected_no_message"))
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
									flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
					"Message": ctx.Tr("repo.pulls.push_rejected"),
 | 
										"Message": ctx.Tr("repo.pulls.push_rejected"),
 | 
				
			||||||
					"Summary": ctx.Tr("repo.pulls.push_rejected_summary"),
 | 
										"Summary": ctx.Tr("repo.pulls.push_rejected_summary"),
 | 
				
			||||||
					"Details": utils.SanitizeFlashErrorString(pushrejErr.Message),
 | 
										"Details": utils.SanitizeFlashErrorString(pushrejErr.Message),
 | 
				
			||||||
| 
						 | 
					@ -1525,7 +1525,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
 | 
				
			||||||
				ctx.JSONError(ctx.Tr("repo.pulls.push_rejected_no_message"))
 | 
									ctx.JSONError(ctx.Tr("repo.pulls.push_rejected_no_message"))
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
 | 
								flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
 | 
				
			||||||
				"Message": ctx.Tr("repo.pulls.push_rejected"),
 | 
									"Message": ctx.Tr("repo.pulls.push_rejected"),
 | 
				
			||||||
				"Summary": ctx.Tr("repo.pulls.push_rejected_summary"),
 | 
									"Summary": ctx.Tr("repo.pulls.push_rejected_summary"),
 | 
				
			||||||
				"Details": utils.SanitizeFlashErrorString(pushrejErr.Message),
 | 
									"Details": utils.SanitizeFlashErrorString(pushrejErr.Message),
 | 
				
			||||||
| 
						 | 
					@ -1534,8 +1534,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
 | 
				
			||||||
				ctx.ServerError("CompareAndPullRequest.HTMLString", err)
 | 
									ctx.ServerError("CompareAndPullRequest.HTMLString", err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ctx.Flash.Error(flashError)
 | 
								ctx.JSONError(flashError)
 | 
				
			||||||
			ctx.JSONRedirect(ctx.Link + "?" + ctx.Req.URL.RawQuery) // FIXME: it's unfriendly, and will make the content lost
 | 
					 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.ServerError("NewPullRequest", err)
 | 
							ctx.ServerError("NewPullRequest", err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ package context
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"html/template"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
| 
						 | 
					@ -104,11 +105,11 @@ func (ctx *Context) JSONTemplate(tmpl base.TplName) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RenderToString renders the template content to a string
 | 
					// RenderToHTML renders the template content to a HTML string
 | 
				
			||||||
func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
 | 
					func (ctx *Context) RenderToHTML(name base.TplName, data map[string]any) (template.HTML, error) {
 | 
				
			||||||
	var buf strings.Builder
 | 
						var buf strings.Builder
 | 
				
			||||||
	err := ctx.Render.HTML(&buf, http.StatusOK, string(name), data, ctx.TemplateContext)
 | 
						err := ctx.Render.HTML(&buf, 0, string(name), data, ctx.TemplateContext)
 | 
				
			||||||
	return buf.String(), err
 | 
						return template.HTML(buf.String()), err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RenderWithErr used for page has form validation but need to prompt error to users.
 | 
					// RenderWithErr used for page has form validation but need to prompt error to users.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,19 +91,24 @@ async function fetchActionDoRequest(actionElem, url, opt) {
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        window.location.reload();
 | 
					        window.location.reload();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
    } else if (resp.status >= 400 && resp.status < 500) {
 | 
					    } else if (resp.status >= 400 && resp.status < 500) {
 | 
				
			||||||
      const data = await resp.json();
 | 
					      const data = await resp.json();
 | 
				
			||||||
      // the code was quite messy, sometimes the backend uses "err", sometimes it uses "error", and even "user_error"
 | 
					      // the code was quite messy, sometimes the backend uses "err", sometimes it uses "error", and even "user_error"
 | 
				
			||||||
      // but at the moment, as a new approach, we only use "errorMessage" here, backend can use JSONError() to respond.
 | 
					      // but at the moment, as a new approach, we only use "errorMessage" here, backend can use JSONError() to respond.
 | 
				
			||||||
      showErrorToast(data.errorMessage || `server error: ${resp.status}`);
 | 
					      if (data.errorMessage) {
 | 
				
			||||||
 | 
					        showErrorToast(data.errorMessage, {useHtmlBody: data.renderFormat === 'html'});
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        showErrorToast(`server error: ${resp.status}`);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      showErrorToast(`server error: ${resp.status}`);
 | 
					      showErrorToast(`server error: ${resp.status}`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } catch (e) {
 | 
					  } catch (e) {
 | 
				
			||||||
    console.error('error when doRequest', e);
 | 
					    console.error('error when doRequest', e);
 | 
				
			||||||
    actionElem.classList.remove('is-loading', 'small-loading-icon');
 | 
					    showErrorToast(`${i18n.network_error} ${e}`);
 | 
				
			||||||
    showErrorToast(i18n.network_error);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  actionElem.classList.remove('is-loading', 'small-loading-icon');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function formFetchAction(e) {
 | 
					async function formFetchAction(e) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,13 +21,12 @@ const levels = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// See https://github.com/apvarun/toastify-js#api for options
 | 
					// See https://github.com/apvarun/toastify-js#api for options
 | 
				
			||||||
function showToast(message, level, {gravity, position, duration, ...other} = {}) {
 | 
					function showToast(message, level, {gravity, position, duration, useHtmlBody, ...other} = {}) {
 | 
				
			||||||
  const {icon, background, duration: levelDuration} = levels[level ?? 'info'];
 | 
					  const {icon, background, duration: levelDuration} = levels[level ?? 'info'];
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const toast = Toastify({
 | 
					  const toast = Toastify({
 | 
				
			||||||
    text: `
 | 
					    text: `
 | 
				
			||||||
      <div class='toast-icon'>${svg(icon)}</div>
 | 
					      <div class='toast-icon'>${svg(icon)}</div>
 | 
				
			||||||
      <div class='toast-body'>${htmlEscape(message)}</div>
 | 
					      <div class='toast-body'>${useHtmlBody ? message : htmlEscape(message)}</div>
 | 
				
			||||||
      <button class='toast-close'>${svg('octicon-x')}</button>
 | 
					      <button class='toast-close'>${svg('octicon-x')}</button>
 | 
				
			||||||
    `,
 | 
					    `,
 | 
				
			||||||
    escapeMarkup: false,
 | 
					    escapeMarkup: false,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue