diff options
author | Gusted <williamzijl7@hotmail.com> | 2021-12-28 13:28:27 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-28 21:28:27 +0800 |
commit | e4e3df6c66dbeac6ac5bceff8ac4f05dbea30d70 (patch) | |
tree | ea7ef42f8d34580b8ec1319f6bc2cd84c6fb973a | |
parent | d2fac636d16a596a36a3088ff05ffe812ba6eff2 (diff) | |
download | gitea-e4e3df6c66dbeac6ac5bceff8ac4f05dbea30d70.tar.gz gitea-e4e3df6c66dbeac6ac5bceff8ac4f05dbea30d70.zip |
Handle invalid issues (#18111)
* Handle invalid issues
- When you hover over a issue reference, and the issue doesn't exist, it
will just hang on the loading animation.
- This patch fixes that by showing them the pop-up with a "Error
occured" message.
* Add I18N
* refactor
* fix comment for lint
* fix unit test for i18n
* fix unit test for i18n
* add comments
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
-rw-r--r-- | integrations/api_releases_test.go | 2 | ||||
-rw-r--r-- | integrations/repo_branch_test.go | 2 | ||||
-rw-r--r-- | modules/context/api.go | 23 | ||||
-rw-r--r-- | options/locale/locale_en-US.ini | 8 | ||||
-rw-r--r-- | templates/base/head.tmpl | 5 | ||||
-rw-r--r-- | web_src/js/components/ContextPopup.vue | 28 |
6 files changed, 45 insertions, 23 deletions
diff --git a/integrations/api_releases_test.go b/integrations/api_releases_test.go index b3d9c898e4..815b749110 100644 --- a/integrations/api_releases_test.go +++ b/integrations/api_releases_test.go @@ -207,7 +207,7 @@ func TestAPIGetReleaseByTag(t *testing.T) { var err *api.APIError DecodeJSON(t, resp, &err) - assert.EqualValues(t, "Not Found", err.Message) + assert.NotEmpty(t, err.Message) } func TestAPIDeleteReleaseByTagName(t *testing.T) { diff --git a/integrations/repo_branch_test.go b/integrations/repo_branch_test.go index af5c475ea7..aef28515e7 100644 --- a/integrations/repo_branch_test.go +++ b/integrations/repo_branch_test.go @@ -141,7 +141,7 @@ func TestCreateBranchInvalidCSRF(t *testing.T) { resp = session.MakeRequest(t, NewRequest(t, "GET", loc), http.StatusOK) htmlDoc := NewHTMLParser(t, resp.Body) assert.Equal(t, - "Bad Request: Invalid CSRF token", + "Bad Request: invalid CSRF token", strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()), ) } diff --git a/modules/context/api.go b/modules/context/api.go index 574d7c4248..635a54c7ef 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -30,6 +30,11 @@ type APIContext struct { Org *APIOrganization } +// Currently, we have the following common fields in error response: +// * message: the message for end users (it shouldn't be used for error type detection) +// if we need to indicate some errors, we should introduce some new fields like ErrorCode or ErrorType +// * url: the swagger document URL + // APIError is error format response // swagger:response error type APIError struct { @@ -47,8 +52,8 @@ type APIValidationError struct { // APIInvalidTopicsError is error format response to invalid topics // swagger:response invalidTopicsError type APIInvalidTopicsError struct { - Topics []string `json:"invalidTopics"` - Message string `json:"message"` + Message string `json:"message"` + InvalidTopics []string `json:"invalidTopics"` } //APIEmpty is an empty response @@ -122,9 +127,9 @@ func (ctx *APIContext) InternalServerError(err error) { }) } -var ( - apiContextKey interface{} = "default_api_context" -) +type apiContextKeyType struct{} + +var apiContextKey = apiContextKeyType{} // WithAPIContext set up api context in request func WithAPIContext(req *http.Request, ctx *APIContext) *http.Request { @@ -351,7 +356,7 @@ func ReferencesGitRepo(allowEmpty bool) func(http.Handler) http.Handler { // NotFound handles 404s for APIContext // String will replace message, errors will be added to a slice func (ctx *APIContext) NotFound(objs ...interface{}) { - var message = "Not Found" + var message = ctx.Tr("error.not_found") var errors []string for _, obj := range objs { // Ignore nil @@ -367,9 +372,9 @@ func (ctx *APIContext) NotFound(objs ...interface{}) { } ctx.JSON(http.StatusNotFound, map[string]interface{}{ - "message": message, - "documentation_url": setting.API.SwaggerURL, - "errors": errors, + "message": message, + "url": setting.API.SwaggerURL, + "errors": errors, }) } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 5248f98069..9164d5ffdc 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -104,10 +104,12 @@ error404 = The page you are trying to reach either <strong>does not exist</stron never = Never [error] -occurred = An error has occurred -report_message = If you are sure this is a Gitea bug, please search for issue on <a href="https://github.com/go-gitea/gitea/issues">GitHub</a> and open new issue if necessary. +occurred = An error occurred +report_message = If you are sure this is a Gitea bug, please search for issues on <a href="https://github.com/go-gitea/gitea/issues" target="_blank">GitHub</a> or open a new issue if necessary. missing_csrf = Bad Request: no CSRF token present -invalid_csrf = Bad Request: Invalid CSRF token +invalid_csrf = Bad Request: invalid CSRF token +not_found = The target couldn't be found. +network_error = Network error [startpage] app_desc = A painless, self-hosted Git service diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index e9c2d512df..8bc6ae689d 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -46,10 +46,13 @@ ]).values()), {{end}} mermaidMaxSourceCharacters: {{MermaidMaxSourceCharacters}}, + {{/* this global i18n object should only contain gereral texts. for specalized texts, it should be provied inside the related modules by: (1) API response (2) HTML data-attribute (3) PageData */}} i18n: { copy_success: '{{.i18n.Tr "copy_success"}}', copy_error: '{{.i18n.Tr "copy_error"}}', - } + error_occurred: '{{.i18n.Tr "error.occurred"}}', + network_error: '{{.i18n.Tr "error.network_error"}}', + }, }; {{/* in case some pages don't render the pageData, we make sure it is an object to prevent null access */}} window.config.pageData = window.config.pageData || {}; diff --git a/web_src/js/components/ContextPopup.vue b/web_src/js/components/ContextPopup.vue index efaa7be89e..c002a3d066 100644 --- a/web_src/js/components/ContextPopup.vue +++ b/web_src/js/components/ContextPopup.vue @@ -16,13 +16,17 @@ </div> </div> </div> + <div v-if="!loading && issue === null"> + <p><small>{{ i18nErrorOccurred }}</small></p> + <p>{{ i18nErrorMessage }}</p> + </div> </div> </template> <script> import {SvgIcon} from '../svg.js'; -const {appSubUrl} = window.config; +const {appSubUrl, i18n} = window.config; // NOTE: see models/issue_label.go for similar implementation const srgbToLinear = (color) => { @@ -49,7 +53,9 @@ export default { data: () => ({ loading: false, - issue: null + issue: null, + i18nErrorOccurred: i18n.error_occurred, + i18nErrorMessage: null, }), computed: { @@ -112,14 +118,20 @@ export default { methods: { load(data, callback) { this.loading = true; - $.get(`${appSubUrl}/api/v1/repos/${data.owner}/${data.repo}/issues/${data.index}`, (issue) => { + this.i18nErrorMessage = null; + $.get(`${appSubUrl}/api/v1/repos/${data.owner}/${data.repo}/issues/${data.index}`).done((issue) => { this.issue = issue; + }).fail((jqXHR) => { + if (jqXHR.responseJSON && jqXHR.responseJSON.message) { + this.i18nErrorMessage = jqXHR.responseJSON.message; + } else { + this.i18nErrorMessage = i18n.network_error; + } + }).always(() => { this.loading = false; - this.$nextTick(() => { - if (callback) { - callback(); - } - }); + if (callback) { + this.$nextTick(callback); + } }); } } |