{% block export_history_html %}
<!-- Export History Modal -->
<div class="modal fade" id="exportHistoryModal" tabindex="-1" aria-labelledby="exportHistoryModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exportHistoryModalLabel">
<i data-lucide="clock" style="width: 18px; height: 18px;" class="me-2"></i>
Export History
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-0" id="exportHistoryContent">
<div class="text-center py-5">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" id="deleteExportsBtn" class="btn btn-outline-danger btn-sm me-auto" disabled>
<i data-lucide="trash-2" style="width: 14px; height: 14px;" class="me-1"></i>
Delete
</button>
<button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block export_history_js %}
<script>
$(document).ready(function() {
var $exportHistoryModal = $('#exportHistoryModal');
var $exportHistoryContent = $('#exportHistoryContent');
var currentPage = 1;
var isLoading = false;
// Load export history when modal opens
// Remove any existing handlers first to prevent duplicate requests
$exportHistoryModal.off('show.bs.modal').on('show.bs.modal', function() {
if (!isLoading) {
loadExportHistory(1);
}
});
// Use event delegation for pagination links (since content is replaced via AJAX)
$exportHistoryContent.on('click', '.export-history-page-link', function(e) {
e.preventDefault();
var page = $(this).data('page');
if (page && !isLoading) {
loadExportHistory(page);
}
});
// Select all checkbox handler
$(document).on('change', '#selectAllExports', function() {
var isChecked = $(this).is(':checked');
$('.export-checkbox').prop('checked', isChecked);
updateDeleteButton();
});
// Individual checkbox handler
$(document).on('change', '.export-checkbox', function() {
updateSelectAllCheckbox();
updateDeleteButton();
});
// Delete button handler
$('#deleteExportsBtn').on('click', function() {
var selectedTokens = $('.export-checkbox:checked').map(function() {
return $(this).data('token');
}).get();
if (selectedTokens.length === 0) {
return;
}
var count = selectedTokens.length;
var message = count === 1
? 'You are about to delete 1 export.'
: 'You are about to delete ' + count + ' exports.';
if (typeof Swal !== 'undefined') {
Swal.fire({
title: 'Delete Exports?',
text: message,
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#dc3545',
confirmButtonText: 'Yes, delete',
cancelButtonText: 'Cancel'
}).then(function(result) {
if (result.isConfirmed) {
deleteExports(selectedTokens);
}
});
} else if (confirm(message)) {
deleteExports(selectedTokens);
}
});
function updateSelectAllCheckbox() {
var totalCheckboxes = $('.export-checkbox').length;
var checkedCheckboxes = $('.export-checkbox:checked').length;
$('#selectAllExports').prop('checked', totalCheckboxes > 0 && totalCheckboxes === checkedCheckboxes);
}
function updateDeleteButton() {
var checkedCount = $('.export-checkbox:checked').length;
$('#deleteExportsBtn').prop('disabled', checkedCount === 0);
}
function deleteExports(tokens) {
$('#deleteExportsBtn').prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span>Deleting...');
$.ajax({
url: '/exports/delete',
method: 'DELETE',
contentType: 'application/json',
data: JSON.stringify({ tokens: tokens }),
success: function() {
loadExportHistory(currentPage);
$('#deleteExportsBtn').prop('disabled', true).html('<i data-lucide="trash-2" style="width: 14px; height: 14px;" class="me-1"></i>Delete');
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
},
error: function(xhr, status, error) {
console.error('Error deleting exports:', error);
alert('Failed to delete exports. Please try again.');
$('#deleteExportsBtn').prop('disabled', false).html('<i data-lucide="trash-2" style="width: 14px; height: 14px;" class="me-1"></i>Delete');
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
}
});
}
function loadExportHistory(page) {
// Prevent duplicate requests
if (isLoading) {
return;
}
isLoading = true;
currentPage = page;
// Show loading
$exportHistoryContent.html('<div class="text-center py-5"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>');
// Build URL with page, limit, and type as query parameter
// Route: /exports/list/{page?1}/{limit?20}
var url = '/exports/list/' + page + '/10?type=applications';
$.ajax({
url: url,
method: 'GET',
success: function(html) {
$exportHistoryContent.html(html);
// Re-initialize Lucide icons and tooltips
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
$('[data-bs-toggle="tooltip"]').each(function() {
new bootstrap.Tooltip(this);
});
// Reset checkboxes and delete button state
$('#selectAllExports').prop('checked', false);
updateDeleteButton();
isLoading = false;
},
error: function(xhr, status, error) {
console.error('Error loading export history:', error);
$exportHistoryContent.html('<div class="text-center py-5 text-danger"><i data-lucide="alert-circle" class="mb-2" style="width: 32px; height: 32px;"></i><p class="mb-0">Failed to load export history</p></div>');
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
isLoading = false;
}
});
}
});
</script>
{% endblock %}