/** * Admin JavaScript for QDR Temporary Shared Storage plugin * * Handles all admin-side functionality including: * - Media page (loading, pagination, sorting, filtering, editing, deleting) * - Settings page (API key generation, settings saving, purging expired files) * * @package QDR_Temporary_Shared_Storage * @since 1.0.0 */ (function($) { 'use strict'; // Media page functionality var QDR_TSS_Media = { currentPage: 1, perPage: 10, totalPages: 1, currentOrderBy: 'upload_date', currentOrder: 'DESC', currentSearchFilename: '', currentSearchReference: '', /** * Initialize the media page */ init: function() { // Load items on page load this.loadItems(); // Initialize event handlers this.initEventHandlers(); // Initialize datepicker this.initDatepicker(); }, /** * Initialize event handlers */ initEventHandlers: function() { var self = this; // Handle sorting $('.qdr-tss-table th.sortable').on('click', function() { var column = $(this).data('sort'); if (self.currentOrderBy === column) { self.currentOrder = self.currentOrder === 'ASC' ? 'DESC' : 'ASC'; } else { self.currentOrderBy = column; self.currentOrder = 'ASC'; } self.loadItems(); }); // Handle search $('#qdr-tss-search-button').on('click', function() { self.currentSearchFilename = $('#qdr-tss-search-filename').val(); self.currentSearchReference = $('#qdr-tss-search-reference').val(); self.currentPage = 1; self.loadItems(); }); // Handle search reset $('#qdr-tss-reset-search').on('click', function() { $('#qdr-tss-search-filename').val(''); $('#qdr-tss-search-reference').val(''); self.currentSearchFilename = ''; self.currentSearchReference = ''; self.currentPage = 1; self.loadItems(); }); // Handle refresh button $('#qdr-tss-refresh').on('click', function() { self.loadItems(); }); // Handle modal close $('.qdr-tss-modal-close, .qdr-tss-modal-cancel').on('click', function() { $('.qdr-tss-modal').hide(); }); // Close modal when clicking outside $(window).on('click', function(e) { if ($(e.target).hasClass('qdr-tss-modal')) { $('.qdr-tss-modal').hide(); } }); // Handle copy shortcode $(document).on('click', '.qdr-tss-copy-shortcode', function() { var shortcode = $('#qdr-tss-details-shortcode code').text(); self.copyToClipboard(shortcode); alert(qdr_tss.strings.shortcode_copied); }); // Handle copy permalink $(document).on('click', '.qdr-tss-copy-permalink', function() { var permalink = $('#qdr-tss-details-permalink a').attr('href'); self.copyToClipboard(permalink); alert(qdr_tss.strings.permalink_copied); }); // Handle edit item form submission $('#qdr-tss-edit-form').on('submit', function(e) { e.preventDefault(); self.updateItem(); }); // Handle confirm delete $(document).on('click', '.qdr-tss-confirm-delete-button', function() { var id = $('#qdr-tss-delete-id').val(); self.deleteItem(id); }); }, /** * Initialize datepicker */ initDatepicker: function() { $(document).on('focus', '.qdr-tss-datepicker', function() { $(this).datepicker({ dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true }); }); }, /** * Initialize action buttons */ initActionButtons: function() { var self = this; // View button $('.qdr-tss-view-button').off('click').on('click', function() { var id = $(this).data('id'); self.viewItem(id); }); // Edit button $('.qdr-tss-edit-button').off('click').on('click', function() { var id = $(this).data('id'); self.editItem(id); }); // Delete button $('.qdr-tss-delete-button').off('click').on('click', function() { var id = $(this).data('id'); self.showDeleteConfirmation(id); }); // Pagination $('.qdr-tss-page-button').off('click').on('click', function() { self.currentPage = parseInt($(this).data('page')); self.loadItems(); }); }, /** * Load items */ loadItems: function() { var self = this; var data = { action: 'qdr_tss_get_items', nonce: qdr_tss.nonce, page: this.currentPage, per_page: this.perPage, orderby: this.currentOrderBy, order: this.currentOrder, original_file_name: this.currentSearchFilename, reference: this.currentSearchReference }; // Show loading indicator $('#qdr-tss-items-list').html(' ' + qdr_tss.strings.loading + ''); $.post(ajaxurl, data, function(response) { if (response.success) { self.renderItems(response.data.items); self.renderPagination(response.data.total, response.data.total_pages); } else { alert(response.data.message || qdr_tss.strings.error_loading_items); } }).fail(function() { $('#qdr-tss-items-list').html('' + qdr_tss.strings.error_loading_items_try_again + ''); }); }, /** * Render items */ renderItems: function(items) { var self = this; var $tbody = $('#qdr-tss-items-list'); $tbody.empty(); if (!items || items.length === 0) { $tbody.append('' + qdr_tss.strings.no_items_found + ''); return; } $.each(items, function(index, item) { var statusClass = self.getItemStatusClass(item); var row = ''; row += '' + item.fileid + ''; row += '' + self.escapeHtml(item.original_file_name) + ''; row += '' + self.escapeHtml(item.description || '') + ''; row += '' + self.escapeHtml(item.message || '') + ''; row += '' + self.formatDate(item.active_from) + ''; row += '' + self.formatDate(item.active_to) + ''; row += '' + self.escapeHtml(item.reference || '') + ''; row += '' + self.formatDate(item.upload_date) + ''; row += '' + item.download_count + ''; row += '' + (item.last_download ? self.formatDate(item.last_download) : '-') + ''; row += ''; row += '
'; row += ''; row += ''; row += ''; row += '
'; row += ''; row += ''; $tbody.append(row); }); // Initialize action buttons this.initActionButtons(); // Update sorting indicators this.updateSortIndicators(); }, /** * Get item status class */ getItemStatusClass: function(item) { var now = new Date(); var activeFrom = new Date(item.active_from); var activeTo = new Date(item.active_to); if (now < activeFrom) { return 'qdr-tss-status-pending'; } else if (now > activeTo) { return 'qdr-tss-status-expired'; } else { return 'qdr-tss-status-active'; } }, /** * Render pagination */ renderPagination: function(total, totalPages) { var $info = $('.qdr-tss-pagination-info'); var $controls = $('.qdr-tss-pagination-controls'); // Update info var startItem = (this.currentPage - 1) * this.perPage + 1; var endItem = Math.min(this.currentPage * this.perPage, total); if (total === 0) { $info.html(qdr_tss.strings.no_items); $controls.empty(); return; } $info.html(qdr_tss.strings.showing + ' ' + startItem + ' - ' + endItem + ' ' + qdr_tss.strings.of + ' ' + total); // Update controls $controls.empty(); if (totalPages <= 1) { return; } // First page if (this.currentPage > 1) { $controls.append(''); } // Previous page if (this.currentPage > 1) { $controls.append(''); } // Page numbers var startPage = Math.max(1, this.currentPage - 2); var endPage = Math.min(totalPages, startPage + 4); if (endPage - startPage < 4) { startPage = Math.max(1, endPage - 4); } for (var i = startPage; i <= endPage; i++) { var activeClass = i === this.currentPage ? 'button-primary' : ''; $controls.append(''); } // Next page if (this.currentPage < totalPages) { $controls.append(''); } // Last page if (this.currentPage < totalPages) { $controls.append(''); } // Rebind click events this.initActionButtons(); }, /** * Update sort indicators */ updateSortIndicators: function() { // Remove all indicators $('.qdr-tss-table th').removeClass('sorted asc desc'); // Add indicator to current sort column var $th = $('.qdr-tss-table th[data-sort="' + this.currentOrderBy + '"]'); $th.addClass('sorted ' + this.currentOrder.toLowerCase()); }, /** * View item details */ viewItem: function(id) { var self = this; // Show loading modal $('#qdr-tss-details-modal').show(); $('.qdr-tss-details-content').html('
' + qdr_tss.strings.loading + '
'); // Get additional data via AJAX var data = { action: 'qdr_tss_get_item_details', nonce: qdr_tss.nonce, id: id }; $.post(ajaxurl, data, function(response) { if (response.success) { var item = response.data.item; // Populate details $('#qdr-tss-details-fileid').text(item.fileid); $('#qdr-tss-details-filename').text(item.original_file_name); $('#qdr-tss-details-description').text(item.description || '-'); $('#qdr-tss-details-message').text(item.message || '-'); $('#qdr-tss-details-reference').text(item.reference || '-'); $('#qdr-tss-details-active-period').text(self.formatDate(item.active_from) + ' - ' + self.formatDate(item.active_to)); $('#qdr-tss-details-filesize').text(self.formatFileSize(item.file_size)); $('#qdr-tss-details-download-count').text(item.download_count); $('#qdr-tss-details-last-download').text(item.last_download ? self.formatDate(item.last_download) : '-'); // Permalink and shortcode $('#qdr-tss-details-permalink').html('' + item.permalink + ''); $('#qdr-tss-details-shortcode').html('' + item.shortcode + ''); // Initialize copy buttons $('.qdr-tss-copy-shortcode').data('text', item.shortcode); $('.qdr-tss-copy-permalink').data('text', item.permalink); } else { alert(response.data.message || qdr_tss.strings.error_loading_item_details); $('#qdr-tss-details-modal').hide(); } }).fail(function() { alert(qdr_tss.strings.error_loading_item_details_try_again); $('#qdr-tss-details-modal').hide(); }); }, /** * Edit item */ editItem: function(id) { // Find item in the table var $row = $('tr[data-id="' + id + '"]'); if ($row.length === 0) return; var $cells = $row.find('td'); // Populate form fields $('#qdr-tss-edit-id').val(id); $('#qdr-tss-edit-description').val($cells.eq(2).text()); $('#qdr-tss-edit-message').val($cells.eq(3).text()); // Parse dates for datepicker var activeFrom = $cells.eq(4).text(); var activeTo = $cells.eq(5).text(); $('#qdr-tss-edit-active-from').val(activeFrom !== '-' ? activeFrom : ''); $('#qdr-tss-edit-active-to').val(activeTo !== '-' ? activeTo : ''); $('#qdr-tss-edit-reference').val($cells.eq(6).text()); // Clear status $('#qdr-tss-edit-status').html(''); // Show modal $('#qdr-tss-edit-modal').show(); }, /** * Update item */ updateItem: function() { var self = this; // Show loading status $('#qdr-tss-edit-status').html('
' + qdr_tss.strings.saving + '
'); var data = { action: 'qdr_tss_edit_item', nonce: qdr_tss.nonce, id: $('#qdr-tss-edit-id').val(), description: $('#qdr-tss-edit-description').val(), message: $('#qdr-tss-edit-message').val(), active_from: $('#qdr-tss-edit-active-from').val(), active_to: $('#qdr-tss-edit-active-to').val(), reference: $('#qdr-tss-edit-reference').val() }; $.post(ajaxurl, data, function(response) { if (response.success) { // Show success status $('#qdr-tss-edit-status').html('

' + (response.data.message || qdr_tss.strings.changes_saved) + '

'); // Hide modal after a delay setTimeout(function() { $('#qdr-tss-edit-modal').hide(); // Reload items self.loadItems(); }, 1000); } else { // Show error status $('#qdr-tss-edit-status').html('

' + (response.data.message || qdr_tss.strings.error_saving_changes) + '

'); } }).fail(function() { // Show error status $('#qdr-tss-edit-status').html('

' + qdr_tss.strings.error_saving_changes_try_again + '

'); }); }, /** * Show delete confirmation */ showDeleteConfirmation: function(id) { $('#qdr-tss-delete-id').val(id); $('#qdr-tss-confirm-delete-modal').show(); }, /** * Delete item */ deleteItem: function(id) { var self = this; var data = { action: 'qdr_tss_delete_item', nonce: qdr_tss.nonce, id: id }; $.post(ajaxurl, data, function(response) { if (response.success) { // Hide modal $('#qdr-tss-confirm-delete-modal').hide(); // Show success message alert(response.data.message || qdr_tss.strings.file_deleted); // Reload items self.loadItems(); } else { alert(response.data.message || qdr_tss.strings.error_deleting_file); } }).fail(function() { alert(qdr_tss.strings.error_deleting_file_try_again); }); }, /** * Format date */ formatDate: function(dateString) { if (!dateString || dateString === '0000-00-00 00:00:00') { return '-'; } var date = new Date(dateString); // Check if date is valid if (isNaN(date.getTime())) { return dateString; } return date.toLocaleDateString() + ' ' + date.toLocaleTimeString(); }, /** * Format file size */ formatFileSize: function(bytes) { if (bytes === 0) return '0 Bytes'; var k = 1024; var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; var i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }, /** * Escape HTML */ escapeHtml: function(text) { if (!text) return ''; var map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.toString().replace(/[&<>"']/g, function(m) { return map[m]; }); }, /** * Copy to clipboard */ copyToClipboard: function(text) { var $temp = $(''); $('body').append($temp); $temp.val(text).select(); document.execCommand('copy'); $temp.remove(); } }; // Settings page functionality var QDR_TSS_Settings = { /** * Initialize the settings page */ init: function() { // Initialize event handlers this.initEventHandlers(); }, /** * Initialize event handlers */ initEventHandlers: function() { var self = this; // Generate new API key $('#qdr-tss-generate-key').on('click', function(e) { e.preventDefault(); self.generateApiKey(); }); // Save settings $('#qdr-tss-settings-form').on('submit', function(e) { e.preventDefault(); self.saveSettings(); }); // Purge expired files $('#qdr-tss-purge-expired').on('click', function(e) { e.preventDefault(); self.purgeExpiredFiles(); }); }, /** * Generate API key */ generateApiKey: function() { // Generate a random string for API key var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var apiKey = ''; for (var i = 0; i < 32; i++) { apiKey += chars.charAt(Math.floor(Math.random() * chars.length)); } $('#qdr-tss-api-key').val(apiKey); }, /** * Save settings */ saveSettings: function() { var data = { action: 'qdr_tss_save_settings', nonce: qdr_tss.nonce, api_key: $('#qdr-tss-api-key').val(), media_category: $('#qdr-tss-media-category').val(), max_upload_size: $('#qdr-tss-max-upload-size').val() }; $.post(ajaxurl, data, function(response) { if (response.success) { alert(response.data.message); } else { alert(response.data.message); } }); }, /** * Purge expired files */ purgeExpiredFiles: function() { if (!confirm(qdr_tss.strings.confirm_purge)) { return; } var data = { action: 'qdr_tss_purge_expired', nonce: qdr_tss.nonce }; $.post(ajaxurl, data, function(response) { if (response.success) { alert(response.data.message); // Reload page to update storage usage location.reload(); } else { alert(response.data.message); } }); } }; // Document ready $(function() { // Initialize appropriate page functionality if ($('.qdr-tss-table').length) { QDR_TSS_Media.init(); } if ($('#qdr-tss-settings-form').length) { QDR_TSS_Settings.init(); } }); })(jQuery);