From aad5f44f6cb605589fa017bc521e47a4a517b57d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 12 Nov 2020 12:09:41 -0500 Subject: [PATCH] Display server errors on attachment upload --- plugins/base/routes.go | 13 ++++++++++--- themes/alps/assets/attachments.js | 31 +++++++++++++++++++++++++++++-- themes/alps/assets/style.css | 9 +++++++++ themes/alps/compose.html | 1 + 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/plugins/base/routes.go b/plugins/base/routes.go index fa8f35b..df32876 100644 --- a/plugins/base/routes.go +++ b/plugins/base/routes.go @@ -737,18 +737,25 @@ func handleComposeNew(ctx *alps.Context) error { func handleComposeAttachment(ctx *alps.Context) error { reader, err := ctx.Request().MultipartReader() if err != nil { - return fmt.Errorf("failed to get multipart form: %v", err) + return ctx.JSON(http.StatusBadRequest, map[string]string{ + "error": "Invalid request", + }) } form, err := reader.ReadForm(32 << 20) // 32 MB if err != nil { - return fmt.Errorf("failed to decode multipart form: %v", err) + return ctx.JSON(http.StatusBadRequest, map[string]string{ + "error": "Invalid request", + }) } var uuids []string for _, fh := range form.File["attachments"] { uuid, err := ctx.Session.PutAttachment(fh, form) if err != nil { - return err + ctx.Logger().Printf("PutAttachment: %v\n", err) + return ctx.JSON(http.StatusBadRequest, map[string]string{ + "error": "failed to store attachment", + }) } uuids = append(uuids, uuid) } diff --git a/themes/alps/assets/attachments.js b/themes/alps/assets/attachments.js index a57b4c5..612808a 100644 --- a/themes/alps/assets/attachments.js +++ b/themes/alps/assets/attachments.js @@ -85,17 +85,40 @@ function attachFile(file) { let formData = new FormData(); formData.append("attachments", file); + const handleError = msg => { + attachments = attachments.filter(a => a !== attachment); + node.classList.add("error"); + node.querySelector(".progress").remove(); + node.querySelector(".size").remove(); + node.querySelector("button").remove(); + node.querySelector(".error").innerText = "Error: " + msg; + updateState(); + }; + xhr.open("POST", "/compose/attachment"); xhr.upload.addEventListener("progress", ev => { attachment.progress = ev.loaded / ev.total; updateState(); }); xhr.addEventListener("load", () => { - // TODO: Handle errors - const resp = JSON.parse(xhr.responseText); + let resp; + try { + resp = JSON.parse(xhr.responseText); + } catch { + resp = { "error": "Error: invalid response" }; + } + + if (xhr.status !== 200) { + handleError(resp["error"]); + return; + } + attachment.uuid = resp[0]; updateState(); }); + xhr.addEventListener("error", () => { + handleError("an unexpected problem occured"); + }); xhr.send(formData); updateState(); @@ -105,6 +128,7 @@ function attachmentNodeFor(file) { const node = document.createElement("div"), progress = document.createElement("span"), filename = document.createElement("span"), + error = document.createElement("span"), size = document.createElement("span"), button = document.createElement("button"); node.classList.add("upload"); @@ -116,6 +140,9 @@ function attachmentNodeFor(file) { filename.innerText = file.name; node.appendChild(filename); + error.classList.add("error"); + node.appendChild(error); + size.classList.add("size"); size.innerText = formatSI(file.size) + "B"; node.appendChild(size); diff --git a/themes/alps/assets/style.css b/themes/alps/assets/style.css index 8b80504..79bc88a 100644 --- a/themes/alps/assets/style.css +++ b/themes/alps/assets/style.css @@ -245,6 +245,15 @@ main.create-update #attachment-list .upload .progress { left: 0; } +main.create-update #attachment-list .upload .error { + display: none; +} + +main.create-update #attachment-list .upload.error .error { + display: block; + color: red; +} + main.create-update textarea { flex: 1 auto; resize: none; diff --git a/themes/alps/compose.html b/themes/alps/compose.html index 1f8320b..f4b7b9a 100644 --- a/themes/alps/compose.html +++ b/themes/alps/compose.html @@ -52,6 +52,7 @@
foobar.pdf + 1234 KiB