From 8af1c13d7ea29847b53120e5b40e37931967f34b Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Mon, 25 Jan 2021 18:01:18 +0000 Subject: [PATCH] Display error messages on form two new strings need translating in lang/form. --- api.go | 8 ++++---- html/form-base.html | 1 + html/form.html | 1 - lang.go | 6 ++++-- lang/form/en-us.json | 4 ++++ storage.go | 6 ++++++ ts/form.ts | 22 +++++++++++++++++++--- ts/modules/common.ts | 5 +++-- views.go | 1 + 9 files changed, 42 insertions(+), 12 deletions(-) diff --git a/api.go b/api.go index 3d3f4b0..04bdcd5 100644 --- a/api.go +++ b/api.go @@ -325,7 +325,7 @@ func (app *appContext) NewUser(gc *gin.Context) { app.debug.Printf("%s: New user attempt", req.Code) if !app.checkInvite(req.Code, false, "") { app.info.Printf("%s New user failed: invalid code", req.Code) - respondBool(401, false, gc) + respond(401, "errorInvalidCode", gc) return } validation := app.validator.validate(req.Password) @@ -344,15 +344,15 @@ func (app *appContext) NewUser(gc *gin.Context) { } existingUser, _, _ := app.jf.UserByName(req.Username, false) if existingUser != nil { - msg := fmt.Sprintf("User already exists named %s", req.Username) + msg := fmt.Sprintf("User %s", req.Username) app.info.Printf("%s New user failed: %s", req.Code, msg) - respond(401, msg, gc) + respond(401, "errorUserExists", gc) return } user, status, err := app.jf.NewUser(req.Username, req.Password) if !(status == 200 || status == 204) || err != nil { app.err.Printf("%s New user failed: Jellyfin responded with %d", req.Code, status) - respond(401, "Unknown error", gc) + respond(401, app.storage.lang.Admin[app.storage.lang.chosenAdminLang].Notifications.get("errorUnknown"), gc) return } app.storage.loadProfiles() diff --git a/html/form-base.html b/html/form-base.html index b702b4d..03be6c1 100644 --- a/html/form-base.html +++ b/html/form-base.html @@ -5,6 +5,7 @@ window.invalidPassword = "{{ .strings.reEnterPasswordInvalid }}"; window.URLBase = "{{ .urlBase }}"; window.code = "{{ .code }}"; + window.messages = JSON.parse({{ .notifications }}); {{ end }} diff --git a/html/form.html b/html/form.html index cb299a9..31da74d 100644 --- a/html/form.html +++ b/html/form.html @@ -13,7 +13,6 @@ {{ .strings.successContinueButton }} -
diff --git a/lang.go b/lang.go index 27f6fb7..cc8940d 100644 --- a/lang.go +++ b/lang.go @@ -48,8 +48,10 @@ func (ls *formLangs) getOptions(chosen string) (string, []string) { } type formLang struct { - Meta langMeta `json:"meta"` - Strings langSection `json:"strings"` + Meta langMeta `json:"meta"` + Strings langSection `json:"strings"` + Notifications langSection `json:"notifications"` + notificationsJSON string ValidationStrings map[string]quantityString `json:"validationStrings"` validationStringsJSON string } diff --git a/lang/form/en-us.json b/lang/form/en-us.json index a1f67da..d4c6732 100644 --- a/lang/form/en-us.json +++ b/lang/form/en-us.json @@ -16,6 +16,10 @@ "successHeader": "Success!", "successContinueButton": "Continue" }, + "notifications": { + "errorUserExists": "User already exists.", + "errorInvalidCode": "Invalid invite code." + }, "validationStrings": { "length": { "singular": "Must have at least {n} character", diff --git a/storage.go b/storage.go index 4b586e9..972b43c 100644 --- a/storage.go +++ b/storage.go @@ -166,12 +166,18 @@ func (st *Storage) loadLangForm() error { } if fname != "en-us.json" { patchLang(&english.Strings, &lang.Strings) + patchLang(&english.Notifications, &lang.Notifications) patchQuantityStrings(&english.ValidationStrings, &lang.ValidationStrings) } + notifications, err := json.Marshal(lang.Notifications) + if err != nil { + return err + } validationStrings, err := json.Marshal(lang.ValidationStrings) if err != nil { return err } + lang.notificationsJSON = string(notifications) lang.validationStringsJSON = string(validationStrings) st.lang.Form[index] = lang return nil diff --git a/ts/form.ts b/ts/form.ts index b2b2581..bc2a364 100644 --- a/ts/form.ts +++ b/ts/form.ts @@ -7,6 +7,7 @@ interface formWindow extends Window { invalidPassword: string; modal: Modal; code: string; + messages: { [key: string]: string }; } interface pwValString { @@ -75,7 +76,8 @@ rePasswordField.addEventListener("keyup", checkPasswords); passwordField.addEventListener("keyup", checkPasswords); interface respDTO { - [ type: string ]: boolean; + response: boolean; + error: string; } interface sendDTO { @@ -96,13 +98,12 @@ const create = (event: SubmitEvent) => { }; _post("/newUser", send, (req: XMLHttpRequest) => { if (req.readyState == 4) { - let vals = JSON.parse(req.response) as respDTO; + let vals = req.response as respDTO; let valid = true; for (let type in vals) { if (requirements[type]) { requirements[type].valid = vals[type]; } if (!vals[type]) { valid = false; } } - toggleLoader(submitSpan); if (req.status == 200 && valid) { window.modal.show(); } else { @@ -114,6 +115,21 @@ const create = (event: SubmitEvent) => { }, 1000); } } + }, true, (req: XMLHttpRequest) => { + if (req.readyState == 4) { + toggleLoader(submitSpan); + if (req.status == 401) { + if (req.response["error"] as string) { + const old = submitSpan.textContent; + if (req.response["error"] in window.messages) { + submitSpan.textContent = window.messages[req.response["error"]]; + } else { + submitSpan.textContent = req.response["error"]; + } + setTimeout(() => { submitSpan.textContent = old; }, 1000); + } + } + } }); }; diff --git a/ts/modules/common.ts b/ts/modules/common.ts index b3b4017..b6dc008 100644 --- a/ts/modules/common.ts +++ b/ts/modules/common.ts @@ -67,7 +67,7 @@ export const _get = (url: string, data: Object, onreadystatechange: (req: XMLHtt req.send(JSON.stringify(data)); }; -export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, response?: boolean): void => { +export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, response?: boolean, statusHandler?: (req: XMLHttpRequest) => void): void => { let req = new XMLHttpRequest(); req.open("POST", window.URLBase + url, true); if (response) { @@ -76,7 +76,8 @@ export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHt req.setRequestHeader("Authorization", "Bearer " + window.token); req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); req.onreadystatechange = () => { - if (req.status == 0) { + if (statusHandler) { statusHandler(req); } + else if (req.status == 0) { window.notifications.connectionError(); return; } else if (req.status == 401) { diff --git a/views.go b/views.go index 5af53b5..d6a316a 100644 --- a/views.go +++ b/views.go @@ -96,6 +96,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) { "username": !app.config.Section("email").Key("no_username").MustBool(false), "strings": app.storage.lang.Form[lang].Strings, "validationStrings": app.storage.lang.Form[lang].validationStringsJSON, + "notifications": app.storage.lang.Form[lang].notificationsJSON, "code": code, }) } else {