diff options
author | Frederick Muriuki Muriithi | 2024-09-05 12:31:48 -0500 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2024-09-05 14:19:55 -0500 |
commit | e13a694540ee65f401652d9ebdb5f845c15fb97e (patch) | |
tree | 93c74cfe70d082b37867ae60c79e9e4fdffa33c8 /uploader | |
parent | b6a38df0eaedb9ac4bb4b602643ca1e97f889b49 (diff) | |
download | gn-uploader-e13a694540ee65f401652d9ebdb5f845c15fb97e.tar.gz |
Provide basic UI for editing the Species details.
Diffstat (limited to 'uploader')
-rw-r--r-- | uploader/species/models.py | 8 | ||||
-rw-r--r-- | uploader/species/views.py | 69 | ||||
-rw-r--r-- | uploader/templates/species/edit-species.html | 127 | ||||
-rw-r--r-- | uploader/templates/species/list-species.html | 1 | ||||
-rw-r--r-- | uploader/templates/species/view-species.html | 4 |
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>… provide details on FamilyOrderId here …</p> +<p>… provide details on OrderId here …</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> |