about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--uploader/background_jobs.py17
-rw-r--r--uploader/phenotypes/views.py10
-rw-r--r--uploader/templates/background-jobs/sui-default-success-page.html17
-rw-r--r--uploader/templates/jobs/sui-job-error.html17
-rw-r--r--uploader/templates/jobs/sui-job-not-found.html11
-rw-r--r--uploader/templates/jobs/sui-job-status.html24
-rw-r--r--uploader/templates/phenotypes/sui-job-status.html140
-rw-r--r--uploader/templates/phenotypes/sui-load-phenotypes-success.html26
-rw-r--r--uploader/templates/phenotypes/sui-review-job-data.html121
9 files changed, 374 insertions, 9 deletions
diff --git a/uploader/background_jobs.py b/uploader/background_jobs.py
index d33c498..a9c0345 100644
--- a/uploader/background_jobs.py
+++ b/uploader/background_jobs.py
@@ -5,7 +5,7 @@ from typing import Callable
 from functools import partial
 
 from flask import (
-    url_for,
+    request,
     redirect,
     Response,
     Blueprint,
@@ -16,6 +16,7 @@ from gn_libs import jobs
 from gn_libs import sqlite3
 from gn_libs.jobs.jobs import JobNotFound
 
+from uploader.flask_extensions import url_for
 from uploader.authorisation import require_login
 
 background_jobs_bp = Blueprint("background-jobs", __name__)
@@ -76,7 +77,9 @@ def handler(job: dict, handler_type: str) -> HandlerType:
     ).get(handler_type)
     if bool(_handler):
         return _handler(job)
-    return render_template("background-jobs/default-success-page.html", job=job)
+    _sui = "sui-" if request.args.get("streamlined_ui") else ""
+    return render_template(f"background-jobs/{_sui}default-success-page.html",
+                           job=job)
 
 
 error_handler = partial(handler, handler_type="error")
@@ -87,6 +90,7 @@ success_handler = partial(handler, handler_type="success")
 @require_login
 def job_status(job_id: uuid.UUID):
     """View the job status."""
+    _sui = "sui-" if request.args.get("streamlined_ui") else ""
     with sqlite3.connection(app.config["ASYNCHRONOUS_JOBS_SQLITE_DB"]) as conn:
         try:
             job = jobs.job(conn, job_id, fulldetails=True)
@@ -99,10 +103,10 @@ def job_status(job_id: uuid.UUID):
             if status == "completed":
                 return success_handler(job)
 
-            return render_template("jobs/job-status.html", job=job)
+            return render_template(f"jobs/{_sui}job-status.html", job=job)
         except JobNotFound as _jnf:
             return render_template(
-                "jobs/job-not-found.html",
+                f"jobs/{_sui}job-not-found.html",
                 job_id=job_id)
 
 
@@ -110,9 +114,10 @@ def job_status(job_id: uuid.UUID):
 @require_login
 def job_error(job_id: uuid.UUID):
     """Handle job errors in a generic manner."""
+    _sui = "sui-" if request.args.get("streamlined_ui") else ""
     with sqlite3.connection(app.config["ASYNCHRONOUS_JOBS_SQLITE_DB"]) as conn:
         try:
             job = jobs.job(conn, job_id, fulldetails=True)
-            return render_template("jobs/job-error.html", job=job)
+            return render_template(f"jobs/{_sui}job-error.html", job=job)
         except JobNotFound as _jnf:
-            return render_template("jobs/job-not-found.html", job_id=job_id)
+            return render_template(f"jobs/{_sui}job-not-found.html", job_id=job_id)
diff --git a/uploader/phenotypes/views.py b/uploader/phenotypes/views.py
index c4fd7fd..364fc79 100644
--- a/uploader/phenotypes/views.py
+++ b/uploader/phenotypes/views.py
@@ -513,7 +513,9 @@ def job_status(
             job = jobs.job(rconn, jobs.jobsnamespace(), str(job_id))
         except jobs.JobNotFound as _jnf:
             job = None
-        return render_template("phenotypes/job-status.html",
+
+        _sui = "sui-" if bool(request.args.get("streamlined_ui")) else ""
+        return render_template(f"phenotypes/{_sui}job-status.html",
                                species=species,
                                population=population,
                                dataset=dataset,
@@ -593,7 +595,8 @@ def review_job_data(
             for filetype,meta in metadata.items()
         }
         _job_metadata = json.loads(job["job-metadata"])
-        return render_template("phenotypes/review-job-data.html",
+        _sui = "sui-" if bool(request.args.get("streamlined_ui")) else ""
+        return render_template(f"phenotypes/{_sui}review-job-data.html",
                                species=species,
                                population=population,
                                dataset=dataset,
@@ -983,7 +986,8 @@ def load_data_success(
                               _publication["Authors"],
                               (_publication["Title"] or ""))
                              if item != "")
-            return render_template("phenotypes/load-phenotypes-success.html",
+            _sui="sui-" if request.args.get("streamlined_ui") else ""
+            return render_template(f"phenotypes/{_sui}load-phenotypes-success.html",
                                    species=species,
                                    population=population,
                                    dataset=dataset,
diff --git a/uploader/templates/background-jobs/sui-default-success-page.html b/uploader/templates/background-jobs/sui-default-success-page.html
new file mode 100644
index 0000000..5732456
--- /dev/null
+++ b/uploader/templates/background-jobs/sui-default-success-page.html
@@ -0,0 +1,17 @@
+{%extends "phenotypes/base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+
+{%block title%}Background Jobs: Success{%endblock%}
+
+{%block pagetitle%}Background Jobs: Success{%endblock%}
+
+{%block contents%}
+{{flash_all_messages()}}
+
+<div class="row">
+  <p>Job <strong>{{job.job_id}}</strong>,
+    {%if job.get("metadata", {}).get("job-type")%}
+    of type '<em>{{job.metadata["job-type"]}}</em>
+    {%endif%}' completed successfully.</p>
+</div>
+{%endblock%}
diff --git a/uploader/templates/jobs/sui-job-error.html b/uploader/templates/jobs/sui-job-error.html
new file mode 100644
index 0000000..1a839a6
--- /dev/null
+++ b/uploader/templates/jobs/sui-job-error.html
@@ -0,0 +1,17 @@
+{%extends "sui-base.html"%}
+
+{%from "flash_messages.html" import flash_all_messages%}
+
+{%block title%}Background Jobs: Error{%endblock%}
+
+{%block pagetitle%}Background Jobs: Error{%endblock%}
+
+{%block contents%}
+
+<h1>Background Jobs: Error</h1>
+<p>Job <strong>{{job["job_id"]}}</strong> failed!</p>
+<p>The error details are in the "STDERR" section below.</p>
+
+<h2>STDERR</h2>
+<pre>{{job["stderr"]}}</pre>
+{%endblock%}
diff --git a/uploader/templates/jobs/sui-job-not-found.html b/uploader/templates/jobs/sui-job-not-found.html
new file mode 100644
index 0000000..96c8586
--- /dev/null
+++ b/uploader/templates/jobs/sui-job-not-found.html
@@ -0,0 +1,11 @@
+{%extends "sui-base.html"%}
+
+{%from "flash_messages.html" import flash_all_messages%}
+
+{%block title%}Background Jobs{%endblock%}
+
+{%block pagetitle%}Background Jobs{%endblock%}
+
+{%block contents%}
+<p>Could not find job with ID: {{job_id}}</p>
+{%endblock%}
diff --git a/uploader/templates/jobs/sui-job-status.html b/uploader/templates/jobs/sui-job-status.html
new file mode 100644
index 0000000..fc5e532
--- /dev/null
+++ b/uploader/templates/jobs/sui-job-status.html
@@ -0,0 +1,24 @@
+{%extends "sui-base.html"%}
+
+{%from "flash_messages.html" import flash_all_messages%}
+
+{%block extrameta%}
+<meta http-equiv="refresh" content="5" />
+{%endblock%}
+
+{%block title%}Background Jobs{%endblock%}
+
+{%block pagetitle%}Background Jobs{%endblock%}
+
+{%block contents%}
+
+<p>Status: {{job["metadata"]["status"]}}</p>
+<p>Job Type: {{job["metadata"]["job-type"]}}</p>
+
+<h2>STDOUT</h2>
+<pre>{{job["stdout"]}}</pre>
+
+<h2>STDERR</h2>
+<pre>{{job["stderr"]}}</pre>
+
+{%endblock%}
diff --git a/uploader/templates/phenotypes/sui-job-status.html b/uploader/templates/phenotypes/sui-job-status.html
new file mode 100644
index 0000000..bca87d5
--- /dev/null
+++ b/uploader/templates/phenotypes/sui-job-status.html
@@ -0,0 +1,140 @@
+{%extends "phenotypes/sui-base.html"%}
+{%from "cli-output.html" import cli_output%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "macro-table-pagination.html" import table_pagination%}
+
+{%block extrameta%}
+{%if job and job.status not in ("success", "completed:success", "error", "completed:error")%}
+<meta http-equiv="refresh" content="5" />
+{%endif%}
+{%endblock%}
+
+{%block title%}Phenotypes{%endblock%}
+
+{%block pagetitle%}Phenotypes{%endblock%}
+
+{%block contents%}
+
+{%if job%}
+<div class="row">
+  <h2 class="heading">{{dataset.FullName}} ({{dataset.Name}})</h2>
+  <h3 class="subheading">upload progress</h3>
+</div>
+<div class="row" style="overflow:scroll;">
+  <p><strong>Process Status:</strong> {{job.status}}</p>
+  {%if metadata%}
+  <table class="table table-responsive">
+    <thead>
+      <tr>
+        <th>File</th>
+        <th>Status</th>
+        <th>Lines Processed</th>
+        <th>Total Errors</th>
+      </tr>
+    </thead>
+
+    <tbody>
+      {%for file,meta in metadata.items()%}
+      <tr>
+        <td>{{file}}</td>
+        <td>{{meta.status}}</td>
+        <td>{{meta.linecount}}</td>
+        <td>{{meta["total-errors"]}}</td>
+      </tr>
+      {%endfor%}
+    </tbody>
+  </table>
+  {%endif%}
+</div>
+
+<div class="row">
+  {%if  job.status in ("completed:success", "success")%}
+  <p>
+    {%if errors | length == 0%}
+    <a href="{{url_for('species.populations.phenotypes.review_job_data',
+           species_id=species.SpeciesId,
+           population_id=population.Id,
+           dataset_id=dataset.Id,
+           job_id=job_id)}}"
+       class="btn btn-primary"
+       title="Continue to process data">Continue</a>
+    {%else%}
+    <span class="text-muted"
+          disabled="disabled"
+          style="border: solid 2px;border-radius: 5px;padding: 0.3em;">
+      Cannot continue due to errors. Please fix the errors first.
+    </span>
+    {%endif%}
+  </p>
+  {%endif%}
+</div>
+
+<h3 class="subheading">upload errors</h3>
+<div class="row" style="max-height: 20em; overflow: scroll;">
+  {%if errors | length == 0 %}
+  <p class="text-info">
+    <span class="glyphicon glyphicon-info-sign"></span>
+    No errors found so far
+  </p>
+  {%else%}
+  <table class="table table-responsive">
+    <thead style="position: sticky; top: 0; background: white;">
+      <tr>
+        <th>File</th>
+        <th>Row</th>
+        <th>Column</th>
+        <th>Value</th>
+        <th>Message</th>
+      </tr>
+    </thead>
+
+    <tbody style="font-size: 0.9em;">
+      {%for error in errors%}
+      <tr>
+        <td>{{error.filename}}</td>
+        <td>{{error.rowtitle}}</td>
+        <td>{{error.coltitle}}</td>
+        <td>{%if error.cellvalue is not none and error.cellvalue | length > 25%}
+          {{error.cellvalue[0:24]}}&hellip;
+          {%else%}
+          {{error.cellvalue}}
+          {%endif%}
+        </td>
+        <td>
+          {%if error.message | length > 250 %}
+          {{error.message[0:249]}}&hellip;
+          {%else%}
+          {{error.message}}
+          {%endif%}
+        </td>
+      </tr>
+      {%endfor%}
+    </tbody>
+  </table>
+  {%endif%}
+</div>
+
+<div class="row">
+  {{cli_output(job, "stdout")}}
+</div>
+
+<div class="row">
+  {{cli_output(job, "stderr")}}
+</div>
+
+{%else%}
+<div class="row">
+  <h3 class="text-danger">No Such Job</h3>
+  <p>Could not find a job with the ID: {{job_id}}</p>
+  <p>
+    Please go back to
+    <a href="{{url_for('species.populations.phenotypes.view_dataset',
+             species_id=species.SpeciesId,
+             population_id=population.Id,
+             dataset_id=dataset.Id)}}"
+       title="'{{dataset.Name}}' dataset page">
+      the '{{dataset.Name}}' dataset page</a>
+    to upload new phenotypes or edit existing ones.</p>
+</div>
+{%endif%}
+{%endblock%}
diff --git a/uploader/templates/phenotypes/sui-load-phenotypes-success.html b/uploader/templates/phenotypes/sui-load-phenotypes-success.html
new file mode 100644
index 0000000..dff0682
--- /dev/null
+++ b/uploader/templates/phenotypes/sui-load-phenotypes-success.html
@@ -0,0 +1,26 @@
+{%extends "phenotypes/sui-base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "macro-table-pagination.html" import table_pagination%}
+
+{%block title%}Phenotypes{%endblock%}
+
+{%block pagetitle%}Phenotypes{%endblock%}
+
+{%block contents%}
+{{super()}}
+
+<div class="row">
+  <p>You have successfully loaded
+    <!-- maybe indicate the number of phenotypes here? -->your
+    new phenotypes into the database.</p>
+  <!-- TODO: Maybe notify user that they have sole access. -->
+  <!-- TODO: Maybe provide a link to go to GeneNetwork to view the data. -->
+  <p>View your data
+    <a href="{{search_page_uri}}"
+       target="_blank">on GeneNetwork2</a>.
+    You might need to login to GeneNetwork2 to view specific traits.</p>
+</div>
+{%endblock%}
+
+
+{%block more_javascript%}{%endblock%}
diff --git a/uploader/templates/phenotypes/sui-review-job-data.html b/uploader/templates/phenotypes/sui-review-job-data.html
new file mode 100644
index 0000000..ea4183d
--- /dev/null
+++ b/uploader/templates/phenotypes/sui-review-job-data.html
@@ -0,0 +1,121 @@
+{%extends "phenotypes/sui-base.html"%}
+{%from "cli-output.html" import cli_output%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "macro-table-pagination.html" import table_pagination%}
+{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%}
+
+{%block extrameta%}
+{%if not job%}
+<meta http-equiv="refresh"
+      content="20; url={{url_for('species.populations.phenotypes.view_dataset', species_id=species.SpeciesId,
+               population_id=population.Id,
+               dataset_id=dataset.Id)}}" />
+{%endif%}
+{%endblock%}
+
+{%block title%}Phenotypes{%endblock%}
+
+{%block pagetitle%}Phenotypes{%endblock%}
+
+{%block lvl4_breadcrumbs%}
+<li {%if activelink=="add-phenotypes"%}
+    class="breadcrumb-item active"
+    {%else%}
+    class="breadcrumb-item"
+    {%endif%}>
+  <a href="{{url_for('species.populations.phenotypes.add_phenotypes',
+           species_id=species.SpeciesId,
+           population_id=population.Id,
+           dataset_id=dataset.Id)}}">View Datasets</a>
+</li>
+{%endblock%}
+
+{%block contents%}
+
+{%if job%}
+<div class="row">
+  <h3 class="heading">Data Review</h3>
+  <p class="text-info"><strong>
+      The data has <em>NOT</em> been added/saved yet. Review the details below
+      and click "Continue" to save the data.</strong></p>
+  <p>The &#x201C;<strong>{{dataset.FullName}}</strong>&#x201D; dataset from the
+    &#x201C;<strong>{{population.FullName}}</strong>&#x201D; population of the
+    species &#x201C;<strong>{{species.SpeciesName}} ({{species.FullName}})</strong>&#x201D;
+    will be updated as follows:</p>
+
+  <ul>
+    {%if publication%}
+    <li>All {{summary.get("pheno", {}).get("total-data-rows", "0")}} phenotypes
+      are linked to the following publication:
+      <ul>
+        <li><strong>Publication Title:</strong>
+          {{publication.Title or "—"}}</li>
+        <li><strong>Author(s):</strong>
+          {{publication.Authors or "—"}}</li>
+      </ul>
+    </li>
+    {%endif%}
+  {%for ftype in ("phenocovar", "pheno", "phenose", "phenonum")%}
+  {%if summary.get(ftype, False)%}
+    <li>A total of {{summary[ftype]["number-of-files"]}} files will be processed
+      adding {%if ftype == "phenocovar"%}(possibly){%endif%}
+      {{summary[ftype]["total-data-rows"]}} new
+      {%if ftype == "phenocovar"%}
+      phenotypes
+      {%else%}
+      {{summary[ftype]["description"]}} rows
+      {%endif%}
+      to the database.
+    </li>
+  {%endif%}
+  {%endfor%}
+  </ul>
+
+  <form id="frm-review-phenotype-data"
+        method="POST"
+        action="{{url_for('species.populations.phenotypes.load_data_to_database',
+                species_id=species.SpeciesId,
+                population_id=population.Id,
+                dataset_id=dataset.Id)}}">
+    <input type="hidden" name="data-qc-job-id" value="{{job.jobid}}" />
+    <input type="submit"
+           value="continue"
+           class="btn btn-primary" />
+  </form>
+</div>
+{%else%}
+<div class="row">
+  <h4 class="subheading">Invalid Job</h3>
+  <p class="text-danger">
+    Could not find a job with the ID: <strong>{{job_id}}.</p>
+  <p>You will be redirected in
+    <span id="countdown-element" class="text-info">20</span> second(s)</p>
+  <p class="text-muted">
+    <small>
+      If you are not redirected, please
+      <a href="{{url_for(
+               'species.populations.phenotypes.view_dataset',
+               species_id=species.SpeciesId,
+               population_id=population.Id,
+               dataset_id=dataset.Id)}}">click here</a> to continue
+    </small>
+  </p>
+</div>
+{%endif%}
+{%endblock%}
+
+
+{%block javascript%}
+<script type="text/javascript">
+  $(document).ready(function() {
+      var countdown = 20;
+      var countdown_element = $("#countdown-element");
+      if(countdown_element.length === 1) {
+          intv = window.setInterval(function() {
+              countdown = countdown - 1;
+              countdown_element.html(countdown);
+          }, 1000);
+      }
+  });
+</script>
+{%endblock%}