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
52 changes: 52 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2163,6 +2163,14 @@ <h3>No suggestions yet</h3>
<div class="panel-header">
<div class="panel-title">Query History</div>
<button class="btn-clear" id="clearHistoryBtn" aria-label="Clear query history">Clear</button>

<button class="btn-clear" id="downloadJsonBtn" aria-label="Download history as JSON">
Download JSON
</button>

<button class="btn-clear" id="downloadCsvBtn" aria-label="Download history as CSV">
Download CSV
</button>
</div>
<div class="history-list" id="historyList" aria-live="polite">
<div class="list-empty">No history yet. Run your first analysis.</div>
Expand Down Expand Up @@ -3065,6 +3073,50 @@ <h3>Quality Score</h3>
renderHistory();
toast('History cleared', 'info');
});

document.getElementById('downloadJsonBtn').addEventListener('click', () => {
if (!history || history.length === 0) {
toast('No history to download', 'info');
return;
}
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(history, null, 2));
const dlNode = document.createElement('a');
dlNode.setAttribute("href", dataStr);
dlNode.setAttribute("download", "history.json");
document.body.appendChild(dlNode);
dlNode.click();
dlNode.remove();
toast('Downloaded history.json', 'success');
});

document.getElementById('downloadCsvBtn').addEventListener('click', () => {
if (!history || history.length === 0) {
toast('No history to download', 'info');
return;
}

const headers = Object.keys(history[0]);
const csvRows = [];
csvRows.push(headers.join(','));

for (const row of history) {
const values = headers.map(header => {
let val = row[header] === null || row[header] === undefined ? '' : String(row[header]);
val = val.replace(/"/g, '""');
return `"${val}"`;
});
csvRows.push(values.join(','));
}

const csvContent = "data:text/csv;charset=utf-8," + encodeURIComponent(csvRows.join('\n'));
const dlNode = document.createElement('a');
dlNode.setAttribute("href", csvContent);
dlNode.setAttribute("download", "history.csv");
document.body.appendChild(dlNode);
dlNode.click();
dlNode.remove();
toast('Downloaded history.csv', 'success');
});
function loadEntry(id) {
const entry = history.find(h => h.id === Number (id));
console.log(entry);
Expand Down
56 changes: 56 additions & 0 deletions frontend/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,62 @@ document.getElementById('clearHistoryBtn').addEventListener('click', () => {
renderHistory();
});

// ── Download History JSON ──
document.getElementById('downloadJsonBtn').addEventListener('click', () => {

if (history.length === 0) {
showToast('No history to download');
return;
}

const blob = new Blob(
[JSON.stringify(history, null, 2)],
{ type: 'application/json' }
);

const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'analysis-history.json';
a.click();
URL.revokeObjectURL(a.href);

});
// ── Download History CSV ──
document.getElementById('downloadCsvBtn').addEventListener('click', () => {

if (history.length === 0) {
showToast('No history to download');
return;
}

const headers = ['id', 'preview', 'mode', 'time'];

const rows = history.map(h =>
[
h.id,
`"${(h.preview || '').replace(/"/g, '""')}"`,
h.mode,
h.time
].join(',')
);

const csvContent = [
headers.join(','),
...rows
].join('\n');

const blob = new Blob(
[csvContent],
{ type: 'text/csv' }
);

const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'analysis-history.csv';
a.click();
URL.revokeObjectURL(a.href);
});

// ── Run Button ──
runBtn.addEventListener('click', runAnalysis);

Expand Down