admin.js 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. /**
  2. * Admin JavaScript for Studiou WC Product Category Manager
  3. */
  4. (function($) {
  5. 'use strict';
  6. // Initialize admin scripts
  7. $(document).ready(function() {
  8. // Debug: Log that script is loaded
  9. console.log('STUDIOU WC: Admin script loaded');
  10. console.log('STUDIOU WC: studiouWcpcm object:', studiouWcpcm);
  11. // Import form handling
  12. if ($('#studiou-wcpcm-import-form').length) {
  13. console.log('STUDIOU WC: Import form found');
  14. initImportForm();
  15. }
  16. // Export form handling
  17. if ($('#studiou-wcpcm-export-form').length) {
  18. console.log('STUDIOU WC: Export form found');
  19. initExportForm();
  20. }
  21. // Move products form handling
  22. if ($('#studiou-wcpcm-move-form').length) {
  23. console.log('STUDIOU WC: Move form found');
  24. initMoveForm();
  25. } else {
  26. console.log('STUDIOU WC: Move form NOT found');
  27. }
  28. // Batch description form handling
  29. if ($('#studiou-wcpcm-batch-description-form').length) {
  30. console.log('STUDIOU WC: Batch description form found');
  31. initBatchDescriptionForm();
  32. }
  33. // Delete products form handling
  34. if ($('#studiou-wcpcm-delete-products-form').length) {
  35. console.log('STUDIOU WC: Delete products form found');
  36. initDeleteProductsForm();
  37. }
  38. // Clear media categories form handling
  39. if ($('#studiou-wcpcm-clear-media-form').length) {
  40. console.log('STUDIOU WC: Clear media form found');
  41. initClearMediaForm();
  42. }
  43. // Sample CSV download handler
  44. if ($('#studiou-wcpcm-download-sample').length) {
  45. initSampleDownload();
  46. }
  47. // Product import form handling
  48. if ($('#studiou-wcpcm-product-import-form').length) {
  49. console.log('STUDIOU WC: Product import form found');
  50. initProductImportForm();
  51. }
  52. // Product export form handling
  53. if ($('#studiou-wcpcm-product-export-form').length) {
  54. console.log('STUDIOU WC: Product export form found');
  55. initProductExportForm();
  56. }
  57. });
  58. /**
  59. * Initialize import form
  60. */
  61. function initImportForm() {
  62. $('#studiou-wcpcm-import-form').on('submit', function(e) {
  63. e.preventDefault();
  64. // Show spinner
  65. var $submitBtn = $(this).find('#studiou-wcpcm-import-button');
  66. var $spinner = $(this).find('.spinner');
  67. $submitBtn.prop('disabled', true);
  68. $spinner.css('visibility', 'visible');
  69. // Clear previous notices
  70. $('.studiou-wcpcm-notice-area').empty();
  71. // Create form data
  72. var formData = new FormData(this);
  73. formData.append('action', 'studiou_wcpcm_import');
  74. formData.append('nonce', studiouWcpcm.nonce);
  75. // Send AJAX request
  76. $.ajax({
  77. url: studiouWcpcm.ajaxUrl,
  78. type: 'POST',
  79. data: formData,
  80. processData: false,
  81. contentType: false,
  82. success: function(response) {
  83. if (response.success) {
  84. showNotice('success', studiouWcpcm.i18n.importSuccess);
  85. // Show results
  86. $('#studiou-wcpcm-import-results').text(response.data.message);
  87. $('.studiou-wcpcm-import-results').show();
  88. } else {
  89. showNotice('error', response.data.message);
  90. }
  91. },
  92. error: function() {
  93. showNotice('error', studiouWcpcm.i18n.importError);
  94. },
  95. complete: function() {
  96. // Hide spinner
  97. $submitBtn.prop('disabled', false);
  98. $spinner.css('visibility', 'hidden');
  99. }
  100. });
  101. });
  102. }
  103. /**
  104. * Initialize export form
  105. */
  106. function initExportForm() {
  107. $('#studiou-wcpcm-export-form').on('submit', function(e) {
  108. e.preventDefault();
  109. // Show spinner
  110. var $submitBtn = $(this).find('#studiou-wcpcm-export-button');
  111. var $spinner = $(this).find('.spinner');
  112. $submitBtn.prop('disabled', true);
  113. $spinner.css('visibility', 'visible');
  114. // Clear previous notices
  115. $('.studiou-wcpcm-notice-area').empty();
  116. // Send AJAX request
  117. $.ajax({
  118. url: studiouWcpcm.ajaxUrl,
  119. type: 'POST',
  120. data: {
  121. action: 'studiou_wcpcm_export',
  122. nonce: studiouWcpcm.nonce
  123. },
  124. success: function(response) {
  125. if (response.success) {
  126. showNotice('success', studiouWcpcm.i18n.exportSuccess);
  127. // Show download link
  128. $('#studiou-wcpcm-export-message').text(response.data.message);
  129. $('#studiou-wcpcm-download-export').attr('href', response.data.download_url);
  130. $('.studiou-wcpcm-export-results').show();
  131. } else {
  132. showNotice('error', response.data.message);
  133. }
  134. },
  135. error: function() {
  136. showNotice('error', studiouWcpcm.i18n.exportError);
  137. },
  138. complete: function() {
  139. // Hide spinner
  140. $submitBtn.prop('disabled', false);
  141. $spinner.css('visibility', 'hidden');
  142. }
  143. });
  144. });
  145. }
  146. /**
  147. * Initialize move products form
  148. */
  149. function initMoveForm() {
  150. console.log('STUDIOU WC: Initializing move form handlers');
  151. // Add debug button click handler first
  152. $('#studiou-wcpcm-move-button').on('click', function(e) {
  153. console.log('STUDIOU WC: Move button clicked directly');
  154. });
  155. $('#studiou-wcpcm-move-form').on('submit', function(e) {
  156. e.preventDefault();
  157. // Debug: Log form submission
  158. console.log('STUDIOU WC: Move form submitted');
  159. // Validate that different categories are selected
  160. var sourceCategory = $('#source_category').val();
  161. var targetCategory = $('#target_category').val();
  162. console.log('STUDIOU WC: Source category:', sourceCategory, 'Target category:', targetCategory);
  163. if (!sourceCategory || !targetCategory) {
  164. console.log('STUDIOU WC: Missing category selection');
  165. showNotice('error', 'Please select both source and target categories');
  166. return;
  167. }
  168. if (sourceCategory === targetCategory) {
  169. console.log('STUDIOU WC: Same category selected');
  170. showNotice('error', studiouWcpcm.i18n.selectDifferentCategories);
  171. return;
  172. }
  173. // Show spinner
  174. var $submitBtn = $(this).find('#studiou-wcpcm-move-button');
  175. var $spinner = $(this).find('.spinner');
  176. $submitBtn.prop('disabled', true);
  177. $spinner.css('visibility', 'visible');
  178. // Clear previous notices
  179. $('.studiou-wcpcm-notice-area').empty();
  180. // Debug: Log AJAX request details
  181. console.log('STUDIOU WC: Sending AJAX request to:', studiouWcpcm.ajaxUrl);
  182. console.log('STUDIOU WC: Nonce:', studiouWcpcm.nonce);
  183. // Send AJAX request
  184. $.ajax({
  185. url: studiouWcpcm.ajaxUrl,
  186. type: 'POST',
  187. data: {
  188. action: 'studiou_wcpcm_move_products',
  189. source_category: sourceCategory,
  190. target_category: targetCategory,
  191. nonce: studiouWcpcm.nonce
  192. },
  193. success: function(response) {
  194. console.log('STUDIOU WC: AJAX response:', response);
  195. if (response.success) {
  196. showNotice('success', studiouWcpcm.i18n.moveSuccess);
  197. // Show results
  198. $('#studiou-wcpcm-move-message').html('<p>' + response.data.message + '</p>');
  199. $('.studiou-wcpcm-move-results').show();
  200. // Refresh the page to update category counts
  201. setTimeout(function() {
  202. location.reload();
  203. }, 3000);
  204. } else {
  205. showNotice('error', response.data.message);
  206. }
  207. },
  208. error: function(xhr, status, error) {
  209. console.error('STUDIOU WC: AJAX error:', status, error);
  210. console.error('STUDIOU WC: Response text:', xhr.responseText);
  211. showNotice('error', studiouWcpcm.i18n.moveError + ': ' + error);
  212. },
  213. complete: function() {
  214. // Hide spinner
  215. $submitBtn.prop('disabled', false);
  216. $spinner.css('visibility', 'hidden');
  217. }
  218. });
  219. });
  220. }
  221. /**
  222. * Initialize batch description form
  223. */
  224. function initBatchDescriptionForm() {
  225. console.log('STUDIOU WC: Initializing batch description form handlers');
  226. // Check all button handler
  227. $('#studiou-wcpcm-check-all').on('click', function(e) {
  228. e.preventDefault();
  229. console.log('STUDIOU WC: Check all button clicked');
  230. $('#categories_list input[type="checkbox"]').prop('checked', true);
  231. });
  232. // Uncheck all button handler
  233. $('#studiou-wcpcm-uncheck-all').on('click', function(e) {
  234. e.preventDefault();
  235. console.log('STUDIOU WC: Uncheck all button clicked');
  236. $('#categories_list input[type="checkbox"]').prop('checked', false);
  237. });
  238. // Form submit handler
  239. $('#studiou-wcpcm-batch-description-form').on('submit', function(e) {
  240. e.preventDefault();
  241. console.log('STUDIOU WC: Batch description form submitted');
  242. // Get selected categories
  243. var selectedCategories = [];
  244. $('#categories_list input[type="checkbox"]:checked').each(function() {
  245. selectedCategories.push($(this).val());
  246. });
  247. var description = $('#category_description').val();
  248. console.log('STUDIOU WC: Selected categories:', selectedCategories);
  249. console.log('STUDIOU WC: Description:', description);
  250. // Validate input
  251. if (selectedCategories.length === 0) {
  252. console.log('STUDIOU WC: No categories selected');
  253. showNotice('error', 'Please select at least one category');
  254. return;
  255. }
  256. // Show spinner
  257. var $submitBtn = $(this).find('#studiou-wcpcm-batch-description-button');
  258. var $spinner = $(this).find('.spinner');
  259. $submitBtn.prop('disabled', true);
  260. $spinner.css('visibility', 'visible');
  261. // Clear previous notices
  262. $('.studiou-wcpcm-notice-area').empty();
  263. // Debug: Log AJAX request details
  264. console.log('STUDIOU WC: Sending batch description AJAX request to:', studiouWcpcm.ajaxUrl);
  265. console.log('STUDIOU WC: Nonce:', studiouWcpcm.nonce);
  266. // Send AJAX request
  267. $.ajax({
  268. url: studiouWcpcm.ajaxUrl,
  269. type: 'POST',
  270. data: {
  271. action: 'studiou_wcpcm_batch_description',
  272. selected_categories: selectedCategories,
  273. description: description,
  274. nonce: studiouWcpcm.nonce
  275. },
  276. success: function(response) {
  277. console.log('STUDIOU WC: Batch description AJAX response:', response);
  278. if (response.success) {
  279. showNotice('success', studiouWcpcm.i18n.batchDescriptionSuccess || 'Batch description operation successful');
  280. // Show results
  281. $('#studiou-wcpcm-batch-description-message').html('<p>' + response.data.message + '</p>');
  282. $('.studiou-wcpcm-batch-description-results').show();
  283. } else {
  284. showNotice('error', response.data.message);
  285. }
  286. },
  287. error: function(xhr, status, error) {
  288. console.error('STUDIOU WC: Batch description AJAX error:', status, error);
  289. console.error('STUDIOU WC: Response text:', xhr.responseText);
  290. showNotice('error', (studiouWcpcm.i18n.batchDescriptionError || 'Batch description operation error') + ': ' + error);
  291. },
  292. complete: function() {
  293. // Hide spinner
  294. $submitBtn.prop('disabled', false);
  295. $spinner.css('visibility', 'hidden');
  296. }
  297. });
  298. });
  299. }
  300. /**
  301. * Initialize sample CSV download
  302. */
  303. function initSampleDownload() {
  304. $('#studiou-wcpcm-download-sample').on('click', function(e) {
  305. e.preventDefault();
  306. // Sample CSV content
  307. var csvContent = 'name,url-name,parent-name,description,display-type,visibility,protected-passwords,operation\n' +
  308. '"Clothing","clothing","","Top quality clothing","default","public","","A"\n' +
  309. '"Men","men","Clothing","Men\'s clothing","products","public","","A"\n' +
  310. '"Women","women","Clothing","Women\'s clothing","products","protected","password123","A"\n' +
  311. '"Kids","kids","Clothing","Kids clothing","products","public","","U"\n' +
  312. '"Accessories","accessories","","All accessories","default","public","","D"';
  313. // Create download link
  314. var blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
  315. var url = URL.createObjectURL(blob);
  316. var link = document.createElement('a');
  317. link.setAttribute('href', url);
  318. link.setAttribute('download', 'sample-product-categories.csv');
  319. link.style.visibility = 'hidden';
  320. document.body.appendChild(link);
  321. link.click();
  322. document.body.removeChild(link);
  323. });
  324. }
  325. /**
  326. * Initialize delete products form
  327. */
  328. function initDeleteProductsForm() {
  329. console.log('STUDIOU WC: Initializing delete products form handlers');
  330. console.log('STUDIOU WC: Form element:', $('#studiou-wcpcm-delete-products-form'));
  331. console.log('STUDIOU WC: Check all button:', $('#studiou-wcpcm-delete-check-all'));
  332. console.log('STUDIOU WC: Delete button:', $('#studiou-wcpcm-delete-products-button'));
  333. // Check all button handler
  334. $('#studiou-wcpcm-delete-check-all').on('click', function(e) {
  335. e.preventDefault();
  336. console.log('STUDIOU WC: Delete check all button clicked');
  337. $('#delete_categories_list input[type="checkbox"]').prop('checked', true);
  338. });
  339. // Uncheck all button handler
  340. $('#studiou-wcpcm-delete-uncheck-all').on('click', function(e) {
  341. e.preventDefault();
  342. console.log('STUDIOU WC: Delete uncheck all button clicked');
  343. $('#delete_categories_list input[type="checkbox"]').prop('checked', false);
  344. });
  345. // Form submit handler
  346. $('#studiou-wcpcm-delete-products-form').on('submit', function(e) {
  347. e.preventDefault();
  348. console.log('STUDIOU WC: Delete products form submitted');
  349. // Get selected categories
  350. var selectedCategories = [];
  351. $('#delete_categories_list input[type="checkbox"]:checked').each(function() {
  352. selectedCategories.push($(this).val());
  353. });
  354. console.log('STUDIOU WC: Selected categories:', selectedCategories);
  355. // Validate input
  356. if (selectedCategories.length === 0) {
  357. console.log('STUDIOU WC: No categories selected');
  358. showNotice('error', studiouWcpcm.i18n.selectAtLeastOneCategory || 'Please select at least one category');
  359. return;
  360. }
  361. // Confirm deletion
  362. if (!confirm(studiouWcpcm.i18n.confirmDelete || 'Are you sure you want to permanently delete ALL products in the selected categories? This action cannot be undone!')) {
  363. console.log('STUDIOU WC: User cancelled deletion');
  364. return;
  365. }
  366. // Show spinner
  367. var $submitBtn = $(this).find('#studiou-wcpcm-delete-products-button');
  368. var $spinner = $(this).find('.spinner');
  369. $submitBtn.prop('disabled', true);
  370. $spinner.css('visibility', 'visible');
  371. // Clear previous notices
  372. $('.studiou-wcpcm-notice-area').empty();
  373. // Hide results, show progress
  374. $('.studiou-wcpcm-delete-results').hide();
  375. $('.studiou-wcpcm-delete-progress').show();
  376. $('#studiou-wcpcm-delete-progress-text').text('Initializing...');
  377. updateProgressBar(0);
  378. // Debug: Log AJAX request details
  379. console.log('STUDIOU WC: Sending delete products AJAX request to:', studiouWcpcm.ajaxUrl);
  380. console.log('STUDIOU WC: Nonce:', studiouWcpcm.nonce);
  381. // Send AJAX request to get product IDs
  382. $.ajax({
  383. url: studiouWcpcm.ajaxUrl,
  384. type: 'POST',
  385. data: {
  386. action: 'studiou_wcpcm_delete_products',
  387. delete_categories: selectedCategories,
  388. nonce: studiouWcpcm.nonce
  389. },
  390. success: function(response) {
  391. console.log('STUDIOU WC: Delete products AJAX response:', response);
  392. if (response.success) {
  393. var productIds = response.data.product_ids;
  394. var totalCount = response.data.total_count;
  395. console.log('STUDIOU WC: Total products to delete:', totalCount);
  396. if (totalCount === 0) {
  397. showNotice('success', studiouWcpcm.i18n.noProductsFound || 'No products found in selected categories');
  398. $('.studiou-wcpcm-delete-progress').hide();
  399. $submitBtn.prop('disabled', false);
  400. $spinner.css('visibility', 'hidden');
  401. return;
  402. }
  403. // Process products in batches
  404. processDeletionBatches(productIds, totalCount, $submitBtn, $spinner);
  405. } else {
  406. showNotice('error', response.data.message);
  407. $('.studiou-wcpcm-delete-progress').hide();
  408. $submitBtn.prop('disabled', false);
  409. $spinner.css('visibility', 'hidden');
  410. }
  411. },
  412. error: function(xhr, status, error) {
  413. console.error('STUDIOU WC: Delete products AJAX error:', status, error);
  414. console.error('STUDIOU WC: Response text:', xhr.responseText);
  415. showNotice('error', (studiouWcpcm.i18n.deleteError || 'Delete products operation error') + ': ' + error);
  416. $('.studiou-wcpcm-delete-progress').hide();
  417. $submitBtn.prop('disabled', false);
  418. $spinner.css('visibility', 'hidden');
  419. }
  420. });
  421. });
  422. }
  423. /**
  424. * Process deletion in batches
  425. */
  426. function processDeletionBatches(productIds, totalCount, $submitBtn, $spinner) {
  427. var batchSize = 10; // Process 10 products at a time
  428. var batches = [];
  429. var totalDeleted = 0;
  430. var totalFailed = 0;
  431. var failedProducts = [];
  432. // Split products into batches
  433. for (var i = 0; i < productIds.length; i += batchSize) {
  434. batches.push(productIds.slice(i, i + batchSize));
  435. }
  436. console.log('STUDIOU WC: Processing ' + batches.length + ' batches of products');
  437. var currentBatch = 0;
  438. function processBatch() {
  439. if (currentBatch >= batches.length) {
  440. // All batches completed
  441. console.log('STUDIOU WC: All batches completed');
  442. onDeletionComplete(totalDeleted, totalFailed, failedProducts, $submitBtn, $spinner);
  443. return;
  444. }
  445. var batch = batches[currentBatch];
  446. var progress = Math.round((currentBatch / batches.length) * 100);
  447. $('#studiou-wcpcm-delete-progress-text').text(
  448. 'Deleting products... ' + (currentBatch * batchSize) + ' of ' + totalCount + ' processed'
  449. );
  450. updateProgressBar(progress);
  451. // Send batch delete request
  452. $.ajax({
  453. url: studiouWcpcm.ajaxUrl,
  454. type: 'POST',
  455. data: {
  456. action: 'studiou_wcpcm_delete_products_batch',
  457. product_ids: batch,
  458. nonce: studiouWcpcm.nonce
  459. },
  460. success: function(response) {
  461. if (response.success) {
  462. totalDeleted += response.data.deleted_count;
  463. totalFailed += response.data.failed_count;
  464. failedProducts = failedProducts.concat(response.data.failed_products);
  465. console.log('STUDIOU WC: Batch ' + currentBatch + ' completed - Deleted: ' +
  466. response.data.deleted_count + ', Failed: ' + response.data.failed_count);
  467. // Process next batch
  468. currentBatch++;
  469. processBatch();
  470. } else {
  471. showNotice('error', response.data.message);
  472. $('.studiou-wcpcm-delete-progress').hide();
  473. $submitBtn.prop('disabled', false);
  474. $spinner.css('visibility', 'hidden');
  475. }
  476. },
  477. error: function(xhr, status, error) {
  478. console.error('STUDIOU WC: Batch delete AJAX error:', status, error);
  479. showNotice('error', 'Error deleting batch: ' + error);
  480. $('.studiou-wcpcm-delete-progress').hide();
  481. $submitBtn.prop('disabled', false);
  482. $spinner.css('visibility', 'hidden');
  483. }
  484. });
  485. }
  486. // Start processing batches
  487. processBatch();
  488. }
  489. /**
  490. * Handle deletion completion
  491. */
  492. function onDeletionComplete(totalDeleted, totalFailed, failedProducts, $submitBtn, $spinner) {
  493. // Update progress bar to 100%
  494. updateProgressBar(100);
  495. $('#studiou-wcpcm-delete-progress-text').text('Deletion complete!');
  496. // Show results
  497. var message = '<p><strong>Deletion Summary:</strong></p>';
  498. message += '<ul>';
  499. message += '<li>Total products deleted: ' + totalDeleted + '</li>';
  500. if (totalFailed > 0) {
  501. message += '<li>Failed to delete: ' + totalFailed + '</li>';
  502. if (failedProducts.length > 0) {
  503. message += '<li>Failed product IDs: ' + failedProducts.join(', ') + '</li>';
  504. }
  505. }
  506. message += '</ul>';
  507. $('#studiou-wcpcm-delete-message').html(message);
  508. $('.studiou-wcpcm-delete-results').show();
  509. // Hide progress after a delay
  510. setTimeout(function() {
  511. $('.studiou-wcpcm-delete-progress').fadeOut();
  512. }, 2000);
  513. if (totalDeleted > 0) {
  514. showNotice('success', (studiouWcpcm.i18n.deleteSuccess || 'Successfully deleted') + ' ' + totalDeleted + ' products');
  515. // Reload page after 3 seconds
  516. setTimeout(function() {
  517. location.reload();
  518. }, 3000);
  519. } else {
  520. showNotice('error', studiouWcpcm.i18n.deleteError || 'Failed to delete any products');
  521. }
  522. $submitBtn.prop('disabled', false);
  523. $spinner.css('visibility', 'hidden');
  524. }
  525. /**
  526. * Update progress bar
  527. */
  528. function updateProgressBar(percentage) {
  529. $('#studiou-wcpcm-delete-progress-bar').css('width', percentage + '%');
  530. $('#studiou-wcpcm-delete-progress-bar').attr('data-progress', percentage + '%');
  531. }
  532. /**
  533. * Initialize clear media categories form
  534. */
  535. function initClearMediaForm() {
  536. console.log('STUDIOU WC: Initializing clear media form handlers');
  537. // Check all button handler
  538. $('#studiou-wcpcm-clear-media-check-all').on('click', function(e) {
  539. e.preventDefault();
  540. console.log('STUDIOU WC: Clear media check all button clicked');
  541. $('#clear_media_categories_list input[type="checkbox"]').prop('checked', true);
  542. });
  543. // Uncheck all button handler
  544. $('#studiou-wcpcm-clear-media-uncheck-all').on('click', function(e) {
  545. e.preventDefault();
  546. console.log('STUDIOU WC: Clear media uncheck all button clicked');
  547. $('#clear_media_categories_list input[type="checkbox"]').prop('checked', false);
  548. });
  549. // Form submit handler
  550. $('#studiou-wcpcm-clear-media-form').on('submit', function(e) {
  551. e.preventDefault();
  552. console.log('STUDIOU WC: Clear media form submitted');
  553. // Get selected categories
  554. var selectedCategories = [];
  555. $('#clear_media_categories_list input[type="checkbox"]:checked').each(function() {
  556. selectedCategories.push($(this).val());
  557. });
  558. console.log('STUDIOU WC: Selected media categories:', selectedCategories);
  559. // Validate input
  560. if (selectedCategories.length === 0) {
  561. console.log('STUDIOU WC: No media categories selected');
  562. showNotice('error', studiouWcpcm.i18n.selectAtLeastOneCategory || 'Please select at least one category');
  563. return;
  564. }
  565. // Confirm deletion
  566. if (!confirm(studiouWcpcm.i18n.confirmClearMedia || 'Are you sure you want to permanently delete ALL media files in the selected media categories? This action cannot be undone!')) {
  567. console.log('STUDIOU WC: User cancelled clear media');
  568. return;
  569. }
  570. // Show spinner
  571. var $submitBtn = $(this).find('#studiou-wcpcm-clear-media-button');
  572. var $spinner = $(this).find('.spinner');
  573. $submitBtn.prop('disabled', true);
  574. $spinner.css('visibility', 'visible');
  575. // Clear previous notices
  576. $('.studiou-wcpcm-notice-area').empty();
  577. // Hide results, show progress
  578. $('.studiou-wcpcm-clear-media-results').hide();
  579. $('.studiou-wcpcm-clear-media-progress').show();
  580. $('#studiou-wcpcm-clear-media-progress-text').text('Initializing...');
  581. updateClearMediaProgressBar(0);
  582. // Send AJAX request to get media IDs
  583. $.ajax({
  584. url: studiouWcpcm.ajaxUrl,
  585. type: 'POST',
  586. data: {
  587. action: 'studiou_wcpcm_clear_media',
  588. media_categories: selectedCategories,
  589. nonce: studiouWcpcm.nonce
  590. },
  591. success: function(response) {
  592. console.log('STUDIOU WC: Clear media AJAX response:', response);
  593. if (response.success) {
  594. var mediaIds = response.data.media_ids;
  595. var totalCount = response.data.total_count;
  596. console.log('STUDIOU WC: Total media files to delete:', totalCount);
  597. if (totalCount === 0) {
  598. showNotice('success', studiouWcpcm.i18n.noMediaFound || 'No media files found in selected categories');
  599. $('.studiou-wcpcm-clear-media-progress').hide();
  600. $submitBtn.prop('disabled', false);
  601. $spinner.css('visibility', 'hidden');
  602. return;
  603. }
  604. // Process media in batches
  605. processMediaDeletionBatches(mediaIds, totalCount, $submitBtn, $spinner);
  606. } else {
  607. showNotice('error', response.data.message);
  608. $('.studiou-wcpcm-clear-media-progress').hide();
  609. $submitBtn.prop('disabled', false);
  610. $spinner.css('visibility', 'hidden');
  611. }
  612. },
  613. error: function(xhr, status, error) {
  614. console.error('STUDIOU WC: Clear media AJAX error:', status, error);
  615. console.error('STUDIOU WC: Response text:', xhr.responseText);
  616. showNotice('error', (studiouWcpcm.i18n.clearMediaError || 'Clear media operation error') + ': ' + error);
  617. $('.studiou-wcpcm-clear-media-progress').hide();
  618. $submitBtn.prop('disabled', false);
  619. $spinner.css('visibility', 'hidden');
  620. }
  621. });
  622. });
  623. }
  624. /**
  625. * Process media deletion in batches
  626. */
  627. function processMediaDeletionBatches(mediaIds, totalCount, $submitBtn, $spinner) {
  628. var batchSize = 10;
  629. var batches = [];
  630. var totalDeleted = 0;
  631. var totalFailed = 0;
  632. var failedMedia = [];
  633. // Split media into batches
  634. for (var i = 0; i < mediaIds.length; i += batchSize) {
  635. batches.push(mediaIds.slice(i, i + batchSize));
  636. }
  637. console.log('STUDIOU WC: Processing ' + batches.length + ' batches of media files');
  638. var currentBatch = 0;
  639. function processBatch() {
  640. if (currentBatch >= batches.length) {
  641. console.log('STUDIOU WC: All media batches completed');
  642. onMediaDeletionComplete(totalDeleted, totalFailed, failedMedia, $submitBtn, $spinner);
  643. return;
  644. }
  645. var batch = batches[currentBatch];
  646. var progress = Math.round((currentBatch / batches.length) * 100);
  647. $('#studiou-wcpcm-clear-media-progress-text').text(
  648. 'Deleting media files... ' + (currentBatch * batchSize) + ' of ' + totalCount + ' processed'
  649. );
  650. updateClearMediaProgressBar(progress);
  651. $.ajax({
  652. url: studiouWcpcm.ajaxUrl,
  653. type: 'POST',
  654. data: {
  655. action: 'studiou_wcpcm_clear_media_batch',
  656. media_ids: batch,
  657. nonce: studiouWcpcm.nonce
  658. },
  659. success: function(response) {
  660. if (response.success) {
  661. totalDeleted += response.data.deleted_count;
  662. totalFailed += response.data.failed_count;
  663. failedMedia = failedMedia.concat(response.data.failed_media);
  664. console.log('STUDIOU WC: Media batch ' + currentBatch + ' completed - Deleted: ' +
  665. response.data.deleted_count + ', Failed: ' + response.data.failed_count);
  666. currentBatch++;
  667. processBatch();
  668. } else {
  669. showNotice('error', response.data.message);
  670. $('.studiou-wcpcm-clear-media-progress').hide();
  671. $submitBtn.prop('disabled', false);
  672. $spinner.css('visibility', 'hidden');
  673. }
  674. },
  675. error: function(xhr, status, error) {
  676. console.error('STUDIOU WC: Media batch delete AJAX error:', status, error);
  677. showNotice('error', 'Error deleting media batch: ' + error);
  678. $('.studiou-wcpcm-clear-media-progress').hide();
  679. $submitBtn.prop('disabled', false);
  680. $spinner.css('visibility', 'hidden');
  681. }
  682. });
  683. }
  684. processBatch();
  685. }
  686. /**
  687. * Handle media deletion completion
  688. */
  689. function onMediaDeletionComplete(totalDeleted, totalFailed, failedMedia, $submitBtn, $spinner) {
  690. updateClearMediaProgressBar(100);
  691. $('#studiou-wcpcm-clear-media-progress-text').text('Deletion complete!');
  692. var message = '<p><strong>Deletion Summary:</strong></p>';
  693. message += '<ul>';
  694. message += '<li>Total media files deleted: ' + totalDeleted + '</li>';
  695. if (totalFailed > 0) {
  696. message += '<li>Failed to delete: ' + totalFailed + '</li>';
  697. if (failedMedia.length > 0) {
  698. message += '<li>Failed media IDs: ' + failedMedia.join(', ') + '</li>';
  699. }
  700. }
  701. message += '</ul>';
  702. $('#studiou-wcpcm-clear-media-message').html(message);
  703. $('.studiou-wcpcm-clear-media-results').show();
  704. setTimeout(function() {
  705. $('.studiou-wcpcm-clear-media-progress').fadeOut();
  706. }, 2000);
  707. if (totalDeleted > 0) {
  708. showNotice('success', (studiouWcpcm.i18n.clearMediaSuccess || 'Successfully deleted') + ' ' + totalDeleted + ' media files');
  709. setTimeout(function() {
  710. location.reload();
  711. }, 3000);
  712. } else {
  713. showNotice('error', studiouWcpcm.i18n.clearMediaError || 'Failed to delete any media files');
  714. }
  715. $submitBtn.prop('disabled', false);
  716. $spinner.css('visibility', 'hidden');
  717. }
  718. /**
  719. * Update clear media progress bar
  720. */
  721. function updateClearMediaProgressBar(percentage) {
  722. $('#studiou-wcpcm-clear-media-progress-bar').css('width', percentage + '%');
  723. $('#studiou-wcpcm-clear-media-progress-bar').attr('data-progress', percentage + '%');
  724. }
  725. /**
  726. * Show notice message
  727. *
  728. * @param {string} type Notice type (success, error)
  729. * @param {string} message Notice message
  730. */
  731. function showNotice(type, message) {
  732. var $notice = $('<div class="studiou-wcpcm-notice studiou-wcpcm-notice-' + type + '"></div>').text(message);
  733. $('.studiou-wcpcm-notice-area').append($notice);
  734. // Scroll to notice
  735. $('html, body').animate({
  736. scrollTop: $('.studiou-wcpcm-notice-area').offset().top - 50
  737. }, 500);
  738. }
  739. /**
  740. * Initialize product import form
  741. */
  742. function initProductImportForm() {
  743. console.log('STUDIOU WC: Initializing product import form handlers');
  744. // Global variables for batch processing
  745. var importTransientKey = null;
  746. var importTotal = 0;
  747. var importProcessed = 0;
  748. var importSuccess = 0;
  749. var importFailed = 0;
  750. var importSkipped = 0;
  751. var importMessages = [];
  752. var importFailedCsv = '';
  753. $('#studiou-wcpcm-product-import-form').on('submit', function(e) {
  754. e.preventDefault();
  755. console.log('STUDIOU WC: Product import form submitted');
  756. // Validate file is selected
  757. var fileInput = $('#import_file')[0];
  758. if (!fileInput.files || !fileInput.files[0]) {
  759. showNotice('error', 'Please select a CSV file to import');
  760. return;
  761. }
  762. // Show spinner and progress
  763. var $submitBtn = $(this).find('#studiou-wcpcm-product-import-button');
  764. var $spinner = $(this).find('.spinner');
  765. $submitBtn.prop('disabled', true);
  766. $spinner.css('visibility', 'visible');
  767. // Clear previous results
  768. $('.studiou-wcpcm-notice-area').empty();
  769. $('.studiou-wcpcm-product-import-results').hide();
  770. $('.studiou-wcpcm-product-import-failed').hide();
  771. // Reset counters
  772. importTransientKey = null;
  773. importTotal = 0;
  774. importProcessed = 0;
  775. importSuccess = 0;
  776. importFailed = 0;
  777. importSkipped = 0;
  778. importMessages = [];
  779. importFailedCsv = '';
  780. // Show progress bar
  781. $('.studiou-wcpcm-product-import-progress').show();
  782. $('#studiou-wcpcm-product-import-progress-text').text('Parsing CSV file...');
  783. updateProductImportProgressBar(0);
  784. // Step 1: Parse CSV file
  785. var formData = new FormData(this);
  786. formData.append('action', 'studiou_wcpcm_product_import_parse');
  787. formData.append('nonce', studiouWcpcm.nonce);
  788. $.ajax({
  789. url: studiouWcpcm.ajaxUrl,
  790. type: 'POST',
  791. data: formData,
  792. processData: false,
  793. contentType: false,
  794. success: function(response) {
  795. console.log('STUDIOU WC: Product import parse response:', response);
  796. if (response.success) {
  797. importTransientKey = response.data.transient_key;
  798. importTotal = response.data.total;
  799. // Start batch processing
  800. processBatch(0, $submitBtn, $spinner);
  801. } else {
  802. showNotice('error', response.data.message || 'Parse failed');
  803. $('.studiou-wcpcm-product-import-progress').hide();
  804. $submitBtn.prop('disabled', false);
  805. $spinner.css('visibility', 'hidden');
  806. }
  807. },
  808. error: function(xhr, status, error) {
  809. console.error('STUDIOU WC: Product import parse error:', status, error);
  810. console.error('STUDIOU WC: Response text:', xhr.responseText);
  811. showNotice('error', 'Product import error: ' + error);
  812. $('.studiou-wcpcm-product-import-progress').hide();
  813. $submitBtn.prop('disabled', false);
  814. $spinner.css('visibility', 'hidden');
  815. }
  816. });
  817. });
  818. // Process batch of products
  819. function processBatch(offset, $submitBtn, $spinner) {
  820. console.log('STUDIOU WC: Processing batch at offset', offset);
  821. $.ajax({
  822. url: studiouWcpcm.ajaxUrl,
  823. type: 'POST',
  824. data: {
  825. action: 'studiou_wcpcm_product_import_batch',
  826. nonce: studiouWcpcm.nonce,
  827. transient_key: importTransientKey,
  828. offset: offset
  829. },
  830. success: function(response) {
  831. console.log('STUDIOU WC: Batch response:', response);
  832. if (response.success) {
  833. // Accumulate results
  834. importSuccess += response.data.success;
  835. importFailed += response.data.failed;
  836. importSkipped += response.data.skipped;
  837. importProcessed = response.data.processed;
  838. importTotal = response.data.total;
  839. importMessages = importMessages.concat(response.data.messages);
  840. if (response.data.failed_csv) {
  841. importFailedCsv = response.data.failed_csv;
  842. }
  843. // Update progress
  844. var percent = (importProcessed / importTotal) * 100;
  845. updateProductImportProgressBar(percent);
  846. $('#studiou-wcpcm-product-import-progress-text').text(
  847. 'Processing: ' + importProcessed + ' / ' + importTotal + ' products'
  848. );
  849. // Check if complete
  850. if (importProcessed >= importTotal) {
  851. // Import complete
  852. $('#studiou-wcpcm-product-import-progress-text').text('Complete!');
  853. showNotice('success', 'Product import completed!');
  854. // Show results
  855. var message = '<p><strong>Import Summary:</strong></p>';
  856. message += '<ul>';
  857. message += '<li>Successful: ' + importSuccess + '</li>';
  858. message += '<li>Failed: ' + importFailed + '</li>';
  859. message += '<li>Skipped: ' + importSkipped + '</li>';
  860. message += '</ul>';
  861. $('#studiou-wcpcm-product-import-message').html(message);
  862. // Show detailed messages
  863. if (importMessages.length > 0) {
  864. var details = '<pre>' + importMessages.join('\n') + '</pre>';
  865. $('#studiou-wcpcm-product-import-details-content').html(details);
  866. }
  867. $('.studiou-wcpcm-product-import-results').show();
  868. // Show save failed button if there are failed items
  869. if (importFailed > 0 && importFailedCsv) {
  870. window.studiouWcpcmFailedCsv = importFailedCsv;
  871. $('.studiou-wcpcm-product-import-failed').show();
  872. }
  873. // Hide progress after delay
  874. setTimeout(function() {
  875. $('.studiou-wcpcm-product-import-progress').fadeOut();
  876. }, 2000);
  877. $submitBtn.prop('disabled', false);
  878. $spinner.css('visibility', 'hidden');
  879. } else {
  880. // Process next batch
  881. processBatch(importProcessed, $submitBtn, $spinner);
  882. }
  883. } else {
  884. showNotice('error', response.data.message || 'Batch processing failed');
  885. $('.studiou-wcpcm-product-import-progress').hide();
  886. $submitBtn.prop('disabled', false);
  887. $spinner.css('visibility', 'hidden');
  888. }
  889. },
  890. error: function(xhr, status, error) {
  891. console.error('STUDIOU WC: Batch processing error:', status, error);
  892. showNotice('error', 'Batch processing error: ' + error);
  893. $('.studiou-wcpcm-product-import-progress').hide();
  894. $submitBtn.prop('disabled', false);
  895. $spinner.css('visibility', 'hidden');
  896. }
  897. });
  898. }
  899. // Save failed products button handler
  900. $('#studiou-wcpcm-save-failed-products').on('click', function(e) {
  901. e.preventDefault();
  902. if (window.studiouWcpcmFailedCsv) {
  903. var blob = new Blob([window.studiouWcpcmFailedCsv], { type: 'text/csv;charset=utf-8;' });
  904. var url = URL.createObjectURL(blob);
  905. var link = document.createElement('a');
  906. link.setAttribute('href', url);
  907. link.setAttribute('download', 'failed-products-' + Date.now() + '.csv');
  908. link.style.visibility = 'hidden';
  909. document.body.appendChild(link);
  910. link.click();
  911. document.body.removeChild(link);
  912. }
  913. });
  914. }
  915. /**
  916. * Initialize product export form
  917. */
  918. function initProductExportForm() {
  919. console.log('STUDIOU WC: Initializing product export form handlers');
  920. // Select all button handler
  921. $('#studiou-wcpcm-export-select-all').on('click', function(e) {
  922. e.preventDefault();
  923. console.log('STUDIOU WC: Export select all button clicked');
  924. $('#export_categories_list input[type="checkbox"]').prop('checked', true);
  925. });
  926. // Deselect all button handler
  927. $('#studiou-wcpcm-export-deselect-all').on('click', function(e) {
  928. e.preventDefault();
  929. console.log('STUDIOU WC: Export deselect all button clicked');
  930. $('#export_categories_list input[type="checkbox"]').prop('checked', false);
  931. });
  932. // Form submit handler
  933. $('#studiou-wcpcm-product-export-form').on('submit', function(e) {
  934. e.preventDefault();
  935. console.log('STUDIOU WC: Product export form submitted');
  936. // Get selected categories
  937. var selectedCategories = [];
  938. $('#export_categories_list input[type="checkbox"]:checked').each(function() {
  939. selectedCategories.push($(this).val());
  940. });
  941. console.log('STUDIOU WC: Selected categories:', selectedCategories);
  942. // Validate input
  943. if (selectedCategories.length === 0) {
  944. console.log('STUDIOU WC: No categories selected');
  945. showNotice('error', 'Please select at least one category');
  946. return;
  947. }
  948. // Show spinner
  949. var $submitBtn = $(this).find('#studiou-wcpcm-product-export-button');
  950. var $spinner = $(this).find('.spinner');
  951. $submitBtn.prop('disabled', true);
  952. $spinner.css('visibility', 'visible');
  953. // Clear previous notices
  954. $('.studiou-wcpcm-notice-area').empty();
  955. $('.studiou-wcpcm-product-export-results').hide();
  956. // Debug: Log AJAX request details
  957. console.log('STUDIOU WC: Sending product export AJAX request to:', studiouWcpcm.ajaxUrl);
  958. console.log('STUDIOU WC: Nonce:', studiouWcpcm.nonce);
  959. // Send AJAX request
  960. $.ajax({
  961. url: studiouWcpcm.ajaxUrl,
  962. type: 'POST',
  963. data: {
  964. action: 'studiou_wcpcm_product_export',
  965. export_categories: selectedCategories,
  966. nonce: studiouWcpcm.nonce
  967. },
  968. success: function(response) {
  969. console.log('STUDIOU WC: Product export AJAX response:', response);
  970. if (response.success) {
  971. showNotice('success', 'Export successful!');
  972. // Show results
  973. $('#studiou-wcpcm-product-export-message').html('<p>' + response.data.message + '</p>');
  974. $('#studiou-wcpcm-download-product-export').attr('href', response.data.download_url);
  975. $('.studiou-wcpcm-product-export-results').show();
  976. } else {
  977. showNotice('error', response.data.message || 'Export failed');
  978. }
  979. },
  980. error: function(xhr, status, error) {
  981. console.error('STUDIOU WC: Product export AJAX error:', status, error);
  982. console.error('STUDIOU WC: Response text:', xhr.responseText);
  983. showNotice('error', 'Product export error: ' + error);
  984. },
  985. complete: function() {
  986. // Hide spinner
  987. $submitBtn.prop('disabled', false);
  988. $spinner.css('visibility', 'hidden');
  989. }
  990. });
  991. });
  992. }
  993. /**
  994. * Update product import progress bar
  995. */
  996. function updateProductImportProgressBar(percentage) {
  997. $('#studiou-wcpcm-product-import-progress-bar').css('width', percentage + '%');
  998. $('#studiou-wcpcm-product-import-progress-bar').attr('data-progress', Math.round(percentage) + '%');
  999. }
  1000. // Additional debug: Check if elements exist after DOM load
  1001. $(window).on('load', function() {
  1002. console.log('STUDIOU WC: Window loaded');
  1003. console.log('STUDIOU WC: Move form exists:', $('#studiou-wcpcm-move-form').length > 0);
  1004. console.log('STUDIOU WC: Move button exists:', $('#studiou-wcpcm-move-button').length > 0);
  1005. console.log('STUDIOU WC: Source select exists:', $('#source_category').length > 0);
  1006. console.log('STUDIOU WC: Target select exists:', $('#target_category').length > 0);
  1007. console.log('STUDIOU WC: Batch description form exists:', $('#studiou-wcpcm-batch-description-form').length > 0);
  1008. console.log('STUDIOU WC: Batch description button exists:', $('#studiou-wcpcm-batch-description-button').length > 0);
  1009. console.log('STUDIOU WC: Delete products form exists:', $('#studiou-wcpcm-delete-products-form').length > 0);
  1010. console.log('STUDIOU WC: Product import form exists:', $('#studiou-wcpcm-product-import-form').length > 0);
  1011. console.log('STUDIOU WC: Product export form exists:', $('#studiou-wcpcm-product-export-form').length > 0);
  1012. console.log('STUDIOU WC: Clear media form exists:', $('#studiou-wcpcm-clear-media-form').length > 0);
  1013. });
  1014. })(jQuery);