about summary refs log tree commit diff
path: root/uploader/species
diff options
context:
space:
mode:
Diffstat (limited to 'uploader/species')
-rw-r--r--uploader/species/models.py61
-rw-r--r--uploader/species/views.py41
2 files changed, 88 insertions, 14 deletions
diff --git a/uploader/species/models.py b/uploader/species/models.py
index 4426b64..acfa51e 100644
--- a/uploader/species/models.py
+++ b/uploader/species/models.py
@@ -28,7 +28,7 @@ def order_species_by_family(species: tuple[dict, ...]) -> list:
             **ordered,
             _key: ordered.get(_key, tuple()) + (current,)
         }
-    ordered = reduce(__order__, species, {})
+    ordered = reduce(__order__, species, {})# type: ignore[var-annotated]
     return sorted(tuple(ordered.items()), key=lambda item: item[0][0])
 
 
@@ -47,7 +47,7 @@ def save_species(conn: mdb.Connection,
                  common_name: str,
                  scientific_name: str,
                  family: str,
-                 taxon_id: Optional[str] = None) -> int:
+                 taxon_id: Optional[str] = None) -> dict:
     """
     Save a new species to the database.
 
@@ -58,17 +58,18 @@ def save_species(conn: mdb.Connection,
     common_name: The species' common name.
     scientific_name; The species' scientific name.
     """
-    genus, species = scientific_name.split(" ")
+    genus, *species_parts = scientific_name.split(" ")
+    species_name: str = " ".join(species_parts)
     families = species_families(conn)
     with conn.cursor() as cursor:
         cursor.execute("SELECT MAX(OrderId) FROM Species")
         species = {
             "common_name": common_name,
             "common_name_lower": common_name.lower(),
-            "menu_name": f"{common_name} ({genus[0]}. {species.lower()})",
+            "menu_name": f"{common_name} ({genus[0]}. {species_name.lower()})",
             "scientific_name": scientific_name,
             "family": family,
-            "family_order": families[family],
+            "family_order": families.get(family, 999999),
             "taxon_id": taxon_id,
             "species_order": cursor.fetchone()[0] + 5
         }
@@ -91,6 +92,56 @@ def save_species(conn: mdb.Connection,
         }
 
 
+def update_species(# pylint: disable=[too-many-arguments, too-many-positional-arguments]
+        conn: mdb.Connection,
+        species_id: int,
+        common_name: str,
+        scientific_name: str,
+        family: str,
+        family_order: int,
+        species_order: int
+):
+    """Update a species' details.
+
+    Parameters
+    ----------
+    conn: A connection to the MariaDB database.
+    species_id: The species identifier
+
+    Key-Word Arguments
+    ------------------
+    common_name: A layman's name for the species
+    scientific_name: A binomial nomenclature name for the species
+    family: The grouping under which the species falls
+    family_order: The ordering for the "family" above
+    species_order: The ordering of this species in relation to others
+    """
+    with conn.cursor(cursorclass=DictCursor) as cursor:
+        genus, *species_parts = scientific_name.split(" ")
+        species_name = " ".join(species_parts)
+        species = {
+            "species_id": species_id,
+            "common_name": common_name,
+            "common_name_lower": common_name.lower(),
+            "menu_name": f"{common_name} ({genus[0]}. {species_name.lower()})",
+            "scientific_name": scientific_name,
+            "family": family,
+            "family_order": family_order,
+            "species_order": species_order
+        }
+        cursor.execute(
+            "UPDATE Species SET "
+            "SpeciesName=%(common_name)s, "
+            "Name=%(common_name_lower)s, "
+            "MenuName=%(menu_name)s, "
+            "FullName=%(scientific_name)s, "
+            "Family=%(family)s, "
+            "FamilyOrderId=%(family_order)s, "
+            "OrderId=%(species_order)s "
+            "WHERE Id=%(species_id)s",
+            species)
+
+
 def species_families(conn: mdb.Connection) -> dict:
     """Retrieve the families under which species are grouped."""
     with conn.cursor(cursorclass=DictCursor) as cursor:
diff --git a/uploader/species/views.py b/uploader/species/views.py
index f39ca98..cea2f68 100644
--- a/uploader/species/views.py
+++ b/uploader/species/views.py
@@ -1,5 +1,7 @@
 """Endpoints handling species."""
+from markupsafe import escape
 from pymonad.either import Left, Right, Either
+from gn_libs.mysqldb import database_connection
 from flask import (flash,
                    request,
                    url_for,
@@ -8,26 +10,32 @@ from flask import (flash,
                    current_app as app)
 
 from uploader.population import popbp
-from uploader.datautils import order_by_family
+from uploader.platforms import platformsbp
 from uploader.ui import make_template_renderer
-from uploader.db_utils import database_connection
 from uploader.oauth2.client import oauth2_get, oauth2_post
 from uploader.authorisation import require_login, require_token
+from uploader.datautils import order_by_family, enumerate_sequence
 
-from .models import all_species, save_species, species_by_id, species_families
+from .models import (all_species,
+                     save_species,
+                     species_by_id,
+                     update_species,
+                     species_families)
 
 
 speciesbp = Blueprint("species", __name__)
 speciesbp.register_blueprint(popbp, url_prefix="/")
+speciesbp.register_blueprint(platformsbp, url_prefix="/")
 render_template = make_template_renderer("species")
 
 
 @speciesbp.route("/", methods=["GET"])
+@require_login
 def list_species():
     """List and display all the species in the database."""
     with database_connection(app.config["SQL_URI"]) as conn:
         return render_template("species/list-species.html",
-                               allspecies=all_species(conn))
+                               allspecies=enumerate_sequence(all_species(conn)))
 
 @speciesbp.route("/<int:species_id>", methods=["GET"])
 @require_login
@@ -55,6 +63,8 @@ def create_species():
         if request.method == "GET":
             return render_template("species/create-species.html",
                                    families=species_families(conn),
+                                   return_to=(
+                                       request.args.get("return_to") or ""),
                                    activelink="create-species")
 
         error = False
@@ -72,7 +82,7 @@ def create_species():
             error = True
 
         parts = tuple(name.strip() for name in scientific_name.split(" "))
-        if len(parts) != 2 or not all(bool(name) for name in parts):
+        if (len(parts) != 2 and len(parts) != 3) or not all(bool(name) for name in parts):
             flash("The scientific name you provided is invalid.", "alert-danger")
             error = True
 
@@ -106,7 +116,15 @@ def create_species():
 
         species = save_species(
             conn, common_name, scientific_name, family, taxon_id)
-        flash("Species saved successfully!", "alert-success")
+        flash(
+            f"You have successfully added species "
+            f"'{escape(species['scientific_name'])} "
+            f"({escape(species['common_name'])})'.",
+            "alert-success")
+
+        return_to = request.form.get("return_to").strip()
+        if return_to:
+            return redirect(url_for(return_to, species_id=species["species_id"]))
         return redirect(url_for("species.view_species", species_id=species["species_id"]))
 
 
@@ -177,9 +195,14 @@ def edit_species_extra(token: dict, species_id: int):# pylint: disable=[unused-a
             ).either(__failure__, lambda res: res)
 
         if bool(species) and request.method == "POST":
-            flash("We would have edited the species, but the feature is not "
-                  "currently implemented …",
-                  "alert-danger")
+            update_species(conn,
+                           species_id,
+                           request.form["species_name"],
+                           request.form["species_fullname"],
+                           request.form["species_family"],
+                           int(request.form["species_familyorderid"]),
+                           int(request.form["species_orderid"]))
+            flash("Updated species successfully.", "alert-success")
             return redirect(url_for("species.edit_species_extra",
                                     species_id=species_id))