diff --git a/caimira/apps/calculator/static/js/co2_form.js b/caimira/apps/calculator/static/js/co2_form.js
index 59189d37..bf9751bd 100644
--- a/caimira/apps/calculator/static/js/co2_form.js
+++ b/caimira/apps/calculator/static/js/co2_form.js
@@ -1,7 +1,5 @@
-// JS file to handle manipulation on CO2 Fitting Algorithm Dialog.
const CO2_data_form = [
'CO2_data',
- 'specific_breaks',
'exposed_coffee_break_option',
'exposed_coffee_duration',
'exposed_finish',
@@ -9,6 +7,8 @@ const CO2_data_form = [
'exposed_lunch_option',
'exposed_lunch_start',
'exposed_start',
+ 'fitting_ventilation_states',
+ 'fitting_ventilation_type',
'infected_coffee_break_option',
'infected_coffee_duration',
'infected_dont_have_breaks_with_exposed',
@@ -21,174 +21,239 @@ const CO2_data_form = [
'room_volume',
'total_people',
'ventilation_type',
- 'windows_duration',
- 'windows_frequency',
- 'window_opening_regime',
-]
-
-// Method to upload a valid excel file
-function upload_file() {
- clear_fitting_result_component();
- $("#generate_fitting_data").show();
- $("#save_and_dismiss_dialog").hide();
- var files = document.getElementById("file_upload").files;
- if (files.length == 0) {
- alert("Please choose any file...");
- return;
+ ];
+
+ // Method to upload a valid excel file
+ function uploadFile(endpoint) {
+ clearFittingResultComponent();
+ const files = document.getElementById("file_upload").files;
+ if (files.length === 0) {
+ alert("Please choose any file...");
+ return;
}
- const filename = files[0].name;
- const extension = filename.substring(filename.lastIndexOf(".")).toUpperCase();
- if (extension == ".XLS" || extension == ".XLSX") {
- //Here calling another method to read excel file into json
- excelFileToJSON(files[0]);
- } else {
- alert("Please select a valid excel file.");
- }
-}
-
-//Method to read excel file and convert it into JSON
-function excelFileToJSON(file) {
+ const file = files[0];
+ const extension = file.name.substring(file.name.lastIndexOf(".")).toUpperCase();
+ extension === ".XLS" || extension === ".XLSX"
+ ? excelFileToJSON(endpoint, file)
+ : alert("Please select a valid excel file.");
+ }
+
+ // Method to read excel file and convert it into JSON
+ function excelFileToJSON(endpoint, file) {
try {
- var reader = new FileReader();
- reader.readAsBinaryString(file);
- reader.onload = function (e) {
- var data = e.target.result;
- var workbook = XLSX.read(data, { type: "binary" });
- var firstSheetName = workbook.SheetNames[0];
- //reading only first sheet data
- var jsonData = XLSX.utils.sheet_to_json(workbook.Sheets[firstSheetName]);
- //displaying the json result into HTML table
- displayJsonToHtmlTable(jsonData);
- };
+ const reader = new FileReader();
+ reader.readAsBinaryString(file);
+ reader.onload = function (e) {
+ const data = e.target.result;
+ const workbook = XLSX.read(data, { type: "binary" });
+ const firstSheetName = workbook.SheetNames[0];
+ const jsonData = XLSX.utils.sheet_to_json(workbook.Sheets[firstSheetName]);
+ displayJsonToHtmlTable(endpoint, jsonData);
+ };
} catch (e) {
- console.error(e);
+ console.error(e);
}
-}
-
-//Method to display the data in HTML Table
-function displayJsonToHtmlTable(jsonData) {
- var table = document.getElementById("display_excel_data");
- var format = document.getElementById("formatted_data");
- let structure = { times: [], CO2: [] };
+ }
+
+ // Method to display the data in HTML Table
+ function displayJsonToHtmlTable(endpoint, jsonData) {
+ const table = document.getElementById("display_excel_data");
+ const format = document.getElementById("CO2_data");
+ const structure = { times: [], CO2: [] };
if (jsonData.length > 0) {
- var htmlData = "
| Time | CO2 Value |
";
- let jsonLength = jsonData.length;
- for (var i = 0; i < jsonLength; i++) {
- var row = jsonData[i];
- if (i < 5) {
- htmlData +=
- `|
- ${row["Times"].toFixed(2)}
- |
- ${row["CO2"].toFixed(2)}
- |
`;
- }
- structure["times"].push(row["Times"]);
- structure["CO2"].push(row["CO2"]);
+ let htmlData = "| Time | CO2 Value |
";
+ const jsonLength = jsonData.length;
+ for (let i = 0; i < jsonLength; i++) {
+ const row = jsonData[i];
+ if (i < 5) {
+ htmlData += `
+
+ | ${row["Times"].toFixed(2)} |
+ ${row["CO2"].toFixed(2)} |
+
`;
}
-
- if (jsonLength >= 5) htmlData += "| ... | ... |
";
- table.innerHTML = htmlData;
- format.value = JSON.stringify(structure);
- $('#generate_fitting_data').prop("disabled", false);
+ structure.times.push(row["Times"]);
+ structure.CO2.push(row["CO2"]);
+ }
+
+ if (jsonLength >= 5) {
+ htmlData += "| ... | ... |
";
+ }
+ format.value = JSON.stringify(structure);
+ $('#generate_fitting_data').prop("disabled", false);
+ $('#fitting_ventilation_states').prop('disabled', false);
+ $('[name=fitting_ventilation_type]').prop('disabled', false);
+ plotCO2Data(endpoint);
} else {
- table.innerHTML = "There is no data in the spreadsheet file";
+ table.innerHTML = "There is no data in the spreadsheet file";
}
-}
-
-// Method to download Excel template available on CERNBox
-function downloadTemplate(uri = 'https://caimira-resources.web.cern.ch/CO2_template.xlsx', filename = 'CO2_template.xlsx') {
- var link = document.createElement("a");
+ }
+
+ // Method to download Excel template available on CERNBox
+ function downloadTemplate(uri = 'https://caimira-resources.web.cern.ch/CO2_template.xlsx', filename = 'CO2_template.xlsx') {
+ const link = document.createElement("a");
link.download = filename;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
-}
-
-function insertErrorFor(referenceNode, text) {
- var element = document.createElement("span");
+ }
+
+ function insertErrorFor(referenceNode, text) {
+ const element = document.createElement("span");
element.setAttribute("class", "error_text");
element.classList.add("red_text");
element.innerHTML = " " + text;
$(referenceNode).before(element);
-}
-
-function validate() {
+ }
+
+ function validateFormInputs(obj) {
$('span.' + "error_text").remove();
let submit = true;
- for (var i = 0; i < CO2_data_form.length; i++) {
- let element = $(`[name=${CO2_data_form[i]}]`)[0];
- if (element.value === '') {
- insertErrorFor($('#CO2_input_data_div'), `'${element.name}' must be defined.`); // raise error for total number and room volume.
+ for (let i = 0; i < CO2_data_form.length; i++) {
+ const element = $(`[name=${CO2_data_form[i]}]`)[0];
+ if (element.name !== 'fitting_ventilation_states' && element.value === '') {
+ insertErrorFor($('#DIVCO2_data_dialog'), `'${element.name}' must be defined.
`);
+ submit = false;
+ }
+ }
+ if (submit) {
+ $($(obj).data('target')).modal('show');
+ }
+ return submit;
+ }
+
+function validateCO2Form() {
+ let submit = true;
+ if (validateFormInputs($('#button_fit_data'))) submit = true;
+
+ // Check if natural ventilation is selected
+ if ($('input[name="fitting_ventilation_type"]:checked')[0].value == 'fitting_natural_ventilation') {
+ // Validate ventilation scheme
+ const element = $('[name=fitting_ventilation_states')[0]
+ if (element.value !== '') {
+ // validate input format
+ try {
+ const parsedValue = JSON.parse(element.value);
+ if (!Array.isArray(parsedValue)) {
+ insertErrorFor($('#DIVCO2_fitting_result'), `'${element.name}' must be a list.`);
+ submit = false;
+ };
+ } catch {
+ insertErrorFor($('#DIVCO2_fitting_result'), `'${element.name}' must be a list of numbers.`);
+ submit = false;
+ };
+ } else {
+ insertErrorFor($('#DIVCO2_fitting_result'), `'${element.name}' must be defined.`);
submit = false;
};
- }
+ };
+
return submit;
}
-function display_transition_times_hour_format(start, stop) {
- var minutes_start = start % 1 * 60;
- var minutes_stop = stop % 1 * 60;
- return Math.floor(start) + ':' + minutes_start.toPrecision(2) + ' - ' + Math.floor(stop) + ':' + minutes_stop.toPrecision(2);
+function displayTransitionTimesHourFormat(start, stop) {
+ var minutes_start = (start % 1 * 60).toPrecision(2);
+ var minutes_stop = (stop % 1 * 60).toPrecision(2);
+ return Math.floor(start) + ':' + ((minutes_start != '0.0') ? minutes_start : '00') + ' - ' + Math.floor(stop) + ':' + ((minutes_stop != '0.0') ? minutes_stop : '00');
}
-function display_fitting_data(json_response) {
- $("#DIV_CO2_fitting_result").show();
+function displayFittingData(json_response) {
+ $("#DIVCO2_fitting_result").show();
$("#CO2_data_plot").attr("src", json_response['CO2_plot']);
// Not needed for the form submit
delete json_response['CO2_plot'];
$("#CO2_fitting_result").val(JSON.stringify(json_response));
$("#exhalation_rate_fit").html('Exhalation rate: ' + String(json_response['exhalation_rate'].toFixed(2)) + ' m³/h');
let ventilation_table = "| Time (HH:MM) | ACH value (h⁻¹) |
";
- json_response['ventilation_values'].map((val, index) => {
- let transition_times = display_transition_times_hour_format(json_response['transition_times'][index], json_response['transition_times'][index + 1]);
+ json_response['ventilation_values'].forEach((val, index) => {
+ let transition_times = displayTransitionTimesHourFormat(json_response['transition_times'][index], json_response['transition_times'][index + 1]);
ventilation_table += `| ${transition_times} | ${val.toPrecision(2)} |
`;
});
+ $('#disable_fitting_algorithm').prop('disabled', false);
$("#ventilation_rate_fit").html(ventilation_table);
$("#generate_fitting_data").html('Fit data');
$("#generate_fitting_data").hide();
$("#save_and_dismiss_dialog").show();
}
-function submit_fitting_algorithm(url) {
- if (validate()) {
- let CO2_mapping = {};
- CO2_data_form.map(el => {
- let element = $(`[name=${el}]`);
- // Validate radio buttons
- if (element.length != 1) CO2_mapping[element[0].name] = $(`[name=${element[0].name}]:checked`)[0].value
- else CO2_mapping[element[0].name] = element[0].value;
- })
- $('#CO2_input_data_div').show();
- $("#generate_fitting_data").html(
- `Loading...`
- );
- $('#CO2_input_data').html(JSON.stringify(CO2_mapping, null, "\t"))
+function formatCO2DataForm(CO2_data_form) {
+ let CO2_mapping = {};
+ CO2_data_form.map(el => {
+ let element = $(`[name=${el}]`);
+ // Validate checkboxes
+ if (element[0].type == 'checkbox') {
+ CO2_mapping[element[0].name] = String(+element[0].checked);
+ }
+ // Validate radio buttons
+ else if (element[0].type == 'radio') CO2_mapping[element[0].name] = $(`[name=${element[0].name}]:checked`)[0].value;
+ else CO2_mapping[element[0].name] = element[0].value;
+ });
+ return CO2_mapping;
+}
+
+function plotCO2Data(url) {
+ if (validateFormInputs()) {
+ let CO2_mapping = formatCO2DataForm(CO2_data_form);
fetch(url, {
method: "POST",
body: JSON.stringify(CO2_mapping),
})
- .then((response) => response.json())
- .then((json_response) => {
- display_fitting_data(json_response);
- });
+ .then((response) =>
+ response.json()
+ .then(json_response => $("#CO2_data_plot").attr("src", json_response['CO2_plot']))
+ .then($('#DIVCO2_fitting_to_submit').show())
+ .catch(error => console.log(error))
+ );
}
}
-function clear_fitting_result_component() {
- $('#generate_fitting_data').prop("disabled", true);
- $("#display_excel_data tbody").remove();
+function submitFittingAlgorithm(url) {
+ if (validateCO2Form()) {
+ // Disable all the ventilation inputs
+ $('#fitting_ventilation_states, [name=fitting_ventilation_type]').prop('disabled', true);
+
+ // Prepare data for submission
+ const CO2_mapping = formatCO2DataForm(CO2_data_form);
+ $('#CO2_input_data_div').show();
+ $('#disable_fitting_algorithm').prop('disabled', true);
+ $('#generate_fitting_data')
+ .html('Loading...')
+ .prop('disabled', true);
+ $('#CO2_input_data').html(JSON.stringify(CO2_mapping, null, '\t'));
+
+ fetch(url, {
+ method: 'POST',
+ body: JSON.stringify(CO2_mapping),
+ })
+ .then((response) => response.json())
+ .then((json_response) => {
+ displayFittingData(json_response);
+ });
+ }
+ }
+
+ function clearFittingResultComponent() {
+ // Remove all the previously generated fitting elements
+ $('#generate_fitting_data').prop('disabled', true);
$('#CO2_fitting_result').val('');
- $('#formatted_data').val('');
- $('span.' + "error_text").remove();
- $('#DIV_CO2_fitting_result').hide();
- $('#CO2_input_data_div').hide();
-}
-
-function clear_fitting_algorithm() {
- clear_fitting_result_component();
- $('#CO2_data_no').click();
- ventilation_from_fitting(false);
-}
+ $('#CO2_data').val('{}');
+ $('#fitting_ventilation_states').val('');
+ $('span.error_text').remove();
+ $('#DIVCO2_fitting_result, #CO2_input_data_div').hide();
+ $('#CO2_data_plot').attr('src', '');
+
+ // Update the ventilation scheme components
+ $('#fitting_ventilation_states, [name=fitting_ventilation_type]').prop('disabled', false);
+
+ // Update the bottom right buttons
+ $('#generate_fitting_data').show();
+ $('#save_and_dismiss_dialog').hide();
+ }
+
+ function disableFittingAlgorithm() {
+ clearFittingResultComponent();
+ $('#CO2_data_no').click();
+ }
+
diff --git a/caimira/apps/calculator/static/js/form.js b/caimira/apps/calculator/static/js/form.js
index 72eff671..f497a3c4 100644
--- a/caimira/apps/calculator/static/js/form.js
+++ b/caimira/apps/calculator/static/js/form.js
@@ -247,8 +247,6 @@ function on_ventilation_type_change() {
ventilation_types = $('input[type=radio][name=ventilation_type]');
ventilation_types.each(function (index) {
if (this.checked) {
-
- if ($(this).val() != 'from_fitting') $('#button_fit_data').attr('data-previous-vent', $(this).val())
getChildElement($(this)).show();
require_fields(this);
} else {
@@ -495,32 +493,13 @@ function on_coffee_break_option_change() {
}
}
-function ventilation_from_fitting(condition_from_fitting) {
- $('input[type=radio][id=no_ventilation]').prop("disabled", condition_from_fitting);
- $('input[type=radio][id=mechanical_ventilation]').prop("disabled", condition_from_fitting);
- $('input[type=radio][id=natural_ventilation]').prop("disabled", condition_from_fitting);
- $('input[type=radio][id=from_fitting]').prop("disabled", !condition_from_fitting);
- if (condition_from_fitting) {
- $('input[type=radio][id=from_fitting]').prop('checked',true);
- $('#DIVfrom_fitting').after($('#window_opening_regime'));
- }
- else {
- let selected_ventilation = $("#button_fit_data").attr('data-previous-vent');
- $(`input[type=radio][id=${selected_ventilation}]`).prop('checked',true);
- $('#DIVopening_distance').after($('#window_opening_regime'));
- }
- on_ventilation_type_change();
-}
-
-function on_CO2_data_option_change() {
- CO2_data_options = $('input[type=radio][name=CO2_data_option]');
- CO2_data_options.each(function (index){
+function on_CO2_fitting_ventilation_change() {
+ ventilation_options = $('input[type=radio][name=fitting_ventilation_type]');
+ ventilation_options.each(function (index) {
if (this.checked) {
- if (this.id == 'CO2_data_yes') ventilation_from_fitting(true);
- else if (this.id == 'CO2_data_no') ventilation_from_fitting(false);
getChildElement($(this)).show();
require_fields(this);
- }
+ }
else {
getChildElement($(this)).hide();
require_fields(this);
@@ -700,6 +679,13 @@ function validate_form(form) {
on_short_range_option_change();
}
+ // Check if fitting is selected
+ if ($('input[type=radio][id=from_fitting]').prop('checked') ) {
+ if ($('#CO2_fitting_result').val() == '')
+ $("input[type=radio][id=no_ventilation]").prop("checked", true);
+ on_ventilation_type_change();
+ }
+
if (submit) {
$("#generate_report").prop("disabled", true);
//Add spinner to button
@@ -969,7 +955,7 @@ $(document).ready(function () {
// Populate CO2 Fitting Algorithm Dialog
let CO2_data = url.searchParams.has('CO2_fitting_result') ? url.searchParams.get('CO2_fitting_result') : null;
- if (CO2_data) display_fitting_data(JSON.parse(CO2_data));
+ if (CO2_data) displayFittingData(JSON.parse(CO2_data));
// Populate primary vaccine dropdown
$("#vaccine_type option").remove();
@@ -1086,11 +1072,11 @@ $(document).ready(function () {
// Call the function now to handle forward/back button presses in the browser.
on_coffee_break_option_change();
- // When the CO2_data_option changes we want to make its respective
+ // When the ventilation on the fitting changes we want to make its respective
// children show/hide.
- $("input[type=radio][name=CO2_data_option]").change(on_CO2_data_option_change);
+ $("input[type=radio][name=fitting_ventilation_type]").change(on_CO2_fitting_ventilation_change);
// Call the function now to handle forward/back button presses in the browser.
- on_CO2_data_option_change();
+ on_CO2_fitting_ventilation_change();
// Setup the maximum number of people at page load (to handle back/forward),
// and update it when total people is changed.