aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/base/routes.go13
-rw-r--r--themes/alps/assets/attachments.js31
-rw-r--r--themes/alps/assets/style.css9
-rw-r--r--themes/alps/compose.html1
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 @@
<div class="upload">
<span class="progress"></span>
<span class="filename">foobar.pdf</span>
+ <span class="error"></span>
<span class="size">1234 KiB</span>
<button>&times;</button>
</div>