Merge branch 'feature/csv_data' into 'master'

Export data in CSV format

Closes #126

See merge request cara/cara!383
This commit is contained in:
Andre Henriques 2022-09-05 10:18:25 +02:00
commit 5a02b5b5ce
5 changed files with 166 additions and 3 deletions

View file

@ -144,6 +144,9 @@ p.notes {
#button_alternative_full_exposure, #button_alternative_hide_high_concentration {
display: none!important;
}
#export-csv {
display: none;
}
}

View file

@ -860,4 +860,99 @@ function copy_clipboard(shareable_link) {
.tooltip('show');
navigator.clipboard.writeText(shareable_link);
}
function check_download_button() {
// Handle the disable property of the download button
let download_button = document.getElementById('downloadCSV');
document.querySelectorAll('input[type="checkbox"]:checked').length <= 1 ? download_button.disabled = true : download_button.disabled = false;
}
function display_column_name_warning(checked) {
let warning_element = document.getElementById("alternative_scenario_warning");
checked ? warning_element.style.display = 'flex' : warning_element.style.display = 'none';
}
function display_rename_column(bool, id) {
check_download_button();
// Change the visibility of renaming section
if (bool) document.getElementById(id).style.display = 'flex';
else document.getElementById(id).style.display = 'none';
}
function export_csv() {
// This function generates a CSV file according to the user's input.
// It is composed of a list of lists.
// The first item of the main list corresponds to the columns' name.
// The remaining items correspond to each of the file row, i.e. the
// respective data from the selected inputs.
let final_export = [];
// Verify which items are checked
let export_lists = document.getElementsByName('checkedItems');
let checked_items = []; // The column to be added, with the id to be identified.
let checked_names = []; // The column with the respective rename.
let has_alternative_scenario = false;
export_lists.forEach(e => {
if (e.checked) {
if (e.id == "Alternative Scenarios") {
Object.entries(alternative_scenarios).map((scenario) => {
if (scenario[0] != 'Current scenario') {
checked_names.push(`Alternative scenario concentration - ${scenario[0]} \u2028(virions m⁻³)`);
has_alternative_scenario = true;
};
});
}
else if (e.id == "Cumulative Dose") {
var has_rename = document.getElementById(`${e.id}__rename`).value;
var column_name = has_rename != '' ? has_rename : e.id;
if (short_range_expirations.length > 0) {
checked_names.push(`Long-Range ${column_name} \u2028(infectious virus)`);
checked_items.push('Long-Range Dose');
// When we have short range interactions, we want the column for the cumulative dose to have the "Total" word before the column name
checked_names.push(`Total ${column_name} \u2028(infectious virus)`);
}
else {
checked_names.push(`${column_name} \u2028(infectious virus)`);
}
checked_items.push(e.id);
}
else {
var has_rename = document.getElementById(`${e.id}__rename`).value;
var column_name = has_rename != '' ? has_rename : e.id;
if (e.id == "Time") checked_names.push(`${column_name} \u2028(h)`);
else if (e.id == "Concentration") checked_names.push(`${column_name} \u2028(virions m⁻³)`);
checked_items.push(e.id);
}
}
});
final_export.push(checked_names);
// Add data for each column.
times.forEach((e, i) => {
let this_row = [];
checked_items.includes("Time") && this_row.push(times[i].toFixed(2));
checked_items.includes("Concentration") && this_row.push(concentrations[i]);
checked_items.includes("Cumulative Dose") && this_row.push(cumulative_doses[i]);
checked_items.includes("Long-Range Dose") && this_row.push(long_range_cumulative_doses[i]);
if (has_alternative_scenario) {
Object.entries(alternative_scenarios).map((scenario) => {
if (scenario[0] != 'Current scenario') {
this_row.push(scenario[1].concentrations[i]);
};
});
};
final_export.push(this_row);
});
// Prepare the CSV file.
let csvContent = "data:text/csv;charset=utf8,"
+ final_export.map(e => e.join(",")).join("\n");
var encodedUri = encodeURI(csvContent);
// Set a name for the file.
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "report_data.csv");
document.body.appendChild(link);
link.click();
}

View file

@ -296,7 +296,7 @@ footer img {
#report_version {
font-size: .5rem;
}
#download-pdf, #pdf_qrcode_aref {
#download-pdf, #pdf_qrcode_aref, #export-csv {
display: none;
}
#scale_warning{

View file

@ -30,7 +30,9 @@
<h2 class="header_text mb-0"><a href="{{ permalink.shortened }}" style="color: #2f4858">REPORT - {{ form.simulation_name }}</a></h2>
<p class="mb-0" id="report_version"> Created {{ creation_date }} using CARA calculator version v{{ form.calculator_version }}</p>
</div>
<button type="button" class="btn btn-outline-dark align-self-center" id="download-pdf" style="margin-right: -100pt" onclick="print();">Print Report</button>
<!-- Export CVS Concentration Button and Print Report Button -->
<button type="button" class="btn btn-outline-dark align-self-center" id="export-csv" data-toggle="modal" data-target="#modalCSV">Export Data</button>
<button type="button" class="btn btn-outline-dark align-self-center ml-3" id="download-pdf" style="margin-right: -100pt" onclick="print();">Print Report</button>
<a href="{{ permalink.link }}" style="float: left;" id="pdf_qrcode_aref" class="align-self-center invisible mr-0"><div id="pdf_qrcode"></div></a>
</div>
@ -224,6 +226,70 @@
{% endif %}
{% endblock report_results %}
<!-- Export Data Concentration Modal -->
<div class="modal fade" id="modalCSV" tabindex="-1" role="dialog" aria-labelledby="modalCSV" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Export data (.csv)</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<b>Select the data to export:</b>
<div class="form-check mt-3">
<input type="checkbox" class="form-check-input" name="checkedItems" id="Time" onclick="display_rename_column(this.checked, 'time-rename-div')" checked disabled>
<label class="form-check-label" for="Time">Time of day</label>
<div id="time-rename-div" class="d-flex align-items-center">
<label class="col-form-label" for="time-rename-div">Column name:</label>
<input type="text" class="form-control form-control-sm col-sm-4 ml-2" id="Time__rename" placeholder="Time" value="Time">
</div>
</div>
{# If short-range interactions are set, we don't display Alternative Scenarios, and there is no need to arrange items in a list #}
{% if form.short_range_option == "short_range_no" %}
<ul style="padding-left: inherit">
<li>
Current Scenario
{% endif %}
<div class="form-check">
<input type="checkbox" class="form-check-input" name="checkedItems" id="Concentration" onclick="display_rename_column(this.checked, 'concentration-rename-div')">
<label class="form-check-label" for="Concentration">Concentration</label>
<div id="concentration-rename-div" class="align-items-center" style="display:none">
<label class="col-form-label" for="concentration-rename-div">Column name:</label>
<input type="text" class="form-control form-control-sm col-sm-4 ml-2" id="Concentration__rename" placeholder="Concentration" value="Concentration">
</div>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" name="checkedItems" id="Cumulative Dose" onclick="display_rename_column(this.checked, 'cumulative-dose-rename-div')">
<label class="form-check-label" for="Cumulative Dose">Cumulative dose</label>
<div id="cumulative-dose-rename-div" class="align-items-center" style="display:none">
<label class="col-form-label" for="cumulative-dose-rename-div">Column name:</label>
<input type="text" class="form-control form-control-sm col-sm-4 ml-2" id="Cumulative Dose__rename" placeholder="Cumulative Dose" value="Cumulative Dose">
</div>
</div>
{% if form.short_range_option == "short_range_no" %}
</li>
<li>
Alternative Scenarios
<div class="form-check">
<input type="checkbox" class="form-check-input" name="checkedItems" id="Alternative Scenarios" onclick="check_download_button(); display_column_name_warning(this.checked);">
<label class="form-check-label" for="Alternative Scenarios">Concentration</label>
<p id="alternative_scenario_warning" class="text-warning" style="display: none">The column name will be the scenario name.</p>
</div>
</li>
{% endif %}
</ul>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button id="downloadCSV" type="button" class="btn btn-primary" onclick="export_csv();" disabled>Download</button>
</div>
</div>
</div>
</div>
{% block report_footer %}
<div class="card bg-light mb-3" id="link-results">
<div class="card-header"><strong>Link to reproduce results </strong>

View file

@ -2,7 +2,6 @@
{% set active_page="home/" %}
{% block main %}
{# <div style="height: 5em; display: block;"></div> #}
<header class= "bg-light">
<div class="container container--padding">
<img src="/static/images/cara_full_text.png" class="logo d-block m-auto" id="desktop_logo">