added quesionnaire export and import

This commit is contained in:
2026-05-22 17:36:40 +02:00
parent be01b85569
commit 244fd16140
8 changed files with 523 additions and 18 deletions

View File

@ -1,4 +1,4 @@
import { apiGet, apiPut, apiDelete } from '../api.js';
import { apiGet, apiPost, apiPut, apiDelete } from '../api.js';
import { canEdit, showToast, getRole } from '../app.js';
import { navigate } from '../router.js';
@ -14,8 +14,11 @@ export async function dashboardPage() {
if (canEdit()) {
document.getElementById('headerActions').innerHTML = `
<input type="file" id="importBundleFile" accept=".json,application/json" hidden>
<button type="button" class="btn" id="importBundleBtn">Import questionnaires</button>
<a href="#/questionnaire/new" class="btn btn-primary">+ New Questionnaire</a>
`;
bindImportBundle();
}
try {
@ -143,6 +146,61 @@ function initGridDrag(questionnaires) {
});
}
function bindImportBundle() {
const fileInput = document.getElementById('importBundleFile');
const btn = document.getElementById('importBundleBtn');
if (!fileInput || !btn) return;
btn.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', async () => {
const file = fileInput.files?.[0];
fileInput.value = '';
if (!file) return;
let bundle;
try {
const text = await file.text();
bundle = JSON.parse(text);
} catch {
showToast('Invalid JSON file', 'error');
return;
}
if (!bundle?.questionnaires || !Array.isArray(bundle.questionnaires)) {
showToast('Not a questionnaire bundle (missing questionnaires array)', 'error');
return;
}
const count = bundle.questionnaires.length;
if (!confirm(`Import ${count} questionnaire(s) from this file?`)) return;
const replace = confirm(
'If a questionnaire ID from the file already exists:\n\n' +
'OK — replace that questionnaire\n' +
'Cancel — import as a new copy (new ID)'
);
btn.disabled = true;
const prev = btn.textContent;
btn.textContent = 'Importing…';
try {
const result = await apiPost('questionnaires.php', {
action: 'importBundle',
bundle,
replaceIfExists: replace,
});
const n = result.imported ?? count;
showToast(`Imported ${n} questionnaire(s)`, 'success');
await dashboardPage();
} catch (e) {
showToast(e.message, 'error');
} finally {
btn.disabled = false;
btn.textContent = prev;
}
});
}
function esc(s) {
const d = document.createElement('div');
d.textContent = s ?? '';