You've already forked wc-licensed-product
Implement version 0.0.2 features
Add product version management: - ProductVersion model and VersionManager class - VersionAdminController with meta box on product edit page - AJAX-based version CRUD (add, delete, toggle status) - JavaScript for version management UI Add email notifications: - LicenseEmailController for order emails - License keys included in order completed emails - Support for both HTML and plain text emails Add REST API rate limiting: - 30 requests per minute per IP - Cloudflare and proxy-aware IP detection - HTTP 429 response with Retry-After header Other changes: - Bump version to 0.0.2 - Update CHANGELOG.md - Add version status styles to admin.css Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
181
assets/js/versions.js
Normal file
181
assets/js/versions.js
Normal file
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* WC Licensed Product - Version Management
|
||||
*
|
||||
* @package Jeremias\WcLicensedProduct
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
var WCLicensedProductVersions = {
|
||||
init: function() {
|
||||
this.bindEvents();
|
||||
},
|
||||
|
||||
bindEvents: function() {
|
||||
$('#add-version-btn').on('click', this.addVersion);
|
||||
$(document).on('click', '.delete-version-btn', this.deleteVersion);
|
||||
$(document).on('click', '.toggle-version-btn', this.toggleVersion);
|
||||
},
|
||||
|
||||
addVersion: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $btn = $(this);
|
||||
var $spinner = $btn.siblings('.spinner');
|
||||
var productId = $btn.data('product-id');
|
||||
var version = $('#new_version').val().trim();
|
||||
var downloadUrl = $('#new_download_url').val().trim();
|
||||
var releaseNotes = $('#new_release_notes').val().trim();
|
||||
|
||||
// Validate version
|
||||
if (!version) {
|
||||
alert(wcLicensedProductVersions.strings.versionRequired);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!/^\d+\.\d+\.\d+$/.test(version)) {
|
||||
alert(wcLicensedProductVersions.strings.versionInvalid);
|
||||
return;
|
||||
}
|
||||
|
||||
$btn.prop('disabled', true);
|
||||
$spinner.addClass('is-active');
|
||||
|
||||
$.ajax({
|
||||
url: wcLicensedProductVersions.ajaxUrl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wc_licensed_product_add_version',
|
||||
nonce: wcLicensedProductVersions.nonce,
|
||||
product_id: productId,
|
||||
version: version,
|
||||
download_url: downloadUrl,
|
||||
release_notes: releaseNotes
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
// Remove "no versions" row if present
|
||||
$('#versions-table tbody .no-versions').remove();
|
||||
|
||||
// Add new row to table
|
||||
$('#versions-table tbody').prepend(response.data.html);
|
||||
|
||||
// Clear form
|
||||
$('#new_version').val('');
|
||||
$('#new_download_url').val('');
|
||||
$('#new_release_notes').val('');
|
||||
} else {
|
||||
alert(response.data.message || wcLicensedProductVersions.strings.error);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert(wcLicensedProductVersions.strings.error);
|
||||
},
|
||||
complete: function() {
|
||||
$btn.prop('disabled', false);
|
||||
$spinner.removeClass('is-active');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
deleteVersion: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (!confirm(wcLicensedProductVersions.strings.confirmDelete)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $btn = $(this);
|
||||
var $row = $btn.closest('tr');
|
||||
var versionId = $btn.data('version-id');
|
||||
|
||||
$btn.prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: wcLicensedProductVersions.ajaxUrl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wc_licensed_product_delete_version',
|
||||
nonce: wcLicensedProductVersions.nonce,
|
||||
version_id: versionId
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$row.fadeOut(300, function() {
|
||||
$(this).remove();
|
||||
|
||||
// Show "no versions" message if table is empty
|
||||
if ($('#versions-table tbody tr').length === 0) {
|
||||
$('#versions-table tbody').append(
|
||||
'<tr class="no-versions"><td colspan="6">' +
|
||||
'No versions found. Add your first version above.' +
|
||||
'</td></tr>'
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert(response.data.message || wcLicensedProductVersions.strings.error);
|
||||
$btn.prop('disabled', false);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert(wcLicensedProductVersions.strings.error);
|
||||
$btn.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggleVersion: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $btn = $(this);
|
||||
var $row = $btn.closest('tr');
|
||||
var versionId = $btn.data('version-id');
|
||||
var currentlyActive = $btn.data('active') === 1 || $btn.data('active') === '1';
|
||||
|
||||
$btn.prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: wcLicensedProductVersions.ajaxUrl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wc_licensed_product_toggle_version',
|
||||
nonce: wcLicensedProductVersions.nonce,
|
||||
version_id: versionId,
|
||||
currently_active: currentlyActive ? 1 : 0
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var isActive = response.data.isActive;
|
||||
var $status = $row.find('.version-status');
|
||||
|
||||
// Update status badge
|
||||
$status
|
||||
.removeClass('version-status-active version-status-inactive')
|
||||
.addClass('version-status-' + (isActive ? 'active' : 'inactive'))
|
||||
.text(isActive ? 'Active' : 'Inactive');
|
||||
|
||||
// Update button
|
||||
$btn
|
||||
.data('active', isActive ? 1 : 0)
|
||||
.text(isActive ? 'Deactivate' : 'Activate');
|
||||
} else {
|
||||
alert(response.data.message || wcLicensedProductVersions.strings.error);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert(wcLicensedProductVersions.strings.error);
|
||||
},
|
||||
complete: function() {
|
||||
$btn.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
WCLicensedProductVersions.init();
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user