feat: add export/import buttons to tickets UI

This commit is contained in:
caoimhinr 2026-06-03 21:03:49 +02:00
parent f354c0ea89
commit 762ae81345

View file

@ -282,6 +282,11 @@ textarea.desc-input {
<div class="search-wrap"> <div class="search-wrap">
<input type="search" id="search-input" placeholder="Search tickets…" autocomplete="off" title="Search title & description (/)"> <input type="search" id="search-input" placeholder="Search tickets…" autocomplete="off" title="Search title & description (/)">
</div> </div>
<button class="btn btn-subtle btn-sm" onclick="exportTickets(); event.stopPropagation()">Export</button>
<label class="btn btn-subtle btn-sm" style="cursor:pointer" title="Import tickets from JSON">
Import
<input type="file" accept=".json,application/json" onchange="importTickets(event)" style="display:none">
</label>
<button class="btn btn-primary btn-sm" onclick="openCreate(); event.stopPropagation()">+ New Ticket</button> <button class="btn btn-primary btn-sm" onclick="openCreate(); event.stopPropagation()">+ New Ticket</button>
</div> </div>
</div> </div>
@ -1186,6 +1191,43 @@ document.getElementById('env-create-overlay').addEventListener('click', e => {
document.addEventListener('click', () => closeEnvDropdown()); document.addEventListener('click', () => closeEnvDropdown());
document.getElementById('env-selector').addEventListener('click', e => e.stopPropagation()); document.getElementById('env-selector').addEventListener('click', e => e.stopPropagation());
// ── Export / Import ──────────────────────────────────────────────────────────
async function exportTickets() {
try {
const data = await api('/api/tickets/export');
const blob = new Blob([JSON.stringify(data, null, 2)], {type: 'application/json'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
const ts = new Date().toISOString().slice(0, 10);
a.href = url;
a.download = `tickets-export-${ts}.json`;
a.click();
URL.revokeObjectURL(url);
} catch(e) {
toast(e.message, true);
}
}
async function importTickets(event) {
const file = event.target.files?.[0];
if (!file) return;
event.target.value = '';
try {
const text = await file.text();
const body = JSON.parse(text);
const result = await api('/api/tickets/import', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(body),
});
toast(`Imported ${result.imported} ticket(s)`);
await loadEnvironments();
} catch(e) {
toast(e.message || 'Import failed', true);
}
}
loadEnvironments(); loadEnvironments();
</script> </script>
{% endblock %} {% endblock %}