aboutsummaryrefslogtreecommitdiff
path: root/uploader/templates/phenotypes
diff options
context:
space:
mode:
Diffstat (limited to 'uploader/templates/phenotypes')
-rw-r--r--uploader/templates/phenotypes/add-phenotypes-base.html357
-rw-r--r--uploader/templates/phenotypes/add-phenotypes-raw-files.html373
-rw-r--r--uploader/templates/phenotypes/bulk-edit-upload.html62
-rw-r--r--uploader/templates/phenotypes/create-dataset.html6
-rw-r--r--uploader/templates/phenotypes/load-phenotypes-success.html42
-rw-r--r--uploader/templates/phenotypes/macro-display-preview-table.html8
-rw-r--r--uploader/templates/phenotypes/macro-display-resumable-elements.html12
-rw-r--r--uploader/templates/phenotypes/review-job-data.html30
-rw-r--r--uploader/templates/phenotypes/view-dataset.html85
9 files changed, 560 insertions, 415 deletions
diff --git a/uploader/templates/phenotypes/add-phenotypes-base.html b/uploader/templates/phenotypes/add-phenotypes-base.html
index 97b55f2..9909c20 100644
--- a/uploader/templates/phenotypes/add-phenotypes-base.html
+++ b/uploader/templates/phenotypes/add-phenotypes-base.html
@@ -42,110 +42,30 @@
{%block frm_add_phenotypes_elements%}{%endblock%}
- <div class="checkbox">
- <label>
- <input id="chk-published" type="checkbox" name="published?" />
- These phenotypes are published</label>
- </div>
-
- <fieldset id="fldset-publication-info" class="hidden">
+ <fieldset id="fldset-publication-info">
<legend>Publication Information</legend>
- <div class="form-group">
- <label for="txt-pubmed-id" class="form-label">Pubmed ID</label>
- <div class="input-group">
- <input id="txt-pubmed-id" name="pubmed-id" type="text"
- class="form-control" />
- <span class="input-group-btn">
- <button id="btn-search-pubmed-id" class="btn btn-info">Search</button>
- </span>
- </div>
- <span id="search-pubmed-id-error"
- class="form-text text-muted text-danger hidden">
- </span><br />
- <span class="form-text text-muted">
- Enter your publication's PubMed ID above and click "Search" to search
- for some (or all) of the publication details requested below.
- </span>
- </div>
-
- <div class="form-group">
- <label for="txt-publication-authors" class="form-label">Authors</label>
- <input id="txt-publication-authors" name="publication-authors"
- type="text" class="form-control" />
- <span class="form-text text-muted">
- Enter the authors in the following format &hellip;</span>
- </div>
-
- <div class="form-group">
- <label for="txt-publication-title" class="form-label">
- Publication Title</label>
- <input id="txt-publication-title" name="publication-title" type="text"
- class="form-control" />
- <span class="form-text text-muted">
- Enter your publication's title.</span>
- </div>
-
- <div class="form-group">
- <label for="txt-publication-abstract" class="form-label">
- Publication Abstract</label>
- <textarea id="txt-publication-abstract" name="publication-abstract"
- class="form-control" rows="10"></textarea>
- <span class="form-text text-muted">
- Enter the abstract for your publication.</span>
- </div>
-
- <div class="form-group">
- <label for="txt-publication-journal" class="form-label">Journal</label>
- <input id="txt-publication-journal" name="journal" type="text"
- class="form-control" />
- <span class="form-text text-muted">
- Enter the name of the journal where your work was published.</span>
- </div>
-
- <div class="form-group">
- <label for="txt-publication-volume" class="form-label">Volume</label>
- <input id="txt-publication-volume" name="publication-volume" type="text"
- class="form-control" />
- <span class="form-text text-muted">
- Enter the volume in the following format &hellip;</span>
- </div>
-
- <div class="form-group">
- <label for="txt-publication-pages" class="form-label">Pages</label>
- <input id="txt-publication-pages" name="publication-pages" type="text"
- class="form-control" />
- <span class="form-text text-muted">
- Enter the journal volume where your work was published.</span>
- </div>
-
- <div class="form-group">
- <label for="select-publication-month" class="form-label">
- Publication Month</label>
- <select id="select-publication-month" name="publication-month"
- class="form-control">
- {%for month in monthnames%}
- <option value="{{month | lower}}"
- {%if current_month | lower == month | lower%}
- selected="selected"
- {%endif%}>{{month | capitalize}}</option>
- {%endfor%}
- </select>
- <span class="form-text text-muted">
- Select the month when the work was published.
- <span class="text-danger">
- This cannot be before, say 1600 and cannot be in the future!</span></span>
- </div>
-
- <div class="form-group">
- <label for="txt-publication-year" class="form-label">Publication Year</label>
- <input id="txt-publication-year" name="publication-year" type="text"
- class="form-control" value="{{current_year}}" />
- <span class="form-text text-muted">
- Enter the year your work was published.
- <span class="text-danger">
- This cannot be before, say 1600 and cannot be in the future!</span>
- </span>
- </div>
+ <input type="hidden" name="publication-id" id="txt-publication-id" />
+ <span class="form-text text-muted">
+ Select a publication for your data. <br />
+ Can't find a publication you can use? Go ahead and
+ <a href="{{url_for(
+ 'publications.create_publication',
+ return_to='species.populations.phenotypes.add_phenotypes',
+ species_id=species.SpeciesId,
+ population_id=population.Id,
+ dataset_id=dataset.Id)}}">create a new publication</a>.</span>
+ <table id="tbl-select-publication" class="table compact stripe">
+ <thead>
+ <tr>
+ <th>#</th>
+ <th>PubMed ID</th>
+ <th>Title</th>
+ <th>Authors</th>
+ </tr>
+ </thead>
+
+ <tbody></tbody>
+ </table>
</fieldset>
<div class="form-group">
@@ -165,165 +85,80 @@
{%block javascript%}
<script type="text/javascript">
- var remove_class = (element, classvalue) => {
- new_classes = (element.attr("class") || "").split(" ").map((val) => {
- return val.trim();
- }).filter((val) => {
- return ((val !== classvalue) &&
- (val !== ""))
- }).join(" ");
-
- if(new_classes === "") {
- element.removeAttr("class");
- } else {
- element.attr("class", new_classes);
- }
- };
-
- var add_class = (element, classvalue) => {
- remove_class(element, classvalue);
- element.attr("class", (element.attr("class") || "") + " " + classvalue);
- };
-
- $("#chk-published").on("click", (event) => {
- pub_details = $("#fldset-publication-info")
- if(event.target.checked) {
- // display the publication details
- remove_class(pub_details, "hidden");
- } else {
- // hide the publication details
- add_class(pub_details, "hidden");
- }
- });
-
- var extract_details = (pubmed_id, details) => {
- var months = {
- "jan": "January",
- "feb": "February",
- "mar": "March",
- "apr": "April",
- "may": "May",
- "jun": "June",
- "jul": "July",
- "aug": "August",
- "sep": "September",
- "oct": "October",
- "nov": "November",
- "dec": "December"
- };
- var _date = details[pubmed_id].pubdate.split(" ");
- return {
- "authors": details[pubmed_id].authors.map((authobj) => {
- return authobj.name;
- }),
- "title": details[pubmed_id].title,
- "journal": details[pubmed_id].fulljournalname,
- "volume": details[pubmed_id].volume,
- "pages": details[pubmed_id].pages,
- "month": _date.length > 1 ? months[_date[1].toLowerCase()] : "jan",
- "year": _date[0],
- };
- };
-
- var update_publication_details = (details) => {
- Object.entries(details).forEach((entry) => {;
- switch(entry[0]) {
- case "authors":
- $("#txt-publication-authors").val(entry[1].join(", "));
- break;
- case "month":
- $("#select-publication-month")
- .children("option")
- .each((index, child) => {
- child.selected = child.value == entry[1].toLowerCase();
- });
- default:
- $("#txt-publication-" + entry[0]).val(entry[1]);
- break;
- }
+ $(function() {
+ var publicationsDataTable = buildDataTable(
+ "#tbl-select-publication",
+ [],
+ [
+ {data: "index"},
+ {
+ searchable: true,
+ data: (pub) => {
+ if(pub.PubMed_ID) {
+ return `<a href="https://pubmed.ncbi.nlm.nih.gov/` +
+ `${pub.PubMed_ID}/" target="_blank" ` +
+ `title="Link to publication on NCBI.">` +
+ `${pub.PubMed_ID}</a>`;
+ }
+ return "";
+ }
+ },
+ {
+ searchable: true,
+ data: (pub) => {
+ var title = "⸻";
+ if(pub.Title) {
+ title = pub.Title
+ }
+ return `<a href="/publications/view/${pub.Id}" ` +
+ `target="_blank" ` +
+ `title="Link to view publication details">` +
+ `${title}</a>`;
+ }
+ },
+ {
+ searchable: true,
+ data: (pub) => {
+ authors = pub.Authors.split(",").map(
+ (item) => {return item.trim();});
+ if(authors.length > 1) {
+ return authors[0] + ", et. al.";
+ }
+ return authors[0];
+ }
+ }
+ ],
+ {
+ serverSide: true,
+ ajax: {
+ url: "/publications/list",
+ dataSrc: "publications"
+ },
+ select: "single",
+ paging: true,
+ scrollY: 700,
+ deferRender: true,
+ scroller: true,
+ scrollCollapse: true,
+ layout: {
+ topStart: "info",
+ topEnd: "search"
+ }
+ });
+ publicationsDataTable.on("select", (event, datatable, type, indexes) => {
+ indexes.forEach((element, index, thearray) => {
+ let row = datatable.row(element).node();
+ console.debug(datatable.row(element).data());
+ $("#frm-add-phenotypes #txt-publication-id").val(
+ datatable.row(element).data().Id);
+ });
+ });
+ publicationsDataTable.on("deselect", (event, datatable, type, indexes) => {
+ indexes.forEach((element, index, thearray) => {
+ let row = datatable.row(element).node();
+ $("#frm-add-phenotypes #txt-publication-id").val(null);
+ });
});
- };
-
- var fetch_publication_abstract = (pubmed_id, pub_details) => {
- $.ajax("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi",
- {
- "method": "GET",
- "data": {
- "db": "pubmed",
- "id": pubmed_id,
- "rettype": "abstract",
- "retmode": "xml"
- },
- "success": (data, textStatus, jqXHR) => {
- update_publication_details({
- ...pub_details,
- ...{
- "abstract": Array.from(data
- .getElementsByTagName(
- "Abstract")[0]
- .children)
- .map((elt) => {return elt.textContent.trim();})
- .join("\r\n")
- }});
- },
- "error": (jqXHR, textStatus, errorThrown) => {},
- "complete": (jqXHR, textStatus) => {},
- "dataType": "xml"
- });
- };
-
- var fetch_publication_details = (pubmed_id, complete_thunks) => {
- error_display = $("#search-pubmed-id-error");
- error_display.text("");
- add_class(error_display, "hidden");
- $.ajax("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi",
- {
- "method": "GET",
- "data": {"db": "pubmed", "id": pubmed_id, "format": "json"},
- "success": (data, textStatus, jqXHR) => {
- // process and update publication details
- hasError = (
- Object.hasOwn(data, "error") ||
- Object.hasOwn(data.result[pubmed_id], "error"));
- if(hasError) {
- error_display.text(
- "There was an error fetching a publication with " +
- "the given PubMed ID! The error received " +
- "was: '" + (
- data.error ||
- data.result[pubmed_id].error) +
- "'. Please check ID you provided and try " +
- "again.");
- remove_class(error_display, "hidden");
- } else {
- fetch_publication_abstract(
- pubmed_id,
- extract_details(pubmed_id, data.result));
- }
- },
- "error": (jqXHR, textStatus, errorThrown) => {},
- "complete": () => {
- complete_thunks.forEach((thunk) => {thunk()});
- },
- "dataType": "json"
- });
- };
-
- $("#btn-search-pubmed-id").on("click", (event) => {
- event.preventDefault();
- var search_button = event.target;
- var pubmed_id = $("#txt-pubmed-id").val().trim();
- remove_class($("#txt-pubmed-id").parent(), "has-error");
- if(pubmed_id == "") {
- add_class($("#txt-pubmed-id").parent(), "has-error");
- return false;
- }
-
- search_button.disabled = true;
- // Fetch publication details
- fetch_publication_details(pubmed_id,
- [() => {search_button.disabled = false;}]);
- return false;
});
</script>
diff --git a/uploader/templates/phenotypes/add-phenotypes-raw-files.html b/uploader/templates/phenotypes/add-phenotypes-raw-files.html
index 7f8d8b0..67b56e3 100644
--- a/uploader/templates/phenotypes/add-phenotypes-raw-files.html
+++ b/uploader/templates/phenotypes/add-phenotypes-raw-files.html
@@ -105,111 +105,213 @@
</div>
</fieldset>
-<fieldset id="fldset-data-files">
+<fieldset id="fldset-files">
<legend>Data File(s)</legend>
- <div class="form-group non-resumable-elements">
- <label for="finput-phenotype-descriptions" class="form-label">
- Phenotype Descriptions</label>
- <input id="finput-phenotype-descriptions"
- name="phenotype-descriptions"
- class="form-control"
- type="file"
- data-preview-table="tbl-preview-pheno-desc"
- required="required" />
- <span class="form-text text-muted">
- Provide a file that contains only the phenotype descriptions,
- <a href="#docs-file-phenotype-description"
- title="Documentation of the phenotype data file format.">
- the documentation for the expected format of the file</a>.</span>
- </div>
-
- {{display_resumable_elements(
- "resumable-phenotype-descriptions",
- "phenotype descriptions",
- '<p>You can drop a CSV file that contains the phenotype descriptions here,
- or you can click the "Browse" button (below and to the right) to select it
- from your computer.</p>
- <p>The CSV file must conform to some standards, as documented in the
- <a href="#docs-file-phenotype-description"
- title="Documentation of the phenotype data file format.">
- "Phenotypes Descriptions" documentation</a> section below.</p>')}}
-
-
- <div class="form-group non-resumable-elements">
- <label for="finput-phenotype-data" class="form-label">Phenotype Data</label>
- <input id="finput-phenotype-data"
- name="phenotype-data"
- class="form-control"
- type="file"
- data-preview-table="tbl-preview-pheno-data"
- required="required" />
- <span class="form-text text-muted">
- Provide a file that contains only the phenotype data. See
- <a href="#docs-file-phenotype-data"
- title="Documentation of the phenotype data file format.">
- the documentation for the expected format of the file</a>.</span>
- </div>
-
- {{display_resumable_elements(
- "resumable-phenotype-data",
- "phenotype data",
- '<p>You can drop a CSV file that contains the phenotype data here,
- or you can click the "Browse" button (below and to the right) to select it
- from your computer.</p>
- <p>The CSV file must conform to some standards, as documented in the
- <a href="#docs-file-phenotype-data"
- title="Documentation of the phenotype data file format.">
- "Phenotypes Data" documentation</a> section below.</p>')}}
-
- {%if population.Family in families_with_se_and_n%}
- <div class="form-group non-resumable-elements">
- <label for="finput-phenotype-se" class="form-label">Phenotype: Standard Errors</label>
- <input id="finput-phenotype-se"
- name="phenotype-se"
- class="form-control"
- type="file"
- data-preview-table="tbl-preview-pheno-se"
- required="required" />
- <span class="form-text text-muted">
- Provide a file that contains only the standard errors for the phenotypes,
- computed from the data above.</span>
- </div>
- {{display_resumable_elements(
- "resumable-phenotype-se",
- "standard errors",
- '<p>You can drop a CSV file that contains the computed standard-errors data
- here, or you can click the "Browse" button (below and to the right) to
- select it from your computer.</p>
- <p>The CSV file must conform to some standards, as documented in the
- <a href="#docs-file-phenotype-se"
- title="Documentation of the phenotype data file format.">
- "Phenotypes Data" documentation</a> section below.</p>')}}
+ <fieldset id="fldset-descriptions-file">
+ <div class="form-group">
+ <div class="form-check">
+ <input id="chk-phenotype-descriptions-transposed"
+ name="phenotype-descriptions-transposed"
+ type="checkbox"
+ class="form-check-input"
+ style="border: solid #8EABF0" />
+ <label for="chk-phenotype-descriptions-transposed"
+ class="form-check-label">
+ Description file transposed?</label>
+ </div>
+
+ <div class="non-resumable-elements">
+ <label for="finput-phenotype-descriptions" class="form-label">
+ Phenotype Descriptions</label>
+ <input id="finput-phenotype-descriptions"
+ name="phenotype-descriptions"
+ class="form-control"
+ type="file"
+ data-preview-table="tbl-preview-pheno-desc"
+ required="required" />
+ <span class="form-text text-muted">
+ Provide a file that contains only the phenotype descriptions,
+ <a href="#docs-file-phenotype-description"
+ title="Documentation of the phenotype data file format.">
+ the documentation for the expected format of the file</a>.</span>
+ </div>
+ {{display_resumable_elements(
+ "resumable-phenotype-descriptions",
+ "phenotype descriptions",
+ '<p>Drag and drop the CSV file that contains the descriptions of your
+ phenotypes here.</p>
+
+ <p>The CSV file should be a matrix of
+ <strong>phenotypes × descriptions</strong> i.e. The first column
+ contains the phenotype names/identifiers whereas the first row is a list
+ of metadata fields like, "description", "units", etc.</p>
+
+ <p>If the format is transposed (i.e.
+ <strong>descriptions × phenotypes</strong>) select the checkbox above.
+ </p>
+
+ <p>Please see the
+ <a href="#docs-file-phenotype-description"
+ title="Documentation of the phenotype data file format.">
+ "Phenotypes Descriptions" documentation</a> section below for more
+ information on the expected format of the file provided here.</p>')}}
+ {{display_preview_table(
+ "tbl-preview-pheno-desc", "phenotype descriptions")}}
+ </div>
+ </fieldset>
+
+
+ <fieldset id="fldset-data-file">
+ <div class="form-group">
+ <div class="form-check">
+ <input id="chk-phenotype-data-transposed"
+ name="phenotype-data-transposed"
+ type="checkbox"
+ class="form-check-input"
+ style="border: solid #8EABF0" />
+ <label for="chk-phenotype-data-transposed" class="form-check-label">
+ Data file transposed?</label>
+ </div>
+
+ <div class="non-resumable-elements">
+ <label for="finput-phenotype-data" class="form-label">Phenotype Data</label>
+ <input id="finput-phenotype-data"
+ name="phenotype-data"
+ class="form-control"
+ type="file"
+ data-preview-table="tbl-preview-pheno-data"
+ required="required" />
+ <span class="form-text text-muted">
+ Provide a file that contains only the phenotype data. See
+ <a href="#docs-file-phenotype-data"
+ title="Documentation of the phenotype data file format.">
+ the documentation for the expected format of the file</a>.</span>
+ </div>
+
+ {{display_resumable_elements(
+ "resumable-phenotype-data",
+ "phenotype data",
+ '<p>Drag and drop a CSV file that contains the phenotypes numerical data
+ here. You can click the "Browse" button (below and to the right) to
+ select the file from your computer.</p>
+
+ <p>The CSV should be a matrix of <strong>samples × phenotypes</strong>,
+ i.e. The first column contains the samples identifiers while the first
+ row is the list of phenotypes identifiers occurring in the phenotypes
+ descriptions file.</p>
+
+ <p>If the format is transposed (i.e <strong>phenotypes × samples</strong>)
+ select the checkbox above.</p>
+ <p>Please see the
+ <a href="#docs-file-phenotype-data"
+ title="Documentation of the phenotype data file format.">
+ "Phenotypes Data" documentation</a> section below for more information
+ on the expected format for the file provided here.</p>')}}
+ {{display_preview_table("tbl-preview-pheno-data", "phenotype data")}}
+ </div>
+ </fieldset>
- <div class="form-group non-resumable-elements">
- <label for="finput-phenotype-n" class="form-label">Phenotype: Number of Samples/Individuals</label>
- <input id="finput-phenotype-n"
- name="phenotype-n"
- class="form-control"
- type="file"
- data-preview-table="tbl-preview-pheno-n"
- required="required" />
- <span class="form-text text-muted">
- Provide a file that contains only the number of samples/individuals used in
- the computation of the standard errors above.</span>
- </div>
- {{display_resumable_elements(
- "resumable-phenotype-n",
- "number of samples/individuals",
- '<p>You can drop a CSV file that contains the number of samples/individuals
- used in computation of the standard-errors here, or you can click the
- "Browse" button (below and to the right) to select it from your computer.
- </p>
- <p>The CSV file must conform to some standards, as documented in the
- <a href="#docs-file-phenotype-n"
- title="Documentation of the phenotype data file format.">
- "Phenotypes Data" documentation</a> section below.</p>')}}
+ {%if population.Family in families_with_se_and_n%}
+ <fieldset id="fldset-se-file">
+ <div class="form-group">
+ <div class="form-check">
+ <input id="chk-phenotype-se-transposed"
+ name="phenotype-se-transposed"
+ type="checkbox"
+ class="form-check-input"
+ style="border: solid #8EABF0" />
+ <label for="chk-phenotype-se-transposed" class="form-check-label">
+ Standard-Errors file transposed?</label>
+ </div>
+ <div class="group non-resumable-elements">
+ <label for="finput-phenotype-se" class="form-label">Phenotype: Standard Errors</label>
+ <input id="finput-phenotype-se"
+ name="phenotype-se"
+ class="form-control"
+ type="file"
+ data-preview-table="tbl-preview-pheno-se"
+ required="required" />
+ <span class="form-text text-muted">
+ Provide a file that contains only the standard errors for the phenotypes,
+ computed from the data above.</span>
+ </div>
+
+ {{display_resumable_elements(
+ "resumable-phenotype-se",
+ "standard errors",
+ '<p>Drag and drop a CSV file that contains the phenotypes standard-errors
+ data here. You can click the "Browse" button (below and to the right) to
+ select the file from your computer.</p>
+
+ <p>The CSV should be a matrix of <strong>samples × phenotypes</strong>,
+ i.e. The first column contains the samples identifiers while the first
+ row is the list of phenotypes identifiers occurring in the phenotypes
+ descriptions file.</p>
+
+ <p>If the format is transposed (i.e <strong>phenotypes × samples</strong>)
+ select the checkbox above.</p>
+
+ <p>Please see the
+ <a href="#docs-file-phenotype-se"
+ title="Documentation of the phenotype data file format.">
+ "Phenotypes Data" documentation</a> section below for more information
+ on the expected format of the file provided here.</p>')}}
+
+ {{display_preview_table("tbl-preview-pheno-se", "standard errors")}}
+ </div>
+ </fieldset>
+
+
+ <fieldset id="fldset-n-file">
+ <div class="form-group">
+ <div class="form-check">
+ <input id="chk-phenotype-n-transposed"
+ name="phenotype-n-transposed"
+ type="checkbox"
+ class="form-check-input"
+ style="border: solid #8EABF0" />
+ <label for="chk-phenotype-n-transposed" class="form-check-label">
+ Counts file transposed?</label>
+ </div>
+ <div class="non-resumable-elements">
+ <label for="finput-phenotype-n" class="form-label">Phenotype: Number of Samples/Individuals</label>
+ <input id="finput-phenotype-n"
+ name="phenotype-n"
+ class="form-control"
+ type="file"
+ data-preview-table="tbl-preview-pheno-n"
+ required="required" />
+ <span class="form-text text-muted">
+ Provide a file that contains only the number of samples/individuals used in
+ the computation of the standard errors above.</span>
+ </div>
+
+ {{display_resumable_elements(
+ "resumable-phenotype-n",
+ "number of samples/individuals",
+ '<p>Drag and drop a CSV file that contains the samples\' phenotypes counts
+ data here. You can click the "Browse" button (below and to the right) to
+ select the file from your computer.</p>
+
+ <p>The CSV should be a matrix of <strong>samples × phenotypes</strong>,
+ i.e. The first column contains the samples identifiers while the first
+ row is the list of phenotypes identifiers occurring in the phenotypes
+ descriptions file.</p>
+
+ <p>If the format is transposed (i.e <strong>phenotypes × samples</strong>)
+ select the checkbox above.</p>
+
+ <p>Please see the
+ <a href="#docs-file-phenotype-se"
+ title="Documentation of the phenotype data file format.">
+ "Phenotypes Data" documentation</a> section below for more information
+ on the expected format of the file provided here.</p>')}}
+
+ {{display_preview_table("tbl-preview-pheno-n", "number of samples/individuals")}}
+ </div>
+ </fieldset>
</fieldset>
{%endif%}
{%endblock%}
@@ -322,15 +424,15 @@
<span id="docs-file-phenotype-data"></span>
<span id="docs-file-phenotype-se"></span>
<span id="docs-file-phenotype-n"></span>
- <p>The data is a matrix of <em>phenotypes × individuals</em>, e.g.</p>
+ <p>The data is a matrix of <em>samples(or individuals) × phenotypes</em>, e.g.</p>
<code>
# num-cases: 2549
# num-phenos: 13
- id,IND001,IND002,IND003,IND004,…<br />
- pheno10001,61.400002,54.099998,483,49.799999,…<br />
- pheno10002,49,50.099998,403,45.5,…<br />
- pheno10003,62.5,53.299999,501,62.900002,…<br />
- pheno10004,53.099998,55.099998,403,NA,…<br />
+ id,pheno10001,pheno10002,pheno10003,pheno10004,53.099998,…<br />
+ IND001,61.400002,49,62.5,55.099998,…<br />
+ IND002,54.099998,50.099998,53.299999,55.099998,…<br />
+ IND003,483,403,501,403,…<br />
+ IND004,49.799999,45.5,62.900002,NA,…<br />
⋮<br /></code>
<p>where <code>IND001,IND002,IND003,IND004,…</code> are the
@@ -346,12 +448,6 @@
{%endblock%}
{%block sidebarcontents%}
-{{display_preview_table("tbl-preview-pheno-desc", "descriptions")}}
-{{display_preview_table("tbl-preview-pheno-data", "data")}}
-{%if population.Family in families_with_se_and_n%}
-{{display_preview_table("tbl-preview-pheno-se", "standard errors")}}
-{{display_preview_table("tbl-preview-pheno-n", "number of samples")}}
-{%endif%}
{{display_pheno_dataset_card(species, population, dataset)}}
{%endblock%}
@@ -429,9 +525,9 @@
});
if(table.find("tbody tr.data-row").length > 0) {
- add_class(table.find(".data-row-template"), "hidden");
+ add_class(table.find(".data-row-template"), "visually-hidden");
} else {
- remove_class(table.find(".data-row-template"), "hidden");
+ remove_class(table.find(".data-row-template"), "visually-hidden");
}
};
@@ -467,13 +563,24 @@
Object.entries(preview_tables_to_elements_map).forEach((mapentry) => {
var preview_table = $(mapentry[0]);
var file_input = $(mapentry[1]);
- if(file_input.length === 1) {
+ if(file_input[0].files.length > 0) {
readFirstNLines(
file_input[0].files[0],
10,
[makePreviewUpdater(preview_table)]);
}
});
+
+ if(typeof(resumables) !== "undefined") {
+ resumables.forEach((resumable) => {
+ if(resumable.files.length > 0) {
+ readFirstNLines(
+ resumable.files[0].file,
+ 10,
+ [makePreviewUpdater(resumable.preview_table)]);
+ }
+ });
+ }
};
[
@@ -506,7 +613,7 @@
var display_element = display_area
.find(".file-display-template")
.clone();
- remove_class(display_element, "hidden");
+ remove_class(display_element, "visually-hidden");
remove_class(display_element, "file-display-template");
add_class(display_element, "file-display");
display_element.find(".filename").text(file.name
@@ -526,7 +633,7 @@
return () => {/*Has no event!*/
var progress = (resumable.progress() * 100).toFixed(2);
var pbar = progress_bar.find(".progress-bar");
- remove_class(progress_bar, "hidden");
+ remove_class(progress_bar, "visually-hidden");
pbar.css("width", progress+"%");
pbar.attr("aria-valuenow", progress);
pbar.text("Uploading: " + progress + "%");
@@ -536,9 +643,9 @@
var retryUpload = (retry_button, cancel_button) => {
retry_button.on("click", (event) => {
resumable.files.forEach((file) => {file.retry();});
- add_class(retry_button, "hidden");
- remove_class(cancel_button, "hidden");
- add_class(browse_button, "hidden");
+ add_class(retry_button, "visually-hidden");
+ remove_class(cancel_button, "visually-hidden");
+ add_class(browse_button, "visually-hidden");
});
};
@@ -549,18 +656,18 @@
file.abort();
}
});
- add_class(cancel_button, "hidden");
- remove_class(retry_button, "hidden");
- remove_class(browse_button, "hidden");
+ add_class(cancel_button, "visually-hidden");
+ remove_class(retry_button, "visually-hidden");
+ remove_class(browse_button, "visually-hidden");
});
};
var startUpload = (browse_button, retry_button, cancel_button) => {
return (event) => {
- remove_class(cancel_button, "hidden");
- add_class(retry_button, "hidden");
- add_class(browse_button, "hidden");
+ remove_class(cancel_button, "visually-hidden");
+ add_class(retry_button, "visually-hidden");
+ add_class(browse_button, "visually-hidden");
};
};
@@ -574,6 +681,7 @@
}));
});
formdata.append("resumable-upload", "true");
+ formdata.append("publication-id", $("#txt-publication-id").val());
return formdata;
}
@@ -642,7 +750,7 @@
file_input.parent(),
$("#" + resumable_element_id),
submit_button,
- ["csv", "tsv"]),
+ ["csv", "tsv", "txt"]),
file_input.parent(),
$("#" + resumable_element_id),
$("#" + resumable_element_id + "-browse-button")),
@@ -678,13 +786,20 @@
["frm-add-phenotypes", "finput-phenotype-se", "resumable-phenotype-se", "tbl-preview-pheno-se"],
["frm-add-phenotypes", "finput-phenotype-n", "resumable-phenotype-n", "tbl-preview-pheno-n"],
].map((row) => {
- return makeResumableObject(row[0], row[1], row[2], row[3]);
+ r = makeResumableObject(row[0], row[1], row[2], row[3]);
+ r.preview_table = $("#" + row[3]);
+ return r;
}).filter((val) => {
return Boolean(val);
});
$("#frm-add-phenotypes input[type=submit]").on("click", (event) => {
event.preventDefault();
+ console.debug();
+ if ($("#txt-publication-id").val() == "") {
+ alert("You MUST provide a publication for the phenotypes.");
+ return false;
+ }
// TODO: Check all the relevant files exist
// TODO: Verify that files are not duplicated
var filenames = [];
diff --git a/uploader/templates/phenotypes/bulk-edit-upload.html b/uploader/templates/phenotypes/bulk-edit-upload.html
new file mode 100644
index 0000000..d0f38f5
--- /dev/null
+++ b/uploader/templates/phenotypes/bulk-edit-upload.html
@@ -0,0 +1,62 @@
+{%extends "phenotypes/base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "macro-table-pagination.html" import table_pagination%}
+{%from "populations/macro-display-population-card.html" import display_population_card%}
+
+{%block title%}Phenotypes{%endblock%}
+
+{%block pagetitle%}Phenotypes{%endblock%}
+
+{%block lvl4_breadcrumbs%}
+<li {%if activelink=="view-dataset"%}
+ class="breadcrumb-item active"
+ {%else%}
+ class="breadcrumb-item"
+ {%endif%}>
+ <a href="{{url_for('species.populations.phenotypes.view_dataset',
+ species_id=species.SpeciesId,
+ population_id=population.Id,
+ dataset_id=dataset.Id)}}">View</a>
+</li>
+{%endblock%}
+
+{%block contents%}
+<div class="row">
+ <p>Upload the edited file you downloaded and edited.</p>
+</div>
+
+<div class="row">
+ <form id="frm-bulk-edit-upload"
+ class="form-horizontal"
+ method="POST"
+ action="{{url_for(
+ 'species.populations.phenotypes.edit_upload_phenotype_data',
+ species_id=species.SpeciesId,
+ population_id=population.Id,
+ dataset_id=dataset.Id)}}"
+ enctype="multipart/form-data">
+
+ <div class="form-group row">
+ <label for="file-upload-bulk-edit-upload"
+ class="form-label col-form-label col-sm-2">
+ Edited File</label>
+ <div class="col-sm-10">
+ <input id="file-upload-bulk-edit-upload"
+ name="file-upload-bulk-edit-upload"
+ class="form-control"
+ type="file"
+ accept="text/tab-separated-values"
+ required="required" />
+ </div>
+ </div>
+
+ <input type="submit" class="btn btn-primary"
+ value="upload to edit" />
+
+ </form>
+</div>
+{%endblock%}
+
+
+{%block javascript%}
+{%endblock%}
diff --git a/uploader/templates/phenotypes/create-dataset.html b/uploader/templates/phenotypes/create-dataset.html
index 8e45491..19a2b34 100644
--- a/uploader/templates/phenotypes/create-dataset.html
+++ b/uploader/templates/phenotypes/create-dataset.html
@@ -42,7 +42,7 @@
<input type="text"
name="dataset-name"
id="txt-dataset-name"
- value="{{original_formdata.get('dataset-name') or (population.InbredSetCode + 'Publish')}}"
+ value="{{original_formdata.get('dataset-name') or (population.Name + 'Publish')}}"
{%if errors["dataset-name"] is defined%}
class="form-control danger"
{%else%}
@@ -51,7 +51,7 @@
required="required" />
<small class="form-text text-muted">
<p>A short representative name for the dataset.</p>
- <p>Recommended: Use the population code and append "Publish" at the end.
+ <p>Recommended: Use the population name and append "Publish" at the end.
<br />This field will only accept names composed of
letters ('A-Za-z'), numbers (0-9), hyphens and underscores.</p>
</small>
@@ -86,7 +86,7 @@
name="dataset-shortname"
type="text"
class="form-control"
- value="{{original_formdata.get('dataset-shortname') or (population.InbredSetCode + ' Publish')}}" />
+ value="{{original_formdata.get('dataset-shortname') or (population.Name + 'Publish')}}" />
<small class="form-text text-muted">
<p>An optional, short name for the dataset. <br />
If this is not provided, it will default to the value provided for the
diff --git a/uploader/templates/phenotypes/load-phenotypes-success.html b/uploader/templates/phenotypes/load-phenotypes-success.html
new file mode 100644
index 0000000..645be16
--- /dev/null
+++ b/uploader/templates/phenotypes/load-phenotypes-success.html
@@ -0,0 +1,42 @@
+{%extends "phenotypes/base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "macro-table-pagination.html" import table_pagination%}
+{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%}
+
+{%block title%}Phenotypes{%endblock%}
+
+{%block pagetitle%}Phenotypes{%endblock%}
+
+{%block lvl4_breadcrumbs%}
+<li {%if activelink=="load-phenotypes-success"%}
+ class="breadcrumb-item active"
+ {%else%}
+ class="breadcrumb-item"
+ {%endif%}>
+ <a href="{{url_for('species.populations.phenotypes.add_phenotypes',
+ species_id=species.SpeciesId,
+ population_id=population.Id,
+ dataset_id=dataset.Id)}}">Add Phenotypes</a>
+</li>
+{%endblock%}
+
+{%block contents%}
+<div class="row">
+ <p>You have successfully loaded
+ <!-- maybe indicate the number of phenotypes here? -->your
+ new phenotypes into the database.</p>
+ <!-- TODO: Maybe notify user that they have sole access. -->
+ <!-- TODO: Maybe provide a link to go to GeneNetwork to view the data. -->
+ <p>View your data
+ <a href="{{search_page_uri}}"
+ target="_blank">on GeneNetwork2</a>.
+ You might need to login to GeneNetwork2 to view specific traits.</p>
+</div>
+{%endblock%}
+
+{%block sidebarcontents%}
+{{display_pheno_dataset_card(species, population, dataset)}}
+{%endblock%}
+
+
+{%block more_javascript%}{%endblock%}
diff --git a/uploader/templates/phenotypes/macro-display-preview-table.html b/uploader/templates/phenotypes/macro-display-preview-table.html
index f54c53e..5a4c422 100644
--- a/uploader/templates/phenotypes/macro-display-preview-table.html
+++ b/uploader/templates/phenotypes/macro-display-preview-table.html
@@ -1,7 +1,7 @@
{%macro display_preview_table(tableid, filetype)%}
-<div class="card" style="max-width: 676px;">
+<div class="card">
<div class="card-body">
- <h5 class="card-title">Phenotypes '{{filetype | title}}' File Preview</h5>
+ <h5 class="card-title">{{filetype | title}}: File Preview</h5>
<div class="card-text" style="overflow: scroll;">
<table id="{{tableid}}" class="table table-condensed table-responsive">
<thead>
@@ -9,9 +9,7 @@
</tr>
<tbody>
<tr>
- <td class="data-row-template text-info">
- Provide a phenotype '{{filetype | lower}}' file to preview.
- </td>
+ <td class="data-row-template text-info"></td>
</tr>
</tbody>
</table>
diff --git a/uploader/templates/phenotypes/macro-display-resumable-elements.html b/uploader/templates/phenotypes/macro-display-resumable-elements.html
index b0bf1b5..ed14ea5 100644
--- a/uploader/templates/phenotypes/macro-display-resumable-elements.html
+++ b/uploader/templates/phenotypes/macro-display-resumable-elements.html
@@ -1,6 +1,6 @@
{%macro display_resumable_elements(id, title, help)%}
<div id="{{id}}"
- class="resumable-elements hidden"
+ class="resumable-elements visually-hidden"
style="background:#D4D4EE;border-radius: 5px;;padding: 1em;border-left: solid #B2B2CC 1px;border-bottom: solid #B2B2CC 2px;margin-top:0.3em;">
<strong style="line-height: 1.2em;">{{title | title}}</strong>
@@ -9,7 +9,7 @@
<div id="{{id}}-selected-files"
class="resumable-selected-files"
style="display:flex;flex-direction:row;flex-wrap: wrap;justify-content:space-around;gap:10px 20px;">
- <div class="panel panel-info file-display-template hidden">
+ <div class="panel panel-info file-display-template visually-hidden">
<div class="panel-heading filename">The Filename Goes Here!</div>
<div class="panel-body">
<ul>
@@ -33,10 +33,10 @@
<a id="{{id}}-browse-button"
class="resumable-browse-button btn btn-info"
- href="#"
+ href="#{{id}}"
style="margin-left: 80%;">Browse</a>
- <div id="{{id}}-progress-bar" class="progress hidden">
+ <div id="{{id}}-progress-bar" class="progress visually-hidden">
<div class="progress-bar"
role="progress-bar"
aria-valuenow="60"
@@ -49,11 +49,11 @@
<div id="{{id}}-cancel-resume-buttons">
<a id="{{id}}-resume-button"
- class="resumable-resume-button btn btn-info hidden"
+ class="resumable-resume-button btn btn-info visually-hidden"
href="#">resume upload</a>
<a id="{{id}}-cancel-button"
- class="resumable-cancel-button btn btn-danger hidden"
+ class="resumable-cancel-button btn btn-danger visually-hidden"
href="#">cancel upload</a>
</div>
</div>
diff --git a/uploader/templates/phenotypes/review-job-data.html b/uploader/templates/phenotypes/review-job-data.html
index 7bc8c62..859df74 100644
--- a/uploader/templates/phenotypes/review-job-data.html
+++ b/uploader/templates/phenotypes/review-job-data.html
@@ -35,14 +35,28 @@
{%if job%}
<div class="row">
<h3 class="heading">Data Review</h3>
+ <p class="text-info"><strong>
+ The data has <em>NOT</em> been added/saved yet. Review the details below
+ and click "Continue" to save the data.</strong></p>
<p>The &#x201C;<strong>{{dataset.FullName}}</strong>&#x201D; dataset from the
&#x201C;<strong>{{population.FullName}}</strong>&#x201D; population of the
species &#x201C;<strong>{{species.SpeciesName}} ({{species.FullName}})</strong>&#x201D;
will be updated as follows:</p>
+ <ul>
+ {%if publication%}
+ <li>All {{summary.get("pheno", {}).get("total-data-rows", "0")}} phenotypes
+ are linked to the following publication:
+ <ul>
+ <li><strong>Publication Title:</strong>
+ {{publication.Title or "—"}}</li>
+ <li><strong>Author(s):</strong>
+ {{publication.Authors or "—"}}</li>
+ </ul>
+ </li>
+ {%endif%}
{%for ftype in ("phenocovar", "pheno", "phenose", "phenonum")%}
{%if summary.get(ftype, False)%}
- <ul>
<li>A total of {{summary[ftype]["number-of-files"]}} files will be processed
adding {%if ftype == "phenocovar"%}(possibly){%endif%}
{{summary[ftype]["total-data-rows"]}} new
@@ -53,11 +67,21 @@
{%endif%}
to the database.
</li>
- </ul>
{%endif%}
{%endfor%}
+ </ul>
- <a href="#" class="not-implemented btn btn-primary">continue</a>
+ <form id="frm-review-phenotype-data"
+ method="POST"
+ action="{{url_for('species.populations.phenotypes.load_data_to_database',
+ species_id=species.SpeciesId,
+ population_id=population.Id,
+ dataset_id=dataset.Id)}}">
+ <input type="hidden" name="data-qc-job-id" value="{{job.jobid}}" />
+ <input type="submit"
+ value="continue"
+ class="btn btn-primary" />
+ </form>
</div>
{%else%}
<div class="row">
diff --git a/uploader/templates/phenotypes/view-dataset.html b/uploader/templates/phenotypes/view-dataset.html
index 10fd428..21563d6 100644
--- a/uploader/templates/phenotypes/view-dataset.html
+++ b/uploader/templates/phenotypes/view-dataset.html
@@ -89,7 +89,12 @@
{%block javascript%}
<script type="text/javascript">
$(function() {
+ var species_id = {{species.SpeciesId}};
+ var population_id = {{population.Id}};
+ var dataset_id = {{dataset.Id}};
+ var dataset_name = "{{dataset.Name}}";
var data = {{phenotypes | tojson}};
+
var dtPhenotypesList = buildDataTable(
"#tbl-phenotypes-list",
data,
@@ -142,19 +147,83 @@
},
{
text: "Bulk Edit (Download Data)",
+ className: "btn btn-info btn-bulk-edit",
+ titleAttr: "Click to download data for editing.",
action: (event, dt, node, config) => {
- alert("Not implemented yet!");
- },
- className: "btn btn-info",
- titleAttr: "Click to download data for editing."
+ var phenoids = [];
+ var selected = dt.rows({selected: true, page: "all"}).data();
+ for(var idx = 0; idx < selected.length; idx++) {
+ phenoids.push({
+ phenotype_id: selected[idx].Id,
+ xref_id: selected[idx].xref_id
+ });
+ }
+ if(phenoids.length == 0) {
+ alert("No record selected. Nothing to do!");
+ return false;
+ }
+
+ $(".btn-bulk-edit").prop("disabled", true);
+ $(".btn-bulk-edit").addClass("d-none");
+ var spinner = $(
+ "<div id='bulk-edit-spinner' class='spinner-grow text-info'>");
+ spinner_content = $(
+ "<span class='visually-hidden'>");
+ spinner_content.html(
+ "Downloading data &hellip;");
+ spinner.append(spinner_content)
+ $(".btn-bulk-edit").parent().append(
+ spinner);
+
+ $.ajax(
+ (`/species/${species_id}/populations/` +
+ `${population_id}/phenotypes/datasets/` +
+ `${dataset_id}/edit-download`),
+ {
+ method: "POST",
+ data: JSON.stringify(phenoids),
+ xhrFields: {
+ responseType: "blob"
+ },
+ success: (data, textStatus, jqXHR) => {
+ var link = document.createElement("a");
+ uri = window.URL.createObjectURL(data);
+ link.href = uri;
+ link.download = `${dataset_name}_data.tsv`;
+
+ document.body.appendChild(link);
+ link.click();
+ window.URL.revokeObjectURL(uri);
+ link.remove();
+ },
+ error: (jQXHR, textStatus, errorThrown) => {
+ console.log("Experienced an error: ", textStatus);
+ console.log("The ERROR: ", errorThrown);
+ },
+ complete: (jqXHR, textStatus) => {
+ $("#bulk-edit-spinner").remove();
+ $(".btn-bulk-edit").removeClass(
+ "d-none");
+ $(".btn-bulk-edit").prop(
+ "disabled", false);
+ },
+ contentType: "application/json"
+ });
+ }
},
{
text: "Bulk Edit (Upload Data)",
+ className: "btn btn-info btn-bulk-edit",
+ titleAttr: "Click to upload edited data you got by clicking the `Bulk Edit (Download Data)` button.",
action: (event, dt, node, config) => {
- alert("Not implemented yet!")
- },
- className: "btn btn-info",
- titleAttr: "Click to upload edited data you got by clicking the `Bulk Edit (Download Data)` button."
+ window.location.assign(
+ `${window.location.protocol}//` +
+ `${window.location.host}` +
+ `/species/${species_id}` +
+ `/populations/${population_id}` +
+ `/phenotypes/datasets/${dataset_id}` +
+ `/edit-upload`)
+ }
}
]
},