Skip to content

Commit 1ab162c

Browse files
committed
feat: process data summary export
for: - checklists - checklist breakdown - critical incidents critical incident breakdowns *not* included because they seem to be broken see: nditech/apollo-issues#230
1 parent fa2baa7 commit 1ab162c

3 files changed

Lines changed: 72 additions & 7 deletions

File tree

apollo/process_analysis/templates/process_analysis/checklist_summary.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ <h4 class="font-weight-light mt-4{{ ' rtl' if g.locale.text_direction == 'rtl' e
148148
tableData.push(row1);
149149
tableData.push(row2);
150150

151-
return [tableData, splitCols];
151+
return tableData;
152152
};
153153

154154
document.querySelector('#export-btn').addEventListener('click', () => {
@@ -159,15 +159,14 @@ <h4 class="font-weight-light mt-4{{ ' rtl' if g.locale.text_direction == 'rtl' e
159159
const workbook = XLSX.utils.book_new();
160160
let worksheet;
161161
tables.forEach((table, index) => {
162-
const [tableData, splitCols] = extractTableData(table);
162+
const tableData = extractTableData(table);
163163
if (index === 0) {
164164
worksheet = XLSX.utils.aoa_to_sheet(tableData);
165165
} else {
166166
XLSX.utils.sheet_add_aoa(worksheet, tableData, {origin: -1});
167167
}
168168
createGapRows(worksheet, 2);
169169
});
170-
// console.log(extractTableData(tables[0]));
171170
const formName = tables[0].dataset.formName;
172171
const filename = `${formName}-process-data-summary-${Math.floor((new Date()).getTime() / 1000)}.xlsx`;
173172
XLSX.utils.book_append_sheet(workbook, worksheet, formName);

apollo/process_analysis/templates/process_analysis/checklist_summary_breakdown.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
<script>
143143
const loader = () => {
144144
document.querySelector('#export-btn').addEventListener('click', () => {
145-
const table = document.querySelector('table[data-aummary-table]');
145+
const table = document.querySelector('table[data-summary-table]');
146146
if (!table) {
147147
return;
148148
}

apollo/process_analysis/templates/process_analysis/critical_incident_summary.html

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
<label for="{{ filter_form.status.id }}" class="sr-only">{{ filter_form.status.label.text }}</label>
1515
{{ filter_form.status(class_='form-control custom-select') }}
1616
</div>
17-
<button type="submit" class="btn btn-primary">{{ _('Filter') }}</button>
17+
<button type="submit" class="btn btn-primary mr-sm-2">{{ _('Filter') }}</button>
18+
<a class="btn btn-outline-secondary" id="export-btn">{{ _('Export process summary') }}</a>
1819
</div>
1920
</form>
2021
{%- endblock %}
@@ -31,7 +32,7 @@
3132
{% if incidents_summary.top %}
3233
<h4 class="font-weight-light mt-4{{ ' rtl' if g.locale.text_direction == 'rtl' else '' }}">{{ _('Summary') }}</h4>
3334
<div class="table-responsive">
34-
<table class="table table-bordered table-striped">
35+
<table class="table table-bordered table-striped" data-summary-table data-form-name="{{ form.name }}">
3536
<tr class="{{ 'rtl' if g.locale.text_direction == 'rtl' else '' }}">
3637
<th width="250">{{ _('Location') }}</th>
3738
<th width="100" style="text-align:center">N</th>
@@ -79,7 +80,7 @@ <h5 class="font-weight-light{{ ' rtl' if g.locale.text_direction == 'rtl' else '
7980
{% set question_summary = form|checklist_question_summary(field, location, dataframe) %}
8081
{% set stats = question_summary.stats %}
8182
<div class="table-responsive">
82-
<table width="100%" class="table table-striped table-bordered">
83+
<table width="100%" class="table table-striped table-bordered" data-summary-table data-form-name="{{ form.name }}">
8384
<tr class="{{ 'rtl' if g.locale.text_direction == 'rtl' else '' }}">
8485
<td width="30" rowspan="{% if stats.urban %}4{% else %}2{% endif %}"><strong>{{ field.tag }}</strong></td>
8586
<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>
@@ -138,3 +139,68 @@ <h5 class="font-weight-light{{ ' rtl' if g.locale.text_direction == 'rtl' else '
138139
</div>
139140
</div>
140141
{% endblock %}
142+
{% block scripts %}
143+
<script src="{{ url_for('static', filename='js/xlsx.mini.min.js') }}"></script>
144+
<script>
145+
const loader = () => {
146+
document.querySelector('#export-btn').addEventListener('click', () => {
147+
const createGapRows = (worksheet, nrows) => {
148+
let ref = XLSX.utils.decode_range(worksheet['!ref']);
149+
ref.e.r += nrows;
150+
worksheet['!ref'] = XLSX.utils.encode_range(ref);
151+
};
152+
153+
const tryParseNumericValue = value => {
154+
const result = Number.parseInt(value);
155+
return isNaN(result) ? value : result;
156+
};
157+
158+
const extractTableData = table => {
159+
let tableData = [], splitCols = {};
160+
Array.from(table.rows).forEach(row => {
161+
let rowData = [];
162+
Array.from(row.cells).forEach(cell => {
163+
if (cell.childNodes.length > 1) {
164+
if (cell.querySelector('br')) {
165+
const value = cell.childNodes[2].textContent.replace('(', '').replace(')', '').trim();
166+
rowData.push(Number.parseInt(value));
167+
} else {
168+
rowData.push(cell.textContent.trim());
169+
}
170+
} else {
171+
rowData.push(tryParseNumericValue(cell.textContent.trim()));
172+
}
173+
});
174+
tableData.push(rowData);
175+
});
176+
177+
return tableData;
178+
};
179+
180+
const tables = Array.from(document.querySelectorAll('table[data-summary-table]'));
181+
if (tables.length === 0) {
182+
return;
183+
}
184+
185+
///*
186+
const workbook = XLSX.utils.book_new();
187+
let worksheet;
188+
tables.forEach((table, index) => {
189+
if (index === 0) {
190+
worksheet = XLSX.utils.aoa_to_sheet(extractTableData(table))
191+
} else {
192+
XLSX.utils.sheet_add_dom(worksheet, table, {origin: -1})
193+
}
194+
createGapRows(worksheet, 2);
195+
});
196+
const formName = tables[0].dataset.formName;
197+
const filename = `${formName}-process-data-summary-${Math.floor((new Date()).getTime() / 1000)}.xlsx`;
198+
XLSX.utils.book_append_sheet(workbook, worksheet, formName);
199+
XLSX.writeFile(workbook, filename);
200+
//*/
201+
//console.log(extractTableData(tables[0]));
202+
});
203+
};
204+
document.addEventListener('DOMContentLoaded', loader);
205+
</script>
206+
{% endblock scripts %}

0 commit comments

Comments
 (0)