Add CSV export on bids page + various fixes.

This commit is contained in:
gerlofvanek 2025-02-24 23:28:39 +01:00
parent 033b0a1583
commit 06d37a2e54
2 changed files with 163 additions and 5 deletions
basicswap
static/js
templates

View file

@ -0,0 +1,141 @@
const BidExporter = {
toCSV(bids, type) {
if (!bids || !bids.length) {
return 'No data to export';
}
const isSent = type === 'sent';
const headers = [
'Date/Time',
'Bid ID',
'Offer ID',
'From Address',
isSent ? 'You Send Amount' : 'You Receive Amount',
isSent ? 'You Send Coin' : 'You Receive Coin',
isSent ? 'You Receive Amount' : 'You Send Amount',
isSent ? 'You Receive Coin' : 'You Send Coin',
'Status',
'Created At',
'Expires At'
];
let csvContent = headers.join(',') + '\n';
bids.forEach(bid => {
const row = [
`"${formatTime(bid.created_at)}"`,
`"${bid.bid_id}"`,
`"${bid.offer_id}"`,
`"${bid.addr_from}"`,
isSent ? bid.amount_from : bid.amount_to,
`"${isSent ? bid.coin_from : bid.coin_to}"`,
isSent ? bid.amount_to : bid.amount_from,
`"${isSent ? bid.coin_to : bid.coin_from}"`,
`"${bid.bid_state}"`,
bid.created_at,
bid.expire_at
];
csvContent += row.join(',') + '\n';
});
return csvContent;
},
download(content, filename) {
try {
const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
return;
}
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
setTimeout(() => {
URL.revokeObjectURL(url);
}, 100);
} catch (error) {
console.error('Error downloading CSV:', error);
const csvData = 'data:text/csv;charset=utf-8,' + encodeURIComponent(content);
const link = document.createElement('a');
link.setAttribute('href', csvData);
link.setAttribute('download', filename);
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
},
exportCurrentView() {
const type = state.currentTab;
const data = state.data[type];
if (!data || !data.length) {
alert('No data to export');
return;
}
const csvContent = this.toCSV(data, type);
const now = new Date();
const dateStr = now.toISOString().split('T')[0];
const filename = `${type}_bids_${dateStr}.csv`;
this.download(csvContent, filename);
}
};
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
if (typeof state !== 'undefined' && typeof EventManager !== 'undefined') {
const exportSentButton = document.getElementById('exportSentBids');
if (exportSentButton) {
EventManager.add(exportSentButton, 'click', (e) => {
e.preventDefault();
state.currentTab = 'sent';
BidExporter.exportCurrentView();
});
}
const exportReceivedButton = document.getElementById('exportReceivedBids');
if (exportReceivedButton) {
EventManager.add(exportReceivedButton, 'click', (e) => {
e.preventDefault();
state.currentTab = 'received';
BidExporter.exportCurrentView();
});
}
}
}, 500);
});
const originalCleanup = window.cleanup || function(){};
window.cleanup = function() {
originalCleanup();
const exportSentButton = document.getElementById('exportSentBids');
const exportReceivedButton = document.getElementById('exportReceivedBids');
if (exportSentButton && typeof EventManager !== 'undefined') {
EventManager.remove(exportSentButton, 'click');
}
if (exportReceivedButton && typeof EventManager !== 'undefined') {
EventManager.remove(exportReceivedButton, 'click');
}
};

View file

@ -1,9 +1,9 @@
{% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, page_back_svg, page_forwards_svg, filter_clear_svg, filter_apply_svg, circular_arrows_svg, input_arrow_down_svg, arrow_right_svg %}
<div class="xl:container mx-auto">
<section class="py-3 px-4 mt-6">
<div class="xl:container mx-auto">
<section class="py-3 px-4 mt-6">
<div class="lg:container mx-auto">
<div class="relative py-8 px-8 bg-coolGray-900 dark:bg-blue-500 rounded-md overflow-hidden">
<img class="absolute z-10 left-4 top-4" src="/static/images/elements/dots-red.svg" alt="">
<img class="absolute z-10 right-4 bottom-4" src="/static/images/elements/dots-red.svg" alt="">
@ -20,6 +20,7 @@
{% include 'inc_messages.html' %}
<div class="xl:container mx-auto">
<section>
<div class="pl-6 pr-6 pt-0 mt-5 h-full overflow-hidden">
<div class="flex flex-wrap items-center justify-between -m-2">
@ -42,6 +43,7 @@
</div>
</div>
</section>
</div>
<section>
<div class="px-6 py-0 h-full overflow-hidden">
@ -229,6 +231,14 @@
<span id="refreshSentText">Refresh</span>
</button>
{% endif %}
<button id="exportSentBids" class="ml-4 inline-flex items-center px-4 py-2.5 font-medium text-sm text-white bg-green-600 hover:bg-green-700 hover:border-green-700 rounded-lg transition duration-200 border border-green-600 rounded-md shadow-button focus:ring-0 focus:outline-none">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span>Export CSV</span>
</button>
</div>
<div id="pagination-controls-sent" class="flex items-center space-x-2" style="display: none;">
<button id="prevPageSent" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-green-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
@ -254,7 +264,6 @@
</div>
</div>
<!-- Received Bids Tab -->
<div class="hidden rounded-lg lg:px-6" id="received" role="tabpanel" aria-labelledby="received-tab">
<div id="received-content">
<div class="xl:container mx-auto lg:px-0">
@ -319,6 +328,14 @@
<span id="refreshReceivedText">Refresh</span>
</button>
{% endif %}
<button id="exportReceivedBids" class="ml-4 inline-flex items-center px-4 py-2.5 font-medium text-sm text-white bg-green-600 hover:bg-green-700 hover:border-green-700 rounded-lg transition duration-200 border border-green-600 rounded-md shadow-button focus:ring-0 focus:outline-none">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span>Export CSV</span>
</button>
</div>
<div id="pagination-controls-received" class="flex items-center space-x-2" style="display: none;">
<button id="prevPageReceived" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-green-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
@ -344,8 +361,8 @@
</div>
</div>
</div>
</div>
<script src="/static/js/bids_sentreceived.js"></script>
<script src="/static/js/bids_export.js"></script>
{% include 'footer.html' %}