Browse Source

Reintroduce error handlerrs.

scossu 4 months ago
parent
commit
07271deebd
3 changed files with 50 additions and 4 deletions
  1. 22 1
      scriptshifter/exceptions.py
  2. 13 1
      scriptshifter/rest_api.py
  3. 15 2
      scriptshifter/templates/index.html

+ 22 - 1
scriptshifter/exceptions.py

@@ -4,6 +4,27 @@ BREAK = "__break"
 CONT = "__continue"
 
 
-class ConfigError(Exception):
+class ApiError(Exception):
+    """ Base class for all exceptions expecting an API response. """
+    status_code = 400
+    msg = "An undefined error occurred."
+
+    def __init__(self, msg=None):
+        if msg is not None:
+            self.msg = msg
+
+    def to_json(self):
+        return {
+            "message": self.msg,
+            "status_code": self.status_code,
+        }
+
+
+class ConfigError(ApiError):
     """ Raised when a malformed configuration is detected. """
     pass
+
+
+class UpstreamError(ApiError):
+    """ Raised when an external service responds with an error code. """
+    pass

+ 13 - 1
scriptshifter/rest_api.py

@@ -2,11 +2,12 @@ import logging
 
 from base64 import b64encode
 from copy import deepcopy
-from json import loads
+from json import dumps, loads
 from os import environ, urandom
 
 from flask import Flask, jsonify, render_template, request
 
+from scriptshifter.exceptions import ApiError
 from scriptshifter.tables import list_tables, load_table
 from scriptshifter.trans import transliterate
 
@@ -31,6 +32,17 @@ def create_app():
 app = create_app()
 
 
+@app.errorhandler(ApiError)
+def handle_exception(e: ApiError):
+    rsp = e.get_response()
+    rsp.data = dumps({
+        "content": e.to_json(),
+        "status_code": e.status_code
+    })
+
+    return rsp
+
+
 @app.route("/", methods=["GET"])
 def index():
     return render_template("index.html", languages=list_tables())

+ 15 - 2
scriptshifter/templates/index.html

@@ -121,15 +121,28 @@
                         label.setAttribute("for", opt.id);
                         label.append(opt.label);
 
-                        let input = document.createElement("input");
-                        if (opt.type == "boolean") {
+                        var input;
+                        if (opt.type == "list") {
+                            input = document.createElement("select");
+                            opt.options.forEach((sel) => {
+                                let option = document.createElement("option");
+                                option.append(sel.label);
+                                option.value = sel.id;
+                                if (option.value == opt.default) {
+                                    option.selected = true;
+                                };
+                                input.append(option);
+                            })
+                        } else if (opt.type == "boolean") {
                             // Use checkbox for boolean type.
+                            input = document.createElement("input");
                             input.setAttribute("type", "checkbox");
                             if (opt.default) {
                                 input.setAttribute("checked", 1);
                             }
                         } else {
                             // Use text for all other types.
+                            input = document.createElement("input");
                             input.value = opt.default;
                         }
                         input.setAttribute("id", opt.id);