diff options
author | Frederick Muriuki Muriithi | 2024-07-25 11:07:33 -0500 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2024-07-25 14:34:09 -0500 |
commit | 754e8f214b940e05298cb360ed829f5c685d55a5 (patch) | |
tree | 62c2c5b601746621f0949b38937ad232f006dee2 /uploader/templates | |
parent | de9e1b9fe37928b864bea28b408de6c14d04526b (diff) | |
download | gn-uploader-754e8f214b940e05298cb360ed829f5c685d55a5.tar.gz |
Rename module: qc_app --> uploader
Diffstat (limited to 'uploader/templates')
54 files changed, 3348 insertions, 0 deletions
diff --git a/uploader/templates/base.html b/uploader/templates/base.html new file mode 100644 index 0000000..eb5e6b7 --- /dev/null +++ b/uploader/templates/base.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta application-name="GeneNetwork Quality-Control Application" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + {%block extrameta%}{%endblock%} + + <title>GN Uploader: {%block title%}{%endblock%}</title> + + <link rel="stylesheet" type="text/css" + href="{{url_for('base.bootstrap', + filename='css/bootstrap.min.css')}}" /> + <link rel="stylesheet" type="text/css" + href="{{url_for('base.bootstrap', + filename='css/bootstrap-theme.min.css')}}" /> + + + <link rel="shortcut icon" type="image/png" sizes="64x64" + href="{{url_for('static', filename='images/CITGLogo.png')}}" /> + + <link rel="stylesheet" type="text/css" href="/static/css/custom-bootstrap.css" /> + <link rel="stylesheet" type="text/css" href="/static/css/styles.css" /> + + {%block css%}{%endblock%} + </head> + + <body> + <div class="navbar navbar-inverse navbar-static-top pull-left" + role="navigation" + style="width: 100%;min-width: 850px;white-space: nowrap;"> + <div class="container-fluid" style="width: 100%"> + <ul class="nav navbar-nav"> + <li><a href="/" style="font-weight: bold">GN Uploader</a></li> + <li> + <a href="{{gnuri or 'https://genenetwork.org'}}">GeneNetwork</a> + </li> + </ul> + </div> + </div> + <div class="container"> + {%block contents%}{%endblock%} + </div> + + <script src="{{url_for('base.jquery', + filename='jquery.min.js')}}"></script> + <script src="{{url_for('base.bootstrap', + filename='js/bootstrap.min.js')}}"></script> + {%block javascript%}{%endblock%} + </body> +</html> diff --git a/uploader/templates/cli-output.html b/uploader/templates/cli-output.html new file mode 100644 index 0000000..33fb73b --- /dev/null +++ b/uploader/templates/cli-output.html @@ -0,0 +1,8 @@ +{%macro cli_output(job, stream)%} + +<h4>{{stream | upper}} Output</h4> +<div class="cli-output"> + <pre>{{job.get(stream, "")}}</pre> +</div> + +{%endmacro%} diff --git a/uploader/templates/continue_from_create_dataset.html b/uploader/templates/continue_from_create_dataset.html new file mode 100644 index 0000000..03bb49c --- /dev/null +++ b/uploader/templates/continue_from_create_dataset.html @@ -0,0 +1,52 @@ +{%extends "base.html"%} +{%from "dbupdate_hidden_fields.html" import hidden_fields%} + +{%block title%}Create Study{%endblock%} + +{%block css%} +<link rel="stylesheet" href="/static/css/two-column-with-separator.css" /> +{%endblock%} + +{%block contents%} +<h2 class="heading">{{filename}}: create study</h2> + +{%with messages = get_flashed_messages(with_categories=true)%} +{%if messages:%} +<ul> + {%for category, message in messages:%} + <li class="{{category}}">{{message}}</li> + {%endfor%} +</ul> +{%endif%} +{%endwith%} + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.final_confirmation')}}" + id="select-platform-form" data-genechips="{{genechips_data}}" + class="two-col-sep-col1"> + <legend>continue with new dataset</legend> + {{hidden_fields( + filename, filetype, species=species, genechipid=genechipid, + studyid=studyid, datasetid=datasetid, totallines=totallines)}} + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +<div class="row"> + <p class="two-col-sep-separator">OR</p> +</div> + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.select_dataset')}}" + id="select-platform-form" data-genechips="{{genechips_data}}" + class="two-col-sep-col2"> + <legend>Select from existing dataset</legend> + {{hidden_fields( + filename, filetype, species=species, genechipid=genechipid, + studyid=studyid, datasetid=datasetid, totallines=totallines)}} + + <button type="submit" class="btn btn-primary">go back</button> + </form> +</div> +{%endblock%} diff --git a/uploader/templates/continue_from_create_study.html b/uploader/templates/continue_from_create_study.html new file mode 100644 index 0000000..34e6e5e --- /dev/null +++ b/uploader/templates/continue_from_create_study.html @@ -0,0 +1,52 @@ +{%extends "base.html"%} +{%from "dbupdate_hidden_fields.html" import hidden_fields%} + +{%block title%}Create Study{%endblock%} + +{%block css%} +<link rel="stylesheet" href="/static/css/two-column-with-separator.css" /> +{%endblock%} + +{%block contents%} +<h2 class="heading">{{filename}}: create study</h2> + +{%with messages = get_flashed_messages(with_categories=true)%} +{%if messages:%} +<ul> + {%for category, message in messages:%} + <li class="{{category}}">{{message}}</li> + {%endfor%} +</ul> +{%endif%} +{%endwith%} + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.select_dataset')}}" + id="select-platform-form" data-genechips="{{genechips_data}}" + class="two-col-sep-col1"> + <legend>continue with new study</legend> + {{hidden_fields( + filename, filetype, species=species, genechipid=genechipid, + studyid=studyid, totallines=totallines)}} + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +<div class="row"> + <p class="two-col-sep-separator">OR</p> +</div> + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.select_study')}}" + id="select-platform-form" data-genechips="{{genechips_data}}" + class="two-col-sep-col2"> + <legend>Select from existing study</legend> + {{hidden_fields( + filename, filetype, species=species, genechipid=genechipid, + studyid=studyid, totallines=totallines)}} + + <button type="submit" class="btn btn-primary">go back</button> + </form> +</div> +{%endblock%} diff --git a/uploader/templates/data_review.html b/uploader/templates/data_review.html new file mode 100644 index 0000000..b7528fd --- /dev/null +++ b/uploader/templates/data_review.html @@ -0,0 +1,85 @@ +{%extends "base.html"%} + +{%block title%}Data Review{%endblock%} + +{%block contents%} +<h1 class="heading">data review</h1> + +<div class="row"> + <h2 id="data-concerns">Data Concerns</h2> + <p>The following are some of the requirements that the data in your file + <strong>MUST</strong> fulfil before it is considered valid for this system: + </p> + + <ol> + <li>File headings + <ul> + <li>The first row in the file should contains the headings. The number of + headings in this first row determines the number of columns expected for + all other lines in the file.</li> + <li>Each heading value in the first row MUST appear in the first row + <strong>ONE AND ONLY ONE</strong> time</li> + <li>The sample/cases (previously 'strains') headers in your first row will be + against those in the <a href="https://genenetwork.org" + title="Link to the GeneNetwork service"> + GeneNetwork</a> database.<br /> + <small class="text-muted"> + If you encounter an error saying your sample(s)/case(s) do not exist + in the GeneNetwork database, then you will have to use the + <a href="{{url_for('samples.select_species')}}" + title="Upload samples/cases feature">Upload Samples/Cases</a> + option on this system to upload them. + </small> + </ul> + </li> + + <li>Data + <ol> + <li><strong>NONE</strong> of the data cells/fields is allowed to be empty. + All fields/cells <strong>MUST</strong> contain a value.</li> + <li>The first column of the data rows will be considered a textual field, + holding the "identifier" for that row<li> + <li>Except for the first column/field for each data row, + <strong>NONE</strong> of the data columns/cells/fields should contain + spurious characters like `eeeee`, `5.555iloveguix`, etc...<br /> + All of them should be decimal values</li> + <li>decimal numbers must conform to the following criteria: + <ul> + <li>when checking an average file decimal numbers must have exactly three + decimal places to the right of the decimal point.</li> + <li>when checking a standard error file decimal numbers must have six or + greater decimal places to the right of the decimal point.</li> + <li>there must be a number to the left side of the decimal place + (e.g. 0.55555 is allowed but .55555 is not).</li> + </ul> + </li> + </ol> + </li> + </ol> +</div> + + +<div class="row"> + <h2 id="file-types">Supported File Types</h2> + We support the following file types: + + <ul> + <li>Tab-Separated value files (.tsv) + <ul> + <li>The <strong>TAB</strong> character is used to separate the fields of each + column</li> + <li>The values of each field <strong>ARE NOT</strong> quoted.</li> + <li>Here is an + <a href="https://gitlab.com/fredmanglis/gnqc_py/-/blob/main/tests/test_data/no_data_errors.tsv"> + example file</a> with a single data row.</li> + </ul> + </li> + <li>.txt files: Content has the same format as .tsv file above</li> + <li>.zip files: each zip file should contain + <strong>ONE AND ONLY ONE</strong> file of the .tsv or .txt type above. + <br />Any zip file with more than one file is invalid, and so is an empty + zip file.</li> + </ul> + +</div> +{%endblock%} diff --git a/uploader/templates/dbupdate_error.html b/uploader/templates/dbupdate_error.html new file mode 100644 index 0000000..e1359d2 --- /dev/null +++ b/uploader/templates/dbupdate_error.html @@ -0,0 +1,12 @@ +{%extends "base.html"%} + +{%block title%}DB Update Error{%endblock%} + +{%block contents%} +<h1 class="heading">database update error</h2> + +<p class="alert-danger"> + <strong>Database Update Error</strong>: {{error_message}} +</p> + +{%endblock%} diff --git a/uploader/templates/dbupdate_hidden_fields.html b/uploader/templates/dbupdate_hidden_fields.html new file mode 100644 index 0000000..ccbc299 --- /dev/null +++ b/uploader/templates/dbupdate_hidden_fields.html @@ -0,0 +1,29 @@ +{%macro hidden_fields(filename, filetype):%} + +<!-- {{kwargs}}: mostly for accessing the kwargs in macro --> + +<input type="hidden" name="filename" value="{{filename}}" /> +<input type="hidden" name="filetype" value="{{filetype}}" /> +{%if kwargs.get("totallines")%} +<input type="hidden" name="totallines" value="{{kwargs['totallines']}}" /> +{%endif%} +{%if kwargs.get("species"):%} +<input type="hidden" name="species" value="{{kwargs['species']}}" /> +{%endif%} +{%if kwargs.get("genechipid"):%} +<input type="hidden" name="genechipid" value="{{kwargs['genechipid']}}" /> +{%endif%} +{%if kwargs.get("inbredsetid"):%} +<input type="hidden" name="inbredsetid" value="{{kwargs['inbredsetid']}}" /> +{%endif%} +{%if kwargs.get("tissueid"):%} +<input type="hidden" name="tissueid" value="{{kwargs['tissueid']}}" /> +{%endif%} +{%if kwargs.get("studyid"):%} +<input type="hidden" name="studyid" value="{{kwargs['studyid']}}" /> +{%endif%} +{%if kwargs.get("datasetid"):%} +<input type="hidden" name="datasetid" value="{{kwargs['datasetid']}}" /> +{%endif%} + +{%endmacro%} diff --git a/uploader/templates/errors_display.html b/uploader/templates/errors_display.html new file mode 100644 index 0000000..715cfcf --- /dev/null +++ b/uploader/templates/errors_display.html @@ -0,0 +1,47 @@ +{%macro errors_display(errors, no_error_msg, error_message, complete)%} + +{%if errors | length == 0 %} +<span {%if complete%}class="alert-success"{%endif%}>{{no_error_msg}}</span> +{%else %} +<p class="alert-danger">{{error_message}}</p> + +<table class="table reports-table"> + <thead> + <tr> + <th>line number</th> + <th>column(s)</th> + <th>error</th> + <th>error message</th> + </tr> + </thead> + + <tbody> + {%for error in errors%} + <tr> + <td>{{error["line"]}}</td> + <td> + {%if isinvalidvalue(error):%} + {{error.column}} + {%elif isduplicateheading(error): %} + {{error.columns}} + {%else: %} + - + {%endif %} + </td> + <td> + {%if isinvalidvalue(error):%} + Invalid Value + {%elif isduplicateheading(error): %} + Duplicate Header + {%else%} + Inconsistent Columns + {%endif %} + </td> + <td>{{error["message"]}}</td> + </tr> + {%endfor%} + </tbody> +</table> +{%endif%} + +{%endmacro%} diff --git a/uploader/templates/final_confirmation.html b/uploader/templates/final_confirmation.html new file mode 100644 index 0000000..0727fc8 --- /dev/null +++ b/uploader/templates/final_confirmation.html @@ -0,0 +1,47 @@ +{%extends "base.html"%} +{%from "dbupdate_hidden_fields.html" import hidden_fields%} + +{%block title%}Confirmation{%endblock%} + +{%macro display_item(item_name, item_data):%} +<li> + <strong>{{item_name}}</strong> + {%if item_data%} + <ul> + {%for term,value in item_data.items():%} + <li><strong>{{term}}:</strong> {{value}}</li> + {%endfor%} + </ul> + {%endif%} +</li> +{%endmacro%} + +{%block contents%} +<h2 class="heading">Final Confirmation</h2> + +<div class="two-col-sep-col1"> + <p><strong>Selected Data</strong></p> + <ul> + <li><strong>File</strong> + <ul> + <li><strong>Filename</strong>: {{filename}}</li> + <li><strong>File Type</strong>: {{filetype}}</li> + </ul> + </li> + {{display_item("Species", the_species)}} + {{display_item("Platform", platform)}} + {{display_item("Study", study)}} + {{display_item("Dataset", dataset)}} + </ul> +</div> + +<form method="POST" action="{{url_for('dbinsert.insert_data')}}"> + {{hidden_fields( + filename, filetype, species=species, genechipid=genechipid, + studyid=studyid,datasetid=datasetid, totallines=totallines)}} + <fieldset> + <input type="submit" class="btn btn-primary" value="confirm" /> + </fieldset> +</form> +</div> +{%endblock%} diff --git a/uploader/templates/flash_messages.html b/uploader/templates/flash_messages.html new file mode 100644 index 0000000..b7af178 --- /dev/null +++ b/uploader/templates/flash_messages.html @@ -0,0 +1,25 @@ +{%macro flash_all_messages()%} +{%with messages = get_flashed_messages(with_categories=true)%} +{%if messages:%} +<ul> + {%for category, message in messages:%} + <li class="{{category}}">{{message}}</li> + {%endfor%} +</ul> +{%endif%} +{%endwith%} +{%endmacro%} + +{%macro flash_messages(filter_class)%} +{%with messages = get_flashed_messages(with_categories=true)%} +{%if messages:%} +<ul> + {%for category, message in messages:%} + {%if filter_class in category%} + <li class="{{category}}">{{message}}</li> + {%endif%} + {%endfor%} +</ul> +{%endif%} +{%endwith%} +{%endmacro%} diff --git a/uploader/templates/http-error.html b/uploader/templates/http-error.html new file mode 100644 index 0000000..374fb86 --- /dev/null +++ b/uploader/templates/http-error.html @@ -0,0 +1,18 @@ +{%extends "base.html"%} + +{%block title%}HTTP Error: {{exc.code}}{%endblock%} + +{%block contents%} +<h1>{{exc.code}}: {{exc.description}}</h1> + +<div class="row"> + <p> + You attempted to access {{request_url}} which failed with the following + error: + </p> +</div> + +<div class="row"> + <pre>{{"\n".join(trace)}}</pre> +</div> +{%endblock%} diff --git a/uploader/templates/index.html b/uploader/templates/index.html new file mode 100644 index 0000000..89d2ae9 --- /dev/null +++ b/uploader/templates/index.html @@ -0,0 +1,81 @@ +{%extends "base.html"%} + +{%block title%}Data Upload{%endblock%} + +{%block contents%} +<div class="row"> + <h1 class="heading">data upload</h1> + + <div class="explainer"> + <p>Each of the sections below gives you a different option for data upload. + Please read the documentation for each section carefully to understand what + each section is about.</p> + </div> +</div> + +<div class="row"> + <h2 class="heading">R/qtl2 Bundles</h2> + + <div class="explainer"> + <p>This feature combines and extends the two upload methods below. Instead of + uploading one item at a time, the R/qtl2 bundle you upload can contain both + the genotypes data (samples/individuals/cases and their data) and the + expression data.</p> + <p>The R/qtl2 bundle, additionally, can contain extra metadata, that neither + of the methods below can handle.</p> + + <a href="{{url_for('upload.rqtl2.select_species')}}" + title="Upload a zip bundle of R/qtl2 files"> + <button class="btn btn-primary">upload R/qtl2 bundle</button></a> + </div> +</div> + + +<div class="row"> + <h2 class="heading">Expression Data</h2> + + <div class="explainer"> + <p>This feature enables you to upload expression data. It expects the data to + be in <strong>tab-separated values (TSV)</strong> files. The data should be + a simple matrix of <em>phenotype × sample</em>, i.e. The first column is a + list of the <em>phenotypes</em> and the first row is a list of + <em>samples/cases</em>.</p> + + <p>If you haven't done so please go to this page to learn the requirements for + file formats and helpful suggestions to enter your data in a fast and easy + way.</p> + + <ol> + <li><strong>PLEASE REVIEW YOUR DATA.</strong>Make sure your data complies + with our system requirements. ( + <a href="{{url_for('entry.data_review')}}#data-concerns" + title="Details for the data expectations.">Help</a> + )</li> + <li><strong>UPLOAD YOUR DATA FOR DATA VERIFICATION.</strong> We accept + <strong>.csv</strong>, <strong>.txt</strong> and <strong>.zip</strong> + files (<a href="{{url_for('entry.data_review')}}#file-types" + title="Details for the data expectations.">Help</a>)</li> + </ol> + </div> + + <a href="{{url_for('entry.upload_file')}}" + title="Upload your expression data" + class="btn btn-primary">upload expression data</a> +</div> + +<div class="row"> + <h2 class="heading">samples/cases</h2> + + <div class="explainer"> + <p>For the expression data above, you need the samples/cases in your file to + already exist in the GeneNetwork database. If there are any samples that do + not already exist the upload of the expression data will fail.</p> + <p>This section gives you the opportunity to upload any missing samples</p> + </div> + + <a href="{{url_for('samples.select_species')}}" + title="Upload samples/cases/individuals for your data" + class="btn btn-primary">upload Samples/Cases</a> +</div> + +{%endblock%} diff --git a/uploader/templates/insert_error.html b/uploader/templates/insert_error.html new file mode 100644 index 0000000..5301288 --- /dev/null +++ b/uploader/templates/insert_error.html @@ -0,0 +1,32 @@ +{%extends "base.html"%} + +{%block title%}Data Insertion Failure{%endblock%} + +{%block contents%} +<h1 class="heading">Insertion Failure</h1> + +<div class="row"> + <p> + There was an error inserting data into the database + </p> + + <p> + Please notify the developers of this issue when you encounter it, + providing the information below. + </p> + + <h4>Debugging Information</h4> + + <ul> + <li><strong>job id</strong>: {{job["jobid"]}}</li> + </ul> +</div> + +<div class="row"> + <h4>STDERR Output</h4> + <pre class="cli-output"> + {{job["stderr"]}} + </pre> +</div> + +{%endblock%} diff --git a/uploader/templates/insert_progress.html b/uploader/templates/insert_progress.html new file mode 100644 index 0000000..52177d6 --- /dev/null +++ b/uploader/templates/insert_progress.html @@ -0,0 +1,46 @@ +{%extends "base.html"%} +{%from "stdout_output.html" import stdout_output%} + +{%block extrameta%} +<meta http-equiv="refresh" content="5"> +{%endblock%} + +{%block title%}Job Status{%endblock%} + +{%block contents%} +<h1 class="heading">{{job_name}}</h1> + +<div class="row"> + <form> + <div class="form-group"> + <label for="job_status" class="form-label">status:</label> + <span class="form-text">{{job_status}}: {{message}}</span> + </div> + +{%if job.get("stdout", "").split("\n\n") | length < 3 %} +{%set lines = 0%} +{%else%} +{%set lines = (job.get("stdout", "").split("\n\n") | length / 3) %} +{%endif%} +{%set totallines = job.get("totallines", lines+3) | int %} +{%if totallines > 1000 %} +{%set fraction = ((lines*1000)/totallines) %} +{%else%} +{%set fraction = (lines/totallines)%} +{%endif%} + + <div class="form-group"> + <label for="job_{{job_id}}" class="form-label">inserting: </label> + <progress id="jobs_{{job_id}}" + value="{{(fraction)}}" + class="form-control">{{fraction*100}}</progress> + <span class="form-text text-muted"> + {{"%.2f" | format(fraction * 100 | float)}}%</span> + </div> + </form> +</div> + + +{{stdout_output(job)}} + +{%endblock%} diff --git a/uploader/templates/insert_success.html b/uploader/templates/insert_success.html new file mode 100644 index 0000000..7e1fa8d --- /dev/null +++ b/uploader/templates/insert_success.html @@ -0,0 +1,19 @@ +{%extends "base.html"%} +{%from "stdout_output.html" import stdout_output%} + +{%block title%}Insertion Success{%endblock%} + +{%block contents%} +<h1 class="heading">Insertion Success</h1> + +<div class="row"> +<p>Data inserted successfully!</p> + +<p>The following queries were run:</p> +</div> + +<div class="row"> + {{stdout_output(job)}} +</div> + +{%endblock%} diff --git a/uploader/templates/job_progress.html b/uploader/templates/job_progress.html new file mode 100644 index 0000000..1af0763 --- /dev/null +++ b/uploader/templates/job_progress.html @@ -0,0 +1,40 @@ +{%extends "base.html"%} +{%from "errors_display.html" import errors_display%} + +{%block extrameta%} +<meta http-equiv="refresh" content="5"> +{%endblock%} + +{%block title%}Job Status{%endblock%} + +{%block contents%} +<h1 class="heading">{{job_name}}</h2> + +<div class="row"> + <form action="{{url_for('parse.abort')}}" method="POST"> + <legend class="heading">Status</legend> + <div class="form-group"> + <label for="job_status" class="form-label">status:</label> + <span class="form-text">{{job_status}}: {{message}}</span><br /> + </div> + + <div class="form-group"> + <label for="job_{{job_id}}" class="form-label">parsing: </label> + <progress id="job_{{job_id}}" + value="{{progress/100}}" + class="form-control"> + {{progress}}</progress> + <span class="form-text text-muted">{{"%.2f" | format(progress)}}%</span> + </div> + + <input type="hidden" name="job_id" value="{{job_id}}" /> + + <button type="submit" class="btn btn-danger">Abort</button> + </form> +</div> + +<div class="row"> + {{errors_display(errors, "No errors found so far", "We have found the following errors so far", False)}} +</div> + +{%endblock%} diff --git a/uploader/templates/no_such_job.html b/uploader/templates/no_such_job.html new file mode 100644 index 0000000..42a2d48 --- /dev/null +++ b/uploader/templates/no_such_job.html @@ -0,0 +1,14 @@ +{%extends "base.html"%} + +{%block extrameta%} +<meta http-equiv="refresh" content="5;url={{url_for('entry.upload_file')}}"> +{%endblock%} + +{%block title%}No Such Job{%endblock%} + +{%block contents%} +<h1 class="heading">No Such Job: {{job_id}}</h2> + +<p>No job, with the id '<em>{{job_id}}</em>' was found!</p> + +{%endblock%} diff --git a/uploader/templates/parse_failure.html b/uploader/templates/parse_failure.html new file mode 100644 index 0000000..31f6be8 --- /dev/null +++ b/uploader/templates/parse_failure.html @@ -0,0 +1,26 @@ +{%extends "base.html"%} + +{%block title%}Worker Failure{%endblock%} + +{%block contents%} +<h1 class="heading">Worker Failure</h1> + +<p> + There was an error while parsing your file. +</p> + +<p> + Please notify the developers of this issue when you encounter it, + providing the information below. +</p> + +<h4>Debugging Information</h4> + +<ul> + <li><strong>job id</strong>: {{job["job_id"]}}</li> + <li><strong>filename</strong>: {{job["filename"]}}</li> + <li><strong>line number</strong>: {{job["line_number"]}}</li> + <li><strong>Progress</strong>: {{job["percent"]}} %</li> +</ul> + +{%endblock%} diff --git a/uploader/templates/parse_results.html b/uploader/templates/parse_results.html new file mode 100644 index 0000000..e2bf7f0 --- /dev/null +++ b/uploader/templates/parse_results.html @@ -0,0 +1,30 @@ +{%extends "base.html"%} +{%from "errors_display.html" import errors_display%} + +{%block title%}Parse Results{%endblock%} + +{%block contents%} +<h1 class="heading">{{job_name}}: parse results</h2> + +{%if user_aborted%} +<span class="alert-warning">Job aborted by the user</span> +{%endif%} + +{{errors_display(errors, "No errors found in the file", "We found the following errors", True)}} + +{%if errors | length == 0 and not user_aborted %} +<form method="post" action="{{url_for('dbinsert.select_platform')}}"> + <input type="hidden" name="job_id" value="{{job_id}}" /> + <input type="submit" value="update database" class="btn btn-primary" /> +</form> +{%endif%} + +{%if errors | length > 0 or user_aborted %} +<br /> +<a href="{{url_for('entry.upload_file')}}" title="Back to index page." + class="btn btn-primary"> + Go back +</a> +{%endif%} + +{%endblock%} diff --git a/uploader/templates/rqtl2/create-geno-dataset-success.html b/uploader/templates/rqtl2/create-geno-dataset-success.html new file mode 100644 index 0000000..1b50221 --- /dev/null +++ b/uploader/templates/rqtl2/create-geno-dataset-success.html @@ -0,0 +1,55 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Select Genotypes Dataset</h2> + +<div class="explainer"> + <p>You successfully created the genotype dataset with the following + information. + <dl> + <dt>ID</dt> + <dd>{{geno_dataset.id}}</dd> + + <dt>Name</dt> + <dd>{{geno_dataset.name}}</dd> + + <dt>Full Name</dt> + <dd>{{geno_dataset.fname}}</dd> + + <dt>Short Name</dt> + <dd>{{geno_dataset.sname}}</dd> + + <dt>Created On</dt> + <dd>{{geno_dataset.today}}</dd> + + <dt>Public?</dt> + <dd>{%if geno_dataset.public == 0%}No{%else%}Yes{%endif%}</dd> + </dl> + </p> +</div> + +<div class="row"> + <form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.select_dataset_info', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + <legend class="heading">select from existing genotype datasets</legend> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" + value="{{geno_dataset.id}}" /> + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/create-probe-dataset-success.html b/uploader/templates/rqtl2/create-probe-dataset-success.html new file mode 100644 index 0000000..790d174 --- /dev/null +++ b/uploader/templates/rqtl2/create-probe-dataset-success.html @@ -0,0 +1,59 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Create ProbeSet Dataset</h2> + +<div class="row"> + <p>You successfully created the ProbeSet dataset with the following + information. + <dl> + <dt>Averaging Method</dt> + <dd>{{avgmethod.Name}}</dd> + + <dt>ID</dt> + <dd>{{dataset.datasetid}}</dd> + + <dt>Name</dt> + <dd>{{dataset.name2}}</dd> + + <dt>Full Name</dt> + <dd>{{dataset.fname}}</dd> + + <dt>Short Name</dt> + <dd>{{dataset.sname}}</dd> + + <dt>Created On</dt> + <dd>{{dataset.today}}</dd> + + <dt>DataScale</dt> + <dd>{{dataset.datascale}}</dd> + </dl> + </p> +</div> + +<div class="row"> + <form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.select_dataset_info', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + <legend class="heading">Create ProbeSet dataset</legend> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="tissueid" value="{{tissue.Id}}" /> + <input type="hidden" name="probe-study-id" value="{{study.Id}}" /> + <input type="hidden" name="probe-dataset-id" value="{{dataset.datasetid}}" /> + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/create-probe-study-success.html b/uploader/templates/rqtl2/create-probe-study-success.html new file mode 100644 index 0000000..d0ee508 --- /dev/null +++ b/uploader/templates/rqtl2/create-probe-study-success.html @@ -0,0 +1,49 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Create ProbeSet Study</h2> + +<div class="row"> + <p>You successfully created the ProbeSet study with the following + information. + <dl> + <dt>ID</dt> + <dd>{{study.id}}</dd> + + <dt>Name</dt> + <dd>{{study.name}}</dd> + + <dt>Full Name</dt> + <dd>{{study.fname}}</dd> + + <dt>Short Name</dt> + <dd>{{study.sname}}</dd> + + <dt>Created On</dt> + <dd>{{study.today}}</dd> + </dl> + </p> + + <form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.select_dataset_info', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + <legend class="heading">Create ProbeSet study</legend> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="probe-study-id" value="{{study.studyid}}" /> + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/create-tissue-success.html b/uploader/templates/rqtl2/create-tissue-success.html new file mode 100644 index 0000000..5f2c5a0 --- /dev/null +++ b/uploader/templates/rqtl2/create-tissue-success.html @@ -0,0 +1,106 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_all_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Select Tissue</h2> + +<div class="row"> + <p>You have successfully added a new tissue, organ or biological material with + the following details:</p> +</div> + +<div class="row"> + {{flash_all_messages()}} + + <form id="frm-create-tissue-display" + method="POST" + action="#"> + <legend class="heading">Create Tissue</legend> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="tissueid" value="{{tissue.Id}}" /> + + <div class="form-group"> + <label>Name</label> + <label>{{tissue.TissueName}}</label> + </div> + + <div class="form-group"> + <label>Short Name</label> + <label>{{tissue.Short_Name}}</label> + </div> + + {%if tissue.BIRN_lex_ID%} + <div class="form-group"> + <label>BIRN Lex ID</label> + <label>{{tissue.BIRN_lex_ID}}</label> + </div> + {%endif%} + + {%if tissue.BIRN_lex_Name%} + <div class="form-group"> + <label>BIRN Lex Name</label> + <label>{{tissue.BIRN_lex_Name}}</label> + </div> + {%endif%} + </form> + + <div id="action-buttons" + style="width:65ch;display:inline-grid;column-gap:5px;"> + + <form id="frm-create-tissue-success-continue" + method="POST" + action="{{url_for('upload.rqtl2.select_dataset_info', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + style="display: inline; width: 100%; grid-column: 1 / 2; + padding-top: 0.5em; text-align: center; border: none; + background-color: inherit;"> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="tissueid" value="{{tissue.Id}}" /> + + <button type="submit" class="btn btn-primary">continue</button> + </form> + </div> +</div> + +<div class="row"> + <p style="display:inline;width:100%;grid-column:2/3;text-align:center; + color:#336699;font-weight:bold;"> + OR + </p> +</div> + +<div class="row"> + <form id="frm-create-tissue-success-select-existing" + method="POST" + action="{{url_for('upload.rqtl2.select_tissue', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + style="display: inline; width: 100%; grid-column: 3 / 4; + padding-top: 0.5em; text-align: center; border: none; + background-color: inherit;"> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + + <button type="submit" class="btn btn-primary"> + select from existing tissues</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/index.html b/uploader/templates/rqtl2/index.html new file mode 100644 index 0000000..f3329c2 --- /dev/null +++ b/uploader/templates/rqtl2/index.html @@ -0,0 +1,36 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Data Upload{%endblock%} + +{%block contents%} +<h1 class="heading">R/qtl2 data upload</h1> + +<h2>R/qtl2 Upload</h2> + +<form method="POST" action="{{url_for('upload.rqtl2.select_species')}}" + id="frm-rqtl2-upload"> + <legend class="heading">upload R/qtl2 bundle</legend> + {{flash_messages("error-rqtl2")}} + + <div class="form-group"> + <label for="select:species" class="form-label">Species</label> + <select id="select:species" + name="species_id" + required="required" + class="form-control"> + <option value="">Select species</option> + {%for spec in species%} + <option value="{{spec.SpeciesId}}">{{spec.MenuName}}</option> + {%endfor%} + </select> + <small class="form-text text-muted"> + Data that you upload to the system should belong to a know species. + Here you can select the species that you wish to upload data for. + </small> + </div> + + <button type="submit" class="btn btn-primary" />submit</button> +</form> + +{%endblock%} diff --git a/uploader/templates/rqtl2/no-such-job.html b/uploader/templates/rqtl2/no-such-job.html new file mode 100644 index 0000000..b17004f --- /dev/null +++ b/uploader/templates/rqtl2/no-such-job.html @@ -0,0 +1,13 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Job Status{%endblock%} + +{%block contents%} +<h1 class="heading">R/qtl2 job status</h1> + +<h2>R/qtl2 Upload: No Such Job</h2> + +<p class="alert-danger">No job with ID {{jobid}} was found.</p> + +{%endblock%} diff --git a/uploader/templates/rqtl2/rqtl2-job-error.html b/uploader/templates/rqtl2/rqtl2-job-error.html new file mode 100644 index 0000000..9817518 --- /dev/null +++ b/uploader/templates/rqtl2/rqtl2-job-error.html @@ -0,0 +1,39 @@ +{%extends "base.html"%} +{%from "cli-output.html" import cli_output%} + +{%block title%}Job Status{%endblock%} + +{%block contents%} +<h1 class="heading">R/qtl2 job status</h1> + +<h2>R/qtl2 Upload: Job Status</h2> + +<div class="explainer"> + <p>The processing of the R/qtl2 bundle you uploaded has failed. We have + provided some information below to help you figure out what the problem + could be.</p> + <p>If you find that you cannot figure out what the problem is on your own, + please contact the team running the system for assistance, providing the + following details: + <ul> + <li>R/qtl2 bundle you uploaded</li> + <li>This URL: <strong>{{request_url()}}</strong></li> + <li>(maybe) a screenshot of this page</li> + </ul> + </p> +</div> + +<h4>stdout</h4> +{{cli_output(job, "stdout")}} + +<h4>stderr</h4> +{{cli_output(job, "stderr")}} + +<h4>Log</h4> +<div class="cli-output"> + {%for msg in messages%} + {{msg}}<br /> + {%endfor%} +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/rqtl2-job-results.html b/uploader/templates/rqtl2/rqtl2-job-results.html new file mode 100644 index 0000000..4ecd415 --- /dev/null +++ b/uploader/templates/rqtl2/rqtl2-job-results.html @@ -0,0 +1,24 @@ +{%extends "base.html"%} +{%from "cli-output.html" import cli_output%} + +{%block title%}Job Status{%endblock%} + +{%block contents%} +<h1 class="heading">R/qtl2 job status</h1> + +<h2>R/qtl2 Upload: Job Status</h2> + +<div class="explainer"> + <p>The processing of the R/qtl2 bundle you uploaded has completed + successfully.</p> + <p>You should now be able to use GeneNetwork to run analyses on your data.</p> +</div> + +<h4>Log</h4> +<div class="cli-output"> + {%for msg in messages%} + {{msg}}<br /> + {%endfor%} +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/rqtl2-job-status.html b/uploader/templates/rqtl2/rqtl2-job-status.html new file mode 100644 index 0000000..e896f88 --- /dev/null +++ b/uploader/templates/rqtl2/rqtl2-job-status.html @@ -0,0 +1,20 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Job Status{%endblock%} + +{%block extrameta%} +<meta http-equiv="refresh" content="3"> +{%endblock%} + +{%block contents%} +<h1 class="heading">R/qtl2 job status</h1> + +<h2>R/qtl2 Upload: Job Status</h2> + +<h4>Log</h4> +<div class="cli-output"> + <pre>{{"\n".join(messages)}}</pre> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/rqtl2-qc-job-error.html b/uploader/templates/rqtl2/rqtl2-qc-job-error.html new file mode 100644 index 0000000..90e8887 --- /dev/null +++ b/uploader/templates/rqtl2/rqtl2-qc-job-error.html @@ -0,0 +1,120 @@ +{%extends "base.html"%} +{%from "cli-output.html" import cli_output%} + +{%block title%}R/qtl2 bundle: QC Job Error{%endblock%} + +{%macro errors_table(tableid, errors)%} +<table id="{{tableid}}" class="table error-table"> + <caption>{{caption}}</caption> + <thead> + <tr> + <th>Line</th> + <th>Column</th> + <th>Value</th> + <th>Message</th> + </tr> + </thead> + <tbody> + {%for error in errors%} + <tr> + <td>{{error.line}}</td> + <td>{{error.column}}</td> + <td>{{error.value}}</td> + <td>{{error.message}}</td> + </tr> + {%else%} + <tr> + <td colspan="4">No errors to display here.</td> + </tr> + {%endfor%} + </tbody> +</table> +{%endmacro%} + +{%block contents%} +<h1 class="heading">R/qtl2 bundle: QC job Error</h1> + +<div class="explainer"> + <p>The R/qtl2 bundle has failed some <emph>Quality Control</emph> checks.</p> + <p>We list below some of the errors that need to be fixed before the data can + be uploaded onto GeneNetwork.</p> +</div> + +{%if errorsgeneric | length > 0%} +<h2 class="heading">Generic Errors ({{errorsgeneric | length}})</h3> +<div class="explainer"> + We found the following generic errors in your R/qtl2 bundle: +</div> + +<h3>Missing Files</h3> +<div class="explainer"> + <p>These files are listed in the bundle's control file, but do not actually + exist in the bundle</p> +</div> +<table id="tbl-errors-missing-files" class="table error-table"> + <thead> + <tr> + <th>Control File Key</th> + <th>Bundle File Name</th> + <th>Message</th> + </tr> + </thead> + <tbody> + {%for error in (errorsgeneric | selectattr("type", "equalto", "MissingFile"))%} + <tr> + <td>{{error.controlfilekey}}</td> + <td>{{error.filename}}</td> + <td>{{error.message}}</td> + </tr> + {%endfor%} + </tbody> +</table> + +<h3>Other Generic Errors</h3> +{{errors_table("tbl-errors-generic", errorsgeneric| selectattr("type", "ne", "MissingFile"))}} +{%endif%} + +{%if errorsgeno | length > 0%} +<h2 class="heading">Geno Errors ({{errorsgeno | length}})</h3> +<div class="explainer"> + We found the following errors in the 'geno' file in your R/qtl2 bundle: +</div> +{{errors_table("tbl-errors-geno", errorsgeno[0:50])}} +{%endif%} + +{%if errorspheno | length > 0%} +<h2 class="heading">Pheno Errors ({{errorspheno | length}})</h3> +<div class="explainer"> + We found the following errors in the 'pheno' file in your R/qtl2 bundle: +</div> +{{errors_table("tbl-errors-pheno", errorspheno[0:50])}} +{%endif%} + +{%if errorsphenose | length > 0%} +<h2 class="heading">Phenose Errors ({{errorsphenose | length}})</h3> +<div class="explainer"> + We found the following errors in the 'phenose' file in your R/qtl2 bundle: +</div> +{{errors_table("tbl-errors-phenose", errorsphenose[0:50])}} +{%endif%} + +{%if errorsphenocovar | length > 0%} +<h2 class="heading">Phenocovar Errors ({{errorsphenocovar | length}})</h3> +<div class="explainer"> + We found the following errors in the 'phenocovar' file in your R/qtl2 bundle: +</div> +{{errorsphenocovar}} +{%endif%} + +<h4>stdout</h4> +{{cli_output(job, "stdout")}} + +<h4>stderr</h4> +{{cli_output(job, "stderr")}} + +<h4>Log</h4> +<div class="cli-output"> + <pre>{{"\n".join(messages)}}</pre> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/rqtl2-qc-job-results.html b/uploader/templates/rqtl2/rqtl2-qc-job-results.html new file mode 100644 index 0000000..59bc8cd --- /dev/null +++ b/uploader/templates/rqtl2/rqtl2-qc-job-results.html @@ -0,0 +1,66 @@ +{%extends "base.html"%} +{%from "cli-output.html" import cli_output%} + +{%block title%}R/qtl2 bundle: QC job results{%endblock%} + +{%block contents%} +<h1 class="heading">R/qtl2 bundle: QC job results</h1> + +<div class="row"> + <p>The R/qtl2 bundle you uploaded has passed all automated quality-control + checks successfully.</p> + <p>You may now continue to load the data into GeneNetwork for the bundle, with + the following details:</p> +</div> + +<div class="row"> + <form id="form-qc-job-results" + action="{{url_for('upload.rqtl2.select_dataset_info', + species_id=species.SpeciesId, + population_id=population.Id)}}" + method="POST"> + <div class="form-group"> + <legend>Species</legend> + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + + <span class="form-label">Name</span> + <span class="form-text">{{species.Name | capitalize}}</span> + + <span class="form-label">Scientific</span> + <span class="form-text">{{species.FullName | capitalize}}</span> + </div> + + <div class="form-group"> + <legend>population</legend> + <input type="hidden" name="population_id" value="{{population.Id}}" /> + + <span class="form-label">Name</span> + <span class="form-text">{{population.InbredSetName}}</span> + + <span class="form-label">Full Name</span> + <span class="form-text">{{population.FullName}}</span> + + <span class="form-label">Genetic Type</span> + <span class="form-text">{{population.GeneticType}}</span> + + <span class="form-label">Description</span> + <span class="form-text">{{population.Description or "-"}}</span> + </div> + + <div class="form-group"> + <legend>R/qtl2 Bundle File</legend> + <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2bundle}}" /> + <input type="hidden" name="original-filename" value="{{rqtl2bundleorig}}" /> + + <span class="form-label">Original Name</span> + <span class="form-text">{{rqtl2bundleorig}}</span> + + <span class="form-label">Internal Name</span> + <span class="form-text">{{rqtl2bundle[0:25]}}…</span> + </div> + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/rqtl2-qc-job-status.html b/uploader/templates/rqtl2/rqtl2-qc-job-status.html new file mode 100644 index 0000000..f4a6266 --- /dev/null +++ b/uploader/templates/rqtl2/rqtl2-qc-job-status.html @@ -0,0 +1,41 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Job Status{%endblock%} + +{%block extrameta%} +<meta http-equiv="refresh" content="3"> +{%endblock%} + +{%block contents%} +<h1 class="heading">R/qtl2 bundle: QC job status</h1> + +{%if geno_percent%} +<p> + <h2>Checking 'geno' file:</h2> + <progress id="prg-geno-checking" value="{{geno_percent}}" max="100"> + {{geno_percent}}%</progress> + {{geno_percent}}%</p> +{%endif%} + +{%if pheno_percent%} +<p> + <h2>Checking 'pheno' file:</h2> + <progress id="prg-pheno-checking" value="{{pheno_percent}}" max="100"> + {{pheno_percent}}%</progress> + {{pheno_percent}}%</p> +{%endif%} + +{%if phenose_percent%} +<p> + <h2>Checking 'phenose' file:</h2> + <progress id="prg-phenose-checking" value="{{phenose_percent}}" max="100"> + {{phenose_percent}}%</progress> + {{phenose_percent}}%</p> +{%endif%} + +<h4>Log</h4> +<div class="cli-output"> + <pre>{{"\n".join(messages)}}</pre> +</div> +{%endblock%} diff --git a/uploader/templates/rqtl2/rqtl2-qc-job-success.html b/uploader/templates/rqtl2/rqtl2-qc-job-success.html new file mode 100644 index 0000000..2861a04 --- /dev/null +++ b/uploader/templates/rqtl2/rqtl2-qc-job-success.html @@ -0,0 +1,37 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_all_messages%} + +{%block title%}R/qtl2 Bundle: Quality Control Successful{%endblock%} + +{%block contents%} +<h2 class="heading">R/qtl2 Bundle: Quality Control Successful</h2> + +<div class="row"> + <p>The R/qtl2 bundle you uploaded has passed <emph>all</emph> quality control + checks successfully, and is now ready for uploading into the database.</p> + <p>Click "Continue" below to proceed.</p> +</div> + +<!-- + The "action" on this form takes us to the next step, where we can + select all the other data necessary to enter the data into the database. + --> +<div class="row"> + <form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.select_dataset_info', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + {{flash_all_messages()}} + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/select-geno-dataset.html b/uploader/templates/rqtl2/select-geno-dataset.html new file mode 100644 index 0000000..873f9c3 --- /dev/null +++ b/uploader/templates/rqtl2/select-geno-dataset.html @@ -0,0 +1,144 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Select Genotypes Dataset</h2> + +<div class="row"> + <p>Your R/qtl2 files bundle contains a "geno" specification. You will + therefore need to select from one of the existing Genotype datasets or + create a new one.</p> + <p>This is the dataset where your data will be organised under.</p> +</div> + +<div class="row"> + <form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.select_geno_dataset', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + <legend class="heading">select from existing genotype datasets</legend> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + + {{flash_messages("error-rqtl2-select-geno-dataset")}} + + <div class="form-group"> + <legend>Datasets</legend> + <label for="select:geno-datasets" class="form-label">Dataset</label> + <select id="select:geno-datasets" + name="geno-dataset-id" + required="required" + {%if datasets | length == 0%} + disabled="disabled" + {%endif%} + class="form-control" + aria-describedby="help-geno-dataset-select-dataset"> + <option value="">Select dataset</option> + {%for dset in datasets%} + <option value="{{dset['Id']}}">{{dset["Name"]}} ({{dset["FullName"]}})</option> + {%endfor%} + </select> + <span id="help-geno-dataset-select-dataset" class="form-text text-muted"> + Select from the existing genotype datasets for species + {{species.SpeciesName}} ({{species.FullName}}). + </span> + </div> + + <button type="submit" class="btn btn-primary">select dataset</button> + </form> +</div> + +<div class="row"> + <p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p> +</div> + +<div class="row"> + <form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.create_geno_dataset', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + <legend class="heading">create a new genotype dataset</legend> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + + {{flash_messages("error-rqtl2-create-geno-dataset")}} + + <div class="form-group"> + <label for="txt:dataset-name" class="form-label">Name</label> + <input type="text" + id="txt:dataset-name" + name="dataset-name" + maxlength="100" + required="required" + class="form-control" + aria-describedby="help-geno-dataset-name" /> + <span id="help-geno-dataset-name" class="form-text text-muted"> + Provide the new name for the genotype dataset, e.g. "BXDGeno" + </span> + </div> + + <div class="form-group"> + <label for="txt:dataset-fullname" class="form-label">Full Name</label> + <input type="text" + id="txt:dataset-fullname" + name="dataset-fullname" + required="required" + maxlength="100" + class="form-control" + aria-describedby="help-geno-dataset-fullname" /> + + <span id="help-geno-dataset-fullname" class="form-text text-muted"> + Provide a longer name that better describes the genotype dataset, e.g. + "BXD Genotypes" + </span> + </div> + + <div class="form-group"> + <label for="txt:dataset-shortname" class="form-label">Short Name</label> + <input type="text" + id="txt:dataset-shortname" + name="dataset-shortname" + maxlength="100" + class="form-control" + aria-describedby="help-geno-dataset-shortname" /> + + <span id="help-geno-dataset-shortname" class="form-text text-muted"> + Provide a short name for the genotype dataset. This is optional. If not + provided, we'll default to the same value as the "Name" above. + </span> + </div> + + <div class="form-group"> + <input type="checkbox" + id="chk:dataset-public" + name="dataset-public" + checked="checked" + class="form-check" + aria-describedby="help-geno-datasent-public" /> + <label for="chk:dataset-public" class="form-check-label">Public?</label> + + <span id="help-geno-dataset-public" class="form-text text-muted"> + Specify whether the dataset will be available publicly. Check to make the + dataset publicly available and uncheck to limit who can access the dataset. + </span> + </div> + + <button type="submit" class="btn btn-primary">create new dataset</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/select-population.html b/uploader/templates/rqtl2/select-population.html new file mode 100644 index 0000000..37731f0 --- /dev/null +++ b/uploader/templates/rqtl2/select-population.html @@ -0,0 +1,136 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Select Grouping/Population{%endblock%} + +{%block contents%} +<h1 class="heading">Select grouping/population</h1> + +<div class="explainer"> + <p>The data is organised in a hierarchical form, beginning with + <em>species</em> at the very top. Under <em>species</em> the data is + organised by <em>population</em>, sometimes referred to as <em>grouping</em>. + (In some really old documents/systems, you might see this referred to as + <em>InbredSet</em>.)</p> + <p>In this section, you get to define what population your data is to be + organised by.</p> +</div> + +<form method="POST" + action="{{url_for('upload.rqtl2.select_population', species_id=species.SpeciesId)}}"> + <legend class="heading">select grouping/population</legend> + {{flash_messages("error-select-population")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + + <div class="form-group"> + <label for="select:inbredset" class="form-label">population</label> + <select id="select:inbredset" + name="inbredset_id" + required="required" + class="form-control"> + <option value="">Select a grouping/population</option> + {%for pop in populations%} + <option value="{{pop.InbredSetId}}"> + {{pop.InbredSetName}} ({{pop.FullName}})</option> + {%endfor%} + </select> + <span class="form-text text-muted">If you are adding data to an already existing + population, simply pick the population from this drop-down selector. If + you cannot find your population from this list, try the form below to + create a new one..</span> + </div> + + <button type="submit" class="btn btn-primary" />select population</button> +</form> + +<p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p> + +<form method="POST" + action="{{url_for('upload.rqtl2.create_population', species_id=species.SpeciesId)}}"> + <legend class="heading">create new grouping/population</legend> + {{flash_messages("error-create-population")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + + <div class="form-group"> + <legend class="heading">mandatory</legend> + + <div class="form-group"> + <label for="txt:inbredset-name" class="form-label">name</label> + <input id="txt:inbredset-name" + name="inbredset_name" + type="text" + required="required" + maxlength="30" + placeholder="Enter grouping/population name" + class="form-control" /> + <span class="form-text text-muted">This is a short name that identifies the + population. Useful for menus, and quick scanning.</span> + </div> + + <div class="form-group"> + <label for="txt:" class="form-label">full name</label> + <input id="txt:inbredset-fullname" + name="inbredset_fullname" + type="text" + required="required" + maxlength="100" + placeholder="Enter the grouping/population's full name" + class="form-control" /> + <span class="form-text text-muted">This can be the same as the name above, or can + be longer. Useful for documentation, and human communication.</span> + </div> + </div> + + <div class="form-group"> + <legend class="heading">optional</legend> + + <div class="form-group"> + <label for="num:public" class="form-label">public?</label> + <select id="num:public" + name="public" + class="form-control"> + <option value="0">0 - Only accessible to authorised users</option> + <option value="1">1 - Publicly accessible to all users</option> + <option value="2" selected> + 2 - Publicly accessible to all users</option> + </select> + <span class="form-text text-muted">This determines whether the + population/grouping will appear on the menus for users.</span> + </div> + + <div class="form-group"> + <label for="txt:inbredset-family" class="form-label">family</label> + <input id="txt:inbredset-family" + name="inbredset_family" + type="text" + placeholder="I am not sure what this is about." + class="form-control" /> + <span class="form-text text-muted">I do not currently know what this is about. + This is a failure on my part to figure out what this is and provide a + useful description. Please feel free to remind me.</span> + </div> + + <div class="form-group"> + <label for="txtarea:" class="form-label">Description</label> + <textarea id="txtarea:description" + name="description" + rows="5" + placeholder="Enter a description of this grouping/population" + class="form-control"></textarea> + <span class="form-text text-muted"> + A long-form description of what the population consists of. Useful for + humans.</span> + </div> + </div> + + <button type="submit" class="btn btn-primary" /> + create grouping/population</button> +</form> + +{%endblock%} + + +{%block javascript%} +{%endblock%} diff --git a/uploader/templates/rqtl2/select-probeset-dataset.html b/uploader/templates/rqtl2/select-probeset-dataset.html new file mode 100644 index 0000000..26f52ed --- /dev/null +++ b/uploader/templates/rqtl2/select-probeset-dataset.html @@ -0,0 +1,191 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Phenotype(ProbeSet) Dataset</h2> + +<div class="row"> + <p>The R/qtl2 bundle you uploaded contains (a) "<strong>pheno</strong>" + file(s). This data needs to be organised under a dataset.</p> + <p>This page gives you the ability to do that.</p> +</div> + +{%if datasets | length > 0%} +<div class="row"> + <form method="POST" + action="{{url_for('upload.rqtl2.select_probeset_dataset', + species_id=species.SpeciesId, population_id=population.Id)}}" + id="frm:select-probeset-dataset"> + <legend class="heading">Select from existing ProbeSet datasets</legend> + {{flash_messages("error-rqtl2")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="tissueid" value="{{tissue.Id}}" /> + <input type="hidden" name="probe-study-id" value="{{probe_study.Id}}" /> + + <div class="form-group"> + <label class="form-label" for="select:probe-dataset">Dataset</label> + <select id="select:probe-dataset" + name="probe-dataset-id" + required="required" + {%if datasets | length == 0%}disabled="disabled"{%endif%} + class="form-control" + aria-describedby="help-probe-dataset"> + <option value="">Select a dataset</option> + {%for dataset in datasets%} + <option value={{dataset.Id}}> + {{dataset.Name}} + {%if dataset.FullName%} + -- ({{dataset.FullName}}) + {%endif%} + </option> + {%endfor%} + </select> + + <span id="help-probe-dataset" class="form-text text-muted"> + Select from existing ProbeSet datasets.</span> + </div> + + <button type="submit" class="btn btn-primary" />select dataset</button> +</form> +</div> + +<div class="row"> + <p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p> +</div> +{%endif%} + +<div class="row"> + <p>Create an entirely new ProbeSet dataset for your data.</p> +</div> + +<div class="row"> + <form method="POST" + action="{{url_for('upload.rqtl2.create_probeset_dataset', + species_id=species.SpeciesId, population_id=population.Id)}}" + id="frm:create-probeset-dataset"> + <legend class="heading">Create a new ProbeSet dataset</legend> + {{flash_messages("error-rqtl2-create-probeset-dataset")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="tissueid" value="{{tissue.Id}}" /> + <input type="hidden" name="probe-study-id" value="{{probe_study.Id}}" /> + + <div class="form-group"> + <label class="form-label" for="select:average">averaging method</label> + <select id="select:average" + name="averageid" + required="required" + class="form-control" + aria-describedby="help-average"> + <option value="">Select averaging method</option> + {%for avgmethod in avgmethods%} + <option value="{{avgmethod.Id}}"> + {{avgmethod.Name}} + {%if avgmethod.Normalization%} + ({{avgmethod.Normalization}}) + {%endif%} + </option> + {%endfor%} + </select> + + <span id="help-average" class="form-text text-muted"> + Select the averaging method used for your data. + </span> + </div> + + <div class="form-group"> + <label class="form-label" for="txt:datasetname">Name</label> + <input type="text" id="txt:datasetname" name="datasetname" + required="required" + maxlength="40" + title="Name of the dataset, e.g 'BXDMicroArray_ProbeSet_June03'. (Required)" + class="form-control" + aria-describedby="help-dataset-name" /> + + <span id="help-dataset-name" class="form-text text-muted"> + Provide a name for the dataset e.g. "BXDMicroArray_ProbeSet_June03". This + is mandatory <strong>MUST</strong> be provided. + </span> + </div> + + <div class="form-group"> + <label class="form-label" for="txt:datasetfullname">Full Name</label> + <input type="text" id="txt:datasetfullname" name="datasetfullname" + required="required" + maxlength="100" + title="A longer name for the dataset, e.g. 'UTHSC Brain mRNA U74Av2 (Jun03) MAS5'. (Required)" + class="form-control" + aria-describedby="help-dataset-fullname" /> + + <span id="help-dataset-fullname" class="form-text text-muted"> + Provide a longer, more descriptive name for the dataset e.g. + "UTHSC Brain mRNA U74Av2 (Jun03) MAS5". This is mandatory and + <strong>MUST</strong> be provided. + </span> + </div> + + <div class="form-group"> + <label class="form-label" for="txt:datasetshortname">Short Name</label> + <input type="text" id="txt:datasetshortname" name="datasetshortname" + maxlength="100" + title="An abbreviated name for the dataset, e.g 'Br_U_0603_M'. (Optional)" + class="form-control" + aria-describedby="help-dataset-shortname" /> + + <span id="help-dataset-shortname" class="form-text text-muted"> + Provide a longer, more descriptive name for the dataset e.g. "Br_U_0603_M". + This is optional. + </span> + </div> + + <div class="form-check"> + <input type="checkbox" id="chk:public" name="datasetpublic" + checked="checked" + title="Whether or not the dataset is accessible by the general public." + class="form-check-input" + aria-describedby="help-public" /> + <label class="form-check-label" for="chk:datasetpublic">Public?</label> + + <span id="help-public" class="form-text text-muted"> + Check to specify that the dataset will be publicly available. Uncheck to + limit access to the dataset. + </span> + </div> + + <div class="form-group"> + <label class="form-label" for="select:datasetdatascale">Data Scale</label> + <select id="select:datasetdatascale" + name="datasetdatascale" + required="required" + class="form-control" + aria-describedby="help-dataset-datascale"> + <option value="log2" selected="selected">log2</option> + <option value="z_score">z_score</option> + <option value="log2_ratio">log2_ratio</option> + <option value="linear">linear</option> + <option value="linear_positive">linear_positive</option> + </select> + + <span id="help-dataset-datascale" class="form-text text-muted"> + Select from a list of scaling methods. + </span> + </div> + + <button type="submit" class="btn btn-primary">create dataset</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/select-probeset-study-id.html b/uploader/templates/rqtl2/select-probeset-study-id.html new file mode 100644 index 0000000..b9bf52e --- /dev/null +++ b/uploader/templates/rqtl2/select-probeset-study-id.html @@ -0,0 +1,143 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages %} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Phenotype(ProbeSet) Study</h2> + +<div class="row"> + <p>The R/qtl2 bundle you uploaded contains (a) "<strong>pheno</strong>" + file(s). This data needs to be organised under a study.</p> + <p>In this page, you can either select from a existing dataset:</p> + + <form method="POST" + action="{{url_for('upload.rqtl2.select_probeset_study', + species_id=species.SpeciesId, population_id=population.Id)}}" + id="frm:select-probeset-study"> + <legend class="heading">Select from existing ProbeSet studies</legend> + {{flash_messages("error-rqtl2-select-probeset-study")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="tissueid" value="{{tissue.Id}}" /> + + <div> + <label for="select:probe-study" class="form-label">Study</label> + <select id="select:probe-study" + name="probe-study-id" + required="required" + aria-describedby="help-select-probeset-study" + {%if studies | length == 0%}disabled="disabled"{%endif%} + class="form-control"> + <option value="">Select a study</option> + {%for study in studies%} + <option value={{study.Id}}> + {{study.Name}} + {%if study.FullName%} + -- ({{study.FullName}}) + {%endif%} + </option> + {%endfor%} + </select> + <small id="help-select-probeset-study" class="form-text text-muted"> + Select from existing ProbeSet studies. + </small> + </div> + + <button type="submit" class="btn btn-primary">select study</button> + </form> +</div> + +<div class="row"> + <p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p> +</div> + +<div class="row"> + + <p>Create a new ProbeSet dataset below:</p> + + <form method="POST" + action="{{url_for('upload.rqtl2.create_probeset_study', + species_id=species.SpeciesId, population_id=population.Id)}}" + id="frm:create-probeset-study"> + <legend class="heading">Create new ProbeSet study</legend> + + {{flash_messages("error-rqtl2-create-probeset-study")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="tissueid" value="{{tissue.Id}}" /> + + <div> + <label for="select:platform" class="form-label">Platform</label> + <select id="select:platform" + name="platformid" + required="required" + aria-describedby="help-select-platform" + {%if platforms | length == 0%}disabled="disabled"{%endif%} + class="form-control"> + <option value="">Select a platform</option> + {%for platform in platforms%} + <option value="{{platform.GeneChipId}}"> + {{platform.GeneChipName}} ({{platform.Name}}) + </option> + {%endfor%} + </select> + <small id="help-select-platform" class="form-text text-muted"> + Select from a list of known genomics platforms. + </small> + </div> + + <div class="form-group"> + <label for="txt:studyname" class="form-label">Study name</label> + <input type="text" id="txt:studyname" name="studyname" + placeholder="Name of the study. (Required)" + required="required" + maxlength="100" + class="form-control" /> + <span class="form-text text-muted" id="help-study-name"> + Provide a name for the study.</span> + </div> + + <div class="form-group"> + <label for="txt:studyfullname" class="form-label">Full Study Name</label> + <input type="text" + id="txt:studyfullname" + name="studyfullname" + placeholder="Longer name of the study. (Optional)" + maxlength="100" + class="form-control" /> + <span class="form-text text-muted" id="help-study-full-name"> + Provide a longer, more descriptive name for the study. This is optional + and you can leave it blank. + </span> + </div> + + <div class="form-group"> + <label for="txt:studyshortname" class="form-label">Short Study Name</label> + <input type="text" + id="txt:studyshortname" + name="studyshortname" + placeholder="Shorter name of the study. (Optional)" + maxlength="100" + class="form-control" /> + <span class="form-text text-muted" id="help-study-short-name"> + Provide a shorter name for the study. This is optional and you can leave + it blank. + </span> + </div> + + <button type="submit" class="btn btn-primary">create study</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/select-tissue.html b/uploader/templates/rqtl2/select-tissue.html new file mode 100644 index 0000000..34e1758 --- /dev/null +++ b/uploader/templates/rqtl2/select-tissue.html @@ -0,0 +1,115 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Tissue</h2> + +<div class="row"> + <p>The data you are uploading concerns a tissue, cell, organ, or other + biological material used in an experiment.</p> + <p>Select the appropriate biological material below</p> +</div> + +{%if tissues | length > 0%} +<div class="row"> + <form method="POST" + action="{{url_for('upload.rqtl2.select_tissue', + species_id=species.SpeciesId, population_id=population.Id)}}" + id="frm:select-probeset-dataset"> + <legend class="heading">Select from existing ProbeSet datasets</legend> + {{flash_messages("error-select-tissue")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + + <div class="form-group"> + <label class="form-label" for="select-tissue">Tissue</label> + <select id="select-tissue" + name="tissueid" + required="required" + {%if tissues | length == 0%}disabled="disabled"{%endif%} + class="form-control" + aria-describedby="help-select-tissue"> + <option value="">Select a tissue</option> + {%for tissue in tissues%} + <option value={{tissue.Id}}> + {{tissue.Name}} + {%if tissue.Short_Name%} + -- ({{tissue.Short_Name}}) + {%endif%} + </option> + {%endfor%} + </select> + + <span id="help-select-tissue" class="form-text text-muted"> + Select from existing biological material.</span> + </div> + + <button type="submit" class="btn btn-primary">use selected</button> + </form> +</div> + +<div class="row"> + <p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p> +</div> +{%endif%} + +<div class="row"> + <p>If you cannot find the biological material in the drop-down above, add it + to the system below.</p> + + <form method="POST" + action="{{url_for('upload.rqtl2.create_tissue', + species_id=species.SpeciesId, population_id=population.Id)}}" + id="frm:create-probeset-dataset"> + <legend class="heading">Add new tissue, organ or biological material</legend> + {{flash_messages("error-create-tissue")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + + <div class="form-group"> + <label class="form-label" for="tissue-name">name</label> + <input type="text" + id="txt-tissuename" + name="tissuename" + required="required" + title = "A name to identify the tissue, organ or biological material." + class="form-control" + aria-describedby="help-tissue-name" /> + + <span class="form-text text-muted" id="help-tissue-name"> + A name to identify the tissue, organ or biological material. + </span> + </div> + + <div class="form-group"> + <label for="txt-shortname" class="form-label">short name</label> + <input type="text" id="txt-tissueshortname" name="tissueshortname" + required="required" + maxlength="7" + title="A short name (e.g. 'Mam') for the biological material." + class="form-control" + aria-describedby="help-tissue-short-name" /> + + <span class="form-text text-muted" id="help-tissue-short-name"> + Provide a short name for the tissue, organ or biological material used in + the experiment. + </span> + </div> + + <button type="submit" class="btn btn-primary" />add new material</button> +</form> +</div> + +{%endblock%} diff --git a/uploader/templates/rqtl2/summary-info.html b/uploader/templates/rqtl2/summary-info.html new file mode 100644 index 0000000..1be87fa --- /dev/null +++ b/uploader/templates/rqtl2/summary-info.html @@ -0,0 +1,65 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Summary</h2> + +<div class="row"> + <p>This is the information you have provided to accompany the R/qtl2 bundle + you have uploaded. Please verify the information is correct before + proceeding.</p> +</div> + +<div class="row"> + <dl> + <dt>Species</dt> + <dd>{{species.SpeciesName}} ({{species.FullName}})</dd> + + <dt>Population</dt> + <dd>{{population.InbredSetName}}</dd> + + {%if geno_dataset%} + <dt>Genotype Dataset</dt> + <dd>{{geno_dataset.Name}} ({{geno_dataset.FullName}})</dd> + {%endif%} + + {%if tissue%} + <dt>Tissue</dt> + <dd>{{tissue.TissueName}} ({{tissue.Name}}, {{tissue.Short_Name}})</dd> + {%endif%} + + {%if probe_study%} + <dt>ProbeSet Study</dt> + <dd>{{probe_study.Name}} ({{probe_study.FullName}})</dd> + {%endif%} + + {%if probe_dataset%} + <dt>ProbeSet Dataset</dt> + <dd>{{probe_dataset.Name2}} ({{probe_dataset.FullName}})</dd> + {%endif%} + </dl> +</div> + +<div class="row"> + <form id="frm:confirm-rqtl2bundle-details" + action="{{url_for('upload.rqtl2.confirm_bundle_details', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + <legend class="heading">Create ProbeSet dataset</legend> + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2_bundle_file}}" /> + <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" /> + <input type="hidden" name="probe-study-id" value="{{probe_study.Id}}" /> + <input type="hidden" name="probe-dataset-id" value="{{probe_dataset.Id}}" /> + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> +{%endblock%} diff --git a/uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html new file mode 100644 index 0000000..07c240f --- /dev/null +++ b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html @@ -0,0 +1,276 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_all_messages%} +{%from "upload_progress_indicator.html" import upload_progress_indicator%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +{%macro rqtl2_file_help()%} +<span class="form-text text-muted"> + <p> + Provide a valid R/qtl2 zip file here. In particular, ensure your zip bundle + contains exactly one control file and the corresponding files mentioned in + the control file. + </p> + <p> + The control file can be either a YAML or JSON file. <em>ALL</em> other data + files in the zip bundle should be CSV files. + </p> + <p>See the + <a href="https://kbroman.org/qtl2/assets/vignettes/input_files.html" + target="_blank"> + R/qtl2 file format specifications + </a> + for more details. + </p> +</span> +{%endmacro%} +{{upload_progress_indicator()}} + +<div id="resumable-file-display-template" + class="panel panel-info" + style="display: none"> + <div class="panel-heading"></div> + <div class="panel-body"></div> +</div> + + +<h2 class="heading">Upload R/qtl2 Bundle</h2> + +<div id="resumable-drop-area" + style="display:none;background:#eeeeee;min-height:12em;border-radius:0.5em;padding:1em;"> + <p> + <a id="resumable-browse-button" href="#" + class="btn btn-info">Browse</a> + </p> + <p class="form-text text-muted"> + You can drag and drop your file here, or click the browse button. + Click on the file to remove it. + </p> + {{rqtl2_file_help()}} + <div id="resumable-selected-files" + style="display:flex;flex-direction:row;flex-wrap: wrap;justify-content:space-around;gap:10px 20px;"></div> + <div id="resumable-class-buttons" style="text-align: right;"> + <button id="resumable-upload-button" + class="btn btn-primary" + style="display: none">start upload</button> + <button id="resumable-cancel-upload-button" + class="btn btn-danger" + style="display: none">cancel upload</button> + </div> + <div id="resumable-progress-bar" class="progress" style="display: none"> + <div class="progress-bar" + role="progress-bar" + aria-valuenow="60" + aria-valuemin="0" + aria-valuemax="100" + style="width: 0%;"> + Uploading: 60% + </div> + </div> +</div> + +<form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.upload_rqtl2_bundle', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data" + data-resumable-target="{{url_for( + 'upload.rqtl2.upload_rqtl2_bundle_chunked_post', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}"> + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + + {{flash_all_messages()}} + + <div class="form-group"> + <legend class="heading">file upload</legend> + <label for="file-rqtl2-bundle" class="form-label">R/qtl2 bundle</label> + <input type="file" id="file-rqtl2-bundle" name="rqtl2_bundle_file" + accept="application/zip, .zip" + required="required" + class="form-control" /> + {{rqtl2_file_help()}} + </div> + + <button type="submit" + class="btn btn-primary" + data-toggle="modal" + data-target="#upload-progress-indicator">upload R/qtl2 bundle</button> +</form> + +{%endblock%} + +{%block javascript%} +<script src="{{url_for('base.node_modules', + filename='resumablejs/resumable.js')}}"></script> +<script type="text/javascript" src="/static/js/upload_progress.js"></script> +<script type="text/javascript"> + function readBinaryFile(file) { + return new Promise((resolve, reject) => { + var _reader = new FileReader(); + _reader.onload = (event) => {resolve(_reader.result);}; + _reader.readAsArrayBuffer(file); + }); + } + + function computeFileChecksum(file) { + return readBinaryFile(file) + .then((content) => { + return window.crypto.subtle.digest( + "SHA-256", new Uint8Array(content)); + }).then((digest) => { + return Uint8ArrayToHex(new Uint8Array(digest)) + }); + } + + function Uint8ArrayToHex(arr) { + var toHex = (val) => { + _hex = val.toString(16); + if(_hex.length < 2) { + return "0" + val; + } + return _hex; + }; + _hexstr = "" + arr.forEach((val) => {_hexstr += toHex(val)}); + return _hexstr + } + + var r = Resumable({ + target: $("#frm-upload-rqtl2-bundle").attr("data-resumable-target"), + fileType: ["zip"], + maxFiles: 1, + forceChunkSize: true, + generateUniqueIdentifier: (file, event) => { + return computeFileChecksum(file).then((checksum) => { + var _relativePath = (file.webkitRelativePath + || file.relativePath + || file.fileName + || file.name); + return checksum + "-" + _relativePath.replace( + /[^a-zA-Z0-9_-]/img, ""); + }); + } + }); + + if(r.support) { + //Hide form and display drag&drop UI + $("#frm-upload-rqtl2-bundle").css("display", "none"); + $("#resumable-drop-area").css("display", "block"); + + // Define UI elements for browse and drag&drop + r.assignDrop(document.getElementById("resumable-drop-area")); + r.assignBrowse(document.getElementById("resumable-browse-button")); + + // Event handlers + + function display_files(files) { + displayArea = $("#resumable-selected-files") + displayArea.empty(); + files.forEach((file) => { + var displayElement = $( + "#resumable-file-display-template").clone(); + displayElement.removeAttr("id"); + displayElement.css("display", ""); + displayElement.find(".panel-heading").text(file.fileName); + list = $("<ul></ul>"); + list.append($("<li><strong>Name</strong>: " + + (file.name + || file.fileName + || file.relativePath + || file.webkitRelativePath) + + "</li>")); + list.append($("<li><strong>Size</strong>: " + + (file.size / (1024*1024)).toFixed(2) + + " MB</li>")); + list.append($("<li><strong>Unique Identifier</strong>: " + + file.uniqueIdentifier + "</li>")); + list.append($("<li><strong>Mime</strong>: " + + file.file.type + + "</li>")); + displayElement.find(".panel-body").append(list); + displayElement.appendTo("#resumable-selected-files"); + }); + } + + r.on("filesAdded", function(files) { + display_files(files); + $("#resumable-upload-button").css("display", ""); + $("#resumable-upload-button").on("click", (event) => { + r.upload(); + }); + }); + + r.on("uploadStart", (event) => { + $("#resumable-upload-button").css("display", "none"); + $("#resumable-cancel-upload-button").css("display", ""); + $("#resumable-cancel-upload-button").on("click", (event) => { + r.files.forEach((file) => { + if(file.isUploading()) { + file.abort(); + } + }); + $("#resumable-cancel-upload-button").css("display", "none"); + $("#resumable-upload-button").on("click", (event) => { + r.files.forEach((file) => {file.retry();}); + }); + $("#resumable-upload-button").css("display", ""); + }); + }); + + r.on("progress", () => { + var progress = (r.progress() * 100).toFixed(2); + var pbar = $("#resumable-progress-bar > .progress-bar"); + $("#resumable-progress-bar").css("display", ""); + pbar.css("width", progress+"%"); + pbar.attr("aria-valuenow", progress); + pbar.text("Uploading: " + progress + "%"); + }) + + r.on("fileSuccess", (file, message) => { + if(message != "OK") { + var uri = (window.location.protocol + + "//" + + window.location.host + + message); + window.location.replace(uri); + } + }); + + r.on("error", (message, file) => { + filename = (file.webkitRelativePath + || file.relativePath + || file.fileName + || file.name); + jsonmsg = JSON.parse(message); + alert("There was an error while uploading your file '" + + filename + + "'. The error message was:\n\n\t" + + jsonmsg.error + + " (" + + jsonmsg.statuscode + + "): " + jsonmsg.message); + }) + } else { + setup_upload_handlers( + "frm-upload-rqtl2-bundle", make_data_uploader( + function (form) { + var formdata = new FormData(); + formdata.append( + "species_id", + form.querySelector('input[name="species_id"]').value); + formdata.append( + "population_id", + form.querySelector('input[name="population_id"]').value); + formdata.append( + "rqtl2_bundle_file", + form.querySelector("#file-rqtl2-bundle").files[0]); + return formdata; + })); + } +</script> +{%endblock%} diff --git a/uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html new file mode 100644 index 0000000..93b1dc9 --- /dev/null +++ b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html @@ -0,0 +1,33 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_all_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +<h2 class="heading">Upload R/qtl2 Bundle</h2> + +<div class="row"> + <p>You have successfully uploaded the zipped bundle of R/qtl2 files.</p> + <p>The next step is to select the various extra information we need to figure + out what to do with the data. You will select/create the relevant studies + and/or datasets to organise the data in the steps that follow.</p> + <p>Click "Continue" below to proceed.</p> + + <form id="frm-upload-rqtl2-bundle" + action="{{url_for('upload.rqtl2.select_dataset_info', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + method="POST" + enctype="multipart/form-data"> + {{flash_all_messages()}} + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <input type="hidden" name="population_id" + value="{{population.InbredSetId}}" /> + <input type="hidden" name="rqtl2_bundle_file" + value="{{rqtl2_bundle_file}}" /> + + <button type="submit" class="btn btn-primary">continue</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/samples/select-population.html b/uploader/templates/samples/select-population.html new file mode 100644 index 0000000..da19ddc --- /dev/null +++ b/uploader/templates/samples/select-population.html @@ -0,0 +1,99 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Select Grouping/Population{%endblock%} + +{%block contents%} +<h1 class="heading">Select grouping/population</h1> + +<div> + <p>We organise the samples/cases/strains in a hierarchichal form, starting + with <strong>species</strong> at the very top. Under species, we have a + grouping in terms of the relevant population + (e.g. Inbred populations, cell tissue, etc.)</p> +</div> + +<form method="POST" action="{{url_for('samples.select_population', + species_id=species.SpeciesId)}}"> + <legend class="heading">select grouping/population</legend> + {{flash_messages("error-select-population")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + + <div class="form-group"> + <label for="select:inbredset" class="form-label">grouping/population</label> + <select id="select:inbredset" + name="inbredset_id" + required="required" + class="form-control"> + <option value="">Select a grouping/population</option> + {%for pop in populations%} + <option value="{{pop.InbredSetId}}"> + {{pop.InbredSetName}} ({{pop.FullName}})</option> + {%endfor%} + </select> + </div> + + <button type="submit" class="btn btn-primary">select population</button> +</form> + +<p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p> + +<form method="POST" action="{{url_for('samples.create_population', + species_id=species.SpeciesId)}}"> + <legend class="heading">create new grouping/population</legend> + {{flash_messages("error-create-population")}} + + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <div class="form-group"> + <legend>mandatory</legend> + + <label for="txt:inbredset-name" class="form-label">name</label> + <input id="txt:inbredset-name" + name="inbredset_name" + type="text" + required="required" + placeholder="Enter grouping/population name" + class="form-control" /> + + <label for="txt:" class="form-label">full name</label> + <input id="txt:inbredset-fullname" + name="inbredset_fullname" + type="text" + required = "required" + placeholder="Enter the grouping/population's full name" + class="form-control" /> + </div> + <div class="form-group"> + <legend>Optional</legend> + + <label for="num:public" class="form-label">public?</label> + <input id="num:public" + name="public" + type="number" + min="0" max="2" value="2" + class="form-control" /> + + <label for="txt:inbredset-family" class="form-label">family</label> + <input id="txt:inbredset-family" + name="inbredset_family" + type="text" + placeholder="I am not sure what this is about." + class="form-control" /> + + <label for="txtarea:" class="form-label">Description</label> + <textarea id="txtarea:description" + name="description" + rows="5" + placeholder="Enter a description of this grouping/population" + class="form-control"></textarea> + </div> + + <button type="submit" class="btn btn-primary">create grouping/population</button> +</form> + +{%endblock%} + + +{%block javascript%} +{%endblock%} diff --git a/uploader/templates/samples/select-species.html b/uploader/templates/samples/select-species.html new file mode 100644 index 0000000..edadc61 --- /dev/null +++ b/uploader/templates/samples/select-species.html @@ -0,0 +1,30 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_all_messages%} + +{%block title%}Select Grouping/Population{%endblock%} + +{%block contents%} +<h2 class="heading">upload samples/cases</h2> + +<p>We need to know what species your data belongs to.</p> + +{{flash_all_messages()}} + +<form method="POST" action="{{url_for('samples.select_species')}}"> + <legend class="heading">upload samples</legend> + <div class="form-group"> + <label for="select_species02" class="form-label">Species</label> + <select id="select_species02" + name="species_id" + required="required" + class="form-control"> + <option value="">Select species</option> + {%for spec in species%} + <option value="{{spec.SpeciesId}}">{{spec.MenuName}}</option> + {%endfor%} + </select> + </div> + + <button type="submit" class="btn btn-primary">submit</button> +</form> +{%endblock%} diff --git a/uploader/templates/samples/upload-failure.html b/uploader/templates/samples/upload-failure.html new file mode 100644 index 0000000..09e2ecf --- /dev/null +++ b/uploader/templates/samples/upload-failure.html @@ -0,0 +1,27 @@ +{%extends "base.html"%} +{%from "cli-output.html" import cli_output%} + +{%block title%}Samples Upload Failure{%endblock%} + +{%block contents%} +<h1 class="heading">{{job.job_name}}</h2> + +<p>There was a failure attempting to upload the samples.</p> + +<p>Here is some information to help with debugging the issue. Provide this + information to the developer/maintainer.</p> + +<h3>Debugging Information</h3> +<ul> + <li><strong>job id</strong>: {{job.job_id}}</li> + <li><strong>status</strong>: {{job.status}}</li> + <li><strong>job type</strong>: {{job["job-type"]}}</li> +</ul> + +<h4>stdout</h4> +{{cli_output(job, "stdout")}} + +<h4>stderr</h4> +{{cli_output(job, "stderr")}} + +{%endblock%} diff --git a/uploader/templates/samples/upload-progress.html b/uploader/templates/samples/upload-progress.html new file mode 100644 index 0000000..7bb02be --- /dev/null +++ b/uploader/templates/samples/upload-progress.html @@ -0,0 +1,22 @@ +{%extends "base.html"%} +{%from "cli-output.html" import cli_output%} + +{%block extrameta%} +<meta http-equiv="refresh" content="5"> +{%endblock%} + +{%block title%}Job Status{%endblock%} + +{%block contents%} +<h1 class="heading">{{job.job_name}}</h2> + +<p> +<strong>status</strong>: +<span>{{job["status"]}} ({{job.get("message", "-")}})</span><br /> +</p> + +<p>saving to database...</p> + +{{cli_output(job, "stdout")}} + +{%endblock%} diff --git a/uploader/templates/samples/upload-samples.html b/uploader/templates/samples/upload-samples.html new file mode 100644 index 0000000..e62de57 --- /dev/null +++ b/uploader/templates/samples/upload-samples.html @@ -0,0 +1,139 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload Samples{%endblock%} + +{%block css%}{%endblock%} + +{%block contents%} +<h1 class="heading">upload samples</h1> + +{{flash_messages("alert-success")}} + +<p>You can now upload a character-separated value (CSV) file that contains + details about your samples. The CSV file should have the following fields: + <dl> + <dt>Name</dt> + <dd>The primary name for the sample</dd> + + <dt>Name2</dt> + <dd>A secondary name for the sample. This can simply be the same as + <strong>Name</strong> above. This field <strong>MUST</strong> contain a + value.</dd> + + <dt>Symbol</dt> + <dd>A symbol for the sample. Can be an empty field.</dd> + + <dt>Alias</dt> + <dd>An alias for the sample. Can be an empty field.</dd> + </dl> +</p> + +<form id="form-samples" + method="POST" + action="{{url_for('samples.upload_samples', + species_id=species.SpeciesId, + population_id=population.InbredSetId)}}" + enctype="multipart/form-data"> + <legend class="heading">upload samples</legend> + + <div class="form-group"> + <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> + <label class="form-label">species:</label> + <span class="form-text">{{species.SpeciesName}} [{{species.MenuName}}]</span> + </div> + + <div class="form-group"> + <input type="hidden" name="inbredset_id" value="{{population.InbredSetId}}" /> + <label class="form-label">grouping/population:</label> + <span class="form-text">{{population.Name}} [{{population.FullName}}]</span> + </div> + + <div class="form-group"> + <label for="file-samples" class="form-label">select file</label> + <input type="file" name="samples_file" id="file:samples" + accept="text/csv, text/tab-separated-values" + class="form-control" /> + </div> + + <div class="form-group"> + <label for="select:separator" class="form-label">field separator</label> + <select id="select:separator" + name="separator" + required="required" + class="form-control"> + <option value="">Select separator for your file: (default is comma)</option> + <option value="	">TAB</option> + <option value=" ">Space</option> + <option value=",">Comma</option> + <option value=";">Semicolon</option> + <option value="other">Other</option> + </select> + <input id="txt:separator" + type="text" + name="other_separator" + class="form-control" /> + <small class="form-text text-muted"> + If you select '<strong>Other</strong>' for the field separator value, + enter the character that separates the fields in your CSV file in the form + field below. + </small> + </div> + + <div class="form-group form-check"> + <input id="chk:heading" + type="checkbox" + name="first_line_heading" + class="form-check-input" /> + <label for="chk:heading" class="form-check-label"> + first line is a heading?</label> + <small class="form-text text-muted"> + Select this if the first line in your file contains headings for the + columns. + </small> + </div> + + <div class="form-group"> + <label for="txt:delimiter" class="form-label">field delimiter</label> + <input id="txt:delimiter" + type="text" + name="field_delimiter" + maxlength="1" + class="form-control" /> + <small class="form-text text-muted"> + If there is a character delimiting the string texts within particular + fields in your CSV, provide the character here. This can be left blank if + no such delimiters exist in your file. + </small> + </div> + + <button type="submit" + class="btn btn-primary">upload samples file</button> +</form> + +<table id="tbl:samples-preview" class="table"> + <caption class="heading">preview content</caption> + + <thead> + <tr> + <th>Name</th> + <th>Name2</th> + <th>Symbol</th> + <th>Alias</th> + </tr> + </thead> + + <tbody> + <tr id="default-row"> + <td colspan="4"> + Please make some selections to preview the data.</td> + </tr> + </tbody> +</table> + +{%endblock%} + + +{%block javascript%} +<script src="/static/js/upload_samples.js" type="text/javascript"></script> +{%endblock%} diff --git a/uploader/templates/samples/upload-success.html b/uploader/templates/samples/upload-success.html new file mode 100644 index 0000000..cb745c3 --- /dev/null +++ b/uploader/templates/samples/upload-success.html @@ -0,0 +1,18 @@ +{%extends "base.html"%} +{%from "cli-output.html" import cli_output%} + +{%block title%}Job Status{%endblock%} + +{%block contents%} +<h1 class="heading">{{job.job_name}}</h2> + +<p> +<strong>status</strong>: +<span>{{job["status"]}} ({{job.get("message", "-")}})</span><br /> +</p> + +<p>Successfully uploaded the samples.</p> + +{{cli_output(job, "stdout")}} + +{%endblock%} diff --git a/uploader/templates/select_dataset.html b/uploader/templates/select_dataset.html new file mode 100644 index 0000000..2f07de8 --- /dev/null +++ b/uploader/templates/select_dataset.html @@ -0,0 +1,161 @@ +{%extends "base.html"%} +{%from "dbupdate_hidden_fields.html" import hidden_fields%} + +{%block title%}Select Dataset{%endblock%} + +{%block css%} +<link rel="stylesheet" href="/static/css/two-column-with-separator.css" /> +{%endblock%} + +{%block contents%} +<h2 class="heading">{{filename}}: select dataset</h2> + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.final_confirmation')}}" + id="select-dataset-form" class="two-col-sep-col1"> + <legend class="heading">choose existing dataset</legend> + {{hidden_fields( + filename, filetype, species=species, genechipid=genechipid, + studyid=studyid, totallines=totallines)}} + + <div class="form-group"> + <label for="datasetid" class="form-label">dataset:</label> + <select id="datasetid" name="datasetid" class="form-control" + {%if datasets | length == 0:%} + disabled="disabled" + {%endif%}> + {%for dataset in datasets:%} + <option value="{{dataset['Id']}}"> + [{{dataset["Name"]}}] - {{dataset["FullName"]}} + </option> + {%endfor%} + </select> + </div> + + <button type="submit" class="btn btn-primary" + {%if datasets | length == 0:%} + disabled="disabled" + {%endif%} />update database</button> +</form> +</div> + +<div class="row"> + <p class="two-col-sep-separator">OR</p> +</div> + +<div class="row"> + <form method="POST" id="create-dataset-form" + action="{{url_for('dbinsert.create_dataset')}}" + class="two-col-sep-col2"> + <legend class="heading">create new dataset</legend> + {{hidden_fields( + filename, filetype, species=species, genechipid=genechipid, + studyid=studyid, totallines=totallines)}} + + {%with messages = get_flashed_messages(with_categories=true)%} + {%if messages:%} + <ul> + {%for category, message in messages:%} + <li class="{{category}}">{{message}}</li> + {%endfor%} + </ul> + {%endif%} + {%endwith%} + + <div class="form-group"> + <label for="avgid" class="form-label">average:</label> + <select id="avgid" name="avgid" required="required" class="form-control"> + <option value="">Select averaging method</option> + {%for method in avgmethods:%} + <option value="{{method['AvgMethodId']}}" + {%if avgid is defined and method['AvgMethodId'] | int == avgid | int%} + selected="selected" + {%endif%}> + {{method["Name"]}} + </option> + {%endfor%} + </select> + </div> + + <div class="form-group"> + <label for="datasetname" class="form-label">name:</label> + <input id="datasetname" name="datasetname" type="text" + class="form-control" + {%if datasetname is defined %} + value="{{datasetname}}" + {%endif%} /> + </div> + + <div class="form-group"> + <label for="datasetname2" class="form-label">name 2:</label> + <input id="datasetname2" name="datasetname2" type="text" + required="required" class="form-control" + {%if datasetname2 is defined %} + value="{{datasetname2}}" + {%endif%} /> + </div> + + <div class="form-group"> + <label for="datasetfullname" class="form-label">full name:</label> + <input id="datasetfullname" name="datasetfullname" type="text" + required="required" class="form-control" + {%if datasetfullname is defined %} + value="{{datasetfullname}}" + {%endif%} /> + </div> + + <div class="form-group"> + <label for="datasetshortname" class="form-label">short name:</label> + <input id="datasetshortname" name="datasetshortname" type="text" + required="required" class="form-control" + {%if datasetshortname is defined %} + value="{{datasetshortname}}" + {%endif%} /> + </div> + + <div class="form-group"> + <label for="datasetpublic" class="form-label">public:</label> + <input id="datasetpublic" name="datasetpublic" type="number" + required="required" min="0" max="2" + {%if datasetpublic is defined %} + value="{{datasetpublic | int}}" + {%else%} + value="0" + {%endif%} + class="form-control" /> + </div> + + <div class="form-group"> + <label for="datasetconfidentiality">confidentiality:</label> + <input id="datasetconfidentiality" name="datasetconfidentiality" + type="number" required="required" min="0" max="2" + {%if datasetconfidentiality is defined %} + value="{{datasetconfidentiality | int}}" + {%else%} + value="0" + {%endif%} + class="form-control" /> + </div> + + <div class="form-group"> + <label for="datasetdatascale" class="form-label">data scale:</label> + <select id="datasetdatascale" name="datasetdatascale" class="form-control"> + <option value="">None</option> + {%for dscale in datascales:%} + <option value="{{dscale}}" + {%if datasetdatascale is defined and dscale == datasetdatascale%} + selected="selected" + {%elif dscale == "log2":%} + selected="selected" + {%endif%}> + {{dscale}} + </option> + {%endfor%} + </select> + </div> + + <button type="submit" class="btn btn-primary">create new dataset</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/select_platform.html b/uploader/templates/select_platform.html new file mode 100644 index 0000000..d9bc68f --- /dev/null +++ b/uploader/templates/select_platform.html @@ -0,0 +1,82 @@ +{%extends "base.html"%} + +{%block title%}Select Dataset{%endblock%} + +{%block contents%} +<h2 class="heading">{{filename}}: select platform</h2> + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.select_study')}}" + id="select-platform-form" data-genechips="{{genechips_data}}"> + <input type="hidden" name="filename" value="{{filename}}" /> + <input type="hidden" name="filetype" value="{{filetype}}" /> + <input type="hidden" name="totallines" value="{{totallines}}" /> + + <div class="form-group"> + <label for="species" class="form-label">species</label> + <select id="species" name="species" class="form-control"> + {%for row in species:%} + <option value="{{row['SpeciesId']}}" + {%if row["Name"] == default_species:%} + selected="selected" + {%endif%}> + {{row["MenuName"]}} + </option> + {%endfor%} + </select> + </div> + + <table id="genechips-table" class="table"> + <caption>select platform</caption> + <thead> + <tr> + <th>Select</th> + <th>GeneChip ID</th> + <th>GeneChip Name</th> + </tr> + </thead> + + <tbody> + {%for chip in genechips:%} + <tr> + <td> + <input type="radio" name="genechipid" value="{{chip['GeneChipId']}}" + required="required" /> + </td> + <td>{{chip["GeneChipId"]}}</td> + <td>{{chip["GeneChipName"]}}</td> + </tr> + {%else%} + <tr> + <td colspan="5">No chips found for selected species</td> + </tr> + {%endfor%} + </tbody> + </table> + + <button type="submit" class="btn btn-primary">submit platform</button> + </form> +</div> +{%endblock%} + +{%block javascript%} +<script type="text/javascript" src="/static/js/utils.js"></script> +<script type="text/javascript" src="/static/js/select_platform.js"></script> +<script type="text/javascript"> + document.getElementById( + "species").addEventListener("change", update_genechips); + document.getElementById( + "genechips-table").getElementsByTagName( + "tbody")[0].addEventListener( + "click", + function(event) { + if(event.target.tagName.toLowerCase() == "td") { + return select_row_radio(event.target.parentElement); + } + if(event.target.tagName.toLowerCase() == "td") { + return select_row_radio(event.target); + } + return false; + }); +</script> +{%endblock%} diff --git a/uploader/templates/select_species.html b/uploader/templates/select_species.html new file mode 100644 index 0000000..3b1a8a9 --- /dev/null +++ b/uploader/templates/select_species.html @@ -0,0 +1,92 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} +{%from "upload_progress_indicator.html" import upload_progress_indicator%} + +{%block title%}expression data: select species{%endblock%} + +{%block contents%} +{{upload_progress_indicator()}} + +<h2 class="heading">expression data: select species</h2> + +<div class="row"> + <form action="{{url_for('entry.upload_file')}}" + method="POST" + enctype="multipart/form-data" + id="frm-upload-expression-data"> + <legend class="heading">upload expression data</legend> + {{flash_messages("error-expr-data")}} + + <div class="form-group"> + <label for="select_species01" class="form-label">Species</label> + <select id="select_species01" + name="speciesid" + required="required" + class="form-control"> + <option value="">Select species</option> + {%for aspecies in species%} + <option value="{{aspecies.SpeciesId}}">{{aspecies.MenuName}}</option> + {%endfor%} + </select> + </div> + + <div class="form-group"> + <legend class="heading">file type</legend> + + <div class="form-check"> + <input type="radio" name="filetype" value="average" id="filetype_average" + required="required" class="form-check-input" /> + <label for="filetype_average" class="form-check-label">average</label> + </div> + + <div class="form-check"> + <input type="radio" name="filetype" value="standard-error" + id="filetype_standard_error" required="required" + class="form-check-input" /> + <label for="filetype_standard_error" class="form-check-label"> + standard error + </label> + </div> + </div> + + <div class="form-group"> + <span id="no-file-error" class="alert-danger" style="display: none;"> + No file selected + </span> + <label for="file_upload" class="form-label">select file</label> + <input type="file" name="qc_text_file" id="file_upload" + accept="text/plain, text/tab-separated-values, application/zip" + class="form-control"/> + </div> + + <button type="submit" + class="btn btn-primary" + data-toggle="modal" + data-target="#upload-progress-indicator">upload file</button> + </form> +</div> +{%endblock%} + + +{%block javascript%} +<script type="text/javascript" src="static/js/upload_progress.js"></script> +<script type="text/javascript"> + function setup_formdata(form) { + var formdata = new FormData(); + formdata.append( + "speciesid", + form.querySelector("#select_species01").value) + formdata.append( + "qc_text_file", + form.querySelector("input[type='file']").files[0]); + formdata.append( + "filetype", + selected_filetype( + Array.from(form.querySelectorAll("input[type='radio']")))); + return formdata; + } + + setup_upload_handlers( + "frm-upload-expression-data", make_data_uploader(setup_formdata)); +</script> +{%endblock%} diff --git a/uploader/templates/select_study.html b/uploader/templates/select_study.html new file mode 100644 index 0000000..648ad4c --- /dev/null +++ b/uploader/templates/select_study.html @@ -0,0 +1,108 @@ +{%extends "base.html"%} +{%from "dbupdate_hidden_fields.html" import hidden_fields%} + +{%block title%}Select Dataset{%endblock%} + +{%block css%} +<link rel="stylesheet" href="/static/css/two-column-with-separator.css" /> +{%endblock%} + +{%block contents%} +<h2 class="heading">{{filename}}: select study</h2> + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.select_dataset')}}" + id="select-platform-form" data-genechips="{{genechips_data}}" + class="two-col-sep-col1"> + <legend class="heading">Select from existing study</legend> + {{hidden_fields(filename, filetype, species=species, genechipid=genechipid, + totallines=totallines)}} + + <div class="form-group"> + <label class="form-label" for="study">study:</label> + <select id="study" name="studyid" class="form-control"> + {%for study in studies:%} + <option value="{{study['Id']}}">{{study["Name"]}}</option> + {%endfor%} + </select> + </div> + + <button type="submit" + class="btn btn-primary" + {%if studies | length == 0:%} + disabled="disabled" + {%endif%} />submit selected study</button> +</form> +</div> + +<div class="row"> + <p class="two-col-sep-separator">OR</p> +</div> + +<div class="row"> + <form method="POST" action="{{url_for('dbinsert.create_study')}}" + id="select-platform-form" data-genechips="{{genechips_data}}" + class="two-col-sep-col2"> + {%with messages = get_flashed_messages(with_categories=true)%} + {%if messages:%} + <ul> + {%for category, message in messages:%} + <li class="{{category}}">{{message}}</li> + {%endfor%} + </ul> + {%endif%} + {%endwith%} + <legend class="heading">Create new study</legend> + {{hidden_fields(filename, filetype, species=species, genechipid=genechipid, + totallines=totallines)}} + + <div class="form-group"> + <label class="form-label" for="studyname">name:</label> + <input type="text" id="studyname" name="studyname" class="form-control" + required="required" + {%if studyname:%} + value="{{studyname}}" + {%endif%} /> + </div> + + <div class="form-group"> + <label class="form-label" for="group">group:</label> + <select id="group" name="inbredsetid" class="form-control" + required="required"> + <option value="">Select group</option> + {%for family in groups:%} + <optgroup label="{{family}}"> + {%for group in groups[family]:%} + <option value="{{group['InbredSetId']}}" + {%if group["InbredSetId"] == selected_group:%} + selected="selected" + {%endif%}> + {{group["FullName"]}} + </option> + {%endfor%} + </optgroup> + {%endfor%} + </select> + </div> + + <div class="form-group"> + <label class="form-label" for="tissue">tissue:</label> + <select id="tissue" name="tissueid" class="form-control" + required="required"> + <option value="">Select type</option> + {%for tissue in tissues:%} + <option value="{{tissue['TissueId']}}" + {%if tissue["TissueId"] == selected_tissue:%} + selected="selected" + {%endif%}> + {{tissue["Name"]}} + </option> + {%endfor%} + </select> + </div> + + <button type="submit" class="btn btn-primary">create study</button> + </form> +</div> + +{%endblock%} diff --git a/uploader/templates/stdout_output.html b/uploader/templates/stdout_output.html new file mode 100644 index 0000000..85345a9 --- /dev/null +++ b/uploader/templates/stdout_output.html @@ -0,0 +1,8 @@ +{%macro stdout_output(job)%} + +<h4>STDOUT Output</h4> +<div class="cli-output"> + <pre>{{job.get("stdout", "")}}</pre> +</div> + +{%endmacro%} diff --git a/uploader/templates/unhandled_exception.html b/uploader/templates/unhandled_exception.html new file mode 100644 index 0000000..6e6a051 --- /dev/null +++ b/uploader/templates/unhandled_exception.html @@ -0,0 +1,21 @@ +{%extends "base.html"%} + +{%block title%}System Error{%endblock%} + +{%block css%} +<link rel="stylesheet" href="/static/css/two-column-with-separator.css" /> +{%endblock%} + +{%block contents%} +<p> + An error has occured, and your request has been aborted. Please notify the + administrator to try and get this sorted. +</p> +<p> + Provide the following information to help the administrator figure out and fix + the issue:<br /> + <hr /><br /> + {{trace}} + <hr /><br /> +</p> +{%endblock%} diff --git a/uploader/templates/upload_progress_indicator.html b/uploader/templates/upload_progress_indicator.html new file mode 100644 index 0000000..e274e83 --- /dev/null +++ b/uploader/templates/upload_progress_indicator.html @@ -0,0 +1,35 @@ +{%macro upload_progress_indicator()%} +<div id="upload-progress-indicator" class="modal fade" tabindex="-1" role="dialog"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h3 class="modal-title">Uploading file</h3> + </div> + + <div class="modal-body"> + <form id="frm-cancel-upload" style="border-style: none;"> + <div class="form-group"> + <span id="progress-filename" class="form-text">No file selected!</span> + <progress id="progress-bar" value="0" max="100" class="form-control"> + 0</progress> + </div> + + <div class="form-group"> + <span class="form-text text-muted" id="progress-text"> + Uploading 0%</span> + <span class="form-text text-muted" id="progress-extra-text"> + Processing</span> + </div> + </form> + </div> + + <div class="modal-footer"> + <button id="btn-cancel-upload" + type="button" + class="btn btn-danger" + data-dismiss="modal">Cancel</button> + </div> + </div> + </div> +</div> +{%endmacro%} diff --git a/uploader/templates/worker_failure.html b/uploader/templates/worker_failure.html new file mode 100644 index 0000000..b65b140 --- /dev/null +++ b/uploader/templates/worker_failure.html @@ -0,0 +1,24 @@ +{%extends "base.html"%} + +{%block title%}Worker Failure{%endblock%} + +{%block contents%} +<h1 class="heading">Worker Failure</h1> + +<p> + There was a critical failure launching the job to parse your file. + This is our fault and (probably) has nothing to do with the file you uploaded. +</p> + +<p> + Please notify the developers of this issue when you encounter it, + providing the link to this page, or the information below. +</p> + +<h4>Debugging Information</h4> + +<ul> + <li><strong>job id</strong>: {{job_id}}</li> +</ul> + +{%endblock%} |