added submission history, data insights, download all functionality

This commit is contained in:
2026-06-01 12:54:56 +02:00
parent 9a6fa22d84
commit bee7b74e53
19 changed files with 1863 additions and 110 deletions

View File

@ -124,6 +124,9 @@ function renderExportTableBody() {
body.querySelectorAll('.export-btn').forEach(btn => {
btn.addEventListener('click', onExportCsvClick);
});
body.querySelectorAll('.export-btn-all').forEach(btn => {
btn.addEventListener('click', onExportAllVersionsClick);
});
}
function exportRowHTML(q) {
@ -134,11 +137,14 @@ function exportRowHTML(q) {
<td><span class="badge badge-${(q.state || 'draft').toLowerCase()}">${esc(q.state || 'draft')}</span></td>
<td>${q.questionCount || 0}</td>
<td>${q.completedCount ?? 0}</td>
<td>
<button class="btn btn-sm btn-primary export-btn" data-id="${esc(q.questionnaireID)}" data-name="${esc(q.name)}" data-version="${esc(q.version)}">
Export CSV
<td class="export-actions-cell">
<button class="btn btn-sm btn-primary export-btn" data-id="${esc(q.questionnaireID)}" data-name="${esc(q.name)}" data-version="${esc(q.version)}" data-all="0">
Export current
</button>
<a href="#/questionnaire/${esc(q.questionnaireID)}/results" class="btn btn-sm">View Results</a>
<button class="btn btn-sm export-btn-all" data-id="${esc(q.questionnaireID)}" data-name="${esc(q.name)}">
All versions
</button>
<a href="#/questionnaire/${esc(q.questionnaireID)}/results" class="btn btn-sm">Results</a>
</td>
</tr>`;
}
@ -176,32 +182,56 @@ function wireExportActions() {
});
}
async function downloadExportCsv(btn, url, filename) {
const token = localStorage.getItem('qdb_token');
const res = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok) {
const err = await res.json().catch(() => ({ error: 'Download failed' }));
throw new Error(err.error?.message || err.error || 'Download failed');
}
const blob = await res.blob();
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = filename;
a.click();
URL.revokeObjectURL(blobUrl);
}
async function onExportCsvClick(ev) {
const btn = ev.currentTarget;
btn.disabled = true;
btn.textContent = 'Downloading...';
const prev = btn.textContent;
btn.textContent = 'Downloading…';
try {
const token = localStorage.getItem('qdb_token');
const res = await fetch(`../api/export.php?questionnaireID=${encodeURIComponent(btn.dataset.id)}&format=csv`, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok) {
const err = await res.json().catch(() => ({ error: 'Download failed' }));
throw new Error(err.error);
}
const blob = await res.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${btn.dataset.name}_v${btn.dataset.version}.csv`;
a.click();
URL.revokeObjectURL(url);
const url = `../api/export?questionnaireID=${encodeURIComponent(btn.dataset.id)}`;
await downloadExportCsv(btn, url, `${btn.dataset.name}_v${btn.dataset.version}.csv`);
showToast('Download started', 'success');
} catch (e) {
showToast(e.message, 'error');
} finally {
btn.disabled = false;
btn.textContent = 'Export CSV';
btn.textContent = prev;
}
}
async function onExportAllVersionsClick(ev) {
const btn = ev.currentTarget;
btn.disabled = true;
const prev = btn.textContent;
btn.textContent = 'Downloading…';
try {
const url = `../api/export?questionnaireID=${encodeURIComponent(btn.dataset.id)}&allVersions=1`;
const stamp = new Date().toISOString().slice(0, 10);
await downloadExportCsv(btn, url, `${btn.dataset.name}_all_versions_${stamp}.csv`);
showToast('All versions download started', 'success');
} catch (e) {
showToast(e.message, 'error');
} finally {
btn.disabled = false;
btn.textContent = prev;
}
}