admin.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /**
  2. * Admin JavaScript for QDR Temporary Shared Storage plugin
  3. *
  4. * Handles all admin-side functionality including:
  5. * - Media page (loading, pagination, sorting, filtering, editing, deleting)
  6. * - Settings page (API key generation, settings saving, purging expired files)
  7. * - New actions: Copy permalink and Force Activate
  8. * - Date validation for active period
  9. *
  10. * @package QDR_Temporary_Shared_Storage
  11. * @since 1.0.0
  12. */
  13. (function($) {
  14. 'use strict';
  15. // Media page functionality
  16. var QDR_TSS_Media = {
  17. currentPage: 1,
  18. perPage: 10,
  19. totalPages: 1,
  20. currentOrderBy: 'upload_date',
  21. currentOrder: 'DESC',
  22. currentSearchFilename: '',
  23. currentSearchReference: '',
  24. /**
  25. * Initialize the media page
  26. */
  27. init: function() {
  28. // Load items on page load
  29. this.loadItems();
  30. // Initialize event handlers
  31. this.initEventHandlers();
  32. // Initialize datepicker
  33. this.initDatepicker();
  34. },
  35. /**
  36. * Initialize event handlers
  37. */
  38. initEventHandlers: function() {
  39. var self = this;
  40. // Handle sorting
  41. $('.qdr-tss-table th.sortable').on('click', function() {
  42. var column = $(this).data('sort');
  43. if (self.currentOrderBy === column) {
  44. self.currentOrder = self.currentOrder === 'ASC' ? 'DESC' : 'ASC';
  45. } else {
  46. self.currentOrderBy = column;
  47. self.currentOrder = 'ASC';
  48. }
  49. self.loadItems();
  50. });
  51. // Handle search
  52. $('#qdr-tss-search-button').on('click', function() {
  53. self.currentSearchFilename = $('#qdr-tss-search-filename').val();
  54. self.currentSearchReference = $('#qdr-tss-search-reference').val();
  55. self.currentPage = 1;
  56. self.loadItems();
  57. });
  58. // Handle search reset
  59. $('#qdr-tss-reset-search').on('click', function() {
  60. $('#qdr-tss-search-filename').val('');
  61. $('#qdr-tss-search-reference').val('');
  62. self.currentSearchFilename = '';
  63. self.currentSearchReference = '';
  64. self.currentPage = 1;
  65. self.loadItems();
  66. });
  67. // Handle refresh button
  68. $('#qdr-tss-refresh').on('click', function() {
  69. self.loadItems();
  70. });
  71. // Handle modal close
  72. $('.qdr-tss-modal-close, .qdr-tss-modal-cancel').on('click', function() {
  73. $('.qdr-tss-modal').hide();
  74. });
  75. // Close modal when clicking outside
  76. $(window).on('click', function(e) {
  77. if ($(e.target).hasClass('qdr-tss-modal')) {
  78. $('.qdr-tss-modal').hide();
  79. }
  80. });
  81. // Handle copy shortcode
  82. $(document).on('click', '.qdr-tss-copy-shortcode', function() {
  83. var shortcode = $('#qdr-tss-details-shortcode code').text();
  84. self.copyToClipboard(shortcode);
  85. alert(qdr_tss.strings.shortcode_copied);
  86. });
  87. // Handle copy permalink
  88. $(document).on('click', '.qdr-tss-copy-permalink', function() {
  89. var permalink = $('#qdr-tss-details-permalink a').attr('href');
  90. self.copyToClipboard(permalink);
  91. alert(qdr_tss.strings.permalink_copied);
  92. });
  93. // Handle edit item form submission
  94. $('#qdr-tss-edit-form').on('submit', function(e) {
  95. e.preventDefault();
  96. // Validate dates before submitting
  97. if (self.validateActivePeriod()) {
  98. self.updateItem();
  99. }
  100. });
  101. // Real-time date validation
  102. $('#qdr-tss-edit-active-from, #qdr-tss-edit-active-to').on('change blur', function() {
  103. self.validateActivePeriod();
  104. });
  105. // Handle confirm delete
  106. $(document).on('click', '.qdr-tss-confirm-delete-button', function() {
  107. var id = $('#qdr-tss-delete-id').val();
  108. self.deleteItem(id);
  109. });
  110. },
  111. /**
  112. * Validate active period dates
  113. */
  114. validateActivePeriod: function() {
  115. var activeFrom = $('#qdr-tss-edit-active-from').val();
  116. var activeTo = $('#qdr-tss-edit-active-to').val();
  117. var errorContainer = $('#qdr-tss-date-validation-error');
  118. // Remove existing error container
  119. errorContainer.remove();
  120. // If either field is empty, no validation needed yet
  121. if (!activeFrom || !activeTo) {
  122. return true;
  123. }
  124. var fromDate = new Date(activeFrom);
  125. var toDate = new Date(activeTo);
  126. // Check if dates are valid
  127. if (isNaN(fromDate.getTime()) || isNaN(toDate.getTime())) {
  128. this.showDateValidationError(qdr_tss.strings.invalid_date_format || 'Invalid date format');
  129. return false;
  130. }
  131. // Check if active from is greater than or equal to active to
  132. if (fromDate >= toDate) {
  133. this.showDateValidationError(qdr_tss.strings.active_from_must_be_before_active_to || 'Active From date must be before Active To date');
  134. return false;
  135. }
  136. return true;
  137. },
  138. /**
  139. * Show date validation error
  140. */
  141. showDateValidationError: function(message) {
  142. var errorHtml = '<div id="qdr-tss-date-validation-error" class="notice notice-error inline" style="margin: 10px 0;"><p>' + message + '</p></div>';
  143. $('#qdr-tss-edit-active-to').closest('.qdr-tss-form-row').after(errorHtml);
  144. },
  145. /**
  146. * Initialize datepicker
  147. */
  148. initDatepicker: function() {
  149. $(document).on('focus', '.qdr-tss-datepicker', function() {
  150. var self = QDR_TSS_Media;
  151. $(this).datepicker({
  152. dateFormat: 'yy-mm-dd',
  153. changeMonth: true,
  154. changeYear: true,
  155. onSelect: function() {
  156. // Trigger validation when date is selected
  157. setTimeout(function() {
  158. self.validateActivePeriod();
  159. }, 100);
  160. }
  161. });
  162. });
  163. },
  164. /**
  165. * Initialize action buttons
  166. */
  167. initActionButtons: function() {
  168. var self = this;
  169. // View button
  170. $('.qdr-tss-view-button').off('click').on('click', function() {
  171. var id = $(this).data('id');
  172. self.viewItem(id);
  173. });
  174. // Edit button
  175. $('.qdr-tss-edit-button').off('click').on('click', function() {
  176. var id = $(this).data('id');
  177. self.editItem(id);
  178. });
  179. // Delete button
  180. $('.qdr-tss-delete-button').off('click').on('click', function() {
  181. var id = $(this).data('id');
  182. self.showDeleteConfirmation(id);
  183. });
  184. // Copy permalink button (NEW)
  185. $('.qdr-tss-copy-permalink-button').off('click').on('click', function() {
  186. var id = $(this).data('id');
  187. self.copyPermalinkToClipboard(id);
  188. });
  189. // Force activate button (NEW)
  190. $('.qdr-tss-force-activate-button').off('click').on('click', function() {
  191. var id = $(this).data('id');
  192. self.forceActivateItem(id);
  193. });
  194. // Pagination
  195. $('.qdr-tss-page-button').off('click').on('click', function() {
  196. self.currentPage = parseInt($(this).data('page'));
  197. self.loadItems();
  198. });
  199. },
  200. /**
  201. * Load items
  202. */
  203. loadItems: function() {
  204. var self = this;
  205. var data = {
  206. action: 'qdr_tss_get_items',
  207. nonce: qdr_tss.nonce,
  208. page: this.currentPage,
  209. per_page: this.perPage,
  210. orderby: this.currentOrderBy,
  211. order: this.currentOrder,
  212. original_file_name: this.currentSearchFilename,
  213. reference: this.currentSearchReference
  214. };
  215. // Show loading indicator
  216. $('#qdr-tss-items-list').html('<tr><td colspan="11" class="qdr-tss-loading"><span class="spinner is-active"></span> ' + qdr_tss.strings.loading + '</td></tr>');
  217. $.post(ajaxurl, data, function(response) {
  218. if (response.success) {
  219. self.renderItems(response.data.items);
  220. self.renderPagination(response.data.total, response.data.total_pages);
  221. } else {
  222. alert(response.data.message || qdr_tss.strings.error_loading_items);
  223. }
  224. }).fail(function() {
  225. $('#qdr-tss-items-list').html('<tr><td colspan="11">' + qdr_tss.strings.error_loading_items_try_again + '</td></tr>');
  226. });
  227. },
  228. /**
  229. * Render items
  230. */
  231. renderItems: function(items) {
  232. var self = this;
  233. var $tbody = $('#qdr-tss-items-list');
  234. $tbody.empty();
  235. if (!items || items.length === 0) {
  236. $tbody.append('<tr><td colspan="11">' + qdr_tss.strings.no_items_found + '</td></tr>');
  237. return;
  238. }
  239. $.each(items, function(index, item) {
  240. var statusClass = self.getItemStatusClass(item);
  241. var row = '<tr data-id="' + item.id + '" class="' + statusClass + '">';
  242. row += '<td>' + item.fileid + '</td>';
  243. row += '<td>' + self.escapeHtml(item.original_file_name) + '</td>';
  244. row += '<td>' + self.escapeHtml(item.description || '') + '</td>';
  245. row += '<td>' + self.escapeHtml(item.message || '') + '</td>';
  246. row += '<td>' + self.formatDate(item.active_from) + '</td>';
  247. row += '<td>' + self.formatDate(item.active_to) + '</td>';
  248. row += '<td>' + self.escapeHtml(item.reference || '') + '</td>';
  249. row += '<td>' + self.formatDate(item.upload_date) + '</td>';
  250. row += '<td>' + item.download_count + '</td>';
  251. row += '<td>' + (item.last_download ? self.formatDate(item.last_download) : '-') + '</td>';
  252. row += '<td class="column-actions">';
  253. row += '<div class="qdr-tss-action-buttons">';
  254. row += '<button class="button qdr-tss-view-button" data-id="' + item.id + '" title="' + qdr_tss.strings.view_details + '"><span class="dashicons dashicons-visibility"></span></button>';
  255. row += '<button class="button qdr-tss-edit-button" data-id="' + item.id + '" title="' + qdr_tss.strings.edit + '"><span class="dashicons dashicons-edit"></span></button>';
  256. row += '<button class="button qdr-tss-copy-permalink-button" data-id="' + item.id + '" title="' + qdr_tss.strings.copy_permalink + '"><span class="dashicons dashicons-admin-links"></span></button>';
  257. row += '<button class="button qdr-tss-force-activate-button" data-id="' + item.id + '" title="' + qdr_tss.strings.force_activate + '"><span class="dashicons dashicons-clock"></span></button>';
  258. row += '<button class="button qdr-tss-delete-button" data-id="' + item.id + '" title="' + qdr_tss.strings.delete + '"><span class="dashicons dashicons-trash"></span></button>';
  259. row += '</div>';
  260. row += '</td>';
  261. row += '</tr>';
  262. $tbody.append(row);
  263. });
  264. // Initialize action buttons
  265. this.initActionButtons();
  266. // Update sorting indicators
  267. this.updateSortIndicators();
  268. },
  269. /**
  270. * Copy permalink to clipboard (NEW FUNCTION)
  271. */
  272. copyPermalinkToClipboard: function(id) {
  273. var self = this;
  274. var data = {
  275. action: 'qdr_tss_get_item_details',
  276. nonce: qdr_tss.nonce,
  277. id: id
  278. };
  279. $.post(ajaxurl, data, function(response) {
  280. if (response.success) {
  281. var permalink = response.data.item.permalink;
  282. self.copyToClipboard(permalink);
  283. alert(qdr_tss.strings.permalink_copied_to_clipboard);
  284. } else {
  285. alert(response.data.message || qdr_tss.strings.error_getting_permalink);
  286. }
  287. }).fail(function() {
  288. alert(qdr_tss.strings.error_getting_permalink_try_again);
  289. });
  290. },
  291. /**
  292. * Force activate item (NEW FUNCTION)
  293. */
  294. forceActivateItem: function(id) {
  295. var self = this;
  296. if (!confirm(qdr_tss.strings.confirm_force_activate)) {
  297. return;
  298. }
  299. var data = {
  300. action: 'qdr_tss_force_activate_item',
  301. nonce: qdr_tss.nonce,
  302. id: id
  303. };
  304. $.post(ajaxurl, data, function(response) {
  305. if (response.success) {
  306. alert(response.data.message || qdr_tss.strings.item_force_activated);
  307. // Reload items to show updated dates
  308. self.loadItems();
  309. } else {
  310. alert(response.data.message || qdr_tss.strings.error_force_activating);
  311. }
  312. }).fail(function() {
  313. alert(qdr_tss.strings.error_force_activating_try_again);
  314. });
  315. },
  316. /**
  317. * Get item status class
  318. */
  319. getItemStatusClass: function(item) {
  320. var now = new Date();
  321. var activeFrom = new Date(item.active_from);
  322. var activeTo = new Date(item.active_to);
  323. if (now < activeFrom) {
  324. return 'qdr-tss-status-pending';
  325. } else if (now > activeTo) {
  326. return 'qdr-tss-status-expired';
  327. } else {
  328. return 'qdr-tss-status-active';
  329. }
  330. },
  331. /**
  332. * Render pagination
  333. */
  334. renderPagination: function(total, totalPages) {
  335. var $info = $('.qdr-tss-pagination-info');
  336. var $controls = $('.qdr-tss-pagination-controls');
  337. // Update info
  338. var startItem = (this.currentPage - 1) * this.perPage + 1;
  339. var endItem = Math.min(this.currentPage * this.perPage, total);
  340. if (total === 0) {
  341. $info.html(qdr_tss.strings.no_items);
  342. $controls.empty();
  343. return;
  344. }
  345. $info.html(qdr_tss.strings.showing + ' ' + startItem + ' - ' + endItem + ' ' + qdr_tss.strings.of + ' ' + total);
  346. // Update controls
  347. $controls.empty();
  348. if (totalPages <= 1) {
  349. return;
  350. }
  351. // First page
  352. if (this.currentPage > 1) {
  353. $controls.append('<button class="button qdr-tss-page-button" data-page="1" title="' + qdr_tss.strings.first_page + '">&laquo;</button>');
  354. }
  355. // Previous page
  356. if (this.currentPage > 1) {
  357. $controls.append('<button class="button qdr-tss-page-button" data-page="' + (this.currentPage - 1) + '" title="' + qdr_tss.strings.previous_page + '">&lsaquo;</button>');
  358. }
  359. // Page numbers
  360. var startPage = Math.max(1, this.currentPage - 2);
  361. var endPage = Math.min(totalPages, startPage + 4);
  362. if (endPage - startPage < 4) {
  363. startPage = Math.max(1, endPage - 4);
  364. }
  365. for (var i = startPage; i <= endPage; i++) {
  366. var activeClass = i === this.currentPage ? 'button-primary' : '';
  367. $controls.append('<button class="button qdr-tss-page-button ' + activeClass + '" data-page="' + i + '">' + i + '</button>');
  368. }
  369. // Next page
  370. if (this.currentPage < totalPages) {
  371. $controls.append('<button class="button qdr-tss-page-button" data-page="' + (this.currentPage + 1) + '" title="' + qdr_tss.strings.next_page + '">&rsaquo;</button>');
  372. }
  373. // Last page
  374. if (this.currentPage < totalPages) {
  375. $controls.append('<button class="button qdr-tss-page-button" data-page="' + totalPages + '" title="' + qdr_tss.strings.last_page + '">&raquo;</button>');
  376. }
  377. // Rebind click events
  378. this.initActionButtons();
  379. },
  380. /**
  381. * Update sort indicators
  382. */
  383. updateSortIndicators: function() {
  384. // Remove all indicators
  385. $('.qdr-tss-table th').removeClass('sorted asc desc');
  386. // Add indicator to current sort column
  387. var $th = $('.qdr-tss-table th[data-sort="' + this.currentOrderBy + '"]');
  388. $th.addClass('sorted ' + this.currentOrder.toLowerCase());
  389. },
  390. /**
  391. * View item details
  392. */
  393. viewItem: function(id) {
  394. var self = this;
  395. // Show loading modal
  396. $('#qdr-tss-details-modal').show();
  397. $('.qdr-tss-details-content').html('<div class="qdr-tss-loading"><span class="spinner is-active"></span> ' + qdr_tss.strings.loading + '</div>');
  398. // Get additional data via AJAX
  399. var data = {
  400. action: 'qdr_tss_get_item_details',
  401. nonce: qdr_tss.nonce,
  402. id: id
  403. };
  404. $.post(ajaxurl, data, function(response) {
  405. if (response.success) {
  406. var item = response.data.item;
  407. // Populate details
  408. $('#qdr-tss-details-fileid').text(item.fileid);
  409. $('#qdr-tss-details-filename').text(item.original_file_name);
  410. $('#qdr-tss-details-description').text(item.description || '-');
  411. $('#qdr-tss-details-message').text(item.message || '-');
  412. $('#qdr-tss-details-reference').text(item.reference || '-');
  413. $('#qdr-tss-details-active-period').text(self.formatDate(item.active_from) + ' - ' + self.formatDate(item.active_to));
  414. $('#qdr-tss-details-filesize').text(self.formatFileSize(item.file_size));
  415. $('#qdr-tss-details-download-count').text(item.download_count);
  416. $('#qdr-tss-details-last-download').text(item.last_download ? self.formatDate(item.last_download) : '-');
  417. // Permalink and shortcode
  418. $('#qdr-tss-details-permalink').html('<a href="' + item.permalink + '" target="_blank">' + item.permalink + '</a>');
  419. $('#qdr-tss-details-shortcode').html('<code>' + item.shortcode + '</code>');
  420. // Initialize copy buttons
  421. $('.qdr-tss-copy-shortcode').data('text', item.shortcode);
  422. $('.qdr-tss-copy-permalink').data('text', item.permalink);
  423. } else {
  424. alert(response.data.message || qdr_tss.strings.error_loading_item_details);
  425. $('#qdr-tss-details-modal').hide();
  426. }
  427. }).fail(function() {
  428. alert(qdr_tss.strings.error_loading_item_details_try_again);
  429. $('#qdr-tss-details-modal').hide();
  430. });
  431. },
  432. /**
  433. * Edit item
  434. */
  435. editItem: function(id) {
  436. // Find item in the table
  437. var $row = $('tr[data-id="' + id + '"]');
  438. if ($row.length === 0) return;
  439. var $cells = $row.find('td');
  440. // Populate form fields
  441. $('#qdr-tss-edit-id').val(id);
  442. $('#qdr-tss-edit-description').val($cells.eq(2).text());
  443. $('#qdr-tss-edit-message').val($cells.eq(3).text());
  444. // Parse dates for datepicker
  445. var activeFrom = $cells.eq(4).text();
  446. var activeTo = $cells.eq(5).text();
  447. $('#qdr-tss-edit-active-from').val(activeFrom !== '-' ? activeFrom : '');
  448. $('#qdr-tss-edit-active-to').val(activeTo !== '-' ? activeTo : '');
  449. $('#qdr-tss-edit-reference').val($cells.eq(6).text());
  450. // Clear status
  451. $('#qdr-tss-edit-status').html('');
  452. // Remove any existing validation errors
  453. $('#qdr-tss-date-validation-error').remove();
  454. // Show modal
  455. $('#qdr-tss-edit-modal').show();
  456. },
  457. /**
  458. * Update item
  459. */
  460. updateItem: function() {
  461. var self = this;
  462. // Show loading status
  463. $('#qdr-tss-edit-status').html('<div class="qdr-tss-loading"><span class="spinner is-active"></span> ' + qdr_tss.strings.saving + '</div>');
  464. var data = {
  465. action: 'qdr_tss_edit_item',
  466. nonce: qdr_tss.nonce,
  467. id: $('#qdr-tss-edit-id').val(),
  468. description: $('#qdr-tss-edit-description').val(),
  469. message: $('#qdr-tss-edit-message').val(),
  470. active_from: $('#qdr-tss-edit-active-from').val(),
  471. active_to: $('#qdr-tss-edit-active-to').val(),
  472. reference: $('#qdr-tss-edit-reference').val()
  473. };
  474. $.post(ajaxurl, data, function(response) {
  475. if (response.success) {
  476. // Show success status
  477. $('#qdr-tss-edit-status').html('<div class="notice notice-success inline"><p>' + (response.data.message || qdr_tss.strings.changes_saved) + '</p></div>');
  478. // Hide modal after a delay
  479. setTimeout(function() {
  480. $('#qdr-tss-edit-modal').hide();
  481. // Reload items
  482. self.loadItems();
  483. }, 1000);
  484. } else {
  485. // Show error status
  486. $('#qdr-tss-edit-status').html('<div class="notice notice-error inline"><p>' + (response.data.message || qdr_tss.strings.error_saving_changes) + '</p></div>');
  487. }
  488. }).fail(function() {
  489. // Show error status
  490. $('#qdr-tss-edit-status').html('<div class="notice notice-error inline"><p>' + qdr_tss.strings.error_saving_changes_try_again + '</p></div>');
  491. });
  492. },
  493. /**
  494. * Show delete confirmation
  495. */
  496. showDeleteConfirmation: function(id) {
  497. $('#qdr-tss-delete-id').val(id);
  498. $('#qdr-tss-confirm-delete-modal').show();
  499. },
  500. /**
  501. * Delete item
  502. */
  503. deleteItem: function(id) {
  504. var self = this;
  505. var data = {
  506. action: 'qdr_tss_delete_item',
  507. nonce: qdr_tss.nonce,
  508. id: id
  509. };
  510. $.post(ajaxurl, data, function(response) {
  511. if (response.success) {
  512. // Hide modal
  513. $('#qdr-tss-confirm-delete-modal').hide();
  514. // Show success message
  515. alert(response.data.message || qdr_tss.strings.file_deleted);
  516. // Reload items
  517. self.loadItems();
  518. } else {
  519. alert(response.data.message || qdr_tss.strings.error_deleting_file);
  520. }
  521. }).fail(function() {
  522. alert(qdr_tss.strings.error_deleting_file_try_again);
  523. });
  524. },
  525. /**
  526. * Format date
  527. */
  528. formatDate: function(dateString) {
  529. if (!dateString || dateString === '0000-00-00 00:00:00') {
  530. return '-';
  531. }
  532. var date = new Date(dateString);
  533. // Check if date is valid
  534. if (isNaN(date.getTime())) {
  535. return dateString;
  536. }
  537. return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
  538. },
  539. /**
  540. * Format file size
  541. */
  542. formatFileSize: function(bytes) {
  543. if (bytes === 0) return '0 Bytes';
  544. var k = 1024;
  545. var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  546. var i = Math.floor(Math.log(bytes) / Math.log(k));
  547. return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  548. },
  549. /**
  550. * Escape HTML
  551. */
  552. escapeHtml: function(text) {
  553. if (!text) return '';
  554. var map = {
  555. '&': '&amp;',
  556. '<': '&lt;',
  557. '>': '&gt;',
  558. '"': '&quot;',
  559. "'": '&#039;'
  560. };
  561. return text.toString().replace(/[&<>"']/g, function(m) { return map[m]; });
  562. },
  563. /**
  564. * Copy to clipboard
  565. */
  566. copyToClipboard: function(text) {
  567. var $temp = $('<input>');
  568. $('body').append($temp);
  569. $temp.val(text).select();
  570. document.execCommand('copy');
  571. $temp.remove();
  572. }
  573. };
  574. // Settings page functionality
  575. var QDR_TSS_Settings = {
  576. /**
  577. * Initialize the settings page
  578. */
  579. init: function() {
  580. // Initialize event handlers
  581. this.initEventHandlers();
  582. },
  583. /**
  584. * Initialize event handlers
  585. */
  586. initEventHandlers: function() {
  587. var self = this;
  588. // Generate new API key
  589. $('#qdr-tss-generate-key').on('click', function(e) {
  590. e.preventDefault();
  591. self.generateApiKey();
  592. });
  593. // Save settings
  594. $('#qdr-tss-settings-form').on('submit', function(e) {
  595. e.preventDefault();
  596. self.saveSettings();
  597. });
  598. // Purge expired files
  599. $('#qdr-tss-purge-expired').on('click', function(e) {
  600. e.preventDefault();
  601. self.purgeExpiredFiles();
  602. });
  603. },
  604. /**
  605. * Generate API key
  606. */
  607. generateApiKey: function() {
  608. // Generate a random string for API key
  609. var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  610. var apiKey = '';
  611. for (var i = 0; i < 32; i++) {
  612. apiKey += chars.charAt(Math.floor(Math.random() * chars.length));
  613. }
  614. $('#qdr-tss-api-key').val(apiKey);
  615. },
  616. /**
  617. * Save settings
  618. */
  619. saveSettings: function() {
  620. var data = {
  621. action: 'qdr_tss_save_settings',
  622. nonce: qdr_tss.nonce,
  623. api_key: $('#qdr-tss-api-key').val(),
  624. media_category: $('#qdr-tss-media-category').val(),
  625. max_upload_size: $('#qdr-tss-max-upload-size').val()
  626. };
  627. $.post(ajaxurl, data, function(response) {
  628. if (response.success) {
  629. alert(response.data.message);
  630. } else {
  631. alert(response.data.message);
  632. }
  633. });
  634. },
  635. /**
  636. * Purge expired files
  637. */
  638. purgeExpiredFiles: function() {
  639. if (!confirm(qdr_tss.strings.confirm_purge)) {
  640. return;
  641. }
  642. var data = {
  643. action: 'qdr_tss_purge_expired',
  644. nonce: qdr_tss.nonce
  645. };
  646. $.post(ajaxurl, data, function(response) {
  647. if (response.success) {
  648. alert(response.data.message);
  649. // Reload page to update storage usage
  650. location.reload();
  651. } else {
  652. alert(response.data.message);
  653. }
  654. });
  655. }
  656. };
  657. // Document ready
  658. $(function() {
  659. // Initialize appropriate page functionality
  660. if ($('.qdr-tss-table').length) {
  661. QDR_TSS_Media.init();
  662. }
  663. if ($('#qdr-tss-settings-form').length) {
  664. QDR_TSS_Settings.init();
  665. }
  666. });
  667. })(jQuery);