2026-01-21 18:55:18 +01:00
|
|
|
|
<div class="wrap">
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<h1 class="wp-heading-inline">{{ __('Licenses') }}</h1>
|
2026-01-23 21:18:32 +01:00
|
|
|
|
<a href="{{ export_csv_url() }}" class="page-title-action">
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<span class="dashicons dashicons-download" style="vertical-align: middle;"></span>
|
|
|
|
|
|
{{ __('Export CSV') }}
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a href="{{ admin_url }}?action=import_csv" class="page-title-action">
|
|
|
|
|
|
<span class="dashicons dashicons-upload" style="vertical-align: middle;"></span>
|
|
|
|
|
|
{{ __('Import CSV') }}
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<hr class="wp-header-end">
|
2026-01-21 18:55:18 +01:00
|
|
|
|
|
|
|
|
|
|
{% for notice in notices %}
|
|
|
|
|
|
<div class="notice notice-{{ notice.type }} is-dismissible">
|
|
|
|
|
|
<p>{{ esc_html(notice.message) }}</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{% endfor %}
|
|
|
|
|
|
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<!-- Search and Filter Form -->
|
|
|
|
|
|
<form method="get" action="" class="wclp-filter-form">
|
|
|
|
|
|
<input type="hidden" name="page" value="wc-licenses">
|
|
|
|
|
|
|
|
|
|
|
|
<p class="search-box">
|
|
|
|
|
|
<label class="screen-reader-text" for="license-search-input">{{ __('Search Licenses') }}</label>
|
|
|
|
|
|
<input type="search" id="license-search-input" name="s" value="{{ filters.search|default('') }}"
|
|
|
|
|
|
placeholder="{{ __('Search license key or domain...') }}">
|
|
|
|
|
|
<input type="submit" id="search-submit" class="button" value="{{ __('Search') }}">
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="tablenav top">
|
|
|
|
|
|
<div class="alignleft actions">
|
|
|
|
|
|
<select name="status">
|
|
|
|
|
|
<option value="all">{{ __('All Statuses') }}</option>
|
|
|
|
|
|
<option value="active" {{ filters.status|default('') == 'active' ? 'selected' : '' }}>{{ __('Active') }}</option>
|
|
|
|
|
|
<option value="inactive" {{ filters.status|default('') == 'inactive' ? 'selected' : '' }}>{{ __('Inactive') }}</option>
|
|
|
|
|
|
<option value="expired" {{ filters.status|default('') == 'expired' ? 'selected' : '' }}>{{ __('Expired') }}</option>
|
|
|
|
|
|
<option value="revoked" {{ filters.status|default('') == 'revoked' ? 'selected' : '' }}>{{ __('Revoked') }}</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
|
|
|
|
<select name="product_id">
|
|
|
|
|
|
<option value="">{{ __('All Products') }}</option>
|
|
|
|
|
|
{% for id, name in products %}
|
|
|
|
|
|
<option value="{{ id }}" {{ filters.product_id|default('') == id ? 'selected' : '' }}>{{ esc_html(name) }}</option>
|
|
|
|
|
|
{% endfor %}
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
|
|
|
|
<input type="submit" class="button" value="{{ __('Filter') }}">
|
|
|
|
|
|
|
|
|
|
|
|
{% if filters is not empty %}
|
|
|
|
|
|
<a href="{{ admin_url }}" class="button">{{ __('Clear') }}</a>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="tablenav-pages">
|
|
|
|
|
|
<span class="displaying-num">{{ total_licenses }} {{ total_licenses == 1 ? __('item') : __('items') }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
|
2026-01-21 18:55:18 +01:00
|
|
|
|
<p class="description">
|
2026-01-21 20:32:35 +01:00
|
|
|
|
{{ __('Showing') }} {{ total_licenses }} {{ total_licenses == 1 ? __('license') : __('licenses') }}
|
|
|
|
|
|
{% if filters is not empty %}
|
|
|
|
|
|
({{ __('filtered') }})
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
| <a href="{{ constant('admin_url')('admin.php?page=wc-reports&tab=licenses') }}">{{ __('View Dashboard') }}</a>
|
2026-01-21 18:55:18 +01:00
|
|
|
|
</p>
|
|
|
|
|
|
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<form method="post" action="{{ admin_url }}" id="licenses-bulk-form">
|
|
|
|
|
|
{{ wp_nonce_field('bulk_license_action', '_wpnonce', true, false)|raw }}
|
|
|
|
|
|
|
|
|
|
|
|
<div class="tablenav top">
|
|
|
|
|
|
<div class="alignleft actions bulkactions">
|
|
|
|
|
|
<select name="bulk_action" id="bulk-action-selector">
|
|
|
|
|
|
<option value="">{{ __('Bulk Actions') }}</option>
|
|
|
|
|
|
<option value="activate">{{ __('Activate') }}</option>
|
|
|
|
|
|
<option value="deactivate">{{ __('Deactivate') }}</option>
|
|
|
|
|
|
<option value="revoke">{{ __('Revoke') }}</option>
|
|
|
|
|
|
<option value="extend_30">{{ __('Extend 30 days') }}</option>
|
|
|
|
|
|
<option value="extend_90">{{ __('Extend 90 days') }}</option>
|
|
|
|
|
|
<option value="extend_365">{{ __('Extend 1 year') }}</option>
|
|
|
|
|
|
<option value="delete">{{ __('Delete') }}</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
<input type="submit" class="button action" value="{{ __('Apply') }}">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<table class="wp-list-table widefat fixed striped licenses-table">
|
|
|
|
|
|
<thead>
|
2026-01-21 18:55:18 +01:00
|
|
|
|
<tr>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<td class="manage-column column-cb check-column">
|
|
|
|
|
|
<input type="checkbox" id="cb-select-all-1">
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<th>{{ __('License Key') }}</th>
|
|
|
|
|
|
<th>{{ __('Product') }}</th>
|
|
|
|
|
|
<th>{{ __('Customer') }}</th>
|
|
|
|
|
|
<th>{{ __('Domain') }}</th>
|
|
|
|
|
|
<th>{{ __('Status') }}</th>
|
2026-01-21 23:50:57 +01:00
|
|
|
|
<th>{{ __('Created') }}</th>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<th>{{ __('Expires') }}</th>
|
|
|
|
|
|
<th>{{ __('Actions') }}</th>
|
2026-01-21 18:55:18 +01:00
|
|
|
|
</tr>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
{% if licenses is empty %}
|
2026-01-21 18:55:18 +01:00
|
|
|
|
<tr>
|
2026-01-21 23:50:57 +01:00
|
|
|
|
<td colspan="9">{{ __('No licenses found.') }}</td>
|
2026-01-21 18:55:18 +01:00
|
|
|
|
</tr>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
{% else %}
|
|
|
|
|
|
{% for item in licenses %}
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th scope="row" class="check-column">
|
|
|
|
|
|
<input type="checkbox" name="license_ids[]" value="{{ item.license.id }}">
|
|
|
|
|
|
</th>
|
2026-01-21 23:13:07 +01:00
|
|
|
|
<td>
|
|
|
|
|
|
<code class="wclp-license-key">{{ item.license.licenseKey }}</code>
|
|
|
|
|
|
<button type="button" class="wclp-copy-btn button-link" data-license-key="{{ esc_attr(item.license.licenseKey) }}" title="{{ __('Copy to clipboard') }}">
|
|
|
|
|
|
<span class="dashicons dashicons-clipboard"></span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</td>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<td>
|
|
|
|
|
|
{% if item.product_edit_url %}
|
|
|
|
|
|
<a href="{{ esc_url(item.product_edit_url) }}">{{ esc_html(item.product_name) }}</a>
|
|
|
|
|
|
{% else %}
|
|
|
|
|
|
{{ esc_html(item.product_name) }}
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<td>
|
|
|
|
|
|
{{ esc_html(item.customer_name) }}
|
|
|
|
|
|
{% if item.customer_email %}
|
|
|
|
|
|
<br><small>{{ esc_html(item.customer_email) }}</small>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</td>
|
2026-01-21 23:13:07 +01:00
|
|
|
|
<td class="wclp-editable-cell" data-field="domain" data-license-id="{{ item.license.id }}">
|
|
|
|
|
|
<span class="wclp-display-value">{{ esc_html(item.license.domain) }}</span>
|
|
|
|
|
|
<button type="button" class="wclp-edit-btn button-link" title="{{ __('Edit') }}">
|
|
|
|
|
|
<span class="dashicons dashicons-edit"></span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<div class="wclp-edit-form" style="display:none;">
|
|
|
|
|
|
<input type="text" class="wclp-edit-input" value="{{ esc_attr(item.license.domain) }}">
|
|
|
|
|
|
<button type="button" class="wclp-save-btn button button-small button-primary">{{ __('Save') }}</button>
|
|
|
|
|
|
<button type="button" class="wclp-cancel-btn button button-small">{{ __('Cancel') }}</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<td class="wclp-editable-cell" data-field="status" data-license-id="{{ item.license.id }}">
|
|
|
|
|
|
<span class="wclp-display-value">
|
2026-01-23 21:18:32 +01:00
|
|
|
|
<span class="license-status license-status-{{ esc_attr(item.license.status) }}">
|
|
|
|
|
|
{{ esc_html(item.license.status)|capitalize }}
|
2026-01-21 23:13:07 +01:00
|
|
|
|
</span>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
</span>
|
2026-01-21 23:13:07 +01:00
|
|
|
|
<button type="button" class="wclp-edit-btn button-link" title="{{ __('Edit') }}">
|
|
|
|
|
|
<span class="dashicons dashicons-edit"></span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<div class="wclp-edit-form" style="display:none;">
|
|
|
|
|
|
<select class="wclp-edit-input">
|
|
|
|
|
|
<option value="active" {{ item.license.status == 'active' ? 'selected' : '' }}>{{ __('Active') }}</option>
|
|
|
|
|
|
<option value="inactive" {{ item.license.status == 'inactive' ? 'selected' : '' }}>{{ __('Inactive') }}</option>
|
|
|
|
|
|
<option value="expired" {{ item.license.status == 'expired' ? 'selected' : '' }}>{{ __('Expired') }}</option>
|
|
|
|
|
|
<option value="revoked" {{ item.license.status == 'revoked' ? 'selected' : '' }}>{{ __('Revoked') }}</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
<button type="button" class="wclp-save-btn button button-small button-primary">{{ __('Save') }}</button>
|
|
|
|
|
|
<button type="button" class="wclp-cancel-btn button button-small">{{ __('Cancel') }}</button>
|
|
|
|
|
|
</div>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
</td>
|
2026-01-21 23:50:57 +01:00
|
|
|
|
<td class="wclp-created-cell">
|
|
|
|
|
|
{{ item.license.createdAt|date('Y-m-d') }}
|
|
|
|
|
|
</td>
|
2026-01-21 23:13:07 +01:00
|
|
|
|
<td class="wclp-editable-cell" data-field="expiry" data-license-id="{{ item.license.id }}">
|
|
|
|
|
|
<span class="wclp-display-value">
|
|
|
|
|
|
{% if item.license.expiresAt %}
|
|
|
|
|
|
{{ item.license.expiresAt|date('Y-m-d') }}
|
|
|
|
|
|
{% else %}
|
|
|
|
|
|
<span class="license-lifetime">{{ __('Lifetime') }}</span>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<button type="button" class="wclp-edit-btn button-link" title="{{ __('Edit') }}">
|
|
|
|
|
|
<span class="dashicons dashicons-edit"></span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<div class="wclp-edit-form" style="display:none;">
|
|
|
|
|
|
<input type="date" class="wclp-edit-input" value="{{ item.license.expiresAt ? item.license.expiresAt|date('Y-m-d') : '' }}" placeholder="{{ __('Leave empty for lifetime') }}">
|
|
|
|
|
|
<button type="button" class="wclp-save-btn button button-small button-primary">{{ __('Save') }}</button>
|
|
|
|
|
|
<button type="button" class="wclp-cancel-btn button button-small">{{ __('Cancel') }}</button>
|
|
|
|
|
|
<button type="button" class="wclp-lifetime-btn button button-small" title="{{ __('Set to lifetime') }}">∞</button>
|
|
|
|
|
|
</div>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
</td>
|
|
|
|
|
|
<td class="license-actions">
|
|
|
|
|
|
<div class="row-actions">
|
2026-01-23 11:37:06 +01:00
|
|
|
|
<span class="test">
|
|
|
|
|
|
<a href="#" class="wclp-test-license-link"
|
|
|
|
|
|
data-license-id="{{ item.license.id }}"
|
|
|
|
|
|
data-license-key="{{ esc_attr(item.license.licenseKey) }}"
|
|
|
|
|
|
data-domain="{{ esc_attr(item.license.domain) }}"
|
|
|
|
|
|
title="{{ __('Test license against API') }}">{{ __('Test') }}</a> |
|
|
|
|
|
|
</span>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
{% if item.license.status != 'revoked' %}
|
|
|
|
|
|
<span class="transfer">
|
|
|
|
|
|
<a href="#" class="wclp-transfer-link"
|
|
|
|
|
|
data-license-id="{{ item.license.id }}"
|
|
|
|
|
|
data-current-domain="{{ esc_attr(item.license.domain) }}"
|
|
|
|
|
|
title="{{ __('Transfer to new domain') }}">{{ __('Transfer') }}</a> |
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<span class="extend">
|
|
|
|
|
|
<a href="{{ extend_url(item.license.id, 30) }}" title="{{ __('Extend by 30 days') }}">+30d</a> |
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<span class="lifetime">
|
|
|
|
|
|
<a href="{{ lifetime_url(item.license.id) }}" title="{{ __('Set to lifetime') }}">∞</a> |
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<span class="revoke">
|
|
|
|
|
|
<a href="{{ revoke_url(item.license.id) }}"
|
|
|
|
|
|
onclick="return confirm('{{ __('Are you sure?') }}')">{{ __('Revoke') }}</a> |
|
|
|
|
|
|
</span>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
<span class="delete">
|
|
|
|
|
|
<a href="{{ delete_url(item.license.id) }}"
|
|
|
|
|
|
class="submitdelete"
|
|
|
|
|
|
onclick="return confirm('{{ __('Are you sure you want to delete this license?') }}')">{{ __('Delete') }}</a>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
{% endfor %}
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
<tfoot>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td class="manage-column column-cb check-column">
|
|
|
|
|
|
<input type="checkbox" id="cb-select-all-2">
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<th>{{ __('License Key') }}</th>
|
|
|
|
|
|
<th>{{ __('Product') }}</th>
|
|
|
|
|
|
<th>{{ __('Customer') }}</th>
|
|
|
|
|
|
<th>{{ __('Domain') }}</th>
|
|
|
|
|
|
<th>{{ __('Status') }}</th>
|
2026-01-21 23:50:57 +01:00
|
|
|
|
<th>{{ __('Created') }}</th>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<th>{{ __('Expires') }}</th>
|
|
|
|
|
|
<th>{{ __('Actions') }}</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</tfoot>
|
|
|
|
|
|
</table>
|
2026-01-21 18:55:18 +01:00
|
|
|
|
|
|
|
|
|
|
<div class="tablenav bottom">
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<div class="alignleft actions bulkactions">
|
|
|
|
|
|
<select name="bulk_action_2" id="bulk-action-selector-bottom">
|
|
|
|
|
|
<option value="">{{ __('Bulk Actions') }}</option>
|
|
|
|
|
|
<option value="activate">{{ __('Activate') }}</option>
|
|
|
|
|
|
<option value="deactivate">{{ __('Deactivate') }}</option>
|
|
|
|
|
|
<option value="revoke">{{ __('Revoke') }}</option>
|
|
|
|
|
|
<option value="extend_30">{{ __('Extend 30 days') }}</option>
|
|
|
|
|
|
<option value="extend_90">{{ __('Extend 90 days') }}</option>
|
|
|
|
|
|
<option value="extend_365">{{ __('Extend 1 year') }}</option>
|
|
|
|
|
|
<option value="delete">{{ __('Delete') }}</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
<input type="submit" class="button action" value="{{ __('Apply') }}">
|
2026-01-21 18:55:18 +01:00
|
|
|
|
</div>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
{% if total_pages > 1 %}
|
|
|
|
|
|
{% set filter_params = '' %}
|
|
|
|
|
|
{% if filters.search is defined and filters.search %}{% set filter_params = filter_params ~ '&s=' ~ filters.search %}{% endif %}
|
|
|
|
|
|
{% if filters.status is defined and filters.status %}{% set filter_params = filter_params ~ '&status=' ~ filters.status %}{% endif %}
|
|
|
|
|
|
{% if filters.product_id is defined and filters.product_id %}{% set filter_params = filter_params ~ '&product_id=' ~ filters.product_id %}{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
<div class="tablenav-pages">
|
|
|
|
|
|
<span class="pagination-links">
|
|
|
|
|
|
{% if current_page > 1 %}
|
|
|
|
|
|
<a class="prev-page button" href="{{ admin_url ~ '&paged=' ~ (current_page - 1) ~ filter_params }}">
|
|
|
|
|
|
<span aria-hidden="true">‹</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
<span class="paging-input">
|
|
|
|
|
|
{{ current_page }} {{ __('of') }} {{ total_pages }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
{% if current_page < total_pages %}
|
|
|
|
|
|
<a class="next-page button" href="{{ admin_url ~ '&paged=' ~ (current_page + 1) ~ filter_params }}">
|
|
|
|
|
|
<span aria-hidden="true">›</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{% endif %}
|
2026-01-21 18:55:18 +01:00
|
|
|
|
</div>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-01-23 11:37:06 +01:00
|
|
|
|
<!-- Test License Modal -->
|
|
|
|
|
|
<div id="wclp-test-modal" class="wclp-modal" style="display:none;">
|
|
|
|
|
|
<div class="wclp-modal-content">
|
|
|
|
|
|
<span class="wclp-modal-close">×</span>
|
|
|
|
|
|
<h2>{{ __('License Validation Test') }}</h2>
|
|
|
|
|
|
<div class="wclp-test-info">
|
|
|
|
|
|
<table class="form-table">
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th scope="row">{{ __('License Key') }}</th>
|
|
|
|
|
|
<td><code id="test-license-key"></code></td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th scope="row">{{ __('Domain') }}</th>
|
|
|
|
|
|
<td><code id="test-domain"></code></td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div id="wclp-test-loading" style="display:none; text-align:center; padding:20px;">
|
|
|
|
|
|
<span class="spinner is-active" style="float:none;"></span>
|
|
|
|
|
|
<p>{{ __('Testing license...') }}</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div id="wclp-test-result" style="display:none;">
|
|
|
|
|
|
<div id="wclp-test-result-content"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p class="submit">
|
|
|
|
|
|
<button type="button" class="button wclp-modal-cancel">{{ __('Close') }}</button>
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-01-21 20:32:35 +01:00
|
|
|
|
<!-- Transfer Modal -->
|
|
|
|
|
|
<div id="wclp-transfer-modal" class="wclp-modal" style="display:none;">
|
|
|
|
|
|
<div class="wclp-modal-content">
|
|
|
|
|
|
<span class="wclp-modal-close">×</span>
|
|
|
|
|
|
<h2>{{ __('Transfer License to New Domain') }}</h2>
|
|
|
|
|
|
<form method="post" action="{{ admin_url }}">
|
|
|
|
|
|
<input type="hidden" name="action" value="transfer_license">
|
|
|
|
|
|
<input type="hidden" name="_wpnonce" value="{{ transfer_nonce() }}">
|
|
|
|
|
|
<input type="hidden" name="license_id" id="transfer-license-id" value="">
|
|
|
|
|
|
<table class="form-table">
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th scope="row"><label>{{ __('Current Domain') }}</label></th>
|
|
|
|
|
|
<td><code id="transfer-current-domain"></code></td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th scope="row"><label for="new_domain">{{ __('New Domain') }}</label></th>
|
|
|
|
|
|
<td>
|
|
|
|
|
|
<input type="text" name="new_domain" id="transfer-new-domain" class="regular-text"
|
|
|
|
|
|
placeholder="example.com" required>
|
|
|
|
|
|
<p class="description">{{ __('Enter the new domain without http:// or www.') }}</p>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
<p class="submit">
|
|
|
|
|
|
<button type="submit" class="button button-primary">{{ __('Transfer License') }}</button>
|
|
|
|
|
|
<button type="button" class="button wclp-modal-cancel">{{ __('Cancel') }}</button>
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
2026-01-21 18:55:18 +01:00
|
|
|
|
</div>
|
2026-01-21 20:32:35 +01:00
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
(function($) {
|
|
|
|
|
|
// Select all checkboxes
|
|
|
|
|
|
$('#cb-select-all-1, #cb-select-all-2').on('change', function() {
|
|
|
|
|
|
$('input[name="license_ids[]"]').prop('checked', this.checked);
|
|
|
|
|
|
$('#cb-select-all-1, #cb-select-all-2').prop('checked', this.checked);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Sync bulk action selects
|
|
|
|
|
|
$('#bulk-action-selector, #bulk-action-selector-bottom').on('change', function() {
|
|
|
|
|
|
var value = $(this).val();
|
|
|
|
|
|
$('#bulk-action-selector, #bulk-action-selector-bottom').val(value);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Use bottom select value if top is empty
|
|
|
|
|
|
$('form').on('submit', function() {
|
|
|
|
|
|
var topAction = $('#bulk-action-selector').val();
|
|
|
|
|
|
var bottomAction = $('#bulk-action-selector-bottom').val();
|
|
|
|
|
|
if (!topAction && bottomAction) {
|
|
|
|
|
|
$('#bulk-action-selector').val(bottomAction);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Transfer modal
|
|
|
|
|
|
var $modal = $('#wclp-transfer-modal');
|
|
|
|
|
|
|
|
|
|
|
|
$('.wclp-transfer-link').on('click', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
var licenseId = $(this).data('license-id');
|
|
|
|
|
|
var currentDomain = $(this).data('current-domain');
|
|
|
|
|
|
|
|
|
|
|
|
$('#transfer-license-id').val(licenseId);
|
|
|
|
|
|
$('#transfer-current-domain').text(currentDomain);
|
|
|
|
|
|
$('#transfer-new-domain').val('');
|
|
|
|
|
|
$modal.show();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$('.wclp-modal-close, .wclp-modal-cancel').on('click', function() {
|
|
|
|
|
|
$modal.hide();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$(window).on('click', function(e) {
|
|
|
|
|
|
if ($(e.target).is($modal)) {
|
|
|
|
|
|
$modal.hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-01-23 11:37:06 +01:00
|
|
|
|
|
|
|
|
|
|
// Test License modal
|
|
|
|
|
|
var $testModal = $('#wclp-test-modal');
|
|
|
|
|
|
var $testLoading = $('#wclp-test-loading');
|
|
|
|
|
|
var $testResult = $('#wclp-test-result');
|
|
|
|
|
|
var $testResultContent = $('#wclp-test-result-content');
|
|
|
|
|
|
|
|
|
|
|
|
$('.wclp-test-license-link').on('click', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
var licenseKey = $(this).data('license-key');
|
|
|
|
|
|
var domain = $(this).data('domain');
|
|
|
|
|
|
|
|
|
|
|
|
// Show modal with info
|
|
|
|
|
|
$('#test-license-key').text(licenseKey);
|
|
|
|
|
|
$('#test-domain').text(domain);
|
|
|
|
|
|
$testLoading.show();
|
|
|
|
|
|
$testResult.hide();
|
|
|
|
|
|
$testModal.show();
|
|
|
|
|
|
|
|
|
|
|
|
// Call the test endpoint
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: wclpAdmin.ajaxUrl,
|
|
|
|
|
|
type: 'POST',
|
|
|
|
|
|
data: {
|
|
|
|
|
|
action: 'wclp_test_license',
|
|
|
|
|
|
nonce: wclpAdmin.editNonce,
|
|
|
|
|
|
license_key: licenseKey,
|
|
|
|
|
|
domain: domain
|
|
|
|
|
|
},
|
|
|
|
|
|
success: function(response) {
|
|
|
|
|
|
$testLoading.hide();
|
|
|
|
|
|
if (response.success) {
|
|
|
|
|
|
var result = response.data;
|
|
|
|
|
|
var html = '';
|
|
|
|
|
|
|
|
|
|
|
|
if (result.valid) {
|
|
|
|
|
|
html = '<div class="notice notice-success inline"><p><strong>✓ {{ __('License is VALID') }}</strong></p></div>';
|
|
|
|
|
|
html += '<table class="widefat striped"><tbody>';
|
2026-01-27 21:22:45 +01:00
|
|
|
|
html += '<tr><th>{{ __('Product') }}</th><td><strong>' + escapeHtml(result.product_name || '-') + '</strong></td></tr>';
|
2026-01-23 11:37:06 +01:00
|
|
|
|
if (result.expires_at) {
|
|
|
|
|
|
html += '<tr><th>{{ __('Expires') }}</th><td>' + escapeHtml(result.expires_at) + '</td></tr>';
|
|
|
|
|
|
} else {
|
2026-01-27 21:22:45 +01:00
|
|
|
|
html += '<tr><th>{{ __('Expires') }}</th><td><span class="license-lifetime">{{ __('Lifetime') }}</span></td></tr>';
|
2026-01-23 11:37:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
html += '</tbody></table>';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
html = '<div class="notice notice-error inline"><p><strong>✗ {{ __('License is INVALID') }}</strong></p></div>';
|
|
|
|
|
|
html += '<table class="widefat striped"><tbody>';
|
|
|
|
|
|
html += '<tr><th>{{ __('Error Code') }}</th><td><code>' + escapeHtml(result.error || 'unknown') + '</code></td></tr>';
|
|
|
|
|
|
html += '<tr><th>{{ __('Message') }}</th><td>' + escapeHtml(result.message || '-') + '</td></tr>';
|
|
|
|
|
|
html += '</tbody></table>';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$testResultContent.html(html);
|
|
|
|
|
|
$testResult.show();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$testResultContent.html('<div class="notice notice-error inline"><p>' + escapeHtml(response.data.message || 'Error') + '</p></div>');
|
|
|
|
|
|
$testResult.show();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
error: function() {
|
|
|
|
|
|
$testLoading.hide();
|
|
|
|
|
|
$testResultContent.html('<div class="notice notice-error inline"><p>{{ __('Failed to test license. Please try again.') }}</p></div>');
|
|
|
|
|
|
$testResult.show();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Close test modal
|
|
|
|
|
|
$testModal.find('.wclp-modal-close, .wclp-modal-cancel').on('click', function() {
|
|
|
|
|
|
$testModal.hide();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$(window).on('click', function(e) {
|
|
|
|
|
|
if ($(e.target).is($testModal)) {
|
|
|
|
|
|
$testModal.hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function escapeHtml(text) {
|
|
|
|
|
|
if (!text) return '';
|
|
|
|
|
|
var div = document.createElement('div');
|
|
|
|
|
|
div.textContent = text;
|
|
|
|
|
|
return div.innerHTML;
|
|
|
|
|
|
}
|
2026-01-21 20:32:35 +01:00
|
|
|
|
})(jQuery);
|
|
|
|
|
|
</script>
|