about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gn3/case_attributes.py73
1 files changed, 64 insertions, 9 deletions
diff --git a/gn3/case_attributes.py b/gn3/case_attributes.py
index 60616e4..98ba047 100644
--- a/gn3/case_attributes.py
+++ b/gn3/case_attributes.py
@@ -13,7 +13,13 @@ from urllib.parse import urljoin
 
 from MySQLdb.cursors import DictCursor
 from authlib.integrations.flask_oauth2.errors import _HTTPException
-from flask import jsonify, request, Response, Blueprint, current_app
+from flask import (
+    jsonify,
+    request,
+    Response,
+    Blueprint,
+    current_app,
+    make_response)
 
 from gn3.commands import run_cmd
 
@@ -279,17 +285,24 @@ def __save_diff__(conn: Connection, diff_data: dict, status: EditStatus) -> int:
             })
         return diff_data.get("db_id") or cursor.lastrowid
 
+def __parse_diff_json__(json_str):
+    """Parse the json string to python objects."""
+    raw_diff = json.loads(json_str)
+    return {
+        **raw_diff,
+        "db_id": int(raw_diff["db_id"]) if raw_diff.get("db_id") else None,
+        "inbredset_id": (int(raw_diff["inbredset_id"])
+                         if raw_diff.get("inbredset_id") else None),
+        "user_id": (uuid.UUID(raw_diff["user_id"])
+                    if raw_diff.get("user_id") else None),
+        "created": (datetime.fromisoformat(raw_diff["created"])
+                    if raw_diff.get("created") else None)
+    }
+
 def __load_diff__(diff_filename):
     """Load the diff."""
     with open(diff_filename, encoding="utf8") as diff_file:
-        the_diff = json.loads(diff_file.read())
-        return {
-            **the_diff,
-            "db_id": int(the_diff["db_id"]),
-            "inbredset_id": int(the_diff["inbredset_id"]),
-            "user_id": uuid.UUID(the_diff["user_id"]),
-            "created": datetime.fromisoformat(the_diff["created"])
-        }
+        return __parse_diff_json__(diff_file.read())
 
 def __apply_diff__(
         conn: Connection, inbredset_id: int, user: User, diff_filename) -> None:
@@ -385,6 +398,48 @@ def edit_case_attributes(inbredset_id: int) -> Response:
                 "diff-filename": str(diff_filename.name)
             })
 
+@caseattr.route("/list/<int:inbredset_id>", methods=["GET"])
+def list_diffs(inbredset_id: int) -> Response:
+    """List any changes that have not been approved/rejected."""
+    def __generate_diff_files__(diffs):
+        diff_dir = Path(current_app.config.get("TMPDIR"), CATTR_DIFFS_DIR)
+        review_files = set(afile.name for afile in diff_dir.iterdir()
+                           if ("-rejected" not in afile.name
+                               and "-approved" not in afile.name))
+        for diff in diffs:
+            the_diff = diff["json_diff_data"]
+            diff_filepath = Path(
+                diff_dir,
+                f"{the_diff['inbredset_id']}:::{the_diff['user_id']}:::"
+                f"{the_diff['created'].isoformat()}.json")
+            if diff_filepath not in review_files:
+                with open(diff_filepath, "w", encoding="utf-8") as dfile:
+                    dfile.write(json.dumps(
+                        {**the_diff, "db_id": diff["id"]},
+                        cls=CAJSONEncoder))
+
+    with (database_connection(current_app.config["SQL_URI"]) as conn,
+          conn.cursor(cursorclass=DictCursor) as cursor):
+        cursor.execute(
+            "SELECT * FROM caseattributes_audit WHERE status='review'")
+        diffs = tuple({
+            **row,
+            "json_diff_data": {
+                **__parse_diff_json__(row["json_diff_data"]),
+                "db_id": row["id"],
+                "created": row["time_stamp"],
+                "user_id": uuid.UUID(row["editor"])
+            }
+        } for row in cursor.fetchall())
+
+    __generate_diff_files__(diffs)
+    resp = make_response(json.dumps(
+        tuple(diff for diff in diffs
+              if diff["json_diff_data"].get("inbredset_id") == inbredset_id),
+        cls=CAJSONEncoder))
+    resp.headers["Content-Type"] = "application/json"
+    return resp
+
 @caseattr.route("/approve/<path:filename>", methods=["POST"])
 def approve_case_attributes_diff(inbredset_id: int) -> Response:
     """Approve the changes to the case attributes in the diff."""