You've already forked wp-fedistream
feat: Add license management and tabbed settings (v0.3.0)
- Implement license management using magdev/wc-licensed-product-client - Reorganize settings page into License, Default Settings, Integrations tabs - Add license validation and activation via AJAX - Frontend features require valid license (admin works always) - Update translations with German (de_CH) for license strings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,4 +4,122 @@
|
||||
* @package WP_FediStream
|
||||
*/
|
||||
|
||||
/* Admin styles will be added here */
|
||||
/* Settings page tabs */
|
||||
.nav-tab-wrapper + .fedistream-settings-content {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.fedistream-settings-content {
|
||||
background: #fff;
|
||||
border: 1px solid #c3c4c7;
|
||||
border-top: none;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Active tab styling */
|
||||
.wrap .nav-tab-wrapper .nav-tab-active {
|
||||
background: #fff;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
|
||||
/* License status banner */
|
||||
.fedistream-license-status {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.fedistream-license-status .dashicons {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.fedistream-license-status.notice-success .dashicons {
|
||||
color: #00a32a;
|
||||
}
|
||||
|
||||
.fedistream-license-status.notice-error .dashicons {
|
||||
color: #d63638;
|
||||
}
|
||||
|
||||
.fedistream-license-status.notice-warning .dashicons {
|
||||
color: #dba617;
|
||||
}
|
||||
|
||||
.fedistream-license-status.notice-info .dashicons {
|
||||
color: #72aee6;
|
||||
}
|
||||
|
||||
/* License form buttons */
|
||||
#fedistream-license-form .button .dashicons {
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* License message display */
|
||||
#fedistream-license-message {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
#fedistream-license-message p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Dashboard stats grid */
|
||||
.fedistream-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.fedistream-stat-box {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
border: 1px solid #ccd0d4;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.fedistream-stat-box h3 {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.fedistream-stat-box p {
|
||||
font-size: 2em;
|
||||
margin: 0;
|
||||
color: #2271b1;
|
||||
}
|
||||
|
||||
/* Quick actions */
|
||||
.fedistream-quick-actions {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
border: 1px solid #ccd0d4;
|
||||
border-radius: 4px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* Info box */
|
||||
.fedistream-info {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
border: 1px solid #ccd0d4;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media screen and (max-width: 782px) {
|
||||
.fedistream-stats {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
#fedistream-license-form .button {
|
||||
display: block;
|
||||
margin: 10px 0 0 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
.fedistream-stats {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,115 @@
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
// Admin scripts will be added here
|
||||
// License validation functionality
|
||||
initLicenseValidation();
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialize license validation AJAX handlers.
|
||||
*/
|
||||
function initLicenseValidation() {
|
||||
var $validateBtn = $('#fedistream-validate-license');
|
||||
var $activateBtn = $('#fedistream-activate-license');
|
||||
var $spinner = $('#fedistream-license-spinner');
|
||||
var $message = $('#fedistream-license-message');
|
||||
|
||||
if (!$validateBtn.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate license button
|
||||
$validateBtn.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
performLicenseAction('fedistream_validate_license', 'Validating...');
|
||||
});
|
||||
|
||||
// Activate license button
|
||||
$activateBtn.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
performLicenseAction('fedistream_activate_license', 'Activating...');
|
||||
});
|
||||
|
||||
/**
|
||||
* Perform license AJAX action.
|
||||
*
|
||||
* @param {string} action AJAX action name.
|
||||
* @param {string} loadingText Loading button text.
|
||||
*/
|
||||
function performLicenseAction(action, loadingText) {
|
||||
var originalText = $validateBtn.text();
|
||||
|
||||
// Show loading state
|
||||
$spinner.addClass('is-active');
|
||||
$validateBtn.prop('disabled', true);
|
||||
$activateBtn.prop('disabled', true);
|
||||
$message.hide();
|
||||
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: action,
|
||||
nonce: fedistreamLicenseNonce
|
||||
},
|
||||
success: function(response) {
|
||||
$spinner.removeClass('is-active');
|
||||
$validateBtn.prop('disabled', false);
|
||||
$activateBtn.prop('disabled', false);
|
||||
|
||||
if (response.success) {
|
||||
showMessage('success', response.data.message);
|
||||
// Reload page to show updated status
|
||||
setTimeout(function() {
|
||||
window.location.reload();
|
||||
}, 1500);
|
||||
} else {
|
||||
showMessage('error', response.data.message || 'An error occurred.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$spinner.removeClass('is-active');
|
||||
$validateBtn.prop('disabled', false);
|
||||
$activateBtn.prop('disabled', false);
|
||||
showMessage('error', 'Request failed. Please try again.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a message to the user.
|
||||
*
|
||||
* @param {string} type Message type: 'success', 'error', 'warning', 'info'.
|
||||
* @param {string} text Message text.
|
||||
*/
|
||||
function showMessage(type, text) {
|
||||
var classMap = {
|
||||
'success': 'notice-success',
|
||||
'error': 'notice-error',
|
||||
'warning': 'notice-warning',
|
||||
'info': 'notice-info'
|
||||
};
|
||||
|
||||
var noticeClass = classMap[type] || 'notice-info';
|
||||
|
||||
$message
|
||||
.removeClass('notice-success notice-error notice-warning notice-info')
|
||||
.addClass('notice ' + noticeClass)
|
||||
.html('<p>' + escapeHtml(text) + '</p>')
|
||||
.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape HTML entities.
|
||||
*
|
||||
* @param {string} text Text to escape.
|
||||
* @return {string} Escaped text.
|
||||
*/
|
||||
function escapeHtml(text) {
|
||||
var div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
||||
Reference in New Issue
Block a user