Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
<label for="{{ filter_form.location_group.id }}" class="sr-only">{{ filter_form.location_group.label.text }}</label>
{{ filter_form.location_group(class_='form-control custom-select') }}
</div>
<button type="submit" class="btn btn-primary">{{ _('Filter') }}</button>
<button type="submit" class="btn btn-primary mr-sm-2">{{ _('Filter') }}</button>
</form>
<a class="btn btn-outline-secondary" id="export-btn">{{ _('Export process summary') }}</a>
</div>
{%- endblock %}

Expand All @@ -32,7 +33,7 @@ <h4 class="font-weight-light mt-4{{ ' rtl' if g.locale.text_direction == 'rtl' e
{% set question_summary = form|checklist_question_summary(field, location, dataframe) %}
{% set stats = question_summary.stats %}
<div class="table-responsive">
<table id="{{ field['tag'] }}" class="table table-striped table-bordered process" style="width:100%">
<table id="{{ field['tag'] }}" class="table table-striped table-bordered process" style="width:100%" data-summary-table="true" data-form-name="{{ form.name }}">
<thead>
<tr class="{{ 'rtl' if g.locale.text_direction == 'rtl' else '' }}">
<th>&nbsp;</th>
Expand Down Expand Up @@ -103,3 +104,75 @@ <h4 class="font-weight-light mt-4{{ ' rtl' if g.locale.text_direction == 'rtl' e
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/xlsx.mini.min.js') }}"></script>
<script type="text/javascript">
const loader = () => {
const createGapRows = (worksheet, nrows) => {
let ref = XLSX.utils.decode_range(worksheet['!ref']);
ref.e.r += nrows;
worksheet['!ref'] = XLSX.utils.encode_range(ref);
};

// this needs to be kept in sync with the HTML structure
// for the summary tables
const extractTableData = (table) => {
let tableData = [];

const row1 = [], row2 = [];
const splitCols = {};
Array.from(table.rows[1].cells).forEach((cell, index) => {
if (index === 0 || index === 1) {
row2.push(cell.textContent.trim());
splitCols[index] = false;
} else {
let colData;
if (cell.firstChild.tagName === 'STRONG') {
colData = cell.textContent;
splitCols[index] = false;
row2.push(Number.parseInt(`${colData.trim()}` || 0));
} else {
colData = cell.firstChild.children[0].textContent;
row2.push(colData.trim());
colData = cell.firstChild.children[1].textContent;
row2.push(Number.parseInt(`${colData.trim()}` || 0));
splitCols[index] = true;
}
}
});
Array.from(table.rows[0].cells).forEach((cell, index) => {
row1.push(cell.textContent.trim());
if (splitCols[index])
row1.push("");
});
tableData.push(row1);
tableData.push(row2);

return tableData;
};

document.querySelector('#export-btn').addEventListener('click', () => {
const tables = Array.from(document.querySelectorAll('table[data-summary-table]'));
if (tables.length === 0) {
return;
}
const workbook = XLSX.utils.book_new();
let worksheet;
tables.forEach((table, index) => {
const tableData = extractTableData(table);
if (index === 0) {
worksheet = XLSX.utils.aoa_to_sheet(tableData);
} else {
XLSX.utils.sheet_add_aoa(worksheet, tableData, {origin: -1});
}
createGapRows(worksheet, 2);
});
const formName = tables[0].dataset.formName;
const filename = `${formName}-process-data-summary-${Math.floor((new Date()).getTime() / 1000)}.xlsx`;
XLSX.utils.book_append_sheet(workbook, worksheet, formName);
XLSX.writeFile(workbook, filename);
});
};
document.addEventListener('DOMContentLoaded', loader);
</script>
{% endblock scripts %}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
<label for="{{ filter_form.location_group.id }}" class="sr-only">{{ filter_form.location_group.label.text }}</label>
{{ filter_form.location_group(class_='form-control custom-select') }}
</div>
<button type="submit" class="btn btn-primary">{{ _('Filter') }}</button>
<button type="submit" class="btn btn-primary mr-sm-2">{{ _('Filter') }}</button>
</form>
<a class="btn btn-outline-secondary" id="export-btn">{{ _('Export process summary') }}</a>
</div>
{%- endblock %}

Expand All @@ -27,7 +28,7 @@
<div class="tab-pane active" id="table">
{% for tag, question, tag_stats in process_summary.top %}
{% with field = form.get_field_by_tag(tag) %}
<table id="mytable" class="table table-striped table-bordered {{- ' rtl' if g.locale.text_direction == 'rtl' else '' }}">
<table id="mytable" class="table table-striped table-bordered {{- ' rtl' if g.locale.text_direction == 'rtl' else '' }}" data-summary-table data-form-name="{{ form.name }}" data-form-tag="{{ tag }}">
{% with %}
{% if field.get('null_value') is none %}{% set buffer = 0 %}{% else %}{% set buffer = 4 %}{% endif %}
<tr>
Expand Down Expand Up @@ -140,3 +141,21 @@
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/xlsx.mini.min.js') }}"></script>
<script>
const loader = () => {
document.querySelector('#export-btn').addEventListener('click', () => {
const table = document.querySelector('table[data-summary-table]');
if (!table) {
return;
}
const workbook = XLSX.utils.table_to_book(table);
const formName = table.dataset.formName;
const filename = `${formName}-process-data-summary-${Math.floor((new Date()).getTime() / 1000)}.xlsx`;
XLSX.writeFile(workbook, filename);
});
};
document.addEventListener('DOMContentLoaded', loader);
</script>
{% endblock scripts %}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
<label for="{{ filter_form.status.id }}" class="sr-only">{{ filter_form.status.label.text }}</label>
{{ filter_form.status(class_='form-control custom-select') }}
</div>
<button type="submit" class="btn btn-primary">{{ _('Filter') }}</button>
<button type="submit" class="btn btn-primary mr-sm-2">{{ _('Filter') }}</button>
<a class="btn btn-outline-secondary" id="export-btn">{{ _('Export process summary') }}</a>
</div>
</form>
{%- endblock %}
Expand All @@ -31,7 +32,7 @@
{% if incidents_summary.top %}
<h4 class="font-weight-light mt-4{{ ' rtl' if g.locale.text_direction == 'rtl' else '' }}">{{ _('Summary') }}</h4>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<table class="table table-bordered table-striped" data-summary-table data-form-name="{{ form.name }}">
<tr class="{{ 'rtl' if g.locale.text_direction == 'rtl' else '' }}">
<th width="250">{{ _('Location') }}</th>
<th width="100" style="text-align:center">N</th>
Expand Down Expand Up @@ -79,7 +80,7 @@ <h5 class="font-weight-light{{ ' rtl' if g.locale.text_direction == 'rtl' else '
{% set question_summary = form|checklist_question_summary(field, location, dataframe) %}
{% set stats = question_summary.stats %}
<div class="table-responsive">
<table width="100%" class="table table-striped table-bordered">
<table width="100%" class="table table-striped table-bordered" data-summary-table data-form-name="{{ form.name }}">
<tr class="{{ 'rtl' if g.locale.text_direction == 'rtl' else '' }}">
<td width="30" rowspan="{% if stats.urban %}4{% else %}2{% endif %}"><strong>{{ field.tag }}</strong></td>
<td rowspan="{% if stats.urban %}4{% else %}2{% endif %}"><a class="text-decoration-none" href="{{ url_for('process_analysis.process_analysis_with_location_and_tag', form_id=form.id, location_id=location.id, tag=field.tag) }}">{{ field.description }}</a></td>
Expand Down Expand Up @@ -138,3 +139,68 @@ <h5 class="font-weight-light{{ ' rtl' if g.locale.text_direction == 'rtl' else '
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/xlsx.mini.min.js') }}"></script>
<script>
const loader = () => {
document.querySelector('#export-btn').addEventListener('click', () => {
const createGapRows = (worksheet, nrows) => {
let ref = XLSX.utils.decode_range(worksheet['!ref']);
ref.e.r += nrows;
worksheet['!ref'] = XLSX.utils.encode_range(ref);
};

const tryParseNumericValue = value => {
const result = Number.parseInt(value);
return isNaN(result) ? value : result;
};

const extractTableData = table => {
let tableData = [], splitCols = {};
Array.from(table.rows).forEach(row => {
let rowData = [];
Array.from(row.cells).forEach(cell => {
if (cell.childNodes.length > 1) {
if (cell.querySelector('br')) {
const value = cell.childNodes[2].textContent.replace('(', '').replace(')', '').trim();
rowData.push(Number.parseInt(value));
} else {
rowData.push(cell.textContent.trim());
}
} else {
rowData.push(tryParseNumericValue(cell.textContent.trim()));
}
});
tableData.push(rowData);
});

return tableData;
};

const tables = Array.from(document.querySelectorAll('table[data-summary-table]'));
if (tables.length === 0) {
return;
}

///*
const workbook = XLSX.utils.book_new();
let worksheet;
tables.forEach((table, index) => {
if (index === 0) {
worksheet = XLSX.utils.aoa_to_sheet(extractTableData(table))
} else {
XLSX.utils.sheet_add_dom(worksheet, table, {origin: -1})
}
createGapRows(worksheet, 2);
});
const formName = tables[0].dataset.formName;
const filename = `${formName}-process-data-summary-${Math.floor((new Date()).getTime() / 1000)}.xlsx`;
XLSX.utils.book_append_sheet(workbook, worksheet, formName);
XLSX.writeFile(workbook, filename);
//*/
//console.log(extractTableData(tables[0]));
});
};
document.addEventListener('DOMContentLoaded', loader);
</script>
{% endblock scripts %}
10 changes: 10 additions & 0 deletions apollo/static/js/xlsx.mini.min.js

Large diffs are not rendered by default.