aboutsummaryrefslogtreecommitdiff
path: root/uploader
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-09-05 12:31:48 -0500
committerFrederick Muriuki Muriithi2024-09-05 14:19:55 -0500
commite13a694540ee65f401652d9ebdb5f845c15fb97e (patch)
tree93c74cfe70d082b37867ae60c79e9e4fdffa33c8 /uploader
parentb6a38df0eaedb9ac4bb4b602643ca1e97f889b49 (diff)
downloadgn-uploader-e13a694540ee65f401652d9ebdb5f845c15fb97e.tar.gz
Provide basic UI for editing the Species details.
Diffstat (limited to 'uploader')
-rw-r--r--uploader/species/models.py8
-rw-r--r--uploader/species/views.py69
-rw-r--r--uploader/templates/species/edit-species.html127
-rw-r--r--uploader/templates/species/list-species.html1
-rw-r--r--uploader/templates/species/view-species.html4
5 files changed, 199 insertions, 10 deletions
diff --git a/uploader/species/models.py b/uploader/species/models.py
index 53e7de0..cea3549 100644
--- a/uploader/species/models.py
+++ b/uploader/species/models.py
@@ -81,3 +81,11 @@ def save_species(conn: mdb.Connection,
**species,
"species_id": species_id
}
+
+
+def species_families(conn: mdb.Connection) -> tuple:
+ """Retrieve the families under which species are grouped."""
+ with conn.cursor(cursorclass=DictCursor) as cursor:
+ cursor.execute(
+ "SELECT DISTINCT(Family) FROM Species WHERE Family IS NOT NULL")
+ return tuple(fam["Family"] for fam in cursor.fetchall())
diff --git a/uploader/species/views.py b/uploader/species/views.py
index 5de5277..d994e41 100644
--- a/uploader/species/views.py
+++ b/uploader/species/views.py
@@ -1,4 +1,5 @@
"""Endpoints handling species."""
+from pymonad.either import Left, Right, Either
from flask import (flash,
request,
url_for,
@@ -9,9 +10,10 @@ from flask import (flash,
from uploader.population import popbp
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 .models import all_species, save_species, species_by_id
+from .models import all_species, save_species, species_by_id, species_families
speciesbp = Blueprint("species", __name__)
@@ -100,11 +102,11 @@ def create_species():
return redirect(url_for("species.view_species", species_id=species["species_id"]))
-@speciesbp.route("/<int:species_id>/edit")
+@speciesbp.route("/<int:species_id>/edit-extra", methods=["GET", "POST"])
@require_login
@require_token
#def edit_species(species_id: int):
-def edit_species(token: dict, species_id: int):
+def edit_species_extra(token: dict, species_id: int):# pylint: disable=[unused-argument]
"""Edit a species' details.
Parameters
@@ -112,9 +114,58 @@ def edit_species(token: dict, species_id: int):
token: A JWT token used for authorisation.
species_id: An identifier for the species being edited.
"""
- app.logger.debug("======================\n"
- "Token: %s\n"
- "SpeciesId: %s\n"
- "======================",
- token, species_id)
- return "Would edit the species."
+ def __failure__(res):
+ app.logger.debug(
+ "There was an error in the attempt to edit the species: %s", res)
+ flash(res, "alert-danger")
+ return redirect(url_for("species.view_species", species_id=species_id))
+
+ def __system_resource_uuid__(resources) -> Either:
+ sys_res = [
+ resource for resource in resources
+ if resource["resource_category"]["resource_category_key"] == "system"
+ ]
+ if len(sys_res) != 1:
+ return Left("Could not find/identify a valid system resource.")
+ return Right(sys_res[0]["resource_id"])
+
+ def __check_privileges__(authorisations):
+ if len(authorisations.items()) != 1:
+ return Left("Got authorisations for more than a single resource!")
+
+ auths = tuple(authorisations.items())[0][1]
+ authorised = "system:species:edit-extra-info" in tuple(
+ privilege["privilege_id"]
+ for role in auths["roles"]
+ for privilege in role["privileges"])
+ if authorised:
+ return Right(authorised)
+ return Left("You are not authorised to edit species extra details.")
+
+ with database_connection(app.config["SQL_URI"]) as conn:
+ species = species_by_id(conn, species_id)
+ families = species_families(conn)
+ if bool(species) and request.method == "GET":
+ return oauth2_get("auth/user/resources").then(
+ __system_resource_uuid__
+ ).then(
+ lambda resource_id: oauth2_post(
+ "auth/resource/authorisation",
+ json={"resource-ids": [resource_id]})
+ ).then(__check_privileges__).then(
+ lambda authorisations: render_template("species/edit-species.html",
+ species=species,
+ families=families,
+ activelink="edit-species")
+ ).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")
+ return redirect(url_for("species.edit_species_extra",
+ species_id=species_id))
+
+ flash("Species with the given identifier was not found!",
+ "alert-danger")
+ return redirect(url_for("species.list_species"))
diff --git a/uploader/templates/species/edit-species.html b/uploader/templates/species/edit-species.html
new file mode 100644
index 0000000..c7c57fb
--- /dev/null
+++ b/uploader/templates/species/edit-species.html
@@ -0,0 +1,127 @@
+{%extends "species/base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+
+{%block title%}Edit Species{%endblock%}
+
+{%block pagetitle%}Edit Species{%endblock%}
+
+{%block css%}
+<style type="text/css">
+ .card {
+ margin-top: 0.3em;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 0.3em;
+ border-color: #AAAAAA;
+ padding: 0.5em;
+ }
+</style>
+{%endblock%}
+
+{%block lvl2_breadcrumbs%}
+<li {%if activelink=="edit-species"%}
+ class="breadcrumb-item active"
+ {%else%}
+ class="breadcrumb-item"
+ {%endif%}>
+ <a href="{{url_for('species.edit_species_extra',
+ species_id=species.SpeciesId)}}">Edit</a>
+</li>
+{%endblock%}
+
+{%block contents%}
+{{flash_all_messages()}}
+<div class="row">
+ <form id="frm-edit-species"
+ method="POST"
+ action="{{url_for('species.edit_species_extra',
+ species_id=species.SpeciesId)}}">
+
+ <legend>Edit Extra Detail for Species '{{species.FullName}}'</legend>
+
+ <input type="hidden" name="species_id" value="{{species.SpeciesId}}" />
+
+ <div class="form-group">
+ <label for="lbl-species-taxonid" class="form-label">
+ Taxonomy Id
+ </label>
+ <label id="lbl-species-taxonid"
+ disabled="disabled"
+ class="form-control">{{species.TaxonomyId}}</label>
+ </div>
+
+ <div class="form-group">
+ <label for="txt-species-name" class="form-label">
+ Common Name
+ </label>
+ <input type="text"
+ id="txt-species-name"
+ name="species_name"
+ required="required"
+ value="{{species.SpeciesName}}"
+ class="form-control" />
+ </div>
+
+ <div class="form-group">
+ <label for="txt-species-fullname" class="form-label">
+ Scientific Name
+ </label>
+ <input type="text"
+ id="txt-species-fullname"
+ name="species_fullname"
+ required="required"
+ value="{{species.FullName}}"
+ class="form-control" />
+ </div>
+
+ <div class="form-group">
+ <label for="select-species-family" class="form-label">
+ Family
+ </label>
+ <select id="select-species-family"
+ name="species_family"
+ class="form-control">
+ <option value="">Select the family</option>
+ {%for family in families%}
+ <option value="{{family}}"
+ {%if species.Family == family%}
+ selected="selected"
+ {%endif%}>{{family}}</option>
+ {%endfor%}
+ </select>
+ </div>
+
+ <div class="form-group">
+ <label for="txt-species-familyorderid" class="form-label">
+ Family Order Id
+ </label>
+ <input type="number"
+ id="txt-species-familyorderid"
+ name="species_familyorderid"
+ value="{{species.FamilyOrderId}}"
+ class="form-control" />
+ </div>
+
+ <div class="form-group">
+ <label for="txt-species-orderid" class="form-label">
+ Order Id
+ </label>
+ <input type="number"
+ id="txt-species-orderid"
+ name="species_orderid"
+ value="{{species.OrderId}}"
+ class="form-control" />
+ </div>
+
+ <div class="form-group">
+ <input type="submit" value="Submit Changes" class="btn btn-primary" />
+ </div>
+
+ </form>
+</div>
+{%endblock%}
+
+{%block sidebarcontents%}
+<p>&hellip; provide details on FamilyOrderId here &hellip;</p>
+<p>&hellip; provide details on OrderId here &hellip;</p>
+{%endblock%}
diff --git a/uploader/templates/species/list-species.html b/uploader/templates/species/list-species.html
index 42094c1..573bcee 100644
--- a/uploader/templates/species/list-species.html
+++ b/uploader/templates/species/list-species.html
@@ -6,6 +6,7 @@
{%block pagetitle%}List Species{%endblock%}
{%block contents%}
+{{flash_all_messages()}}
<div class="row">
<p>
All data in GeneNetwork revolves around species. This is the core of the
diff --git a/uploader/templates/species/view-species.html b/uploader/templates/species/view-species.html
index 15b2969..bf5f0c1 100644
--- a/uploader/templates/species/view-species.html
+++ b/uploader/templates/species/view-species.html
@@ -29,6 +29,7 @@
{%endblock%}
{%block contents%}
+{{flash_all_messages()}}
<div class="row">
<h2>Details on species {{species.FullName}}</h2>
@@ -92,7 +93,8 @@
<dd>{{species.OrderId}}</dd>
</dl>
</div>
- <a href="{{url_for('species.edit_species', species_id=species.SpeciesId)}}"
+ <a href="{{url_for('species.edit_species_extra',
+ species_id=species.SpeciesId)}}"
class="card-link"
title="Edit the species' internal-use details.">Edit</a>
</div>